自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(226)
  • 资源 (2)
  • 收藏
  • 关注

原创 TypeScript的类型描述文件d.ts

接口和类型别名是定义自定义类型的重要工具。接口用于描述对象的形状,而类型别名用于为类型定义一个别名。x: number;y: number;我们可以使用接口或类型别名来约束对象的结构,并通过类型注解将其应用于变量、函数参数等。

2024-05-19 13:21:07 798

原创 消消乐算法总结

最近在工作中遇到一个问题,做一个消消乐的demo项目,连续相同数目超过四个后就要消除。我在网上看了很多解决方案,有十字形,横向,纵向,梯形搜索。越看越迷糊。这不是用一个BFS就能解决的问题吗?为什么要设定这么多情况?难道是为了优化吗?但是用BFS的同时用一个矩阵记录已经寻找过的元素不就可以提高效率吗?鉴于网上的解决方案如此的低级,还有的需要收费,或者说我没有找到。所以今天我就讲讲我的解决方案并附上代码,希望能有人从我的文章获得收益。消消乐其实也就是两个算法的组合:消除算法,填充算法。

2024-04-23 23:11:55 695 4

原创 实时渲染 -- 流明(Lumen)

首先我们需要知道Lumen需要解决哪些问题。很多人都会问,既然已经有了硬件的Raytracing ,我们为什么还要Lumen呢。这是由于很多硬件并不支持 Realtime Raytracing,对于支持的那些硬件, N 卡还算是勉强可以,而 A 卡支持的比较糟糕。并且实际测试中,3080大概 1 秒钟能做10 个billion 的计算,这个实际的计算量用来做GI 的话,实际还是比较费力的。

2024-04-15 11:36:34 660 3

原创 实时渲染 -- 全局光照(Global Illumination)

我们今天的课程主题是动态全局光照和Lumen ,在讲Lumen之前,我们需要首先需要了解GI(Global Illumination),如果不把GI讲清楚,大家将会陷入Lumen复杂深邃的技术细节中。如果不了解GI的发展演变,大家会感觉Lumen中的某些细节处理是凭空从天上掉下来的。但其实不然,Lumen中的很多算法和思想在之前的一些GI算法中都有出现和实践过,因此Lumen更像一个各种GI算法的集大成者。我们只有理解GI最宏观的体系结构,你才能理解Lumen 是怎么产生的。

2024-04-14 16:27:26 693

原创 图形学物体拾取:CPU VS GPU

消耗性能低;对于射线碰撞,没有精度问题;但是只能拾取Mesh这种粒度;除了拾取Mesh还可以拾取图元,比如三角形;依靠物理系统,消耗性能比较高;会有精度问题,比如图纸放大缩小上百倍很难拾取(本人因放大缩小图纸感受到了精度问题);打通了引擎Runtime和编辑器开发的桥梁,通过物体的拾取就可以挂载其他辅助的组件,例如Gizmos,进而编辑场景。或者通过脚本来调用raycast对场景的物体进行射线检测或者动画拾取。

2024-04-09 01:05:06 702

原创 JS中bind、call与apply 区别

我们就可以使用call方法调用obj.sayHello, 并将obj.sayHello中的this修改为obj1,把 ‘设计师’, ‘画画’ 这两个参数出给obj.sayHello。区别在于传参形式不同,apply接受两个参数,第一个参数是要指向的this对象,第二个参数是一个数组,数组里面的元素会被展开传入fn,作为fn的参数。关于call、apply、bind函数,它们主要用来改变this指向的,在很多框架中常有用到,而且也是面试官喜欢问到的问题:多数会问道三者的区别, 以及手动实现它们。

2024-04-08 21:18:05 264

原创 JS变量声明var、let、const详解

varletconst函数级作用域块级作用域块级作用域重复声明不可重复声明不可重复声明变量提升不存在变量提升不存在变量提升值可更改值可更改值不可更改全局变量挂载到window全局变量不会挂载到window全局变量不会挂载到window不使用varconst优先,let次之i

2024-04-08 20:26:47 950

原创 实时渲染 -- 体素化(Voxelization)

我们之前讨论的大部分问题都是关于面表示的。由于这些方法不需要显式地表示物体的内部空间,所以非常高效。体建模方法表示的是实体而不是表面。使用体模型可以产生更丰富的仿真效果,如物体的运动学行为和半透明光照效果。

2024-04-05 13:05:54 1017

原创 实时渲染 -- 材质(Materials)

(1) 非负性:fr(ωi ->ωr ) ≥ 0(2)线性:BRDF可以分成多项分别计算后相加(类似Blinn-Phong模型分成高光+漫发射+环境光)(3)可逆性:调换BRDF的入射光和出射光,返回值是一样的(4)能量守恒:不能违背能量守恒原则。下面公式,其实可以看做是半球上所有方向入射光的能量Li总 的一个系数,这个系数必须满足 ≤ 1(5)各向异性/各向同性BRDF:不管是各项同性还是异性材质都遵循光的可逆性,互换出入射光,BRDF返回值不变。

2024-04-04 15:10:25 959

原创 游戏引擎中的物理应用

而在更多情况下,动画和物理的区分并不像上述一样清晰,而是直接互相融合,比如抱着一个小女孩跑步的过程,一方面小女孩自身拥有一定的晃动动画,另一方面随着整体位置的移动,动画带来的角色物理信息会一起输入到物理系统去更新最终呈现出来的融合效果,使得避免动画单纯重复(只动画)和小女孩乱晃(只物理/布娃娃)。3维物体的切割也是类似。分割3维物体的一个难点是处理切割处的纹理问题,一般有两种方式:1、直接制作对应的三维纹理,切割时直接用(麻烦、贵)2、离线计算好这些纹理,一旦破碎则切换到对应的纹理,(要瞬时处理)。

2024-04-03 11:41:02 1308

原创 游戏引擎中的物理系统

在这个基础上,优化方法是取凸包A的某条边a做轴时,直接将凸包B的所有顶点投影到a的垂线上,因为这样可以保证凸包A的所有顶点都在垂线上a的一侧,所以只需要判断凸包B上所有顶点在垂线上的投影是否在另一侧就行。这种方法下,由于实际游戏中的时间片Δt不可能和现实中一样小,所以会导致能量不守恒(变多)(如图中右侧所示,实际位移是偏多的),误差越来越大,物体逐渐甩出去。但实际游戏中时间不是连续的,而是由一帧帧实现的,所以通常需要解决的问题是在已知当前物体位置和速度的前提下获取之后某时刻的物体位置和速度信息。

2024-04-02 23:29:02 1458 1

原创 游戏引擎之高级动画技术

虽然线性插值本身简单,但其实现的一个重要前提是能够找到两个clip中匹配的对应pose(帧)去做插值,因而我们需要艺术家在做DCC(Digital Content Creator)时确保两个clip的节奏相同,这样可以在归一化后保证每一帧都对应一样的动作(比如取时间t时走的pose是踏在地上,跑也是一样,只是动作有所不同)。简单讲就是blending总是以additive的形式去融合,比如直接在眼睛的位置上加上闭着的眼睛,而不会将睁着的眼睛和闭着的去做插值。event概念引用于UE,即事件。

2024-04-02 19:52:41 3560 2

原创 判断点在多边形内的算法

在计算几何中,判定点是否在多边形内,是个非常有趣的问题。

2024-04-01 14:08:54 1079 6

原创 游戏引擎中的声音系统

多普勒效应(Doppler effect)是波源与观察者有相对运动时,观察者接受到波的频率与波源发出的频率并不相同的现象。生活中比较常见的例子是远方急驶过来的火车鸣笛声变得尖细(即频率变高,波长变短),而离我们而去的火车鸣笛声变得低沉(即频率变低,波长变长),这就是多普勒效应现象,同样的现象也发生在私家车鸣响与火车的敲钟声,音频参见[声的多普勒效应]。三维场景中有无数的声源,每个声源从不同的方向,不同的距离表现的效果都不一样。高频的声音衰减的快,低频的声音衰减的慢。不同的材质对声音的吸收也不同。

2024-04-01 12:33:31 1636 2

原创 游戏引擎中的粒子系统

当我们渲染普通场景时,由于Z-buffer的帮助,其实只需要渲染接触到的场景的第一个物体(其他被遮挡不需要渲染),但粒子效果有时候(最差情况下)会在一瞬间产生叠满整个分辨率好多层的粒子,而且它们不存在完全遮挡关系,所以相当于一下子要进行超大量的渲染。当时间跳转到下一次tick时,会新建一个alive list1,并依序检索alive list中的粒子,如果发现某个粒子死亡了,就会把这个粒子序号移到死亡列表中,并且在渲染时也跳过这个粒子,如果仍存活就照抄到alive list1中。

2024-04-01 11:33:57 1167

原创 游戏引擎中的大气和云的渲染

从而导致原方法LUT参数中的高度 h 以及太阳顶角 η都不需要参与预计算(因为都实时更新了),所以新方法的LUT表中只需要计算出观察的天顶角 θ 和一个水平方向环绕360度的夹角 ϕ (对应原来太阳到观察视角水平方向的夹角)即可。因为上述缺点,一种更简化的多次散射方案被提出,其特点在于认为任何散射都是各向同性的,向所有方向均匀散射,所以对一个介质来说,其所有邻居介质收到来自它的散射能量都是相同的,因而一次散射带来的结果只是整体削减(吸收)了固定百分比。实际计算时,Ray Marching是最常用的方法。

2024-03-31 18:49:01 924

原创 Unity -- 遮挡剔除

勾选后,由下图可见,刚才视锥内保留的好多物体又消失了,这是因为相机处于室内,室内墙不透明,视锥内的室外物体都被室内墙挡住看不见,使用遮挡剔除后,那些物体也被剔除掉了,所以不可见了,但是对比下图右下角游戏视图的内容和前面没有任何剔除以及视锥剔除后游戏视图的内容,完全一样,也就是说,遮挡剔除后,也不会改变游戏视图的内容,但是在视锥剔除的基础上,又进一步大幅度降低了相机的渲染量,运行时作品会更加流畅,因为被剔除物体的几何、材质、光照贴图、粒子系统等都不再被渲染了。简单地说,就是把被遮挡住的物体剔除掉。

2024-03-28 09:37:02 1288

原创 JS事件循环机制

JavaScript事件循环机制是JavaScript中处理异步操作的一种机制。它基于事件队列和事件循环的概念,用于管理和执行异步任务。当JavaScript代码执行时,同步任务会立即执行,而异步任务会被放入事件队列中。事件队列是一个先进先出的数据结构(队列),用于存储待执行的异步任务。事件循环是一个持续运行的过程,它会不断地从事件队列中取出任务并执行。执行同步任务:JavaScript引擎会按照代码的顺序执行同步任务。执行微任务:在同步任务执行完毕后,JavaScript引擎会检查微任务队列。

2024-03-27 09:26:44 847

原创 纹理压缩算法

我们知道游戏中对于3D物体表面细节的表现最重要的还是靠贴图来实现的,那么越是高分辨率越是真彩色的贴图自然表现力也是越强,但是同时带来的问题是所需占用的内存会成倍的上升,而节省内存这一点在目前的游戏中还是非常非常重要的。所以各个平台上都在使用纹理压缩的技术,让纹理贴图在内存占用和显示效果能达到一个尽可能的平衡。纹理压缩是为了解决内存、带宽问题,专为在计算机图形渲染系统中存储纹理而使用的图像压缩技术。画质比较 : RGBA > ASTC 4×4 > ASTC 6×6 > ETC2 ≈ ETC1。

2024-03-26 09:55:01 696

原创 游戏引擎中的地形系统

首先,根据屏幕的分辨率,在模型的可见面上镶嵌和最终象素尺寸相同的微多边形。接着再为新的多边形确定好新的法线方向。一种实现的方式是比如有1000个顶点,根据纹理中的数据对平面特定区域的顶点的高度进行位移。但是会有一个T junctions的问题,这个得查找对应周围的边是不是更加细分,如果更加细分,那我相邻没有细分的也要进行切分。我们会把我们用到的存到内存中,没有用到的放在磁盘中,然后通过分页来对磁盘内容进行索引。事实上我们的游戏中会有非常多的纹理,我们的纹理会存储在Texture array。

2024-03-24 15:59:26 1491 1

原创 基于物理的实时渲染 -- PBR

PBR,或者用更通俗一些的称呼是指基于物理的渲染(Physically Based Rendering),它指的是一些在不同程度上都基于与现实世界的物理原理更相符的基本理论所构成的渲染技术的集合。正因为基于物理的渲染目的便是为了使用一种更符合物理学规律的方式来模拟光线,因此这种渲染方式与我们原来的Phong或者Blinn-Phong光照算法相比总体上看起来要更真实一些。

2024-03-24 14:34:55 851

原创 渲染管线 -- 后处理

Bloom的实现原理:我们首先根据一个阈值提取出图像中的较亮区域,把它们存储在一张渲染纹理中,再利用高斯模糊对这张渲染纹理进行模糊处理,模拟光线扩散的效果,最后再将其和原图像进行混合,得到最终的效果。根据距离摄像机的远近绘制,最远的物体最后绘制,这样来说天空盒是最后绘制的。延迟渲染在计算光照的时候,需要注意的是每个光源创建一个包围盒来算他对于pixel的贡献,这样计算才能正确获得光照加速。我的理解是AO,表示正半球上有多少部分能够看到,实际上就是计算渲染方程中的可见性函数,目的是突出阴影。

2024-03-23 16:33:59 819

原创 现代游戏引擎架构

保证同一时间内只有一个线程可以操作修改资源,可是这样又会引起死锁的问题。最著名的就是银行家算法。是一个轻量级的线程,在切换是不需要调用中断,由程序员调用即可。用不同的线程,进行不同的逻辑计算。快的线程需要等慢的线程结束。但是摩尔定律已经不在适用了,硬件的发展目前已经达到瓶颈。游戏的渲染计算对算力要求很高,所以我们需要把操作系统的资源利用到极致。进程与线程: 进程有独立的存储单元 线程是进程之内的,会共享内存。原子操作,可以不用加锁,但是会浪费CPU资源。多添加几个线程,可以动态分配线程资源。

2024-03-22 15:38:10 565

原创 数据结构 - 链表

使用单向环形链表解决Josephu问题,用不带头结点的单向循环链表先构成一个有n个节点的链表,然后由k节点起从1开始计数,直到第m时,对应节点删除,然后从被删除的下一个节点开始从1开始计数,直到最后一个节点被删除结束算法。链表是一个在物理存储单元中不连续,没有顺序的的存储结构,关于它的顺序是由链表中的指针链接实现的,是一种递归的数据结构,链表有一系列节点组成,而这些节点会在运行时动态生成。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。双向链表可以自我删除,单向链表不可以,需要靠辅助节点来删除。

2024-03-22 14:32:31 452

原创 游戏引擎中网络游戏的基础

在玩家B的客户端看到的玩家A只是玩家A的复制品,他的行为逻辑是由服务器计算反馈的。优化:不等最慢的客户端,设定一个deadline,超出deadline后就不管没有提交的输入了,而是发放已经提交的输入。帧同步的过程:每一帧所有的客户端把你输入交给服务器,服务器汇总后再发给每个客户端,每个客户端按照同样的逻辑处理这些输入。例如游戏中的回放并不是游戏战斗过程的录屏,而是在游戏时记录所有玩家的输入,然后将这些输入重新计算就可以得到同样的效果。随机数:每个客户端生成的随机数也是一样的,使用随机种子。

2024-03-17 01:27:00 2132

原创 游戏引擎中的动画基础

视觉残留理论 - 影像在我们的视网膜上残留1/24s。交互:游戏中的玩家动画需要和场景中的物体进行交互。实时:最慢需要在1/30秒内算完所有的场景渲染和动画数据。(可以用动画压缩解决)真实:多个动画的融合,表情的变化。

2024-03-16 18:26:53 1169

原创 DHCP协议详解

DHCP 协议是从 BOOTP 协议发展而来。但 BOOTP 运行在相对静态的环境中,每台设备配置专门的 BOOTP 参数文件,该文件会在相当长的时间内保持不变。DHCP 允许设备动态地获取 IP 地址,而不是静态指定每台主机地址。DHCP 能够分配其它的配置参数,客户端仅用一个消息就获取它所需要的所有配置信息。大刘他们的设备使用 DHCP 功能后,只要连接到网络,就可以进行 TCP/IP 通信。对于路由器和交换机,通常是手动配置 IP 地址等参数。

2024-03-06 16:38:38 994

原创 游戏引擎渲染流程

我们首先看到渲染技术的发展游戏渲染面临的挑战:一个容器中同一时刻有大量的游戏对象需要进行渲染,并且不同对象渲染的形式、算法还有所差异,这些使得游戏的绘制系统变得非常复杂;其次,游戏引擎的渲染还要与当代的硬件适配;同时,游戏引擎需要保证渲染的稳定性,即使进入非常巨大复杂的场景,也要在至少1/30ms内完成绘制,随着玩家需求的提高,这一时间甚至可能被缩短到1/60ms、1/120ms之内;

2024-03-05 19:05:34 1205

原创 游戏引擎分层简介

至于数据结构和容器,编程语言中自带的数据结构可能会出现一些问题,比如C++中的Vector在添加对象时开辟的储存空间会成倍增长,在添加大量对象后,使用的储存空间我们将无法得知,可能会产生内存空洞,而引擎中的数据结构更加方便内存的管理,提高访问效率;游戏中有的不只是一行行的源代码,还有各种格式的多媒体文件,如PhotoShop的PSD文件、3DSMAX的MAX文件,加载管理这一系列的图形、图像、音频、视频文件以及其他数据,就是资源层的任务了。这样的分层架构使得上层灵活,底层稳定,更有利于功能的更新和开发。

2024-03-03 21:17:18 3749

原创 计算机图形学之动画

在关键的位置上制作一帧画面,而中间的过程采用自动生成的方式形成动画自动生成可以用线性插值的方式,但是很生硬:用splines来平滑过度或者有必要的突变则会有更好的动画效果:但是这样的动画不符合物理规律,只是看起来合适。

2024-03-03 19:11:25 996

原创 游戏空间划分技术

空间划分算法有很多,比如均匀网格四/八叉树k-d树Bsp树,每一种算法都有自己的优缺点,我们需要从理论上理解这些算法,然后在实际项目中进行灵活的运用。游戏中经常使用空间划分算法来优化碰撞,视锥体剔除,邻近查询,因此每当我们讨论一个算法的时候都会从这三方面进行探讨。另外我们还将考虑静态对象和动态对象对算法的影响,主要体现在空间节点的快速更新能力,以及对象快速变更节点的能力。

2024-02-24 13:36:42 1041

原创 Unity中.Net与Mono的关系

NET是一个开发框架,它遵循并采用CIL(Common Intermediate Language)和CLR(Common Language Runtime)两种约定,CIL标准为一种编译标准:将不同编程语言(C#, JS, VB等)使用各自的编译器,按照统一的标准编译成语义一致的CIL中间码, 这样虽然代码使用的语言不同,但编译出的产物是一样的。CLR标准为一种执行标准:不同的操作系统可以根据CLR这一执行标准开发出自己平台的中间码执行器,这样CIL这个标准中间产物就可以在不同的平台执行了。

2024-02-23 11:30:58 1405

原创 关于Laya引擎的一些思考

又假如,在一个剧情游戏中,两人在对话。此时,Text文本对象,就会不断的向大图合集进行文本图集的提交,占满大图集后,又需要创建一个新的图集继续提交,而不用的旧图集,如果没达到GC条件,也会一直存在,所以如果此次查看内存占用统计信息,就可以看到会一直在涨内存,直到GC条件达到之后,才会被销毁。如果采用了Text文本,那每一个Text文本对象中的文本字符会一起形成小图集提交到大图合集中,比如游戏中某个文本对象有300字,其中一个字符发生改变,也会对该文本对象的300字整段文本图集重新提到大图合集中。

2024-02-23 01:40:45 1364

原创 C#中的关键字params的用法

params关键字的作用在于可以让方法参数的数目可变。params的参数类型必须是一维数组。一旦在方法加入了params关键字之后,它的后面就不能再有任何其它参数了。换句话说就是,params必须放在方法的所有参数的最后。方法中只能允许一个params关键字。public void 做饭(家庭成员 主厨, 家庭成员 洗菜)public void 做饭(params 家庭成员[] members)如上图,我们有一个“做饭”的方法,做饭的时候,可能有1个人去做饭,也可能2个,也还可能3个人。

2024-02-22 10:43:11 1025

原创 网络同步—帧同步和状态同步解析

同步就是要多个客户端表现效果是一致的,而且对于大多数的游戏,不仅仅要表现一致,还要客户端和服务器的数据也是一致的。所以同步是个网络游戏概念,只有网络游戏才需要同步,而单机游戏是不需要同步的。帧同步和状态同步是在网络游戏和多人在线应用中常见的两种同步方法,它们用于确保所有参与者看到的游戏状态一致。

2024-02-19 18:07:11 1018

原创 FTP协议详解

FTP为File Transfer Protocol的缩写,即文件传输协议,是TCP/IP 协议族中的协议之一。FTP是一个用于在计算机网络上在客户端和服务器之间进行文件传输的应用层协议。RFC 959定义了FTP协议规范。同大多数Internet服务一样,FTP也是一个客户/服务器系统(C/S系统)。用户通过一个客户端程序连接至在远程计算机上运行的服务器程序。依照FTP协议提供服务,进行文件传送的计算机就是FTP服务器,而连接FTP服务器,遵循FTP协议与服务器传送文件的电脑就是FTP客户端。

2024-02-19 15:31:38 1857

原创 RIP协议详解

RIP(Routing Information Protocol,路由信息协议)是最早的动态路由协议,其原理简单,配置容易。RIP是一种基于距离矢量算法的路由信息协议,基于UDP端口520,属于应用层协议。动态路由协议,能够自动发现路由、计算路由,主要用于局域网和小规模网际网络中的路由选择。RIP基于距离矢量路由选择算法,也就是说它通过跳数(hop count)作为度量路由之间的距离,默认最大跳数为15跳,超过15跳的网络被认为是不可达的。

2024-02-18 11:58:55 2979

原创 数据结构 - 线索树

当然,我们肯定需要借助结点的指针域来保存直接前驱和直接后继的地址。其实,在上图的普通二叉树中(以中序遍历得到的序列),部分结点(指针域不为空的结点)是可以找到其直接前驱或后继的,比如结点 E 的左孩子 G 就是结点 E 的直接前驱;结点 A 的右孩子 C 就是结点 A 的直接后继。但部分结点(指针域为空)是行不通的,比如结点 G 的直接后继是 E,直接前驱是 B,但在二叉树中却不能得出这样的结论。怎么办呢?

2024-02-08 23:43:47 1812

原创 浮点数加、减运算步骤

精度位数格式单精度 float4个字节32位符号位1位,阶码8位,尾数23位双精度 double8个字节64位符号位1位,阶码11位,尾数52位1.2 浮点的表示方法浮点数在机器中的形式如下所示,采用这种数据格式的机器称为浮点机浮点数由阶码j和尾数S两部分组成,阶码是整数,阶符和阶码的位数m合起来反应浮点数的表述范围及小数点的实际位置;尾数是小数,其位数n反映了浮点数的精度,数符表示浮点数的正负。1.3 浮点数表示范围。

2024-01-31 16:02:21 1628

原创 数据结构:大顶堆、小顶堆

堆是一种完全二叉树。完全二叉树的定义:所有节点从上往下,从左往右的依次排列,不能有空位置,是为完全二叉树。根节点(堆顶元素)是所有节点中的最大值(父节点都大于左右子节点)。大顶堆常用于实现优先队列,且可用于构建堆排序算法。小顶堆中的根节点是所有节点中的最小值(父节点都小于左右子节点)。小顶堆常用于问题如:查找流中的前 K 个最小元素。

2024-01-30 16:14:32 1415

动物军团小游戏项目工程

cocos制作的对战类小游戏,微信搜索动物军团

2023-07-11

基于Django框架的毕业生就业推荐系统

基于Django框架的毕业生就业推荐系统

2023-05-06

MySQL数据库.docx

mysql学习笔记

2021-12-09

Unity知识点.docx

包含unity基本,进阶所有知识点

2021-10-04

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除