博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
引擎设计跟踪(五)
阅读量:4881 次
发布时间:2019-06-11

本文共 3775 字,大约阅读时间需要 12 分钟。

最近主要的更新:

媒体库(MediaLibrary),
集成FreeImage
地形高度画刷,
地形贴图画刷,
地形法线计算,
天空球,光源 

以上支持无缝编辑.

另外,写了命令行参数解析以及Editor的Splash,纯当作消遣娱乐了,呵呵.

关于媒体库:
类似UE的Contetn Brower,当然比它要简陋的多了.呵呵.MediaLibrary的窗口可以使用两种方式:模态窗口和非模态窗口.
非模态窗口就像UE那中模式,显示的时候不抢占前台,不影响其他操作,而且运行时不需要重复构建窗体,缺点是需要额外的通信,比如拖动项目到目标窗口(UE的模式)
模态窗口就相反,好处是do-modal 之后就可以返回选择的结果,避免了OLE,drag之类的东西,这个没有做过,不知道复杂不.所以我还是选择了模态窗口模式.
为了使媒体库的数据和UI分离,实现了两个类,一个全局的IMediaLibrary singleton,来保存所有文件的分类和路径信息(纯数据模块),和一个MediaLibraryUI(UI模块),来读取纯数据并显示.同时需要一个IPreviewer接口,来生成文件的预览缩略图,
需要IPreview,而不是直接生成的原因是,某些资源(model,paticle等等,目前这些都还没有实现)是需要调用渲染系统来生成缩略图的,而渲染系统的细节对于编辑器,甚至对于整个上层逻辑都是不可见的,所以要添加这样一个接口来解藕.
目前只实现了一个ImagePreviewer来生成贴图和画刷的缩略图.

 

关于FreeImage:

之前用Ogre没有看过FreeImage,这次粗略的看了一下,还是比较灵活的,比如FreeImageIO这个接口(C语言风格的指针集合),之前是用GDI+加载文件,目前已经改成利用这个FreeIamage接口加上引擎的IStream来加载图片,这样以后如果有自己的资源包格式,就方便多了.

同时,为了避免对FreeImage的直接依赖,仍然是先定义了简单的公共接口(IImage和IImageManager),然后用插件的形式将FreeImage加入进来. 

 

关于地形工具:

由于地形的画刷类型(高度,贴图等等)的目标(地形)区域判断和源(画刷)区域判断几乎都是一致的,还有射线检测,绘制贴花等,所以把这功能放在基类里面,这样可以尽量避免冗余代码.
地形高度和法线等的编辑有两种方式:
1,直接编辑地形的硬件缓冲区,就是包含顶点(Vector3)数据的VertexBuffer: modify-->vertexbuffer
2,先编辑地形的资源数据(就是nxn*(short/int/char)的高度图和法线图),再将heitmap转换为渲染需要的顶点数据 :modify-->heightmap-->vertexbuffer
第一种方式的实时效率比较高,直接提交到显卡就可以了,缺点是资源保存的时候需要回转数据为nxn的高度图等,
第二种方式直接修改了资源的数据,这样在数据保存的时候,就避免了数据回转(将顶点数据转换为高度图) ,当然缺点是运行时多了一个中间步骤.就是再将高度图转换位显卡顶点数据
由于第二种方式后面的heightmap->vertexbuffer的转换过程,与地形初始加载时候的过程类似,所以比较简单,又考虑到Undo/Redo可能会节省内存空间(这个功能还没有做,也没做过,只是感觉会的),
同时这种编辑方式跟具体的渲染(顶点流格式)无关所以耦合度更低~ 选择了第二种方式.

比较繁琐的是顶点的法线更新,由于是使用了一次性命令来更新所有地形,所以为了效率考虑,方法参考了Ogre的思路:使用后台线程更新.由于之前的TaskManager已经可以很方便的添加(后台/前台)任务,所以现在写起来比较简单.需要考虑的问题是无缝模式的法线更新,虽然是逐Tile更新的,但是边缘的发现更新,还是需要邻接Tile的顶点数据的,这里处理就会比较麻烦,每次更新一个tile,都要将相邻的tile顶点数据也传进去.

 

关于命令行解析:

定义个全局的ICmdParser可以添加支持的命令,命令有全名--开头的,也有缩写-开头的一个字幕,如--help,-h等.然后把argc,argv传给ICmdParser,让它解析,之后应用程序就可以通过ICmdParser来读取命令行的配置了.
顺便将两个EXE工程,Editor和Game合并为一个工程,通过命令行来切换模式--mode=Game 或者--mode=Editor.
首先定义个Application类,还有对应的工厂,于是可以实现EditorApplication和GameApplication,--mode的可选项是遍历了Application的工厂来添加的.于是注册了EditorApplication和GameApplication之后,--mode中就出现了两个选项.以后如果添加新的应用类型,--mode的参数就会自动添加新的选项了.流程如下:
--mode options generator:
for each available object in Application factory
  add object name to the option(Game,Editor,etc.)
其实引擎里面很多地方都使用了枚举工厂的可用对象来生成UI等可选的列表,从而方便用户选择,这样就避免了硬编码添加.
另外添加了--config选项来强制打开配置界面,配置完成后退出程序.
Splash的写法就相对简单了,除了在OnCtlColor 里面设置文字信息的透明背景之后,还要在每次更新文字之后,InvalidateRect:
CStaticTextCtrl->GetWindowRect(&rect);
ScreenToClient(&rect);
InvalidateRect(&rect);
上面的代码比较简单,就不解释了.
 SplashWindow是一个非模态的TopMost窗口,显示之后,就可以初始化editor的资源了,同时将资源路径交给SplashWindow显示就可以了.
还有天空球和光源,比较简单了,光源是很简单的方向光,为了渲染地形的法线用的.天空球是手动创建的球形Vertexbuffer+UV.由于之前的设计里面有渲染前的回调函数:
void updateRelativeCamera(const Vector3& cameraPos,const Quaternion& cameraRotation);所以天空球就可以根据摄像机的位置来更新位置了.
还有光照的shader,目前使用了Shader Model3.0的动态循环来实现多光源,代码贴出来:

#define MAX_LIGHT_COUNT 8int light_count;float4 light_vector[MAX_LIGHT_COUNT];float4 light_diffuse[MAX_LIGHT_COUNT];float4 light_ambient;float4 light_specular[MAX_LIGHT_COUNT];float4 eye_position;float4 calculateLight(float3 worldPos,float3 worldNormal){	float4 light = float4(light_ambient.xyz,1);		float3 eye_dir = normalize(eye_position.xyz - worldPos);	worldNormal = normalize(worldNormal);		for( int i = 0; i < light_count; ++i )	{		//calculate diffuse		float3 light_dir = normalize(light_vector[i].xyz - light_vector[i].w*worldPos);		light.xyz += light_diffuse[i] * dot( worldNormal, light_dir );				//calculate specular		float3 half_vec = normalize(light_dir + eye_dir);		float specular = pow( dot(half_vec,worldNormal),32);		light.xyz += light_specular[i] * specular;	}		//return saturate(light);	return light;}

  

下一步的计划是研究模型和动画,以及Max的模型动画导出.不过最近准备忙别的事情了,这个计划等到以后有时间了再搞.
最后还是传统,贴张图纪念下 (512*512)*(3*3 )

转载于:https://www.cnblogs.com/crazii/archive/2011/09/11/3D_Engine_Note.html

你可能感兴趣的文章
免费下载知网文献的方法 | sci-hub免费下载SCI论文方法
查看>>
测试用例,变量之间,相互调用的方法,和修改原来初始化变量的方法
查看>>
ASP.NET MVC中将控制器分离到类库的实现(转)
查看>>
Poj 2304 Combination Lock(模拟顺、逆时钟开组合锁)
查看>>
Palindrome Number
查看>>
H5上传功能
查看>>
three.js尝试(二)模拟游戏开发:3D人物在地图上行走
查看>>
PHP命名空间(Namespace)的使用详解
查看>>
java项目@override报错问题
查看>>
DataTable 和Json 字符串互转
查看>>
Django中Template does not exit
查看>>
Redis安装 java中的连接 序列化 反序列化
查看>>
hdu 1896 优先队列的应用
查看>>
递推和迭代的比较
查看>>
12306HTTP请求过程
查看>>
加快mysql数据库导入
查看>>
位运算
查看>>
有意思的网站
查看>>
HTML 常见代码整合;
查看>>
【php】文件系统
查看>>