qradiant

 关卡编辑器的代码分析
 
 
 

对于做一个quake3游戏而言,我们可以使用关卡编辑器来制造游戏,

使用quake3的关卡编辑器,可以制造场景,设立玩家的出发点等等。

doom3则是将这个代码中model模型变成了lwo,md5,ma文件等等

image使用了dds图像了,material比quake的shader语言更加的丰富了


quake3关卡编辑器如图所示

(1)

quake3关卡编辑器的的brush如下

图片选自 http://wiki.splashdamage.com/index.php/Brush_Basics

 

 

(2)

patch,来做曲面的

 

 


这一篇主要乃是关卡编辑器代码的一些大致上的了解。

游戏中要用到的这个资源的目录,包括了这个

例如quake3这个关卡编辑器在安装以后,会产生一下的游戏资源在安装的位置上
base

 mapobject里面包括了,md3模型
texture里面包含了三个贴图的文件包
common.pk3里面包含了游戏要用到的贴图,

关卡编辑器部分
dist_t这个乃是对于关卡编辑器运行过程中的这个键盘的按键的键值的分析
distlist链表了者也
命令行,来解压程序

z视图这个乃是这个minheight,maxheight的处理了者也
增加了点,设置点的处理等等
得到了包围盒,清除了包围盒了者也
得void REN_ClearBuffers (void);
void REN_DrawCameraFace (face_t *idpol);
void REN_DrawXYFace (face_t *idpol);
void REN_BeginCamera (void);
void REN_BeginXY (void);
渲染的代码非常的少者也
到了最近的包围盒了者也
网上找到了一篇文章


1、坐标系统

 

    《QUAKE》中使用了标准的“左手系”坐标,如图所表示。“左手  

”的意思是指你把左手半握拳,大拇指树起来的话,大拇指就表示了Z

轴,其余四个手指是从X轴指向Y轴。

有一些物体当然是摆放得比较随意,比较斜一点,这时就要用到

一个“角度”的概念了。《QUAKE》中的角度是如下设定的:

 

   0-359: 普通角度

   -1: 上

    -2: 下

 

2、刷子(Brush)

 

刷子是《QUAKE》的地图中两个最重要的概念之一。每一个刷子都

定义了一个单独的区域。每一个区域都被看成是四个以上相互交叉的

面形成的。而每一个面又是由不在同一直线上的三个点定义的。注意

的是这三个点必须是按照顺时针的顺序排列。不过笔者至今没有弄清

楚为什么这些老外要把它叫做“BRUSH”。每一个刷子的声明

(Statement。注意!我们开始涉及到C语言的概念了!)都应是如下

形式:

 

{

( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0

( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0

}

 

也许您第一次看到它们的时候会觉得有些脑子发晕,反正我是。其

实这一大堆东西就是定义了一个从点(128,128,64)到点(256,384,

268)的长方体。每一行的意思如下:

 

128 0 0

128 1 0

128 0 1

GROUND1_6

0

0

0

1.0

1.0

第一点

第二点

第三点

材质

x_off

y_off

旋转角度

X轴范围

Y轴范围

 

 

解释:

 

第一点、第二点和第三点:这三点定义了一个面,所以当然不能是

在同一条直线上。每一个面只能被定义一次。

 

材质:所使用MIP材质的名字(MIP将会在以后讲到)

 

x_off:材质的X轴偏移,必须是16的倍数

 

y_off:材质的Y轴偏移,同样必须是16的倍数

 

旋转角度:材质旋转的角度,单位是度。

 

X轴范围:材质在X轴方向上的长度范围

 

Y轴范围:材质在Y轴方向上的长度范围

 

3、*.MAP文件基础知识

 

其实MAP文件的结构挺简单的,它就是一个文本文件。所有的

《QUAKE》编辑器都应该同时支持UNIX和DOS两种文本格式。

MAP文件是对《QUAKE》的关卡建造格式的说明。建议在改动

时尽量修改MAP文件,因为所有的id Software发布的工具都是针

对MAP文件做改动的。注意其实MAP文件都是一组“未编译”的数

据,只有在它转换为*.BSP文件之后才可以被《QUAKE》所认识。

转换是用专门的BSP转换工具来完成的,比如QBSP.exe。另外,MAP

文件还要由专门的光影处理器处理过,这样《QUAKE》才能计算出

在某个地方的光线强度。否则的话在游戏中会以最强光线显示这

部分地图。最后,为了使此地图在游戏中运行时速度更快和不出

错,还要用VIS这样的工具进行处理。总之,《QUAKE》总的地图

设计是一件非常费时间的事,比当年设计《DOOM》的地图要复杂

得多,即使你现在用的机器比那时候快了很多,但是可能你花费

的时间会更多。

 

MAP文件通常的结构如下:

 

{

entity

{

brush (optional)

}

}

...

 

在MAP文件中可以加进注释,方法和C++中是一样的,用“//”

表示后面是注释的内容。

 

在MAP文件中可以使用很多种实体(entity)和刷子的组合。

但是所有的MAP文件都要有一个worldspawn的实体,它通常都是

文件的第一个入口,里面定义了所有这个关卡中常用的刷子。每

一个MAP文件中只能有一个worldspawn实体。其构造如下:

"classname" "worldspawn" // 表示这是建造本关卡的QUAKEC函数开始!

"wad" "DIRPATH" // 表示使用哪一个图形文件,即*.WAD文件

"message" "TITLE" // 本关的名字

"worldtype" "#" // 本关的类型,0表示为中世纪的,1表示古巴比伦式

(这是基本模式), 2表示金属

"sounds" "#" // 决定放哪一首CD音轨

 

下面是一个简单的MAP文件示例:

 

{

"sounds" "1"

"classname" "worldspawn"

"wad" "/gfx/base.wad"

 

"worldtype" "0"

{

( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0

( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0

}

}

{

"classname" "info_player_start"

"origin" "256 384 160"

}

 

你可以看到,所有的刷子都包括在实物里了。其实MAP文件中

最复杂的部分是在于实物,这也是我们下面要进一步讨论的。

 

二、实物(entity)的基本知识

 

1、基本结构

 

实物是在MAP文件中另外一个重要的组成部分。实物当然可以

理解为一个东西,但是不完全是。有时它是一个触发的机关,有时

它是活动的暗门。一个实物的结构通常如下:

 

{

"classname" "light"

"origin" "0 128 64"

"light" "255"

}

 

这就是普通的实物结构的声明。“普通”的意思是说它还没有

和刷子结构联系起来。当两者联系起来之后的声明形式如下:

 

{

"classname" "func_door"

"angle" "0"

"speed" "16"

"targetname" "t1"

"sounds" "1"

"wait" "16"

{ 

( 128 0 0 ) ( 128 1 0 ) ( 128 0 1 ) GROUND1_6 0 0 0 1.0 1.0

( 256 0 0 ) ( 256 0 1 ) ( 256 1 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 128 0 ) ( 0 128 1 ) ( 1 128 0 ) GROUND1_6 0 0 0 1.0 1.0

( 0 384 0 ) ( 1 384 0 ) ( 0 384 1 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 64 ) ( 1 0 64 ) ( 0 1 64 ) GROUND1_6 0 0 0 1.0 1.0

( 0 0 128 ) ( 0 1 128 ) ( 1 0 128 ) GROUND1_6 0 0 0 1.0 1.0

}

}

 

注意,和实物相结合的刷子有一个“原始”标签,它是用来对在关

卡中的位置作一些偏移。

 

在接下来的部分中,我将给大家介绍一下实物的结构及其中的各个

选项。各个入口(entry)其实可以按任意次序排列,另外还有很多的

可选项。

 

2、spawnflag标签

 

spawnflag标签是一个附加的标签,就是说即使一个实体中已经有了

一个原始标签后也可以再加上一个SPAWNFLAG标签。它是用来说明一些额

外的属性:

 

1 - 额外的生命或弹药(比如生命超过100等)

2 - 超高生命

256 - 表示普通难度以上

512 - 困难难度以上

1792 - 这个值仅仅在死亡模式中才使用。

 

3、实物的语法

 

在《QUAKE》中,实物(entity)可以定义怪兽、物品,

另外还可以定义即将发生某种事件的位置。它们其实和DOOM

中的THINGS和LINEDEF这两种类型相对应。

实物的定义当中包括了一系列的项目:此实物是什么东

西,它什么时候出现,在什么位置出现等。每一条项目的后

面都跟有一些对它各方面的详细规定。每一个实物的定义都

有一个“类名(class name),类名就是在QUAKEC中的函数

名,它与“代码堆(code lump)”有很密切的关系。在对它

们作出说明的时候,我用到了“特性(specfics)”和“内

容”这两个词,也许他们并不是很确切,不过id并没有规定

他们叫什么,而且国外的玩家在说明他们的时候用的两个单

词也不是很容易恰当地翻译过来,就用他们吧!

 

特 性 内 容 说 明

 

"classname" "name" // 定义实物的类型,是必须要求的选项

"origin" "X Y Z" // 定义其在空间中开始放置的位置坐标

"angle" "#" // 此实物面对的方向或是移动的方向,有时用角度来表示

"light" "#" // 这是在光影类名中要使用的数值

"target" "t#" // 对应一个目标名

"targetname" "t#" // 就象是DOOM中的linedef标签

"killtarget" "#" // 当此角色击中你的时候带给你的伤害力

"spawnflags" "#" // 用来说明一个非缺省的实物

"style" "#" // 同上,是用来说明一个非缺省的实物

"message" "string" // 当事件被触发的时候显示的信息,用/n表示信息结束

"mangle" "X Y Z" // 指出中断镜头的视角

{BRUSH INFO} // 这是在描述触发事件、门或是平台等的实物中加进的刷子,它

用一对括号圈起来

 

下面是仅在描述游戏中的怪物角色的实物使用的特性:

 

"speed" "#" // 此角色的移动速度

"wait" "#" // 在反复移动间的停顿时间,用秒或十分之几表示

"lip" "#" // 此特性和调整角色的开始位置有关

"dmg" "#" // 表示当此角色击中你的时候带来的伤害力

"health" "#" // 在此角色在被触发以前的伤害力

"delay" "#" // 事件触发以前的时间

"sounds" "#" // 此角色的声音

"wad" "wadfile" // 此关卡中的材质使用的wad2 图象文件

"height" "#" // 一个平台可以上升的高度

 

实际使用中的结构如下:

 

{

"specific1" "arg1" // 第一个特性,通常就是类名

"specific2" "arg2" // 第二个

... // 其它特性...

{

 

<INSERT BRUSH INFO HERE> // 这部分是对于描述门、触发器或是平台的实物中加

进的刷子

 

}

}

 

在最后《QUAKE》中使用的*.bsp文件中的怪物数目取决

于一个叫model structure(角色结构)的结构中的数目,而

这个数目又来自原始的*.map文件中定义的数目。worldspawn

模块则定义了整个关卡的内容。

《QUAKE》中的怪物角色是定义在一个长方体中的,这个

长方体用两个对角点的坐标定义。因此可以想象,《QUAKE》

中的角色是始终和地面平行的。不过如果这么推理的话如果

角色出现在一个斜坡上就有些不合理了……

 

4、全部实物列表(对《QUAKE》1.01版)

 

air_bubbles : 上升的气泡

ambient_drip : 滴水的声音

ambient_drone : 机器的声音

ambient_comp_hum : 电脑的背景声效

ambient_swamp1 : 青蛙的呱呱声

ambient_swamp2 : 这种声效和上面的青蛙叫声很接近


func_door : 门

func_door_secret : 这是一种通过触发来打开的门

func_wall : ……一堵可以移动的墙?

func_button : 一个按钮

func_train : 平台,但是是那种会沿着固定的轨道移动的平台

func_plat : 升降机

func_dm_only : 这是一种只在deathmatch中出现的升降机

info_null : 这——什么都不是

info_intermission : 一种静止的镜头


info_player_start : 主玩家扮演的角色出现的位置,只能有一个。主玩家就

是在联网中建立新游戏的那个


info_player_deathmatch : 开始一个死亡模式,这个实物可以有多个

info_player_coop : 开始一个合作模式,它也可以有多个

info_player_start2 : ? 开始另外一个游戏?

info_teleport_destination : 给角色一个传送的目的地

 

所有的项目都有一个目标标签(target tag)。当目标标签被碰到后将触发某个特定事件。


item_cells : 雷电枪的弹药

item_rockets : 火箭炮和榴弹的弹药

item_shells : 射钉枪和超级射钉枪的弹药

item_spikes : 步枪和双筒猎枪的弹药

item_health : 救护包

item_artifact_envirosuit : 生化防护衣

item_artifact_super_damage : 四倍攻击力

item_artifact_invulnerability : 无限防护力

item_artifact_invisibility : 隐形戒指

item_armorInv : 红色装甲

item_armor2 : 黄色装甲

item_armor1 : 绿色装甲

item_key1 : 银色装甲

item_key2 : 金钥匙

item_sigil : 过关符号

light : 预设的光线,但是没有可见的光源。

light_torch_small_walltorch : 墙上的小火炬

light_flame_large_yellow : 黄色的大火焰

light_flame_small_yellow : 黄色小火焰

light_flame_small_white : 白色小火焰

light_fluoro : 荧光灯,发出嗡嗡声

light_fluorospark : 荧光灯,发出滋滋声


misc_fireball : 小火球

misc_explobox : 炸药包

path_corner : 用来定义轨道平台的路径

trap_spikeshooter : 发射钉子的机关

trap_shooter : 这是一种不用触发就一直向外发射钉子的机关

trigger_teleport : 升降机,由walkover的值触发

trigger_changelevel : 改变关卡

trigger_setskill : 改变难度

trigger_counter : 在被触发到指定的次数以后激发某个事件

trigger_once : 只能使用一次的触发事件(比如打开一道门)

trigger_multiple : 可重复触发的触发事件(比如


entity
这东西乃是quake1里面的东西了者也
开门的一个entity的表示方式了者也
{
"wait" "-1"
"classname" "func_door"
"angle" "270"
"targetname" "t15"
"spawnflags" "2048"
"message" "This door opens elsewhere..."



这个打开门的函数的处理
消息,乃是这个打开门的处理了者也

wait等候对于ai的这个的处理了者也
角度为这个270度的处理了者也
目标的解析
复活的标志的处理
quake1中的这个shader的解析的处理了者也
"message" "Entering the Military Base"
"wad" "gfx/base.wad"
"classname" "worldspawn"


则个在渲染器里面加载的时候用来确定物体的位置朝向的。
"classname" "info_player_deathmatch"     死亡竞赛的重生点
"origin" "-272 2928 -56"
"angle" "0"
}
对于这个玩家的死亡竞赛的这个起点的解析了者也


{
"classname" "info_player_deathmatch"
"origin" "832 2048 -152"
"angle" "0"
}
}
{
"classname" "item_health"
"origin" "1288 1736 -432"
"spawnflags" "1"
}

以下quake3的东西了者也


basic


基础部分

在关卡编辑器开始时,使用mfc来初始化这个opengl这个驱动等等的处理

检测鼠标,键盘的输入,滑动等等


我自己自个划分的有 界面层 ,操作层,介质层
界面层
专门画显示界面的


xy,z视图的对话框的处理

          例如画三个视图的,一个显示3D的画面


地图
创建新的地图
创建新的地图,首先会
何关卡。

打开现有关卡
打开现有关卡,首先会站。通过点击按钮旁边的下拉菜
单箭头将会出现最近打开的地图。

保存当前关卡
保存 当前关卡 正如在关卡浏览器中指定的 。仅保存当前没有保存或者自从上次保存已经发生改变的
关卡。
保存所有关卡
保存所有没有保存或者自上次保存后已经发生改变的关卡。
取消 重复

注意在一定的操作后您可以 取消 重复 之前的动作 比如打开地图、构建关卡等 。


设备层

        鼠标,键盘按键的操作


操作层
   对于这个介质的处理,平移,旋转,缩放,选择等等的处理
   在各个介质里定义这个所对应的方法,者也


介质层
    这个主要是关卡编辑器中加载创建的物体者也!

主要可以分为

3d max做出来了这个模型,

photoshop做出来了纹理图片了者也

这些东西在关卡编辑器中,被整合了进来了

关卡编辑器负责的整个的场景的营造,和怪物的摆放,还有玩家的位置的摆放处理了者也

q3ase做出来了这个游戏中的脚本了者也

最后这个引擎加载上了全部的游戏资源,赖在游戏中进行处理了



quake3的关卡编辑器,其实就像是在创建一个项目时,在安装下来了这个关卡编辑器后,会有这个baseq3这个文件包,里面包含了

texture(图片)

(模型),

maps(地图文件包的位置,里面包含了三张地图, 

      q3dm7smple1,q3dm1sample.map,q3dm1等等地图了)

script文件包,(shader文件)


基本上一个关卡中可以用到的模型,纹理图像,等等


shader文件来表示这个模型对应的entity的名字,和图像的名字

其实就像使用torque关卡编辑器一样,很快将穿件一个游戏的资源全部的组合在了一块了者也



关卡编辑器其实是只对于brush进行编辑的,加载md3模型,shader文件,图像文件,声音文件等等者
也。


 主要包括了对于brush的操作了者也
curve patch裁剪的patch处理了者也

纹理的处理
entity的处理

灯光的处理
编译的处理

ENTITY DESCRIPTIONS
bot的行为文件的处理
TRICKS, TIPS, AND TUTORIALS.
做死亡的这个声音
SHORTCUT KEYS AND MOUSE FUNCTIONS
包括了这六七个部分等等了者也

spines
样条曲线的处理

spine中的选择点的处理了者也
这个spline的这个增加了点的处理了者也

以下另一部分东西者也

对于点的处理


点构成了线,线构成面,面构成了体,最最基本的思想了

以下是对于点的操作,最为基本之基本了者也

class idPointListInterface {

public:

idPointListInterface() {

selectedPoints.Clear();

};

~idPointListInterface() {};

virtual int numPoints() {

return 0;

}

virtual void addPoint(const float x, const float y, const float z) {}

virtual void addPoint(const idVec3_t &v) {}

virtual void removePoint(int index) {}

virtual idVec3_t *getPoint(int index) { return NULL; }

int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {

idVec3_t origin(ox, oy, oz);

idVec3_t dir(dx, dy, dz);

return selectPointByRay(origin, dir, single);

}


int selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {

int i, besti, count;

float d, bestd;

idVec3_t temp, temp2;


// find the point closest to the ray

besti = -1;

bestd = 8;

count = numPoints();


for (i=0; i < count; i++) {

temp = *getPoint(i);

temp2 = temp;

temp -= origin;

d = DotProduct(temp, direction);

__VectorMA (origin, d, direction, temp);

                       temp2 -= temp;

d = temp2.Length();

if (d <= bestd) {

bestd = d;

besti = i;

}

}


if (besti >= 0) {

selectPoint(besti, single);

}


return besti;

}


int isPointSelected(int index) {

int count = selectedPoints.Num();

for (int i = 0; i < count; i++) {

if (selectedPoints[i] == index) {

return i;

}

}

return -1;

}

int selectPoint(int index, bool single) {

if (index >= 0 && index < numPoints()) {

if (single) {

deselectAll();

} else {

if (isPointSelected(index) >= 0) {

selectedPoints.Remove(index);

}

}

return selectedPoints.Append(index);

}

return -1;

}

void selectAll() {

selectedPoints.Clear();

for (int i = 0; i < numPoints(); i++) {

selectedPoints.Append(i);

}

}


void deselectAll() {

selectedPoints.Clear();

}


int numSelectedPoints();

    

idVec3_t *getSelectedPoint(int index) {

assert(index >= 0 && index < numSelectedPoints());

return getPoint(selectedPoints[index]);

}

virtual void updateSelection(float x, float y, float z) {

idVec3_t move(x, y, z);

updateSelection(move);

}


virtual void updateSelection(const idVec3_t &move) {

int count = selectedPoints.Num();

for (int i = 0; i < count; i++) {

*getPoint(selectedPoints[i]) += move;

}

}


void drawSelection() {

int count = selectedPoints.Num();

for (int i = 0; i < count; i++) {

glBox(red, *getPoint(selectedPoints[i]), 4);

}

}


protected:

idList<int> selectedPoints;


};

对于这个点的列表的处理了者也

数学类库等一些东西

数学类库的处理,计算向量的长度等等的处理者也
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
{
float angle;
static float sr, sp, sy, cr, cp, cy;
// static to help MS compiler fp bugs

angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);

if (forward)
{
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
}
if (right)
{
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
right[1] = (-1*sr*sp*sy+-1*cr*cy);
right[2] = -1*sr*cp;
}
if (up)
{
up[0] = (cr*sp*cy+-sr*-sy);
up[1] = (cr*sp*sy+-sr*cy);
up[2] = cr*cp;
}
}


float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
int i;
vec3_t corner;
float a, b;

for (i=0 ; i<3 ; i++) {
a = fabs( mins[i] );
b = fabs( maxs[i] );
corner[i] = a > b ? a : b;
}

return VectorLength (corner);
}
计算这个一个圆的半径的

void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
}

void AxisClear( vec3_t axis[3] ) {
axis[0][0] = 1;
axis[0][1] = 0;
axis[0][2] = 0;
axis[1][0] = 0;
axis[1][1] = 1;
axis[1][2] = 0;
axis[2][0] = 0;
axis[2][1] = 0;
axis[2][2] = 1;
}
角度的偏移了者也
用于实体等的这个方向的切换了者也

float idVec3_t::toYaw( void ) {

float yaw;

if ( ( y == 0 ) && ( x == 0 ) ) {

yaw = 0;

} else {

yaw = atan2( y, x ) * 180 / M_PI;

if ( yaw < 0 ) {

yaw += 360;

}

}


return yaw;

}

这个乃是Paich这个角度的处理


float idVec3_t::toPitch( void ) {

float forward;

float pitch;

if ( ( x == 0 ) && ( y == 0 ) ) {

if ( z > 0 ) {

pitch = 90;

} else {

pitch = 270;

}

} else {

forward = ( float )idSqrt( x * x + y * y );

pitch = atan2( z, forward ) * 180 / M_PI;

if ( pitch < 0 ) {

pitch += 360;

}

}


return pitch;

}


/*

angles_t idVec3_t::toAngles( void ) {

float forward;

float yaw;

float pitch;

if ( ( x == 0 ) && ( y == 0 ) ) {

yaw = 0;

if ( z > 0 ) {

pitch = 90;

} else {

pitch = 270;

}

} else {

yaw = atan2( y, x ) * 180 / M_PI;

if ( yaw < 0 ) {

yaw += 360;

}


forward = ( float )idSqrt( x * x + y * y );

pitch = atan2( z, forward ) * 180 / M_PI;

if ( pitch < 0 ) {

pitch += 360;

}

}


return angles_t( -pitch, yaw, 0 );

}

*/


idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) {

float omega, cosom, sinom, scale0, scale1;


cosom = w1 * w2;

if ( ( 1.0 - cosom ) > LERP_DELTA ) {

omega = acos( cosom );

sinom = sin( omega );

scale0 = sin( ( 1.0 - t ) * omega ) / sinom;

scale1 = sin( t * omega ) / sinom;

} else {

scale0 = 1.0 - t;

scale1 = t;

}


return ( w1 * scale0 + w2 * scale1 );

}


/*

=============

idVec3_t::string


This is just a convenience function

for printing vectors

=============

*/

char *idVec3_t::string( void ) {

static int index = 0;

static char str[ 8 ][ 36 ];

char *s;


// use an array so that multiple toString's won't collide

s = str[ index ];

index = (index + 1)&7;


sprintf( s, "%.2f %.2f %.2f", x, y, z );


return s;

}

还包括矩阵,angle角度等等数学的处理了
四元数

cmdlib文件
包含了

brush类


(1)房间等等,基本几何体 ,方状,箱子状的物体,主要使用brush来处理

3D 物体(对象)被储存成 3D 世界中的一系列点(被称为顶点), 彼此之间有相互关系,
所以计算机知道如何在世界中的这些点之间画线或者是填充表面。 
一个立方体由8个点组成,每个角一个点。立方体有6个表面,
 分别代表它的每一个面。 这就是 3D 对象储存的基础。 
对于一些比较复杂的 3D 物体,
 比如说一个 Quake 的关卡,将有数以千计(有时数以十万计)的顶点, 和数以千计的多边形表面。  
brush其实有六个面,每个面有这个几个顶点的处理,这样子的话,brush的处理,这样子的话,那么就是

当打开doom3或者quake3的关卡编辑器,默认情况下,都是在做brush的操作了者也

对于brush这个对话框,其实也是根据这个矩形对话框的宽度和高度,来生成了这个brush的
对于brush的脚本的处理了者也


对于多个brush进行csg连接,merge组合的处理。来生成了场景的处理了
出怪物等等

其实关卡编辑器用于制作相对比较大的场景,房间,地形的编辑者也,

小的物品entity例如 灯,门,怪物,武器等等都是模型文件而已,不使用这个quake3的关卡编辑器制
作的。
可以设置这个物体的摆放位置,方向,角度,名字,表面的纹理者也
设立触发器,与其关联的的事件,例如调动门,调动电梯,调动跳台

设置info



info_player_start : 主玩家扮演的角色出现的位置,只能有一个。主玩家就

是在联网中建立新游戏的那个,玩家在游戏中出现的位置了者也

info_player_deathmatch :  玩家死亡之后重生的位置了


path_corner : 用来定义轨道平台的路径

触发器的调用函数了者也


func_door : 门

func_wall : ……一堵可以移动的墙?

func_button : 一个按钮

func_train : 平台,但是是那种会沿着固定的轨道移动的平台

func_plat : 升降机



最后保存在map文件中的brush的结构为了这个

// entity 0

{

"classname" "worldspawn"

// brush 0

{

( 104 24 0 ) ( 104 24 8 ) ( 104 112 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

( 120 56 0 ) ( 120 56 8 ) ( 96 56 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

( 96 176 0 ) ( 96 176 8 ) ( 96 88 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

( 96 0 0 ) ( 96 0 8 ) ( 104 0 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

( 104 56 8 ) ( 104 0 8 ) ( 96 0 8 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

( 96 56 0 ) ( 96 0 0 ) ( 104 0 0 ) ayx/oldstone/oldstone5 0 0 0 0.500000 0.500000 0 0 0

}



对于这个点的编辑,我想这个点也是作为一个链表来处理的者也

对于这个对话框,分为了照相机的画面,xy对话框,还有,xz对话框,还有,yz对话框等等
几种模式,来显示了这个
对于新建一个map文件,乃是创建了这个brush,链表,entity链表等等的处理了,
还有对于编辑
删除了brush,则是从brush把选择中的brush删除掉了者也,
删除entity则是删除掉了这个所有的选中的entity来处理了
天空盒,玩家的起点,死亡竞赛的重生点多等等使用的这个红色箱子,来表示的,
这个武器等等模型则是使用md3模型来显示的的者也,
主要操作的东西有这么几种了者也


 brush这个可以是3面的,4面,5面,6面的等等


构成brush的多边形用这个winding来表示 


  对于brush的创建,(挖空,csg组合等等)
struct brush

brush可以用来创建房间,台阶,等等很多地方体结构的东西,可以是3面体,4面体,5面体,6面体

等等

对于brush的组合,挖空,选择边,点,添加上纹理等等


很长的时间内想不通这个quake3的纹理坐标生成,是怎么回事的,后来我终于知道了,是同时给brush
的六个面同时生成纹理坐标的
对于brush,很长时间里我感觉只有这个winding
对于brush生成了六个面的纹理坐标了者也

构成的,不明白node为什么有surface这个构成



构成了brush的面为这个side


struct side

{

winding*w; //构成了这个brush的side的凸多边性

int NumberWinding;//一个side面被分割成多少个凸多边形

};


这个winding乃是指得是凸多边形,这个是构成面的东西,可以把面分割成了无数个winding了,

构成这个一个面的墙壁照片,纹理!这个纹理图片可以是bmp图片,也可以是这个tga,jpg图片,

在经过对于纹理的平移,旋转,缩放等等的处理,来使得纹理图片贴在墙上的

我们可以替换纹理图片,

在quake3关卡编辑器中设置纹理的过滤方式,例如线性过滤,双线性过滤,各向异性过滤等等,过滤


对于关卡编辑器中的这个纹理加载,
先要加载
shader文件
要加载这个jpg,bmptga文件格式的处理者也
winding的中心,brush增加上了一个side面的处理者也

对于这个md3文件的加载,
bsp处理对于


这个两个的组合brush其实乃是这个把两个brush的这个winding组合在了一起了者也!

对于brush各个面上side生成纹理的坐标算法,这样子我们才能把这个贴图添加到了brush上的每个面上了

那是通过3维点的点的处理等等

我们也可以设置这个side面的属性,例如是岩浆,液体,


runscrip,运行这个brush的脚本的处理者也



对于关卡编辑器中的东西,一共有了这个几种类型,
 圆柱体,bevel
Cylinder  A pipe is created. Checking “seams” caps the ends. 
Bevel    A matching bevel is created. Checking “seams” creates a bent square tube. 
Endcap   A matching endcap is created. Checking “seams” creates an arch.* 
Patch Mesh  A mesh that echoes the shape of the selected patch is created, but with XY dim
smaller or larger by the measure of the thickness (smaller if the normals are on 
concave side; larger if on the convex side). 
=================




Brush_BestSplitFace
对于brush的这个分割的处理了


returns the best face to split the brush with.
return NULL if the brush is convex


对于brush这个最好的分割面的处理
void Brush_Scale(brush_t* b)
{
  for (face_t* f = b->brush_faces ; f ; f=f->next)
  {
  for (int i=0 ; i<3 ; i++)
    {
      VectorScale (f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i]);
    }
  }
对于brush的缩放的处理


Brush_SplitBrushByFace (b, &split, &front, &back);
if (back)
Brush_Free (back);
if (front)
Brush_AddToList (front, &selected_brushes);
}
Brush_Free (b);
分割这个brush的这个面了者也,然后,我就是不大懂了这一块了者也


Brush_Merge

 Returns a new brush that is created by merging brush1 and brush2.
 May return NULL if brush1 and brush2 do not create a convex brush when merged.
 The input brushes brush1 and brush2 stay intact.

 if onlyshape is true then the merge is allowed based on the shape only
 otherwise the texture/shader references of faces in the same plane have to
 be the same as well.

组合这个brush,将两个的brush组合到了一块,形成了一个新的brush,将两个brush的winding
全部集中给了这个新的brush了者也

// check if the new brush would be convex... flipped planes make a brush non-convex

// link the new brush to an entity
Entity_LinkBrush (brush1->owner, newbrush);
// build windings for the faces
Brush_BuildWindings( newbrush, false);
return newbrush;
返回了这个brush的组合链表了者也
对于这个关卡编辑器中的这个brush能组合的全部组合了者也

Brush_MergeList


 Tries to merge all brushes in the list into one new brush.
 The input brush list stays intact.
 Returns NULL if no merged brush can be created.
 To create a new brush the brushes in the list may not overlap and
 the outer faces of the brushes together should make a new convex brush.

 if onlyshape is true then the merge is allowed based on the shape only
 otherwise the texture/shader references of faces in the same plane have to
 be the same as well.

brush的这个减掉的处理了者也


对于brush的merge,乃是将两个brush组合成为了一个新的brush,
先要检查这两个个brush这个的这个包围盒的处理

有几种情况,brush1包括了brush2,两个brush有这个共同的面,等等

然后先在内存中生成了一个新的brush,然后将构成了两个brush的winding复制过去即可者也
对于merge brush list,组合这个选中的所有的brush,来进行这个处理

 Tries to merge all brushes in the list into one new brush.
 The input brush list stays intact.
 Returns NULL if no merged brush can be created.
 To create a new brush the brushes in the list may not overlap and
 the outer faces of the brushes together should make a new convex brush.

 if onlyshape is true then the merge is allowed based on the shape only
 otherwise the texture/shader references of faces in the same plane have to
 be the same as well.

将新的brush插入到了brush链表中了


/*
------------------------------------------------------------
Brush_Subtract
------------------------------------------------------------
*/



 Returns a list of brushes that remain after B is subtracted from A.
遍历这个brushlist,然后找到了这个该减掉的face
,然后减掉了即可了者也
// add the brushes back into the selection
for (b = newlist; b; b = next)

 May by empty if A is contained inside B.
 The originals are undisturbed.
对于这个brush的名字的处理等等
brush的分配处理者也
brush的id号码者也
因为是多个brush者也

输出这个平面,输出这个向量者也



/*
-----------------------------------------
brush六个面进行的这个纹理映射的处理了者也
-----------------------------------------------
*/

有了这个brush以后,要进行对于brush的所有的面,生成了纹理的坐标

void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
{
int bestaxis;
float dot,best;
int i;
best = 0;
bestaxis = 0;
for (i=0 ; i<6 ; i++)
{
dot = DotProduct (pln->normal, baseaxis[i*3]);
if (dot > best)
{
best = dot;
bestaxis = i;
}
}
VectorCopy (baseaxis[bestaxis*3+1], xv);
VectorCopy (baseaxis[bestaxis*3+2], yv);
}



对于这个brush的六个面的纹理映射
东墙,西墙,搞,低,等等还有这个
设置这个灯光的
设置这个brush的平面的这个属性等等
SetShadeForPlane对于这个平面也加上了这个内容的设置了者也

Light different planes differently to
improve recognition
================

qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)

CSG_MakeHollow
csg的处理,这个hollow挖空的处理方式怎么来进行的
对于沿着法线来进行这个网格的处理


把法线沿着这个来进行这个缩放了
分割这个brush的这个面的处理了



hollow的处理
乃是遍历selectBrush链表,对于所有的选择到的brush,
无论这个brush类型是patch,地形的brush,还是正常的brush,都沿着法线的方向,扩大一定的倍数,
然后将这个增多的边,增加到了brush链表中去



Brush_Merge

 Returns a new brush that is created by merging brush1 and brush2.
 May return NULL if brush1 and brush2 do not create a convex brush when merged.
 The input brushes brush1 and brush2 stay intact.

 if onlyshape is true then the merge is allowed based on the shape only
 otherwise the texture/shader references of faces in the same plane have to
 be the same as well.
=============
RB_IterateStagesGeneric( input );

//
if ( tess.fogNum && tess.shader->fogPass ) {
RB_FogPass();
}




CSG_Merge

原来这个brush这个乃是一个全局的这个brush啊,
这个brush的名字的处理者也
原来这个面的分配与处理啊
面的释放,这个brush这个的面恐怕有这个宽度了者也



面face的复制
乃是对于复制这个face的所有的这个winding 
包含了这个的者也








surface的标志
在quake3关卡编辑器中按下了s键的时候,会出现了surface标志对话框
针对于brush的每个face面,都可以指定了这个面的类型,来使得做ai的时候
来生成具体的行走方式了者也

surfaceflag关于这个面的标志等等
各种标志,表示这个区域的类型的,例如
这个对于岩浆,火山,梯子等等,noclip等等
用来对于游戏遍历时候的这个区域类型的判断处理了者也
infoParm_t infoParms[] = {
// server relevant contents
{"water", 1, 0, CONTENTS_WATER },水面
{"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging
{"lava", 1, 0, CONTENTS_LAVA }, // very damaging 岩浆
{"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
{"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
{"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc)
{"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag



// utility relevant attributes
{"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes
{"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces
{"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp
{"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas
{"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
{"clusterportal",1, 0,  CONTENTS_CLUSTERPORTAL },// for bots
{"donotenter",  1,  0,  CONTENTS_DONOTENTER }, // for bots
{"botclip",     1,  0,  CONTENTS_BOTCLIP }, // for bots
{"nobotclip", 0, 0, CONTENTS_NOBOTCLIP }, // don't use for bot clipping

{"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering
{"sky", 0, SURF_SKY, 0 }, // emit light from an environment map
{"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it
{"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis
{"hint", 0, SURF_HINT, 0 }, // use as a primary splitter

// server attributes
{"slick", 0, SURF_SLICK, 0 },
{"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
{"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode
{"ladder", 0, SURF_LADDER, 0 },梯子
{"nodamage", 0, SURF_NODAMAGE, 0 },
{"metalsteps", 0, SURF_METALSTEPS,0 },
{"flesh", 0, SURF_FLESH, 0 },
{"nosteps", 0, SURF_NOSTEPS, 0 },

// drawsurf attributes
{"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap)
{"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes
{"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap
{"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights
{"dust", 0, SURF_DUST, 0} // leave dust trail when walking on this surface
};

CONTENTS_LAVA
CONTENTS_SLIME 
CONTENTS_TELEPORTER
CONTENTS_JUMPPAD
CONTENTS_DONOTENTER
CONTENTS_MOVER

其实是表示的(mesh,patch,winding,flare四个的一个统称罢了)
这个surface的系数者也,
我必须加入了这个基本的知识,才能够达到了详细讲述这个quake3体系的纹理者也


shade文件这个怎么来处理呢?brush这个怎么来处理呢?

对于node部分,结构包含的是这个surface,将model 的mesh,,brush的winding最后,传给了surface这个者也


patch 

g_patch_texdef.SetName(Patch_GetTextureName());
    }
else
    {
//strcpy(g_patch_texdef.name, pt->name);
g_patch_texdef.SetName(pt->name);
设置了这个patch的这个名字和这个纹理的名字的处理等等者也


如果是这个patch模式的话,那么这个对于patch来进行这个偏移的处理
如果
原来这个patch果真是做曲面的啊
在quake3或者doom3关卡编辑器的菜单中点中了这个patch选中以后,进入了这个patch模式




patch对话框,从中得到了这个宽度和这个高度,
其实是网格的高度与这个宽度,根据这个宽度和这个高度生成了这个网格了

为了生成了这个曲面的处理了,使用这个贝赛曲面来处理,
至少
由这个网格mesh来构成的
typedef struct {
int width, height;
drawVert_t *verts;
} mesh_t;

Moving the Control Points
这个裁剪乃是这个根据了这个贝赛曲线的这个裁剪点,来做这个曲面的者也

quake3中的这个patch的处理了者也
typedef struct {
int width, height;
drawVert_t *verts;
} mesh_t;


控制点,来生成了这个球面的处理了者也

当然生成曲面的方法还有这个nurbs的这个乃是在doom3游戏中的使用的者也



entity的处理了者也

对于entity起名字,

物体

    小的物体,entity (例如,触发器,md3模型,声音,武器,子弹 ,等等

都作为了这个entity这个的)




model

md3模型的处理


加载表示物体的md3 model,预先把3dmax,做成的3ds模型,ase模型等等

转化为了md3模型,

然后加入到了编辑器中,通过平移,旋转,缩放,等等安放到了合适的位置者也,

和合适的角度



entity物体

entity这个结构包含了各种属性

例如,实体的名字,target的属性等等的处理了

主要是指的这个声音,路径点,模型,武器,健康包等等游戏中用到的各种资源文件者也

关在卡编辑器中,我们可以指明白每个物体的名称,对应的模型的路径,是什么

(例如门,灯,楼梯,等等)位置,角度,方向者也

entity这个主要就是这个起点,位置,角度,这个物体的属性等等的处理了者也

,对应的模型,


 分析这个entity果真是分析了这个entity,来加载这个东西了者也,现在就成熟的多了者也 
 分析这个entity的文件头
 选择实体,entity,
 设置这个entity这个的位置
 得到了这个entity的起点了者也


(比如quake3游戏中那些静态的网格模型,骷髅灯,跳台)

声音(像doom3中经常有这个怪物的声音,非常的恐怖的哪一种等等)

等等

,关联的纹理,名字者也、

entity的 EPAIRS内容了者也
对于这个实体的这个词头的处理等等
 Worldspawn例如这个这个世界重生点的一个声明了者也

加载这个 md3 model,


        {"classname",   "worldspawn"},
{"color",       "0 0 0"},
{"rem",         "Only used for the world entity."},
{"rem", "cdtrack - number of CD track to play when level starts"},
{"rem", "fog_value - level of fog for this map"},
// light_walltorch // 
        {"classname", "light_walltorch"}, 
        {"size", "-8 -8 -8 8 8 8"}, 
         {"color", "0 1 0"}, 
        {"flag", "START_ON"}, 
        {"rem", "style - number of style to use, 0-63"},
        {"rem", "nelnosmama - string to define lightstyle"},
 
颜色,尺寸的处理等等

effect_snow


地形的处理等等

对于quake3的地形
GTKRadiant包含了这个组件gtksurf了者也
这个可以产生地形。这个可以产生quake2,quake3的地形了

这个地形乃是从对话框里面得到的这个值,从而得到这个地形的尺寸,再把这个长度和宽度分割成了mesh、
的样子了
对于地形的选择,其实乃是这个在地形的三角形选中了者也
MakeTerrain这个生成了这个法线和这个纹理的处理


加载上了高度图来处理这个地形的!

typedef struct {
int index;
vec3_t xyz;
vec4_t rgba;
vec2_t tc;
} terravert_t;
Itersects a ray with a terrain
Returns the face hit and the distance along the ray the intersection occured at
Returns NULL and 0 if not hit at all


void Terrain_UpdateSelected( vec3_t vMove ) {

(3


)地形,主要是将一张alpha地图加载上了,加载高度图,然后把这张地图最后映射到了山体上了,这样子,

来得到了山体的高度了,这个我也不太懂这个怎么来做的

做山体的地形的处理,这个东西,原来有这么多的东西了者也?我真的没有想到了者也

地形上的增加的这个点,显示出来了这个地形
原来地形乃是使用的这个mesh来显示出来的者也
地形使用了这个alphamap地形的处理了者也

比如我看到的堆顶点的方式来制造的这个者也

对于地形上,加上了顶点者也

计算这个地形的尺寸了者也

对于地形上插入了这个brush,就像是这个在山地上加入了这个一个房间一样,

我们要给这个山体加上了纹理者也,

如果选择到了这个brush添加到了这个上面,那么调用这个brush里的函数者也

对于山体的命名这个,

对于山体地形的制造,这个乃是使用的这个mesh网格点的的方式来制造的这个,


最后写入了这个地形的文件了者也

地形得到了这个键值,插入点者也,还有这个随机点者也
对于地形增加了纹理者也
挪离纹理者也
做一个新的地形
增加brush对于地形
地形的复制
地形的brush变成了mesh
地形分析这个面
地形计算这个包围盒
地形的移动
计算这个地形的法线
找到这个地形的替换纹理
ReplaceQTexture
选择纹理
对于这个地形,真的是添加上了这个alpha图像这个的者也!
对于这个地形,我们也生成了地形的纹理坐标了啊

在这个brush里面做上了这个地形!

(5)

对于声音的处理了

声音在quake3中这个乃是作为entity的一部分来处理的

wav设置这个声音方面,加载声音等等的处理

在doom3中的这个


(4)


天空体 ,我们必须加上了这个表示天空的位置,属性,这样子就等于做上了这个天空盒子

例如天空盒的高度,云的高度

这个触发器,以及其他的playersart等等,还有其他的东西,使用了一个红色的小箱子,来表示了者也

路径点的设置,这样子,机器人就能按照我们给出的路径进行移动了,

重生点,这样,死后重生的位置等等,用于死后的重生

还有第一次出生的位置等等的设置,这样子在游戏开始后,我们就能够在这个这个位置上把照相机的

位置放到了这里了者也

等等都使用了这个一个红色的箱子来表示
当然quake3中必须有一个玩家的出生点来表示的


光源的处理

这个新建一个光源
在quake3关卡编辑器中右击出现来的菜单中,菜单中选择light,在关卡编辑器的对话框中可以出现了灯光了者也
则添加了一个灯光了者也



这个光源在quake3中为点光源了
在q3游戏中,如果没有光源,没有光,将是漆黑一片的者也,

为了在对话框中显示出来光能够招到的范围volume
需要画出光灯的弧度



设置点的大小
选择区域者也
BenchMark会这个基准点者也
真的好复杂的啊,根本不好做者也


纹理图像的各种信息

在quake3关卡编辑器中,按下了n键,可以弹出来了这个纹理的对话框了者也
其中加载的游戏的资源文件包 shader,
base_Wall.shader,
base_door.shader
base_sky
等等
在纹理的对话框中显示出来纹理图像了者也,这样子来给brush的表面设置纹理了


当然有一个纹理图像的对话框,来使得用户,来选择纹理了,
加载纹理对话框,在纹理的对话框中找到了这个所有的纹理的图片了


对于这个shader这个脚本,来解析,其中的图像文件
加载这个bmp文件。tga等等

纹理可以缩放,旋转,平移者也
旋转纹理等等

为了使得纹理在brush上映射好了,可能要对于纹理进行微调

可以进行对于纹理的偏移,shift-H,shift-v
scal-eH, scale-v纹理的缩放了者也
rotate旋转

选择的这个纹理的大小尺寸的处理

要给brush的表面上,进行纹理坐标,乃么就要给brush,patch的表面生成了纹理坐标的映射,
在这个brush side面上的这个映射的处理
在patch上面的映射的处理了

findTexture这个对话框,来寻找纹理,还有替换纹理
纹理的信息,纹理的名字等等的处理


ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &local_bp, NULL );
这个转换了纹理矩阵为了这个quake3的纹理矩阵来处理
如果是brush,那么就算了brush的纹理矩阵的处理等等



shader脚本

表示所有的物体的属性的文件,

并非是现在的cg,glsl,hlsl等等文件了者也!


有关entity物体的属性,brush的属性用来表示他们属性的文件,称为shader文件,

这个文件保存了物体的位置,

brush的位置,还有这个brush各个面上的属性,例如各个面上的纹理的名字,面上的属性(液体,岩浆,等等)

的处理者也

shader属性文件类
保存这个场景以内物体的属性者也,例如这个brush的位置,方向,纹理坐标者也

等等


quake3使用shader脚本来表示物体的属性,entity,纹理,灯光,等等的信息者也

例如entity的起点者也,名称,等等的信息的处理者也

等等,随着我自己看quake3的代码的深入很多时候真的很佩服这个引擎的功能之多者也


shader脚本,(表示纹理的阶段)

textures/sfx/metalbridge06_bounce

{

//q3map_surfacelight 2000

surfaceparm nodamage

q3map_lightimage textures/sfx/jumppadsmall.tga

q3map_surfacelight 400

{

map textures/sfx/metalbridge06_bounce.tga

rgbGen identity

}

{

clampmap textures/sfx/jumppadsmall.tga

blendfunc gl_one gl_one                    //纹理的 混合方式

tcMod stretch sin 1.2 .8 0 1.5

rgbGen wave square .5 .5 .25 1.5

}

// END

}

quake3关卡编辑器可以加载jpeg图像,pk3图像,因为有这两个的库存在的者也,我们解压加载pke3文件,寻找路径者也 

这一部分应该移除到了这个shader脚本之外的

可以控制水波wave是由三角形,四边形,等等其他的属性,把他们保存下来,

在渲染时,根据这个水波的类型,来进行渲染者也

水波在渲染时使用什么图元来进行显示呢?例如这个triangle等等的处理者也

天空盒的参数等等

裁剪面方式(裁剪前面,裁剪后面,)

纹理的参数等等,

例如

textures/liquids/lava     //表示的纹理是液体里面的岩浆

{

deformVertexes wave sin 0 3 0 0.1//表示这个岩浆的属性者也

tessSize 64

{

map textures/common/lava.tga    //岩浆图像的路径者也

}

}

根据这个shader这个脚本制定的很多方面来执行命令者也

雾的颜色,(rgb等等),deform这个的属性,表示brush这个的形式者也

quake3关卡编辑器可以加载jpeg图像,pk3图像,因为有这两个的库存在的者也,我们解压加载pke3文件,寻找路径


代码中发现了brush的合并,想减,这个者也,对于brush的脚本进行运行
设置光源的属性,


Item图标者也

选择与撤销怎么来实现的呢?


(3)变换这个视图模式,例如三视图画图,只有一个xyz视图,来进行画图者也

设置这些物体,不过是最后编译时显示出来者也,其实并没有什么的

最后编译成的这个map地图格式是什么样子呢?


在编辑器中主要是windows的消息机制,把玩家所做的操作等等,来保存下来,在一

画出来几种视图,来使得这个显示等等,


对于这个shader这个部分的处理者也



关卡编辑器中对于这个照相机的处理者也


照相机对话框

对于关卡编辑器中的这个照相机的位置的显示,要加载表示这个照相机的图标,
从而来标志照相机的位置,从这个照相机的这个朝向上,来表示照相机的朝向了

在,xy,xz,还有这个 yz对话框的视图上来进行显示出来


对于改变了这个墙壁的处理,位置的拖动
,照相机鼠标的控制
,照相机鼠标的上,下等等的处理



照相机对话框中场景的显示的模式有
camera_draw_mode;
cd_wire,    网格
cd_solid,   实体
cd_texture, 带纹理的显示方式
cd_light,   光照
cd_blend   混合

这个照相机的模型,用来显示这个照相机对话框里面渲染的属性的处理
例如线框模式,纹理模式,等等

对话框事件,还有这个cameradlg这个的处理等等

键值的处理,
例如按下了n键就显示出来了这个entity的对话框的处理
quake3乃是把键值 消息压入了堆栈中了者也!
键值的处理者也

对于这个键值的处理,设置键值等等的处理者也
对于这个enity的这个键值的处理,怎么来处理的呢/
对于各种键值的绑定的处理怎么来处理的呢/

清除这个entity这个链表的内存者也
得到了这个临近的内存中的这个模型了者也




选择模式

选择类型有
选择点,选择边,选择面,

选择
face select,面的选择
point select
brush select
等等各种选择的处理

选择地形区域,选择复制,选择移动,

选择删除等等的处理
只有先进入选择模式,才能够的对于面,边,点的推移,挪动,释放了者也、

选择brush的时候的处理,
对于这个所有的brush,来一个一个的判断了,看那一个选择中了者也
再在这里,对于所选的这个brush,再判断这个brush是属于地形brush,patch brush,还是基本的brush,来进行处理了
对于brush,patch,terrain等等的选择了者也
如果选择模式为这个增加点的话,那么给所选的物体增加上了点
如果选择模式为这个编辑这个点的话,那么编辑所在物体的点
如果选择模式为这个编辑这个裁剪的点的话,那么编辑这个所在的点了
如果选择模式为这个brush的话,那么处理brush的内容了 
选择模式为这个地形的纹理,
地形的点的处理的情况下,那么处理这地形的点,和地形的纹理
对于选择这个移动的话,如果选中了地形brush,那么移动地形的brush,
如果选中了patch,那么移动patch的brush,

patch modde这个patch的模式的处理了等等
float m_shift[2];
float m_rotate;
float m_scale[2];



 

 




 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值