aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp4164
1 files changed, 2082 insertions, 2082 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp
index 0e0c05a..00b0fa1 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CQ3LevelMesh.cpp
@@ -1,2082 +1,2082 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "IrrCompileConfig.h" 5#include "IrrCompileConfig.h"
6#ifdef _IRR_COMPILE_WITH_BSP_LOADER_ 6#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
7 7
8#include "CQ3LevelMesh.h" 8#include "CQ3LevelMesh.h"
9#include "ISceneManager.h" 9#include "ISceneManager.h"
10#include "os.h" 10#include "os.h"
11#include "SMeshBufferLightMap.h" 11#include "SMeshBufferLightMap.h"
12#include "irrString.h" 12#include "irrString.h"
13#include "ILightSceneNode.h" 13#include "ILightSceneNode.h"
14#include "IQ3Shader.h" 14#include "IQ3Shader.h"
15#include "IFileList.h" 15#include "IFileList.h"
16 16
17//#define TJUNCTION_SOLVER_ROUND 17//#define TJUNCTION_SOLVER_ROUND
18//#define TJUNCTION_SOLVER_0125 18//#define TJUNCTION_SOLVER_0125
19 19
20namespace irr 20namespace irr
21{ 21{
22namespace scene 22namespace scene
23{ 23{
24 24
25 using namespace quake3; 25 using namespace quake3;
26 26
27//! constructor 27//! constructor
28CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr, 28CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr,
29 const Q3LevelLoadParameter &loadParam) 29 const Q3LevelLoadParameter &loadParam)
30 : LoadParam(loadParam), Textures(0), NumTextures(0), LightMaps(0), NumLightMaps(0), 30 : LoadParam(loadParam), Textures(0), NumTextures(0), LightMaps(0), NumLightMaps(0),
31 Vertices(0), NumVertices(0), Faces(0), NumFaces(0), Models(0), NumModels(0), 31 Vertices(0), NumVertices(0), Faces(0), NumFaces(0), Models(0), NumModels(0),
32 Planes(0), NumPlanes(0), Nodes(0), NumNodes(0), Leafs(0), NumLeafs(0), 32 Planes(0), NumPlanes(0), Nodes(0), NumNodes(0), Leafs(0), NumLeafs(0),
33 LeafFaces(0), NumLeafFaces(0), MeshVerts(0), NumMeshVerts(0), 33 LeafFaces(0), NumLeafFaces(0), MeshVerts(0), NumMeshVerts(0),
34 Brushes(0), NumBrushes(0), BrushEntities(0), FileSystem(fs), 34 Brushes(0), NumBrushes(0), BrushEntities(0), FileSystem(fs),
35 SceneManager(smgr), FramesPerSecond(25.f) 35 SceneManager(smgr), FramesPerSecond(25.f)
36{ 36{
37 #ifdef _DEBUG 37 #ifdef _DEBUG
38 IReferenceCounted::setDebugName("CQ3LevelMesh"); 38 IReferenceCounted::setDebugName("CQ3LevelMesh");
39 #endif 39 #endif
40 40
41 for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) 41 for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i )
42 { 42 {
43 Mesh[i] = 0; 43 Mesh[i] = 0;
44 } 44 }
45 45
46 Driver = smgr ? smgr->getVideoDriver() : 0; 46 Driver = smgr ? smgr->getVideoDriver() : 0;
47 if (Driver) 47 if (Driver)
48 Driver->grab(); 48 Driver->grab();
49 49
50 if (FileSystem) 50 if (FileSystem)
51 FileSystem->grab(); 51 FileSystem->grab();
52 52
53 // load default shaders 53 // load default shaders
54 InitShader(); 54 InitShader();
55} 55}
56 56
57 57
58//! destructor 58//! destructor
59CQ3LevelMesh::~CQ3LevelMesh() 59CQ3LevelMesh::~CQ3LevelMesh()
60{ 60{
61 cleanLoader (); 61 cleanLoader ();
62 62
63 if (Driver) 63 if (Driver)
64 Driver->drop(); 64 Driver->drop();
65 65
66 if (FileSystem) 66 if (FileSystem)
67 FileSystem->drop(); 67 FileSystem->drop();
68 68
69 s32 i; 69 s32 i;
70 70
71 for ( i = 0; i!= E_Q3_MESH_SIZE; ++i ) 71 for ( i = 0; i!= E_Q3_MESH_SIZE; ++i )
72 { 72 {
73 if ( Mesh[i] ) 73 if ( Mesh[i] )
74 { 74 {
75 Mesh[i]->drop(); 75 Mesh[i]->drop();
76 Mesh[i] = 0; 76 Mesh[i] = 0;
77 } 77 }
78 } 78 }
79 79
80 for ( i = 1; i < NumModels; i++ ) 80 for ( i = 1; i < NumModels; i++ )
81 { 81 {
82 BrushEntities[i]->drop(); 82 BrushEntities[i]->drop();
83 } 83 }
84 delete [] BrushEntities; BrushEntities = 0; 84 delete [] BrushEntities; BrushEntities = 0;
85 85
86 ReleaseShader(); 86 ReleaseShader();
87 ReleaseEntity(); 87 ReleaseEntity();
88} 88}
89 89
90 90
91//! loads a level from a .bsp-File. Also tries to load all needed textures. Returns true if successful. 91//! loads a level from a .bsp-File. Also tries to load all needed textures. Returns true if successful.
92bool CQ3LevelMesh::loadFile(io::IReadFile* file) 92bool CQ3LevelMesh::loadFile(io::IReadFile* file)
93{ 93{
94 if (!file) 94 if (!file)
95 return false; 95 return false;
96 96
97 LevelName = file->getFileName(); 97 LevelName = file->getFileName();
98 98
99 file->read(&header, sizeof(tBSPHeader)); 99 file->read(&header, sizeof(tBSPHeader));
100 100
101 #ifdef __BIG_ENDIAN__ 101 #ifdef __BIG_ENDIAN__
102 header.strID = os::Byteswap::byteswap(header.strID); 102 header.strID = os::Byteswap::byteswap(header.strID);
103 header.version = os::Byteswap::byteswap(header.version); 103 header.version = os::Byteswap::byteswap(header.version);
104 #endif 104 #endif
105 105
106 if ( (header.strID != 0x50534249 || // IBSP 106 if ( (header.strID != 0x50534249 || // IBSP
107 ( header.version != 0x2e // quake3 107 ( header.version != 0x2e // quake3
108 && header.version != 0x2f // rtcw 108 && header.version != 0x2f // rtcw
109 ) 109 )
110 ) 110 )
111 && 111 &&
112 ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof 112 ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof
113 ) 113 )
114 { 114 {
115 os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR); 115 os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR);
116 return false; 116 return false;
117 } 117 }
118 118
119#if 0 119#if 0
120 if ( header.strID == 0x50534252 ) // RBSP Raven 120 if ( header.strID == 0x50534252 ) // RBSP Raven
121 { 121 {
122 LoadParam.swapHeader = 1; 122 LoadParam.swapHeader = 1;
123 } 123 }
124#endif 124#endif
125 125
126 // now read lumps 126 // now read lumps
127 file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps); 127 file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps);
128 128
129 s32 i; 129 s32 i;
130 if ( LoadParam.swapHeader ) 130 if ( LoadParam.swapHeader )
131 { 131 {
132 for ( i=0; i< kMaxLumps;++i) 132 for ( i=0; i< kMaxLumps;++i)
133 { 133 {
134 Lumps[i].offset = os::Byteswap::byteswap(Lumps[i].offset); 134 Lumps[i].offset = os::Byteswap::byteswap(Lumps[i].offset);
135 Lumps[i].length = os::Byteswap::byteswap(Lumps[i].length); 135 Lumps[i].length = os::Byteswap::byteswap(Lumps[i].length);
136 } 136 }
137 } 137 }
138 138
139 ReleaseEntity(); 139 ReleaseEntity();
140 140
141 // load everything 141 // load everything
142 loadEntities(&Lumps[kEntities], file); // load the entities 142 loadEntities(&Lumps[kEntities], file); // load the entities
143 loadTextures(&Lumps[kShaders], file); // Load the textures 143 loadTextures(&Lumps[kShaders], file); // Load the textures
144 loadLightmaps(&Lumps[kLightmaps], file); // Load the lightmaps 144 loadLightmaps(&Lumps[kLightmaps], file); // Load the lightmaps
145 loadVerts(&Lumps[kVertices], file); // Load the vertices 145 loadVerts(&Lumps[kVertices], file); // Load the vertices
146 loadFaces(&Lumps[kFaces], file); // Load the faces 146 loadFaces(&Lumps[kFaces], file); // Load the faces
147 loadPlanes(&Lumps[kPlanes], file); // Load the Planes of the BSP 147 loadPlanes(&Lumps[kPlanes], file); // Load the Planes of the BSP
148 loadNodes(&Lumps[kNodes], file); // load the Nodes of the BSP 148 loadNodes(&Lumps[kNodes], file); // load the Nodes of the BSP
149 loadLeafs(&Lumps[kLeafs], file); // load the Leafs of the BSP 149 loadLeafs(&Lumps[kLeafs], file); // load the Leafs of the BSP
150 loadLeafFaces(&Lumps[kLeafFaces], file); // load the Faces of the Leafs of the BSP 150 loadLeafFaces(&Lumps[kLeafFaces], file); // load the Faces of the Leafs of the BSP
151 loadVisData(&Lumps[kVisData], file); // load the visibility data of the clusters 151 loadVisData(&Lumps[kVisData], file); // load the visibility data of the clusters
152 loadModels(&Lumps[kModels], file); // load the models 152 loadModels(&Lumps[kModels], file); // load the models
153 loadMeshVerts(&Lumps[kMeshVerts], file); // load the mesh vertices 153 loadMeshVerts(&Lumps[kMeshVerts], file); // load the mesh vertices
154 loadBrushes(&Lumps[kBrushes], file); // load the brushes of the BSP 154 loadBrushes(&Lumps[kBrushes], file); // load the brushes of the BSP
155 loadBrushSides(&Lumps[kBrushSides], file); // load the brushsides of the BSP 155 loadBrushSides(&Lumps[kBrushSides], file); // load the brushsides of the BSP
156 loadLeafBrushes(&Lumps[kLeafBrushes], file); // load the brushes of the leaf 156 loadLeafBrushes(&Lumps[kLeafBrushes], file); // load the brushes of the leaf
157 loadFogs(&Lumps[kFogs], file ); // load the fogs 157 loadFogs(&Lumps[kFogs], file ); // load the fogs
158 158
159 loadTextures(); 159 loadTextures();
160 constructMesh(); 160 constructMesh();
161 solveTJunction(); 161 solveTJunction();
162 162
163 cleanMeshes(); 163 cleanMeshes();
164 calcBoundingBoxes(); 164 calcBoundingBoxes();
165 cleanLoader(); 165 cleanLoader();
166 166
167 return true; 167 return true;
168} 168}
169 169
170/*! 170/*!
171*/ 171*/
172void CQ3LevelMesh::cleanLoader () 172void CQ3LevelMesh::cleanLoader ()
173{ 173{
174 delete [] Textures; Textures = 0; 174 delete [] Textures; Textures = 0;
175 delete [] LightMaps; LightMaps = 0; 175 delete [] LightMaps; LightMaps = 0;
176 delete [] Vertices; Vertices = 0; 176 delete [] Vertices; Vertices = 0;
177 delete [] Faces; Faces = 0; 177 delete [] Faces; Faces = 0;
178 delete [] Models; Models = 0; 178 delete [] Models; Models = 0;
179 delete [] Planes; Planes = 0; 179 delete [] Planes; Planes = 0;
180 delete [] Nodes; Nodes = 0; 180 delete [] Nodes; Nodes = 0;
181 delete [] Leafs; Leafs = 0; 181 delete [] Leafs; Leafs = 0;
182 delete [] LeafFaces; LeafFaces = 0; 182 delete [] LeafFaces; LeafFaces = 0;
183 delete [] MeshVerts; MeshVerts = 0; 183 delete [] MeshVerts; MeshVerts = 0;
184 delete [] Brushes; Brushes = 0; 184 delete [] Brushes; Brushes = 0;
185 185
186 Lightmap.clear(); 186 Lightmap.clear();
187 Tex.clear(); 187 Tex.clear();
188} 188}
189 189
190//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. 190//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
191u32 CQ3LevelMesh::getFrameCount() const 191u32 CQ3LevelMesh::getFrameCount() const
192{ 192{
193 return 1; 193 return 1;
194} 194}
195 195
196 196
197//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. 197//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
198IMesh* CQ3LevelMesh::getMesh(s32 frameInMs, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) 198IMesh* CQ3LevelMesh::getMesh(s32 frameInMs, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
199{ 199{
200 return Mesh[frameInMs]; 200 return Mesh[frameInMs];
201} 201}
202 202
203 203
204void CQ3LevelMesh::loadTextures(tBSPLump* l, io::IReadFile* file) 204void CQ3LevelMesh::loadTextures(tBSPLump* l, io::IReadFile* file)
205{ 205{
206 NumTextures = l->length / sizeof(tBSPTexture); 206 NumTextures = l->length / sizeof(tBSPTexture);
207 if ( !NumTextures ) 207 if ( !NumTextures )
208 return; 208 return;
209 Textures = new tBSPTexture[NumTextures]; 209 Textures = new tBSPTexture[NumTextures];
210 210
211 file->seek(l->offset); 211 file->seek(l->offset);
212 file->read(Textures, l->length); 212 file->read(Textures, l->length);
213 213
214 if ( LoadParam.swapHeader ) 214 if ( LoadParam.swapHeader )
215 { 215 {
216 for (s32 i=0;i<NumTextures;++i) 216 for (s32 i=0;i<NumTextures;++i)
217 { 217 {
218 Textures[i].flags = os::Byteswap::byteswap(Textures[i].flags); 218 Textures[i].flags = os::Byteswap::byteswap(Textures[i].flags);
219 Textures[i].contents = os::Byteswap::byteswap(Textures[i].contents); 219 Textures[i].contents = os::Byteswap::byteswap(Textures[i].contents);
220 //os::Printer::log("Loaded texture", Textures[i].strName, ELL_INFORMATION); 220 //os::Printer::log("Loaded texture", Textures[i].strName, ELL_INFORMATION);
221 } 221 }
222 } 222 }
223} 223}
224 224
225 225
226void CQ3LevelMesh::loadLightmaps(tBSPLump* l, io::IReadFile* file) 226void CQ3LevelMesh::loadLightmaps(tBSPLump* l, io::IReadFile* file)
227{ 227{
228 NumLightMaps = l->length / sizeof(tBSPLightmap); 228 NumLightMaps = l->length / sizeof(tBSPLightmap);
229 if ( !NumLightMaps ) 229 if ( !NumLightMaps )
230 return; 230 return;
231 LightMaps = new tBSPLightmap[NumLightMaps]; 231 LightMaps = new tBSPLightmap[NumLightMaps];
232 232
233 file->seek(l->offset); 233 file->seek(l->offset);
234 file->read(LightMaps, l->length); 234 file->read(LightMaps, l->length);
235} 235}
236 236
237/*! 237/*!
238*/ 238*/
239void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) 239void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file)
240{ 240{
241 NumVertices = l->length / sizeof(tBSPVertex); 241 NumVertices = l->length / sizeof(tBSPVertex);
242 if ( !NumVertices ) 242 if ( !NumVertices )
243 return; 243 return;
244 Vertices = new tBSPVertex[NumVertices]; 244 Vertices = new tBSPVertex[NumVertices];
245 245
246 file->seek(l->offset); 246 file->seek(l->offset);
247 file->read(Vertices, l->length); 247 file->read(Vertices, l->length);
248 248
249 if ( LoadParam.swapHeader ) 249 if ( LoadParam.swapHeader )
250 for (s32 i=0;i<NumVertices;i++) 250 for (s32 i=0;i<NumVertices;i++)
251 { 251 {
252 Vertices[i].vPosition[0] = os::Byteswap::byteswap(Vertices[i].vPosition[0]); 252 Vertices[i].vPosition[0] = os::Byteswap::byteswap(Vertices[i].vPosition[0]);
253 Vertices[i].vPosition[1] = os::Byteswap::byteswap(Vertices[i].vPosition[1]); 253 Vertices[i].vPosition[1] = os::Byteswap::byteswap(Vertices[i].vPosition[1]);
254 Vertices[i].vPosition[2] = os::Byteswap::byteswap(Vertices[i].vPosition[2]); 254 Vertices[i].vPosition[2] = os::Byteswap::byteswap(Vertices[i].vPosition[2]);
255 Vertices[i].vTextureCoord[0] = os::Byteswap::byteswap(Vertices[i].vTextureCoord[0]); 255 Vertices[i].vTextureCoord[0] = os::Byteswap::byteswap(Vertices[i].vTextureCoord[0]);
256 Vertices[i].vTextureCoord[1] = os::Byteswap::byteswap(Vertices[i].vTextureCoord[1]); 256 Vertices[i].vTextureCoord[1] = os::Byteswap::byteswap(Vertices[i].vTextureCoord[1]);
257 Vertices[i].vLightmapCoord[0] = os::Byteswap::byteswap(Vertices[i].vLightmapCoord[0]); 257 Vertices[i].vLightmapCoord[0] = os::Byteswap::byteswap(Vertices[i].vLightmapCoord[0]);
258 Vertices[i].vLightmapCoord[1] = os::Byteswap::byteswap(Vertices[i].vLightmapCoord[1]); 258 Vertices[i].vLightmapCoord[1] = os::Byteswap::byteswap(Vertices[i].vLightmapCoord[1]);
259 Vertices[i].vNormal[0] = os::Byteswap::byteswap(Vertices[i].vNormal[0]); 259 Vertices[i].vNormal[0] = os::Byteswap::byteswap(Vertices[i].vNormal[0]);
260 Vertices[i].vNormal[1] = os::Byteswap::byteswap(Vertices[i].vNormal[1]); 260 Vertices[i].vNormal[1] = os::Byteswap::byteswap(Vertices[i].vNormal[1]);
261 Vertices[i].vNormal[2] = os::Byteswap::byteswap(Vertices[i].vNormal[2]); 261 Vertices[i].vNormal[2] = os::Byteswap::byteswap(Vertices[i].vNormal[2]);
262 } 262 }
263} 263}
264 264
265 265
266/*! 266/*!
267*/ 267*/
268void CQ3LevelMesh::loadFaces(tBSPLump* l, io::IReadFile* file) 268void CQ3LevelMesh::loadFaces(tBSPLump* l, io::IReadFile* file)
269{ 269{
270 NumFaces = l->length / sizeof(tBSPFace); 270 NumFaces = l->length / sizeof(tBSPFace);
271 if (!NumFaces) 271 if (!NumFaces)
272 return; 272 return;
273 Faces = new tBSPFace[NumFaces]; 273 Faces = new tBSPFace[NumFaces];
274 274
275 file->seek(l->offset); 275 file->seek(l->offset);
276 file->read(Faces, l->length); 276 file->read(Faces, l->length);
277 277
278 if ( LoadParam.swapHeader ) 278 if ( LoadParam.swapHeader )
279 { 279 {
280 for ( s32 i=0;i<NumFaces;i++) 280 for ( s32 i=0;i<NumFaces;i++)
281 { 281 {
282 Faces[i].textureID = os::Byteswap::byteswap(Faces[i].textureID); 282 Faces[i].textureID = os::Byteswap::byteswap(Faces[i].textureID);
283 Faces[i].fogNum = os::Byteswap::byteswap(Faces[i].fogNum); 283 Faces[i].fogNum = os::Byteswap::byteswap(Faces[i].fogNum);
284 Faces[i].type = os::Byteswap::byteswap(Faces[i].type); 284 Faces[i].type = os::Byteswap::byteswap(Faces[i].type);
285 Faces[i].vertexIndex = os::Byteswap::byteswap(Faces[i].vertexIndex); 285 Faces[i].vertexIndex = os::Byteswap::byteswap(Faces[i].vertexIndex);
286 Faces[i].numOfVerts = os::Byteswap::byteswap(Faces[i].numOfVerts); 286 Faces[i].numOfVerts = os::Byteswap::byteswap(Faces[i].numOfVerts);
287 Faces[i].meshVertIndex = os::Byteswap::byteswap(Faces[i].meshVertIndex); 287 Faces[i].meshVertIndex = os::Byteswap::byteswap(Faces[i].meshVertIndex);
288 Faces[i].numMeshVerts = os::Byteswap::byteswap(Faces[i].numMeshVerts); 288 Faces[i].numMeshVerts = os::Byteswap::byteswap(Faces[i].numMeshVerts);
289 Faces[i].lightmapID = os::Byteswap::byteswap(Faces[i].lightmapID); 289 Faces[i].lightmapID = os::Byteswap::byteswap(Faces[i].lightmapID);
290 Faces[i].lMapCorner[0] = os::Byteswap::byteswap(Faces[i].lMapCorner[0]); 290 Faces[i].lMapCorner[0] = os::Byteswap::byteswap(Faces[i].lMapCorner[0]);
291 Faces[i].lMapCorner[1] = os::Byteswap::byteswap(Faces[i].lMapCorner[1]); 291 Faces[i].lMapCorner[1] = os::Byteswap::byteswap(Faces[i].lMapCorner[1]);
292 Faces[i].lMapSize[0] = os::Byteswap::byteswap(Faces[i].lMapSize[0]); 292 Faces[i].lMapSize[0] = os::Byteswap::byteswap(Faces[i].lMapSize[0]);
293 Faces[i].lMapSize[1] = os::Byteswap::byteswap(Faces[i].lMapSize[1]); 293 Faces[i].lMapSize[1] = os::Byteswap::byteswap(Faces[i].lMapSize[1]);
294 Faces[i].lMapPos[0] = os::Byteswap::byteswap(Faces[i].lMapPos[0]); 294 Faces[i].lMapPos[0] = os::Byteswap::byteswap(Faces[i].lMapPos[0]);
295 Faces[i].lMapPos[1] = os::Byteswap::byteswap(Faces[i].lMapPos[1]); 295 Faces[i].lMapPos[1] = os::Byteswap::byteswap(Faces[i].lMapPos[1]);
296 Faces[i].lMapPos[2] = os::Byteswap::byteswap(Faces[i].lMapPos[2]); 296 Faces[i].lMapPos[2] = os::Byteswap::byteswap(Faces[i].lMapPos[2]);
297 Faces[i].lMapBitsets[0][0] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][0]); 297 Faces[i].lMapBitsets[0][0] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][0]);
298 Faces[i].lMapBitsets[0][1] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][1]); 298 Faces[i].lMapBitsets[0][1] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][1]);
299 Faces[i].lMapBitsets[0][2] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][2]); 299 Faces[i].lMapBitsets[0][2] = os::Byteswap::byteswap(Faces[i].lMapBitsets[0][2]);
300 Faces[i].lMapBitsets[1][0] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][0]); 300 Faces[i].lMapBitsets[1][0] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][0]);
301 Faces[i].lMapBitsets[1][1] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][1]); 301 Faces[i].lMapBitsets[1][1] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][1]);
302 Faces[i].lMapBitsets[1][2] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][2]); 302 Faces[i].lMapBitsets[1][2] = os::Byteswap::byteswap(Faces[i].lMapBitsets[1][2]);
303 Faces[i].vNormal[0] = os::Byteswap::byteswap(Faces[i].vNormal[0]); 303 Faces[i].vNormal[0] = os::Byteswap::byteswap(Faces[i].vNormal[0]);
304 Faces[i].vNormal[1] = os::Byteswap::byteswap(Faces[i].vNormal[1]); 304 Faces[i].vNormal[1] = os::Byteswap::byteswap(Faces[i].vNormal[1]);
305 Faces[i].vNormal[2] = os::Byteswap::byteswap(Faces[i].vNormal[2]); 305 Faces[i].vNormal[2] = os::Byteswap::byteswap(Faces[i].vNormal[2]);
306 Faces[i].size[0] = os::Byteswap::byteswap(Faces[i].size[0]); 306 Faces[i].size[0] = os::Byteswap::byteswap(Faces[i].size[0]);
307 Faces[i].size[1] = os::Byteswap::byteswap(Faces[i].size[1]); 307 Faces[i].size[1] = os::Byteswap::byteswap(Faces[i].size[1]);
308 } 308 }
309 } 309 }
310} 310}
311 311
312 312
313/*! 313/*!
314*/ 314*/
315void CQ3LevelMesh::loadPlanes(tBSPLump* l, io::IReadFile* file) 315void CQ3LevelMesh::loadPlanes(tBSPLump* l, io::IReadFile* file)
316{ 316{
317 // ignore 317 // ignore
318} 318}
319 319
320 320
321/*! 321/*!
322*/ 322*/
323void CQ3LevelMesh::loadNodes(tBSPLump* l, io::IReadFile* file) 323void CQ3LevelMesh::loadNodes(tBSPLump* l, io::IReadFile* file)
324{ 324{
325 // ignore 325 // ignore
326} 326}
327 327
328 328
329/*! 329/*!
330*/ 330*/
331void CQ3LevelMesh::loadLeafs(tBSPLump* l, io::IReadFile* file) 331void CQ3LevelMesh::loadLeafs(tBSPLump* l, io::IReadFile* file)
332{ 332{
333 // ignore 333 // ignore
334} 334}
335 335
336 336
337/*! 337/*!
338*/ 338*/
339void CQ3LevelMesh::loadLeafFaces(tBSPLump* l, io::IReadFile* file) 339void CQ3LevelMesh::loadLeafFaces(tBSPLump* l, io::IReadFile* file)
340{ 340{
341 // ignore 341 // ignore
342} 342}
343 343
344 344
345/*! 345/*!
346*/ 346*/
347void CQ3LevelMesh::loadVisData(tBSPLump* l, io::IReadFile* file) 347void CQ3LevelMesh::loadVisData(tBSPLump* l, io::IReadFile* file)
348{ 348{
349 // ignore 349 // ignore
350} 350}
351 351
352 352
353/*! 353/*!
354*/ 354*/
355void CQ3LevelMesh::loadEntities(tBSPLump* l, io::IReadFile* file) 355void CQ3LevelMesh::loadEntities(tBSPLump* l, io::IReadFile* file)
356{ 356{
357 core::array<u8> entity; 357 core::array<u8> entity;
358 entity.set_used( l->length + 2 ); 358 entity.set_used( l->length + 2 );
359 entity[l->length + 1 ] = 0; 359 entity[l->length + 1 ] = 0;
360 360
361 file->seek(l->offset); 361 file->seek(l->offset);
362 file->read( entity.pointer(), l->length); 362 file->read( entity.pointer(), l->length);
363 363
364 parser_parse( entity.pointer(), l->length, &CQ3LevelMesh::scriptcallback_entity ); 364 parser_parse( entity.pointer(), l->length, &CQ3LevelMesh::scriptcallback_entity );
365} 365}
366 366
367 367
368/*! 368/*!
369 load fog brushes 369 load fog brushes
370*/ 370*/
371void CQ3LevelMesh::loadFogs(tBSPLump* l, io::IReadFile* file) 371void CQ3LevelMesh::loadFogs(tBSPLump* l, io::IReadFile* file)
372{ 372{
373 u32 files = l->length / sizeof(tBSPFog); 373 u32 files = l->length / sizeof(tBSPFog);
374 374
375 file->seek( l->offset ); 375 file->seek( l->offset );
376 tBSPFog fog; 376 tBSPFog fog;
377 const IShader *shader; 377 const IShader *shader;
378 STexShader t; 378 STexShader t;
379 for ( u32 i = 0; i!= files; ++i ) 379 for ( u32 i = 0; i!= files; ++i )
380 { 380 {
381 file->read( &fog, sizeof( fog ) ); 381 file->read( &fog, sizeof( fog ) );
382 382
383 shader = getShader( fog.shader ); 383 shader = getShader( fog.shader );
384 t.Texture = 0; 384 t.Texture = 0;
385 t.ShaderID = shader ? shader->ID : -1; 385 t.ShaderID = shader ? shader->ID : -1;
386 386
387 FogMap.push_back ( t ); 387 FogMap.push_back ( t );
388 } 388 }
389} 389}
390 390
391 391
392/*! 392/*!
393 load models named in bsp 393 load models named in bsp
394*/ 394*/
395void CQ3LevelMesh::loadModels(tBSPLump* l, io::IReadFile* file) 395void CQ3LevelMesh::loadModels(tBSPLump* l, io::IReadFile* file)
396{ 396{
397 NumModels = l->length / sizeof(tBSPModel); 397 NumModels = l->length / sizeof(tBSPModel);
398 Models = new tBSPModel[NumModels]; 398 Models = new tBSPModel[NumModels];
399 399
400 file->seek( l->offset ); 400 file->seek( l->offset );
401 file->read(Models, l->length); 401 file->read(Models, l->length);
402 402
403 if ( LoadParam.swapHeader ) 403 if ( LoadParam.swapHeader )
404 { 404 {
405 for ( s32 i = 0; i < NumModels; i++) 405 for ( s32 i = 0; i < NumModels; i++)
406 { 406 {
407 Models[i].min[0] = os::Byteswap::byteswap(Models[i].min[0]); 407 Models[i].min[0] = os::Byteswap::byteswap(Models[i].min[0]);
408 Models[i].min[1] = os::Byteswap::byteswap(Models[i].min[1]); 408 Models[i].min[1] = os::Byteswap::byteswap(Models[i].min[1]);
409 Models[i].min[2] = os::Byteswap::byteswap(Models[i].min[2]); 409 Models[i].min[2] = os::Byteswap::byteswap(Models[i].min[2]);
410 Models[i].max[0] = os::Byteswap::byteswap(Models[i].max[0]); 410 Models[i].max[0] = os::Byteswap::byteswap(Models[i].max[0]);
411 Models[i].max[1] = os::Byteswap::byteswap(Models[i].max[1]); 411 Models[i].max[1] = os::Byteswap::byteswap(Models[i].max[1]);
412 Models[i].max[2] = os::Byteswap::byteswap(Models[i].max[2]); 412 Models[i].max[2] = os::Byteswap::byteswap(Models[i].max[2]);
413 413
414 Models[i].faceIndex = os::Byteswap::byteswap(Models[i].faceIndex); 414 Models[i].faceIndex = os::Byteswap::byteswap(Models[i].faceIndex);
415 Models[i].numOfFaces = os::Byteswap::byteswap(Models[i].numOfFaces); 415 Models[i].numOfFaces = os::Byteswap::byteswap(Models[i].numOfFaces);
416 Models[i].brushIndex = os::Byteswap::byteswap(Models[i].brushIndex); 416 Models[i].brushIndex = os::Byteswap::byteswap(Models[i].brushIndex);
417 Models[i].numOfBrushes = os::Byteswap::byteswap(Models[i].numOfBrushes); 417 Models[i].numOfBrushes = os::Byteswap::byteswap(Models[i].numOfBrushes);
418 } 418 }
419 } 419 }
420 420
421 BrushEntities = new SMesh*[NumModels]; 421 BrushEntities = new SMesh*[NumModels];
422} 422}
423 423
424/*! 424/*!
425*/ 425*/
426void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) 426void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file)
427{ 427{
428 NumMeshVerts = l->length / sizeof(s32); 428 NumMeshVerts = l->length / sizeof(s32);
429 if (!NumMeshVerts) 429 if (!NumMeshVerts)
430 return; 430 return;
431 MeshVerts = new s32[NumMeshVerts]; 431 MeshVerts = new s32[NumMeshVerts];
432 432
433 file->seek(l->offset); 433 file->seek(l->offset);
434 file->read(MeshVerts, l->length); 434 file->read(MeshVerts, l->length);
435 435
436 if ( LoadParam.swapHeader ) 436 if ( LoadParam.swapHeader )
437 { 437 {
438 for (int i=0;i<NumMeshVerts;i++) 438 for (int i=0;i<NumMeshVerts;i++)
439 MeshVerts[i] = os::Byteswap::byteswap(MeshVerts[i]); 439 MeshVerts[i] = os::Byteswap::byteswap(MeshVerts[i]);
440 } 440 }
441} 441}
442 442
443/*! 443/*!
444*/ 444*/
445void CQ3LevelMesh::loadBrushes(tBSPLump* l, io::IReadFile* file) 445void CQ3LevelMesh::loadBrushes(tBSPLump* l, io::IReadFile* file)
446{ 446{
447 // ignore 447 // ignore
448} 448}
449 449
450/*! 450/*!
451*/ 451*/
452void CQ3LevelMesh::loadBrushSides(tBSPLump* l, io::IReadFile* file) 452void CQ3LevelMesh::loadBrushSides(tBSPLump* l, io::IReadFile* file)
453{ 453{
454 // ignore 454 // ignore
455} 455}
456 456
457/*! 457/*!
458*/ 458*/
459void CQ3LevelMesh::loadLeafBrushes(tBSPLump* l, io::IReadFile* file) 459void CQ3LevelMesh::loadLeafBrushes(tBSPLump* l, io::IReadFile* file)
460{ 460{
461 // ignore 461 // ignore
462} 462}
463 463
464/*! 464/*!
465*/ 465*/
466inline bool isQ3WhiteSpace( const u8 symbol ) 466inline bool isQ3WhiteSpace( const u8 symbol )
467{ 467{
468 return symbol == ' ' || symbol == '\t' || symbol == '\r'; 468 return symbol == ' ' || symbol == '\t' || symbol == '\r';
469} 469}
470 470
471/*! 471/*!
472*/ 472*/
473inline bool isQ3ValidName( const u8 symbol ) 473inline bool isQ3ValidName( const u8 symbol )
474{ 474{
475 return (symbol >= 'a' && symbol <= 'z' ) || 475 return (symbol >= 'a' && symbol <= 'z' ) ||
476 (symbol >= 'A' && symbol <= 'Z' ) || 476 (symbol >= 'A' && symbol <= 'Z' ) ||
477 (symbol >= '0' && symbol <= '9' ) || 477 (symbol >= '0' && symbol <= '9' ) ||
478 (symbol == '/' || symbol == '_' || symbol == '.' ); 478 (symbol == '/' || symbol == '_' || symbol == '.' );
479} 479}
480 480
481/*! 481/*!
482*/ 482*/
483void CQ3LevelMesh::parser_nextToken() 483void CQ3LevelMesh::parser_nextToken()
484{ 484{
485 u8 symbol; 485 u8 symbol;
486 486
487 Parser.token = ""; 487 Parser.token = "";
488 Parser.tokenresult = Q3_TOKEN_UNRESOLVED; 488 Parser.tokenresult = Q3_TOKEN_UNRESOLVED;
489 489
490 // skip white space 490 // skip white space
491 do 491 do
492 { 492 {
493 if ( Parser.index >= Parser.sourcesize ) 493 if ( Parser.index >= Parser.sourcesize )
494 { 494 {
495 Parser.tokenresult = Q3_TOKEN_EOF; 495 Parser.tokenresult = Q3_TOKEN_EOF;
496 return; 496 return;
497 } 497 }
498 498
499 symbol = Parser.source [ Parser.index ]; 499 symbol = Parser.source [ Parser.index ];
500 Parser.index += 1; 500 Parser.index += 1;
501 } while ( isQ3WhiteSpace( symbol ) ); 501 } while ( isQ3WhiteSpace( symbol ) );
502 502
503 // first symbol, one symbol 503 // first symbol, one symbol
504 switch ( symbol ) 504 switch ( symbol )
505 { 505 {
506 case 0: 506 case 0:
507 Parser.tokenresult = Q3_TOKEN_EOF; 507 Parser.tokenresult = Q3_TOKEN_EOF;
508 return; 508 return;
509 509
510 case '/': 510 case '/':
511 // comment or divide 511 // comment or divide
512 if ( Parser.index >= Parser.sourcesize ) 512 if ( Parser.index >= Parser.sourcesize )
513 { 513 {
514 Parser.tokenresult = Q3_TOKEN_EOF; 514 Parser.tokenresult = Q3_TOKEN_EOF;
515 return; 515 return;
516 } 516 }
517 symbol = Parser.source [ Parser.index ]; 517 symbol = Parser.source [ Parser.index ];
518 Parser.index += 1; 518 Parser.index += 1;
519 if ( isQ3WhiteSpace( symbol ) ) 519 if ( isQ3WhiteSpace( symbol ) )
520 { 520 {
521 Parser.tokenresult = Q3_TOKEN_MATH_DIVIDE; 521 Parser.tokenresult = Q3_TOKEN_MATH_DIVIDE;
522 return; 522 return;
523 } 523 }
524 else 524 else
525 if ( symbol == '*' ) 525 if ( symbol == '*' )
526 { 526 {
527 // C-style comment in quake? 527 // C-style comment in quake?
528 } 528 }
529 else 529 else
530 if ( symbol == '/' ) 530 if ( symbol == '/' )
531 { 531 {
532 // skip to eol 532 // skip to eol
533 do 533 do
534 { 534 {
535 if ( Parser.index >= Parser.sourcesize ) 535 if ( Parser.index >= Parser.sourcesize )
536 { 536 {
537 Parser.tokenresult = Q3_TOKEN_EOF; 537 Parser.tokenresult = Q3_TOKEN_EOF;
538 return; 538 return;
539 } 539 }
540 symbol = Parser.source [ Parser.index ]; 540 symbol = Parser.source [ Parser.index ];
541 Parser.index += 1; 541 Parser.index += 1;
542 } while ( symbol != '\n' ); 542 } while ( symbol != '\n' );
543 Parser.tokenresult = Q3_TOKEN_COMMENT; 543 Parser.tokenresult = Q3_TOKEN_COMMENT;
544 return; 544 return;
545 } 545 }
546 // take /[name] as valid token..?!?!?. mhmm, maybe 546 // take /[name] as valid token..?!?!?. mhmm, maybe
547 break; 547 break;
548 548
549 case '\n': 549 case '\n':
550 Parser.tokenresult = Q3_TOKEN_EOL; 550 Parser.tokenresult = Q3_TOKEN_EOL;
551 return; 551 return;
552 case '{': 552 case '{':
553 Parser.tokenresult = Q3_TOKEN_START_LIST; 553 Parser.tokenresult = Q3_TOKEN_START_LIST;
554 return; 554 return;
555 case '}': 555 case '}':
556 Parser.tokenresult = Q3_TOKEN_END_LIST; 556 Parser.tokenresult = Q3_TOKEN_END_LIST;
557 return; 557 return;
558 558
559 case '"': 559 case '"':
560 // string literal 560 // string literal
561 do 561 do
562 { 562 {
563 if ( Parser.index >= Parser.sourcesize ) 563 if ( Parser.index >= Parser.sourcesize )
564 { 564 {
565 Parser.tokenresult = Q3_TOKEN_EOF; 565 Parser.tokenresult = Q3_TOKEN_EOF;
566 return; 566 return;
567 } 567 }
568 symbol = Parser.source [ Parser.index ]; 568 symbol = Parser.source [ Parser.index ];
569 Parser.index += 1; 569 Parser.index += 1;
570 if ( symbol != '"' ) 570 if ( symbol != '"' )
571 Parser.token.append( symbol ); 571 Parser.token.append( symbol );
572 } while ( symbol != '"' ); 572 } while ( symbol != '"' );
573 Parser.tokenresult = Q3_TOKEN_ENTITY; 573 Parser.tokenresult = Q3_TOKEN_ENTITY;
574 return; 574 return;
575 } 575 }
576 576
577 // user identity 577 // user identity
578 Parser.token.append( symbol ); 578 Parser.token.append( symbol );
579 579
580 // continue till whitespace 580 // continue till whitespace
581 bool validName = true; 581 bool validName = true;
582 do 582 do
583 { 583 {
584 if ( Parser.index >= Parser.sourcesize ) 584 if ( Parser.index >= Parser.sourcesize )
585 { 585 {
586 Parser.tokenresult = Q3_TOKEN_EOF; 586 Parser.tokenresult = Q3_TOKEN_EOF;
587 return; 587 return;
588 } 588 }
589 symbol = Parser.source [ Parser.index ]; 589 symbol = Parser.source [ Parser.index ];
590 590
591 validName = isQ3ValidName( symbol ); 591 validName = isQ3ValidName( symbol );
592 if ( validName ) 592 if ( validName )
593 { 593 {
594 Parser.token.append( symbol ); 594 Parser.token.append( symbol );
595 Parser.index += 1; 595 Parser.index += 1;
596 } 596 }
597 } while ( validName ); 597 } while ( validName );
598 598
599 Parser.tokenresult = Q3_TOKEN_TOKEN; 599 Parser.tokenresult = Q3_TOKEN_TOKEN;
600 return; 600 return;
601} 601}
602 602
603 603
604/* 604/*
605 parse entity & shader 605 parse entity & shader
606 calls callback on content in {} 606 calls callback on content in {}
607*/ 607*/
608void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh::tParserCallback callback ) 608void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh::tParserCallback callback )
609{ 609{
610 Parser.source = static_cast<const c8*>(data); 610 Parser.source = static_cast<const c8*>(data);
611 Parser.sourcesize = size; 611 Parser.sourcesize = size;
612 Parser.index = 0; 612 Parser.index = 0;
613 613
614 SVarGroupList *groupList; 614 SVarGroupList *groupList;
615 615
616 s32 active; 616 s32 active;
617 s32 last; 617 s32 last;
618 618
619 SVariable entity ( "" ); 619 SVariable entity ( "" );
620 620
621 groupList = new SVarGroupList(); 621 groupList = new SVarGroupList();
622 622
623 groupList->VariableGroup.push_back( SVarGroup() ); 623 groupList->VariableGroup.push_back( SVarGroup() );
624 active = last = 0; 624 active = last = 0;
625 625
626 do 626 do
627 { 627 {
628 parser_nextToken(); 628 parser_nextToken();
629 629
630 switch ( Parser.tokenresult ) 630 switch ( Parser.tokenresult )
631 { 631 {
632 case Q3_TOKEN_START_LIST: 632 case Q3_TOKEN_START_LIST:
633 { 633 {
634 //stack = core::min_( stack + 1, 7 ); 634 //stack = core::min_( stack + 1, 7 );
635 635
636 groupList->VariableGroup.push_back( SVarGroup() ); 636 groupList->VariableGroup.push_back( SVarGroup() );
637 last = active; 637 last = active;
638 active = groupList->VariableGroup.size() - 1; 638 active = groupList->VariableGroup.size() - 1;
639 entity.clear(); 639 entity.clear();
640 } break; 640 } break;
641 641
642 // a unregisterd variable is finished 642 // a unregisterd variable is finished
643 case Q3_TOKEN_EOL: 643 case Q3_TOKEN_EOL:
644 { 644 {
645 if ( entity.isValid() ) 645 if ( entity.isValid() )
646 { 646 {
647 groupList->VariableGroup[active].Variable.push_back( entity ); 647 groupList->VariableGroup[active].Variable.push_back( entity );
648 entity.clear(); 648 entity.clear();
649 } 649 }
650 } break; 650 } break;
651 651
652 case Q3_TOKEN_TOKEN: 652 case Q3_TOKEN_TOKEN:
653 case Q3_TOKEN_ENTITY: 653 case Q3_TOKEN_ENTITY:
654 { 654 {
655 Parser.token.make_lower(); 655 Parser.token.make_lower();
656 656
657 // store content based on line-delemiter 657 // store content based on line-delemiter
658 if ( 0 == entity.isValid() ) 658 if ( 0 == entity.isValid() )
659 { 659 {
660 entity.name = Parser.token; 660 entity.name = Parser.token;
661 entity.content = ""; 661 entity.content = "";
662 662
663 } 663 }
664 else 664 else
665 { 665 {
666 if ( entity.content.size() ) 666 if ( entity.content.size() )
667 { 667 {
668 entity.content += " "; 668 entity.content += " ";
669 } 669 }
670 entity.content += Parser.token; 670 entity.content += Parser.token;
671 } 671 }
672 } break; 672 } break;
673 673
674 case Q3_TOKEN_END_LIST: 674 case Q3_TOKEN_END_LIST:
675 { 675 {
676 //stack = core::max_( stack - 1, 0 ); 676 //stack = core::max_( stack - 1, 0 );
677 677
678 // close tag for first 678 // close tag for first
679 if ( active == 1 ) 679 if ( active == 1 )
680 { 680 {
681 (this->*callback)( groupList, Q3_TOKEN_END_LIST ); 681 (this->*callback)( groupList, Q3_TOKEN_END_LIST );
682 682
683 // new group 683 // new group
684 groupList->drop(); 684 groupList->drop();
685 groupList = new SVarGroupList(); 685 groupList = new SVarGroupList();
686 groupList->VariableGroup.push_back( SVarGroup() ); 686 groupList->VariableGroup.push_back( SVarGroup() );
687 last = 0; 687 last = 0;
688 } 688 }
689 689
690 active = last; 690 active = last;
691 entity.clear(); 691 entity.clear();
692 692
693 } break; 693 } break;
694 694
695 default: 695 default:
696 break; 696 break;
697 } 697 }
698 698
699 } while ( Parser.tokenresult != Q3_TOKEN_EOF ); 699 } while ( Parser.tokenresult != Q3_TOKEN_EOF );
700 700
701 (this->*callback)( groupList, Q3_TOKEN_EOF ); 701 (this->*callback)( groupList, Q3_TOKEN_EOF );
702 702
703 groupList->drop(); 703 groupList->drop();
704} 704}
705 705
706 706
707/* 707/*
708 this loader applies only textures for stage 1 & 2 708 this loader applies only textures for stage 1 & 2
709*/ 709*/
710s32 CQ3LevelMesh::setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const 710s32 CQ3LevelMesh::setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const
711{ 711{
712 material.MaterialType = video::EMT_SOLID; 712 material.MaterialType = video::EMT_SOLID;
713 material.Wireframe = false; 713 material.Wireframe = false;
714 material.Lighting = false; 714 material.Lighting = false;
715 material.BackfaceCulling = false; 715 material.BackfaceCulling = false;
716 material.setTexture(0, 0); 716 material.setTexture(0, 0);
717 material.setTexture(1, 0); 717 material.setTexture(1, 0);
718 material.setTexture(2, 0); 718 material.setTexture(2, 0);
719 material.setTexture(3, 0); 719 material.setTexture(3, 0);
720 material.ZBuffer = video::ECFN_LESSEQUAL; 720 material.ZBuffer = video::ECFN_LESSEQUAL;
721 material.ZWriteEnable = false; 721 material.ZWriteEnable = false;
722 material.MaterialTypeParam = 0.f; 722 material.MaterialTypeParam = 0.f;
723 723
724 s32 shaderState = -1; 724 s32 shaderState = -1;
725 725
726 if ( (u32) face->fogNum < FogMap.size() ) 726 if ( (u32) face->fogNum < FogMap.size() )
727 { 727 {
728 material.setTexture(0, FogMap [ face->fogNum ].Texture); 728 material.setTexture(0, FogMap [ face->fogNum ].Texture);
729 shaderState = FogMap [ face->fogNum ].ShaderID; 729 shaderState = FogMap [ face->fogNum ].ShaderID;
730 } 730 }
731 731
732 return shaderState; 732 return shaderState;
733 733
734} 734}
735/* 735/*
736 this loader applies only textures for stage 1 & 2 736 this loader applies only textures for stage 1 & 2
737*/ 737*/
738s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace * face ) const 738s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace * face ) const
739{ 739{
740 material.MaterialType = video::EMT_SOLID; 740 material.MaterialType = video::EMT_SOLID;
741 material.Wireframe = false; 741 material.Wireframe = false;
742 material.Lighting = false; 742 material.Lighting = false;
743 material.BackfaceCulling = true; 743 material.BackfaceCulling = true;
744 material.setTexture(0, 0); 744 material.setTexture(0, 0);
745 material.setTexture(1, 0); 745 material.setTexture(1, 0);
746 material.setTexture(2, 0); 746 material.setTexture(2, 0);
747 material.setTexture(3, 0); 747 material.setTexture(3, 0);
748 material.ZBuffer = video::ECFN_LESSEQUAL; 748 material.ZBuffer = video::ECFN_LESSEQUAL;
749 material.ZWriteEnable = true; 749 material.ZWriteEnable = true;
750 material.MaterialTypeParam = 0.f; 750 material.MaterialTypeParam = 0.f;
751 751
752 s32 shaderState = -1; 752 s32 shaderState = -1;
753 753
754 if ( face->textureID >= 0 && face->textureID < (s32)Tex.size() ) 754 if ( face->textureID >= 0 && face->textureID < (s32)Tex.size() )
755 { 755 {
756 material.setTexture(0, Tex [ face->textureID ].Texture); 756 material.setTexture(0, Tex [ face->textureID ].Texture);
757 shaderState = Tex [ face->textureID ].ShaderID; 757 shaderState = Tex [ face->textureID ].ShaderID;
758 } 758 }
759 759
760 if ( face->lightmapID >= 0 && face->lightmapID < (s32)Lightmap.size() ) 760 if ( face->lightmapID >= 0 && face->lightmapID < (s32)Lightmap.size() )
761 { 761 {
762 material.setTexture(1, Lightmap [ face->lightmapID ]); 762 material.setTexture(1, Lightmap [ face->lightmapID ]);
763 material.MaterialType = LoadParam.defaultLightMapMaterial; 763 material.MaterialType = LoadParam.defaultLightMapMaterial;
764 } 764 }
765 765
766 // store shader ID 766 // store shader ID
767 material.MaterialTypeParam2 = (f32) shaderState; 767 material.MaterialTypeParam2 = (f32) shaderState;
768 768
769 const IShader *shader = getShader(shaderState); 769 const IShader *shader = getShader(shaderState);
770 if ( 0 == shader ) 770 if ( 0 == shader )
771 return shaderState; 771 return shaderState;
772 772
773 return shaderState; 773 return shaderState;
774 774
775#if 0 775#if 0
776 const SVarGroup *group; 776 const SVarGroup *group;
777 777
778 778
779 // generic 779 // generic
780 group = shader->getGroup( 1 ); 780 group = shader->getGroup( 1 );
781 if ( group ) 781 if ( group )
782 { 782 {
783 material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); 783 material.BackfaceCulling = getCullingFunction( group->get( "cull" ) );
784 784
785 if ( group->isDefined( "surfaceparm", "nolightmap" ) ) 785 if ( group->isDefined( "surfaceparm", "nolightmap" ) )
786 { 786 {
787 material.MaterialType = video::EMT_SOLID; 787 material.MaterialType = video::EMT_SOLID;
788 material.setTexture(1, 0); 788 material.setTexture(1, 0);
789 } 789 }
790 790
791 } 791 }
792 792
793 // try to get the best of the 8 texture stages.. 793 // try to get the best of the 8 texture stages..
794 794
795 // texture 1, texture 2 795 // texture 1, texture 2
796 u32 startPos; 796 u32 startPos;
797 for ( s32 g = 2; g <= 3; ++g ) 797 for ( s32 g = 2; g <= 3; ++g )
798 { 798 {
799 group = shader->getGroup( g ); 799 group = shader->getGroup( g );
800 if ( 0 == group ) 800 if ( 0 == group )
801 continue; 801 continue;
802 802
803 startPos = 0; 803 startPos = 0;
804 804
805 if ( group->isDefined( "depthwrite" ) ) 805 if ( group->isDefined( "depthwrite" ) )
806 { 806 {
807 material.ZWriteEnable = true; 807 material.ZWriteEnable = true;
808 } 808 }
809 809
810 SBlendFunc blendfunc ( LoadParam.defaultModulate ); 810 SBlendFunc blendfunc ( LoadParam.defaultModulate );
811 getBlendFunc( group->get( "blendfunc" ), blendfunc ); 811 getBlendFunc( group->get( "blendfunc" ), blendfunc );
812 getBlendFunc( group->get( "alphafunc" ), blendfunc ); 812 getBlendFunc( group->get( "alphafunc" ), blendfunc );
813 813
814 if ( 0 == LoadParam.alpharef && 814 if ( 0 == LoadParam.alpharef &&
815 ( blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL || 815 ( blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL ||
816 blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF 816 blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF
817 ) 817 )
818 ) 818 )
819 { 819 {
820 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; 820 blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
821 blendfunc.param0 = 0.f; 821 blendfunc.param0 = 0.f;
822 } 822 }
823 823
824 material.MaterialType = blendfunc.type; 824 material.MaterialType = blendfunc.type;
825 material.MaterialTypeParam = blendfunc.param0; 825 material.MaterialTypeParam = blendfunc.param0;
826 826
827 // try if we can match better 827 // try if we can match better
828 shaderState |= (material.MaterialType == video::EMT_SOLID ) ? 0x00020000 : 0; 828 shaderState |= (material.MaterialType == video::EMT_SOLID ) ? 0x00020000 : 0;
829 } 829 }
830 830
831 //material.BackfaceCulling = false; 831 //material.BackfaceCulling = false;
832 832
833 if ( shader->VarGroup->VariableGroup.size() <= 4 ) 833 if ( shader->VarGroup->VariableGroup.size() <= 4 )
834 { 834 {
835 shaderState |= 0x00010000; 835 shaderState |= 0x00010000;
836 } 836 }
837 837
838 material.MaterialTypeParam2 = (f32) shaderState; 838 material.MaterialTypeParam2 = (f32) shaderState;
839 return shaderState; 839 return shaderState;
840#endif 840#endif
841} 841}
842 842
843/*! 843/*!
844 Internal function to build a mesh. 844 Internal function to build a mesh.
845*/ 845*/
846scene::SMesh** CQ3LevelMesh::buildMesh(s32 num) 846scene::SMesh** CQ3LevelMesh::buildMesh(s32 num)
847{ 847{
848 scene::SMesh** newmesh = new SMesh *[quake3::E_Q3_MESH_SIZE]; 848 scene::SMesh** newmesh = new SMesh *[quake3::E_Q3_MESH_SIZE];
849 849
850 s32 i, j, k,s; 850 s32 i, j, k,s;
851 851
852 for (i = 0; i < E_Q3_MESH_SIZE; i++) 852 for (i = 0; i < E_Q3_MESH_SIZE; i++)
853 { 853 {
854 newmesh[i] = new SMesh(); 854 newmesh[i] = new SMesh();
855 } 855 }
856 856
857 s32 *index; 857 s32 *index;
858 858
859 video::S3DVertex2TCoords temp[3]; 859 video::S3DVertex2TCoords temp[3];
860 video::SMaterial material; 860 video::SMaterial material;
861 video::SMaterial material2; 861 video::SMaterial material2;
862 862
863 SToBuffer item [ E_Q3_MESH_SIZE ]; 863 SToBuffer item [ E_Q3_MESH_SIZE ];
864 u32 itemSize; 864 u32 itemSize;
865 865
866 for (i = Models[num].faceIndex; i < Models[num].numOfFaces + Models[num].faceIndex; ++i) 866 for (i = Models[num].faceIndex; i < Models[num].numOfFaces + Models[num].faceIndex; ++i)
867 { 867 {
868 const tBSPFace * face = Faces + i; 868 const tBSPFace * face = Faces + i;
869 869
870 s32 shaderState = setShaderMaterial( material, face ); 870 s32 shaderState = setShaderMaterial( material, face );
871 itemSize = 0; 871 itemSize = 0;
872 872
873 const IShader *shader = getShader(shaderState); 873 const IShader *shader = getShader(shaderState);
874 874
875 if ( face->fogNum >= 0 ) 875 if ( face->fogNum >= 0 )
876 { 876 {
877 setShaderFogMaterial ( material2, face ); 877 setShaderFogMaterial ( material2, face );
878 item[itemSize].index = E_Q3_MESH_FOG; 878 item[itemSize].index = E_Q3_MESH_FOG;
879 item[itemSize].takeVertexColor = 1; 879 item[itemSize].takeVertexColor = 1;
880 itemSize += 1; 880 itemSize += 1;
881 } 881 }
882 882
883 switch( face->type ) 883 switch( face->type )
884 { 884 {
885 case 1: // normal polygons 885 case 1: // normal polygons
886 case 2: // patches 886 case 2: // patches
887 case 3: // meshes 887 case 3: // meshes
888 if ( 0 == shader ) 888 if ( 0 == shader )
889 { 889 {
890 if ( LoadParam.cleanUnResolvedMeshes || material.getTexture(0) ) 890 if ( LoadParam.cleanUnResolvedMeshes || material.getTexture(0) )
891 { 891 {
892 item[itemSize].takeVertexColor = 1; 892 item[itemSize].takeVertexColor = 1;
893 item[itemSize].index = E_Q3_MESH_GEOMETRY; 893 item[itemSize].index = E_Q3_MESH_GEOMETRY;
894 itemSize += 1; 894 itemSize += 1;
895 } 895 }
896 else 896 else
897 { 897 {
898 item[itemSize].takeVertexColor = 1; 898 item[itemSize].takeVertexColor = 1;
899 item[itemSize].index = E_Q3_MESH_UNRESOLVED; 899 item[itemSize].index = E_Q3_MESH_UNRESOLVED;
900 itemSize += 1; 900 itemSize += 1;
901 } 901 }
902 } 902 }
903 else 903 else
904 { 904 {
905 item[itemSize].takeVertexColor = 1; 905 item[itemSize].takeVertexColor = 1;
906 item[itemSize].index = E_Q3_MESH_ITEMS; 906 item[itemSize].index = E_Q3_MESH_ITEMS;
907 itemSize += 1; 907 itemSize += 1;
908 } 908 }
909 break; 909 break;
910 910
911 case 4: // billboards 911 case 4: // billboards
912 //item[itemSize].takeVertexColor = 1; 912 //item[itemSize].takeVertexColor = 1;
913 //item[itemSize].index = E_Q3_MESH_ITEMS; 913 //item[itemSize].index = E_Q3_MESH_ITEMS;
914 //itemSize += 1; 914 //itemSize += 1;
915 break; 915 break;
916 916
917 } 917 }
918 918
919 for ( u32 g = 0; g != itemSize; ++g ) 919 for ( u32 g = 0; g != itemSize; ++g )
920 { 920 {
921 scene::SMeshBufferLightMap* buffer = 0; 921 scene::SMeshBufferLightMap* buffer = 0;
922 922
923 if ( item[g].index == E_Q3_MESH_GEOMETRY ) 923 if ( item[g].index == E_Q3_MESH_GEOMETRY )
924 { 924 {
925 if ( 0 == item[g].takeVertexColor ) 925 if ( 0 == item[g].takeVertexColor )
926 { 926 {
927 item[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; 927 item[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0;
928 } 928 }
929 929
930 if (Faces[i].lightmapID < -1 || Faces[i].lightmapID > NumLightMaps-1) 930 if (Faces[i].lightmapID < -1 || Faces[i].lightmapID > NumLightMaps-1)
931 { 931 {
932 Faces[i].lightmapID = -1; 932 Faces[i].lightmapID = -1;
933 } 933 }
934 934
935#if 0 935#if 0
936 // there are lightmapsids and textureid with -1 936 // there are lightmapsids and textureid with -1
937 const s32 tmp_index = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); 937 const s32 tmp_index = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1);
938 buffer = (SMeshBufferLightMap*) newmesh[E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); 938 buffer = (SMeshBufferLightMap*) newmesh[E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index);
939 buffer->setHardwareMappingHint ( EHM_STATIC ); 939 buffer->setHardwareMappingHint ( EHM_STATIC );
940 buffer->getMaterial() = material; 940 buffer->getMaterial() = material;
941#endif 941#endif
942 } 942 }
943 943
944 // Construct a unique mesh for each shader or combine meshbuffers for same shader 944 // Construct a unique mesh for each shader or combine meshbuffers for same shader
945 if ( 0 == buffer ) 945 if ( 0 == buffer )
946 { 946 {
947 947
948 if ( LoadParam.mergeShaderBuffer == 1 ) 948 if ( LoadParam.mergeShaderBuffer == 1 )
949 { 949 {
950 // combine 950 // combine
951 buffer = (SMeshBufferLightMap*) newmesh[ item[g].index ]->getMeshBuffer( 951 buffer = (SMeshBufferLightMap*) newmesh[ item[g].index ]->getMeshBuffer(
952 item[g].index != E_Q3_MESH_FOG ? material : material2 ); 952 item[g].index != E_Q3_MESH_FOG ? material : material2 );
953 } 953 }
954 954
955 // create a seperate mesh buffer 955 // create a seperate mesh buffer
956 if ( 0 == buffer ) 956 if ( 0 == buffer )
957 { 957 {
958 buffer = new scene::SMeshBufferLightMap(); 958 buffer = new scene::SMeshBufferLightMap();
959 newmesh[ item[g].index ]->addMeshBuffer( buffer ); 959 newmesh[ item[g].index ]->addMeshBuffer( buffer );
960 buffer->drop(); 960 buffer->drop();
961 buffer->getMaterial() = item[g].index != E_Q3_MESH_FOG ? material : material2; 961 buffer->getMaterial() = item[g].index != E_Q3_MESH_FOG ? material : material2;
962 if ( item[g].index == E_Q3_MESH_GEOMETRY ) 962 if ( item[g].index == E_Q3_MESH_GEOMETRY )
963 buffer->setHardwareMappingHint ( EHM_STATIC ); 963 buffer->setHardwareMappingHint ( EHM_STATIC );
964 } 964 }
965 } 965 }
966 966
967 967
968 switch(Faces[i].type) 968 switch(Faces[i].type)
969 { 969 {
970 case 4: // billboards 970 case 4: // billboards
971 break; 971 break;
972 case 2: // patches 972 case 2: // patches
973 createCurvedSurface_bezier( buffer, i, 973 createCurvedSurface_bezier( buffer, i,
974 LoadParam.patchTesselation, 974 LoadParam.patchTesselation,
975 item[g].takeVertexColor 975 item[g].takeVertexColor
976 ); 976 );
977 break; 977 break;
978 978
979 case 1: // normal polygons 979 case 1: // normal polygons
980 case 3: // mesh vertices 980 case 3: // mesh vertices
981 index = MeshVerts + face->meshVertIndex; 981 index = MeshVerts + face->meshVertIndex;
982 k = buffer->getVertexCount(); 982 k = buffer->getVertexCount();
983 983
984 // reallocate better if many small meshes are used 984 // reallocate better if many small meshes are used
985 s = buffer->getIndexCount()+face->numMeshVerts; 985 s = buffer->getIndexCount()+face->numMeshVerts;
986 if ( buffer->Indices.allocated_size () < (u32) s ) 986 if ( buffer->Indices.allocated_size () < (u32) s )
987 { 987 {
988 if ( buffer->Indices.allocated_size () > 0 && 988 if ( buffer->Indices.allocated_size () > 0 &&
989 face->numMeshVerts < 20 && NumFaces > 1000 989 face->numMeshVerts < 20 && NumFaces > 1000
990 ) 990 )
991 { 991 {
992 s = buffer->getIndexCount() + (NumFaces >> 3 * face->numMeshVerts ); 992 s = buffer->getIndexCount() + (NumFaces >> 3 * face->numMeshVerts );
993 } 993 }
994 buffer->Indices.reallocate( s); 994 buffer->Indices.reallocate( s);
995 } 995 }
996 996
997 for ( j = 0; j < face->numMeshVerts; ++j ) 997 for ( j = 0; j < face->numMeshVerts; ++j )
998 { 998 {
999 buffer->Indices.push_back( k + index [j] ); 999 buffer->Indices.push_back( k + index [j] );
1000 } 1000 }
1001 1001
1002 s = k+face->numOfVerts; 1002 s = k+face->numOfVerts;
1003 if ( buffer->Vertices.allocated_size () < (u32) s ) 1003 if ( buffer->Vertices.allocated_size () < (u32) s )
1004 { 1004 {
1005 if ( buffer->Indices.allocated_size () > 0 && 1005 if ( buffer->Indices.allocated_size () > 0 &&
1006 face->numOfVerts < 20 && NumFaces > 1000 1006 face->numOfVerts < 20 && NumFaces > 1000
1007 ) 1007 )
1008 { 1008 {
1009 s = buffer->getIndexCount() + (NumFaces >> 3 * face->numOfVerts ); 1009 s = buffer->getIndexCount() + (NumFaces >> 3 * face->numOfVerts );
1010 } 1010 }
1011 buffer->Vertices.reallocate( s); 1011 buffer->Vertices.reallocate( s);
1012 } 1012 }
1013 for ( j = 0; j != face->numOfVerts; ++j ) 1013 for ( j = 0; j != face->numOfVerts; ++j )
1014 { 1014 {
1015 copy( &temp[0], &Vertices[ j + face->vertexIndex ], item[g].takeVertexColor ); 1015 copy( &temp[0], &Vertices[ j + face->vertexIndex ], item[g].takeVertexColor );
1016 buffer->Vertices.push_back( temp[0] ); 1016 buffer->Vertices.push_back( temp[0] );
1017 } 1017 }
1018 break; 1018 break;
1019 1019
1020 } // end switch 1020 } // end switch
1021 } 1021 }
1022 } 1022 }
1023 1023
1024 return newmesh; 1024 return newmesh;
1025} 1025}
1026 1026
1027/*! 1027/*!
1028*/ 1028*/
1029void CQ3LevelMesh::solveTJunction() 1029void CQ3LevelMesh::solveTJunction()
1030{ 1030{
1031} 1031}
1032 1032
1033/*! 1033/*!
1034 constructs a mesh from the quake 3 level file. 1034 constructs a mesh from the quake 3 level file.
1035*/ 1035*/
1036void CQ3LevelMesh::constructMesh() 1036void CQ3LevelMesh::constructMesh()
1037{ 1037{
1038 if ( LoadParam.verbose > 0 ) 1038 if ( LoadParam.verbose > 0 )
1039 { 1039 {
1040 LoadParam.startTime = os::Timer::getRealTime(); 1040 LoadParam.startTime = os::Timer::getRealTime();
1041 1041
1042 if ( LoadParam.verbose > 1 ) 1042 if ( LoadParam.verbose > 1 )
1043 { 1043 {
1044 snprintf( buf, sizeof ( buf ), 1044 snprintf( buf, sizeof ( buf ),
1045 "quake3::constructMesh start to create %d faces, %d vertices,%d mesh vertices", 1045 "quake3::constructMesh start to create %d faces, %d vertices,%d mesh vertices",
1046 NumFaces, 1046 NumFaces,
1047 NumVertices, 1047 NumVertices,
1048 NumMeshVerts 1048 NumMeshVerts
1049 ); 1049 );
1050 os::Printer::log(buf, ELL_INFORMATION); 1050 os::Printer::log(buf, ELL_INFORMATION);
1051 } 1051 }
1052 1052
1053 } 1053 }
1054 1054
1055 s32 i, j; 1055 s32 i, j;
1056 1056
1057 // First the main level 1057 // First the main level
1058 SMesh **tmp = buildMesh(0); 1058 SMesh **tmp = buildMesh(0);
1059 1059
1060 for (i = 0; i < E_Q3_MESH_SIZE; i++) 1060 for (i = 0; i < E_Q3_MESH_SIZE; i++)
1061 { 1061 {
1062 Mesh[i] = tmp[i]; 1062 Mesh[i] = tmp[i];
1063 } 1063 }
1064 delete [] tmp; 1064 delete [] tmp;
1065 1065
1066 // Then the brush entities 1066 // Then the brush entities
1067 1067
1068 for (i = 1; i < NumModels; i++) 1068 for (i = 1; i < NumModels; i++)
1069 { 1069 {
1070 tmp = buildMesh(i); 1070 tmp = buildMesh(i);
1071 BrushEntities[i] = tmp[0]; 1071 BrushEntities[i] = tmp[0];
1072 1072
1073 // We only care about the main geometry here 1073 // We only care about the main geometry here
1074 for (j = 1; j < E_Q3_MESH_SIZE; j++) 1074 for (j = 1; j < E_Q3_MESH_SIZE; j++)
1075 { 1075 {
1076 tmp[j]->drop(); 1076 tmp[j]->drop();
1077 } 1077 }
1078 delete [] tmp; 1078 delete [] tmp;
1079 } 1079 }
1080 1080
1081 if ( LoadParam.verbose > 0 ) 1081 if ( LoadParam.verbose > 0 )
1082 { 1082 {
1083 LoadParam.endTime = os::Timer::getRealTime(); 1083 LoadParam.endTime = os::Timer::getRealTime();
1084 1084
1085 snprintf( buf, sizeof ( buf ), 1085 snprintf( buf, sizeof ( buf ),
1086 "quake3::constructMesh needed %04d ms to create %d faces, %d vertices,%d mesh vertices", 1086 "quake3::constructMesh needed %04d ms to create %d faces, %d vertices,%d mesh vertices",
1087 LoadParam.endTime - LoadParam.startTime, 1087 LoadParam.endTime - LoadParam.startTime,
1088 NumFaces, 1088 NumFaces,
1089 NumVertices, 1089 NumVertices,
1090 NumMeshVerts 1090 NumMeshVerts
1091 ); 1091 );
1092 os::Printer::log(buf, ELL_INFORMATION); 1092 os::Printer::log(buf, ELL_INFORMATION);
1093 } 1093 }
1094 1094
1095} 1095}
1096 1096
1097 1097
1098void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const 1098void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const
1099{ 1099{
1100#if defined (TJUNCTION_SOLVER_ROUND) 1100#if defined (TJUNCTION_SOLVER_ROUND)
1101 dest.Pos.X = core::round_( (f32) Pos.X ); 1101 dest.Pos.X = core::round_( (f32) Pos.X );
1102 dest.Pos.Y = core::round_( (f32) Pos.Y ); 1102 dest.Pos.Y = core::round_( (f32) Pos.Y );
1103 dest.Pos.Z = core::round_( (f32) Pos.Z ); 1103 dest.Pos.Z = core::round_( (f32) Pos.Z );
1104#elif defined (TJUNCTION_SOLVER_0125) 1104#elif defined (TJUNCTION_SOLVER_0125)
1105 dest.Pos.X = (f32) ( floor ( Pos.X * 8.f + 0.5 ) * 0.125 ); 1105 dest.Pos.X = (f32) ( floor ( Pos.X * 8.f + 0.5 ) * 0.125 );
1106 dest.Pos.Y = (f32) ( floor ( Pos.Y * 8.f + 0.5 ) * 0.125 ); 1106 dest.Pos.Y = (f32) ( floor ( Pos.Y * 8.f + 0.5 ) * 0.125 );
1107 dest.Pos.Z = (f32) ( floor ( Pos.Z * 8.f + 0.5 ) * 0.125 ); 1107 dest.Pos.Z = (f32) ( floor ( Pos.Z * 8.f + 0.5 ) * 0.125 );
1108#else 1108#else
1109 dest.Pos.X = (f32) Pos.X; 1109 dest.Pos.X = (f32) Pos.X;
1110 dest.Pos.Y = (f32) Pos.Y; 1110 dest.Pos.Y = (f32) Pos.Y;
1111 dest.Pos.Z = (f32) Pos.Z; 1111 dest.Pos.Z = (f32) Pos.Z;
1112#endif 1112#endif
1113 1113
1114 dest.Normal.X = (f32) Normal.X; 1114 dest.Normal.X = (f32) Normal.X;
1115 dest.Normal.Y = (f32) Normal.Y; 1115 dest.Normal.Y = (f32) Normal.Y;
1116 dest.Normal.Z = (f32) Normal.Z; 1116 dest.Normal.Z = (f32) Normal.Z;
1117 dest.Normal.normalize(); 1117 dest.Normal.normalize();
1118 1118
1119 dest.Color = Color.toSColor(); 1119 dest.Color = Color.toSColor();
1120 1120
1121 dest.TCoords.X = (f32) TCoords.X; 1121 dest.TCoords.X = (f32) TCoords.X;
1122 dest.TCoords.Y = (f32) TCoords.Y; 1122 dest.TCoords.Y = (f32) TCoords.Y;
1123 1123
1124 dest.TCoords2.X = (f32) TCoords2.X; 1124 dest.TCoords2.X = (f32) TCoords2.X;
1125 dest.TCoords2.Y = (f32) TCoords2.Y; 1125 dest.TCoords2.Y = (f32) TCoords2.Y;
1126} 1126}
1127 1127
1128 1128
1129void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const 1129void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const
1130{ 1130{
1131#if defined (TJUNCTION_SOLVER_ROUND) 1131#if defined (TJUNCTION_SOLVER_ROUND)
1132 dest->Pos.X = core::round_( source->vPosition[0] ); 1132 dest->Pos.X = core::round_( source->vPosition[0] );
1133 dest->Pos.Y = core::round_( source->vPosition[2] ); 1133 dest->Pos.Y = core::round_( source->vPosition[2] );
1134 dest->Pos.Z = core::round_( source->vPosition[1] ); 1134 dest->Pos.Z = core::round_( source->vPosition[1] );
1135#elif defined (TJUNCTION_SOLVER_0125) 1135#elif defined (TJUNCTION_SOLVER_0125)
1136 dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); 1136 dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 );
1137 dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); 1137 dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 );
1138 dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); 1138 dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 );
1139#else 1139#else
1140 dest->Pos.X = source->vPosition[0]; 1140 dest->Pos.X = source->vPosition[0];
1141 dest->Pos.Y = source->vPosition[2]; 1141 dest->Pos.Y = source->vPosition[2];
1142 dest->Pos.Z = source->vPosition[1]; 1142 dest->Pos.Z = source->vPosition[1];
1143#endif 1143#endif
1144 1144
1145 dest->Normal.X = source->vNormal[0]; 1145 dest->Normal.X = source->vNormal[0];
1146 dest->Normal.Y = source->vNormal[2]; 1146 dest->Normal.Y = source->vNormal[2];
1147 dest->Normal.Z = source->vNormal[1]; 1147 dest->Normal.Z = source->vNormal[1];
1148 dest->Normal.normalize(); 1148 dest->Normal.normalize();
1149 1149
1150 dest->TCoords.X = source->vTextureCoord[0]; 1150 dest->TCoords.X = source->vTextureCoord[0];
1151 dest->TCoords.Y = source->vTextureCoord[1]; 1151 dest->TCoords.Y = source->vTextureCoord[1];
1152 dest->TCoords2.X = source->vLightmapCoord[0]; 1152 dest->TCoords2.X = source->vLightmapCoord[0];
1153 dest->TCoords2.Y = source->vLightmapCoord[1]; 1153 dest->TCoords2.Y = source->vLightmapCoord[1];
1154 1154
1155 if ( vertexcolor ) 1155 if ( vertexcolor )
1156 { 1156 {
1157 //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); 1157 //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 );
1158 u32 a = source->color[3]; 1158 u32 a = source->color[3];
1159 u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); 1159 u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 );
1160 u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); 1160 u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 );
1161 u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); 1161 u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 );
1162 1162
1163 dest->Color.set(a * 1.f/255.f, r * 1.f/255.f, 1163 dest->Color.set(a * 1.f/255.f, r * 1.f/255.f,
1164 g * 1.f/255.f, b * 1.f/255.f); 1164 g * 1.f/255.f, b * 1.f/255.f);
1165 } 1165 }
1166 else 1166 else
1167 { 1167 {
1168 dest->Color.set( 1.f, 1.f, 1.f, 1.f ); 1168 dest->Color.set( 1.f, 1.f, 1.f, 1.f );
1169 } 1169 }
1170} 1170}
1171 1171
1172 1172
1173inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const 1173inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const
1174{ 1174{
1175#if defined (TJUNCTION_SOLVER_ROUND) 1175#if defined (TJUNCTION_SOLVER_ROUND)
1176 dest->Pos.X = core::round_( source->vPosition[0] ); 1176 dest->Pos.X = core::round_( source->vPosition[0] );
1177 dest->Pos.Y = core::round_( source->vPosition[2] ); 1177 dest->Pos.Y = core::round_( source->vPosition[2] );
1178 dest->Pos.Z = core::round_( source->vPosition[1] ); 1178 dest->Pos.Z = core::round_( source->vPosition[1] );
1179#elif defined (TJUNCTION_SOLVER_0125) 1179#elif defined (TJUNCTION_SOLVER_0125)
1180 dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); 1180 dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 );
1181 dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); 1181 dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 );
1182 dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); 1182 dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 );
1183#else 1183#else
1184 dest->Pos.X = source->vPosition[0]; 1184 dest->Pos.X = source->vPosition[0];
1185 dest->Pos.Y = source->vPosition[2]; 1185 dest->Pos.Y = source->vPosition[2];
1186 dest->Pos.Z = source->vPosition[1]; 1186 dest->Pos.Z = source->vPosition[1];
1187#endif 1187#endif
1188 1188
1189 dest->Normal.X = source->vNormal[0]; 1189 dest->Normal.X = source->vNormal[0];
1190 dest->Normal.Y = source->vNormal[2]; 1190 dest->Normal.Y = source->vNormal[2];
1191 dest->Normal.Z = source->vNormal[1]; 1191 dest->Normal.Z = source->vNormal[1];
1192 dest->Normal.normalize(); 1192 dest->Normal.normalize();
1193 1193
1194 dest->TCoords.X = source->vTextureCoord[0]; 1194 dest->TCoords.X = source->vTextureCoord[0];
1195 dest->TCoords.Y = source->vTextureCoord[1]; 1195 dest->TCoords.Y = source->vTextureCoord[1];
1196 dest->TCoords2.X = source->vLightmapCoord[0]; 1196 dest->TCoords2.X = source->vLightmapCoord[0];
1197 dest->TCoords2.Y = source->vLightmapCoord[1]; 1197 dest->TCoords2.Y = source->vLightmapCoord[1];
1198 1198
1199 if ( vertexcolor ) 1199 if ( vertexcolor )
1200 { 1200 {
1201 //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); 1201 //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 );
1202 u32 a = source->color[3]; 1202 u32 a = source->color[3];
1203 u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); 1203 u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 );
1204 u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); 1204 u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 );
1205 u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); 1205 u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 );
1206 1206
1207 dest->Color.set(a << 24 | r << 16 | g << 8 | b); 1207 dest->Color.set(a << 24 | r << 16 | g << 8 | b);
1208 } 1208 }
1209 else 1209 else
1210 { 1210 {
1211 dest->Color.set(0xFFFFFFFF); 1211 dest->Color.set(0xFFFFFFFF);
1212 } 1212 }
1213} 1213}
1214 1214
1215 1215
1216void CQ3LevelMesh::SBezier::tesselate( s32 level ) 1216void CQ3LevelMesh::SBezier::tesselate( s32 level )
1217{ 1217{
1218 //Calculate how many vertices across/down there are 1218 //Calculate how many vertices across/down there are
1219 s32 j, k; 1219 s32 j, k;
1220 1220
1221 column[0].set_used( level + 1 ); 1221 column[0].set_used( level + 1 );
1222 column[1].set_used( level + 1 ); 1222 column[1].set_used( level + 1 );
1223 column[2].set_used( level + 1 ); 1223 column[2].set_used( level + 1 );
1224 1224
1225 const f64 w = 0.0 + (1.0 / (f64) level ); 1225 const f64 w = 0.0 + (1.0 / (f64) level );
1226 1226
1227 //Tesselate along the columns 1227 //Tesselate along the columns
1228 for( j = 0; j <= level; ++j) 1228 for( j = 0; j <= level; ++j)
1229 { 1229 {
1230 const f64 f = w * (f64) j; 1230 const f64 f = w * (f64) j;
1231 1231
1232 column[0][j] = control[0].getInterpolated_quadratic(control[3], control[6], f ); 1232 column[0][j] = control[0].getInterpolated_quadratic(control[3], control[6], f );
1233 column[1][j] = control[1].getInterpolated_quadratic(control[4], control[7], f ); 1233 column[1][j] = control[1].getInterpolated_quadratic(control[4], control[7], f );
1234 column[2][j] = control[2].getInterpolated_quadratic(control[5], control[8], f ); 1234 column[2][j] = control[2].getInterpolated_quadratic(control[5], control[8], f );
1235 } 1235 }
1236 1236
1237 const u32 idx = Patch->Vertices.size(); 1237 const u32 idx = Patch->Vertices.size();
1238 Patch->Vertices.reallocate(idx+level*level); 1238 Patch->Vertices.reallocate(idx+level*level);
1239 //Tesselate across the rows to get final vertices 1239 //Tesselate across the rows to get final vertices
1240 video::S3DVertex2TCoords v; 1240 video::S3DVertex2TCoords v;
1241 S3DVertex2TCoords_64 f; 1241 S3DVertex2TCoords_64 f;
1242 for( j = 0; j <= level; ++j) 1242 for( j = 0; j <= level; ++j)
1243 { 1243 {
1244 for( k = 0; k <= level; ++k) 1244 for( k = 0; k <= level; ++k)
1245 { 1245 {
1246 f = column[0][j].getInterpolated_quadratic(column[1][j], column[2][j], w * (f64) k); 1246 f = column[0][j].getInterpolated_quadratic(column[1][j], column[2][j], w * (f64) k);
1247 f.copy( v ); 1247 f.copy( v );
1248 Patch->Vertices.push_back( v ); 1248 Patch->Vertices.push_back( v );
1249 } 1249 }
1250 } 1250 }
1251 1251
1252 Patch->Indices.reallocate(Patch->Indices.size()+6*level*level); 1252 Patch->Indices.reallocate(Patch->Indices.size()+6*level*level);
1253 // connect 1253 // connect
1254 for( j = 0; j < level; ++j) 1254 for( j = 0; j < level; ++j)
1255 { 1255 {
1256 for( k = 0; k < level; ++k) 1256 for( k = 0; k < level; ++k)
1257 { 1257 {
1258 const s32 inx = idx + ( k * ( level + 1 ) ) + j; 1258 const s32 inx = idx + ( k * ( level + 1 ) ) + j;
1259 1259
1260 Patch->Indices.push_back( inx + 0 ); 1260 Patch->Indices.push_back( inx + 0 );
1261 Patch->Indices.push_back( inx + (level + 1 ) + 0 ); 1261 Patch->Indices.push_back( inx + (level + 1 ) + 0 );
1262 Patch->Indices.push_back( inx + (level + 1 ) + 1 ); 1262 Patch->Indices.push_back( inx + (level + 1 ) + 1 );
1263 1263
1264 Patch->Indices.push_back( inx + 0 ); 1264 Patch->Indices.push_back( inx + 0 );
1265 Patch->Indices.push_back( inx + (level + 1 ) + 1 ); 1265 Patch->Indices.push_back( inx + (level + 1 ) + 1 );
1266 Patch->Indices.push_back( inx + 1 ); 1266 Patch->Indices.push_back( inx + 1 );
1267 } 1267 }
1268 } 1268 }
1269} 1269}
1270 1270
1271 1271
1272/*! 1272/*!
1273 no subdivision 1273 no subdivision
1274*/ 1274*/
1275void CQ3LevelMesh::createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, 1275void CQ3LevelMesh::createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer,
1276 s32 faceIndex, 1276 s32 faceIndex,
1277 s32 patchTesselation, 1277 s32 patchTesselation,
1278 s32 storevertexcolor) 1278 s32 storevertexcolor)
1279{ 1279{
1280 tBSPFace * face = &Faces[faceIndex]; 1280 tBSPFace * face = &Faces[faceIndex];
1281 u32 j,k,m; 1281 u32 j,k,m;
1282 1282
1283 // number of control points across & up 1283 // number of control points across & up
1284 const u32 controlWidth = face->size[0]; 1284 const u32 controlWidth = face->size[0];
1285 const u32 controlHeight = face->size[1]; 1285 const u32 controlHeight = face->size[1];
1286 if ( 0 == controlWidth || 0 == controlHeight ) 1286 if ( 0 == controlWidth || 0 == controlHeight )
1287 return; 1287 return;
1288 1288
1289 video::S3DVertex2TCoords v; 1289 video::S3DVertex2TCoords v;
1290 1290
1291 m = meshBuffer->Vertices.size(); 1291 m = meshBuffer->Vertices.size();
1292 meshBuffer->Vertices.reallocate(m+controlHeight * controlWidth); 1292 meshBuffer->Vertices.reallocate(m+controlHeight * controlWidth);
1293 for ( j = 0; j!= controlHeight * controlWidth; ++j ) 1293 for ( j = 0; j!= controlHeight * controlWidth; ++j )
1294 { 1294 {
1295 copy( &v, &Vertices [ face->vertexIndex + j ], storevertexcolor ); 1295 copy( &v, &Vertices [ face->vertexIndex + j ], storevertexcolor );
1296 meshBuffer->Vertices.push_back( v ); 1296 meshBuffer->Vertices.push_back( v );
1297 } 1297 }
1298 1298
1299 meshBuffer->Indices.reallocate(meshBuffer->Indices.size()+6*(controlHeight-1) * (controlWidth-1)); 1299 meshBuffer->Indices.reallocate(meshBuffer->Indices.size()+6*(controlHeight-1) * (controlWidth-1));
1300 for ( j = 0; j!= controlHeight - 1; ++j ) 1300 for ( j = 0; j!= controlHeight - 1; ++j )
1301 { 1301 {
1302 for ( k = 0; k!= controlWidth - 1; ++k ) 1302 for ( k = 0; k!= controlWidth - 1; ++k )
1303 { 1303 {
1304 meshBuffer->Indices.push_back( m + k + 0 ); 1304 meshBuffer->Indices.push_back( m + k + 0 );
1305 meshBuffer->Indices.push_back( m + k + controlWidth + 0 ); 1305 meshBuffer->Indices.push_back( m + k + controlWidth + 0 );
1306 meshBuffer->Indices.push_back( m + k + controlWidth + 1 ); 1306 meshBuffer->Indices.push_back( m + k + controlWidth + 1 );
1307 1307
1308 meshBuffer->Indices.push_back( m + k + 0 ); 1308 meshBuffer->Indices.push_back( m + k + 0 );
1309 meshBuffer->Indices.push_back( m + k + controlWidth + 1 ); 1309 meshBuffer->Indices.push_back( m + k + controlWidth + 1 );
1310 meshBuffer->Indices.push_back( m + k + 1 ); 1310 meshBuffer->Indices.push_back( m + k + 1 );
1311 } 1311 }
1312 m += controlWidth; 1312 m += controlWidth;
1313 } 1313 }
1314} 1314}
1315 1315
1316 1316
1317/*! 1317/*!
1318*/ 1318*/
1319void CQ3LevelMesh::createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, 1319void CQ3LevelMesh::createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer,
1320 s32 faceIndex, 1320 s32 faceIndex,
1321 s32 patchTesselation, 1321 s32 patchTesselation,
1322 s32 storevertexcolor) 1322 s32 storevertexcolor)
1323{ 1323{
1324 1324
1325 tBSPFace * face = &Faces[faceIndex]; 1325 tBSPFace * face = &Faces[faceIndex];
1326 u32 j,k; 1326 u32 j,k;
1327 1327
1328 // number of control points across & up 1328 // number of control points across & up
1329 const u32 controlWidth = face->size[0]; 1329 const u32 controlWidth = face->size[0];
1330 const u32 controlHeight = face->size[1]; 1330 const u32 controlHeight = face->size[1];
1331 1331
1332 if ( 0 == controlWidth || 0 == controlHeight ) 1332 if ( 0 == controlWidth || 0 == controlHeight )
1333 return; 1333 return;
1334 1334
1335 // number of biquadratic patches 1335 // number of biquadratic patches
1336 const u32 biquadWidth = (controlWidth - 1)/2; 1336 const u32 biquadWidth = (controlWidth - 1)/2;
1337 const u32 biquadHeight = (controlHeight -1)/2; 1337 const u32 biquadHeight = (controlHeight -1)/2;
1338 1338
1339 if ( LoadParam.verbose > 1 ) 1339 if ( LoadParam.verbose > 1 )
1340 { 1340 {
1341 LoadParam.startTime = os::Timer::getRealTime(); 1341 LoadParam.startTime = os::Timer::getRealTime();
1342 } 1342 }
1343 1343
1344 // Create space for a temporary array of the patch's control points 1344 // Create space for a temporary array of the patch's control points
1345 core::array<S3DVertex2TCoords_64> controlPoint; 1345 core::array<S3DVertex2TCoords_64> controlPoint;
1346 controlPoint.set_used( controlWidth * controlHeight ); 1346 controlPoint.set_used( controlWidth * controlHeight );
1347 1347
1348 for( j = 0; j < controlPoint.size(); ++j) 1348 for( j = 0; j < controlPoint.size(); ++j)
1349 { 1349 {
1350 copy( &controlPoint[j], &Vertices [ face->vertexIndex + j ], storevertexcolor ); 1350 copy( &controlPoint[j], &Vertices [ face->vertexIndex + j ], storevertexcolor );
1351 } 1351 }
1352 1352
1353 // create a temporary patch 1353 // create a temporary patch
1354 Bezier.Patch = new scene::SMeshBufferLightMap(); 1354 Bezier.Patch = new scene::SMeshBufferLightMap();
1355 1355
1356 //Loop through the biquadratic patches 1356 //Loop through the biquadratic patches
1357 for( j = 0; j < biquadHeight; ++j) 1357 for( j = 0; j < biquadHeight; ++j)
1358 { 1358 {
1359 for( k = 0; k < biquadWidth; ++k) 1359 for( k = 0; k < biquadWidth; ++k)
1360 { 1360 {
1361 // set up this patch 1361 // set up this patch
1362 const s32 inx = j*controlWidth*2 + k*2; 1362 const s32 inx = j*controlWidth*2 + k*2;
1363 1363
1364 // setup bezier control points for this patch 1364 // setup bezier control points for this patch
1365 Bezier.control[0] = controlPoint[ inx + 0]; 1365 Bezier.control[0] = controlPoint[ inx + 0];
1366 Bezier.control[1] = controlPoint[ inx + 1]; 1366 Bezier.control[1] = controlPoint[ inx + 1];
1367 Bezier.control[2] = controlPoint[ inx + 2]; 1367 Bezier.control[2] = controlPoint[ inx + 2];
1368 Bezier.control[3] = controlPoint[ inx + controlWidth + 0 ]; 1368 Bezier.control[3] = controlPoint[ inx + controlWidth + 0 ];
1369 Bezier.control[4] = controlPoint[ inx + controlWidth + 1 ]; 1369 Bezier.control[4] = controlPoint[ inx + controlWidth + 1 ];
1370 Bezier.control[5] = controlPoint[ inx + controlWidth + 2 ]; 1370 Bezier.control[5] = controlPoint[ inx + controlWidth + 2 ];
1371 Bezier.control[6] = controlPoint[ inx + controlWidth * 2 + 0]; 1371 Bezier.control[6] = controlPoint[ inx + controlWidth * 2 + 0];
1372 Bezier.control[7] = controlPoint[ inx + controlWidth * 2 + 1]; 1372 Bezier.control[7] = controlPoint[ inx + controlWidth * 2 + 1];
1373 Bezier.control[8] = controlPoint[ inx + controlWidth * 2 + 2]; 1373 Bezier.control[8] = controlPoint[ inx + controlWidth * 2 + 2];
1374 1374
1375 Bezier.tesselate( patchTesselation ); 1375 Bezier.tesselate( patchTesselation );
1376 } 1376 }
1377 } 1377 }
1378 1378
1379 // stitch together with existing geometry 1379 // stitch together with existing geometry
1380 // TODO: only border needs to be checked 1380 // TODO: only border needs to be checked
1381 const u32 bsize = Bezier.Patch->getVertexCount(); 1381 const u32 bsize = Bezier.Patch->getVertexCount();
1382 const u32 msize = meshBuffer->getVertexCount(); 1382 const u32 msize = meshBuffer->getVertexCount();
1383/* 1383/*
1384 for ( j = 0; j!= bsize; ++j ) 1384 for ( j = 0; j!= bsize; ++j )
1385 { 1385 {
1386 const core::vector3df &v = Bezier.Patch->Vertices[j].Pos; 1386 const core::vector3df &v = Bezier.Patch->Vertices[j].Pos;
1387 1387
1388 for ( k = 0; k!= msize; ++k ) 1388 for ( k = 0; k!= msize; ++k )
1389 { 1389 {
1390 const core::vector3df &m = meshBuffer->Vertices[k].Pos; 1390 const core::vector3df &m = meshBuffer->Vertices[k].Pos;
1391 1391
1392 if ( !v.equals( m, tolerance ) ) 1392 if ( !v.equals( m, tolerance ) )
1393 continue; 1393 continue;
1394 1394
1395 meshBuffer->Vertices[k].Pos = v; 1395 meshBuffer->Vertices[k].Pos = v;
1396 //Bezier.Patch->Vertices[j].Pos = m; 1396 //Bezier.Patch->Vertices[j].Pos = m;
1397 } 1397 }
1398 } 1398 }
1399*/ 1399*/
1400 1400
1401 // add Patch to meshbuffer 1401 // add Patch to meshbuffer
1402 meshBuffer->Vertices.reallocate(msize+bsize); 1402 meshBuffer->Vertices.reallocate(msize+bsize);
1403 for ( j = 0; j!= bsize; ++j ) 1403 for ( j = 0; j!= bsize; ++j )
1404 { 1404 {
1405 meshBuffer->Vertices.push_back( Bezier.Patch->Vertices[j] ); 1405 meshBuffer->Vertices.push_back( Bezier.Patch->Vertices[j] );
1406 } 1406 }
1407 1407
1408 // add indices to meshbuffer 1408 // add indices to meshbuffer
1409 meshBuffer->Indices.reallocate(meshBuffer->getIndexCount()+Bezier.Patch->getIndexCount()); 1409 meshBuffer->Indices.reallocate(meshBuffer->getIndexCount()+Bezier.Patch->getIndexCount());
1410 for ( j = 0; j!= Bezier.Patch->getIndexCount(); ++j ) 1410 for ( j = 0; j!= Bezier.Patch->getIndexCount(); ++j )
1411 { 1411 {
1412 meshBuffer->Indices.push_back( msize + Bezier.Patch->Indices[j] ); 1412 meshBuffer->Indices.push_back( msize + Bezier.Patch->Indices[j] );
1413 } 1413 }
1414 1414
1415 delete Bezier.Patch; 1415 delete Bezier.Patch;
1416 1416
1417 if ( LoadParam.verbose > 1 ) 1417 if ( LoadParam.verbose > 1 )
1418 { 1418 {
1419 LoadParam.endTime = os::Timer::getRealTime(); 1419 LoadParam.endTime = os::Timer::getRealTime();
1420 1420
1421 snprintf( buf, sizeof ( buf ), 1421 snprintf( buf, sizeof ( buf ),
1422 "quake3::createCurvedSurface_bezier needed %04d ms to create bezier patch.(%dx%d)", 1422 "quake3::createCurvedSurface_bezier needed %04d ms to create bezier patch.(%dx%d)",
1423 LoadParam.endTime - LoadParam.startTime, 1423 LoadParam.endTime - LoadParam.startTime,
1424 biquadWidth, 1424 biquadWidth,
1425 biquadHeight 1425 biquadHeight
1426 ); 1426 );
1427 os::Printer::log(buf, ELL_INFORMATION); 1427 os::Printer::log(buf, ELL_INFORMATION);
1428 } 1428 }
1429 1429
1430} 1430}
1431 1431
1432 1432
1433 1433
1434/*! 1434/*!
1435 Loads entities from file 1435 Loads entities from file
1436*/ 1436*/
1437void CQ3LevelMesh::getConfiguration( io::IReadFile* file ) 1437void CQ3LevelMesh::getConfiguration( io::IReadFile* file )
1438{ 1438{
1439 tBSPLump l; 1439 tBSPLump l;
1440 l.offset = file->getPos(); 1440 l.offset = file->getPos();
1441 l.length = file->getSize (); 1441 l.length = file->getSize ();
1442 1442
1443 core::array<u8> entity; 1443 core::array<u8> entity;
1444 entity.set_used( l.length + 2 ); 1444 entity.set_used( l.length + 2 );
1445 entity[l.length + 1 ] = 0; 1445 entity[l.length + 1 ] = 0;
1446 1446
1447 file->seek(l.offset); 1447 file->seek(l.offset);
1448 file->read( entity.pointer(), l.length); 1448 file->read( entity.pointer(), l.length);
1449 1449
1450 parser_parse( entity.pointer(), l.length, &CQ3LevelMesh::scriptcallback_config ); 1450 parser_parse( entity.pointer(), l.length, &CQ3LevelMesh::scriptcallback_config );
1451 1451
1452 if ( Entity.size () ) 1452 if ( Entity.size () )
1453 Entity.getLast().name = file->getFileName(); 1453 Entity.getLast().name = file->getFileName();
1454} 1454}
1455 1455
1456 1456
1457//! get's an interface to the entities 1457//! get's an interface to the entities
1458tQ3EntityList & CQ3LevelMesh::getEntityList() 1458tQ3EntityList & CQ3LevelMesh::getEntityList()
1459{ 1459{
1460// Entity.sort(); 1460// Entity.sort();
1461 return Entity; 1461 return Entity;
1462} 1462}
1463 1463
1464//! returns the requested brush entity 1464//! returns the requested brush entity
1465IMesh* CQ3LevelMesh::getBrushEntityMesh(s32 num) const 1465IMesh* CQ3LevelMesh::getBrushEntityMesh(s32 num) const
1466{ 1466{
1467 if (num < 1 || num >= NumModels) 1467 if (num < 1 || num >= NumModels)
1468 return 0; 1468 return 0;
1469 1469
1470 return BrushEntities[num]; 1470 return BrushEntities[num];
1471} 1471}
1472 1472
1473//! returns the requested brush entity 1473//! returns the requested brush entity
1474IMesh* CQ3LevelMesh::getBrushEntityMesh(quake3::IEntity &ent) const 1474IMesh* CQ3LevelMesh::getBrushEntityMesh(quake3::IEntity &ent) const
1475{ 1475{
1476 // This is a helper function to parse the entity, 1476 // This is a helper function to parse the entity,
1477 // so you don't have to. 1477 // so you don't have to.
1478 1478
1479 s32 num; 1479 s32 num;
1480 1480
1481 const quake3::SVarGroup* group = ent.getGroup(1); 1481 const quake3::SVarGroup* group = ent.getGroup(1);
1482 const core::stringc& modnum = group->get("model"); 1482 const core::stringc& modnum = group->get("model");
1483 1483
1484 if (!group->isDefined("model")) 1484 if (!group->isDefined("model"))
1485 return 0; 1485 return 0;
1486 1486
1487 const char *temp = modnum.c_str() + 1; // We skip the first character. 1487 const char *temp = modnum.c_str() + 1; // We skip the first character.
1488 num = core::strtol10(temp); 1488 num = core::strtol10(temp);
1489 1489
1490 return getBrushEntityMesh(num); 1490 return getBrushEntityMesh(num);
1491} 1491}
1492 1492
1493 1493
1494/*! 1494/*!
1495*/ 1495*/
1496const IShader * CQ3LevelMesh::getShader(u32 index) const 1496const IShader * CQ3LevelMesh::getShader(u32 index) const
1497{ 1497{
1498 index &= 0xFFFF; 1498 index &= 0xFFFF;
1499 1499
1500 if ( index < Shader.size() ) 1500 if ( index < Shader.size() )
1501 { 1501 {
1502 return &Shader[index]; 1502 return &Shader[index];
1503 } 1503 }
1504 1504
1505 return 0; 1505 return 0;
1506} 1506}
1507 1507
1508 1508
1509/*! 1509/*!
1510 loads the shader definition 1510 loads the shader definition
1511*/ 1511*/
1512const IShader* CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) 1512const IShader* CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid )
1513{ 1513{
1514 core::stringc searchName ( filename ); 1514 core::stringc searchName ( filename );
1515 1515
1516 IShader search; 1516 IShader search;
1517 search.name = searchName; 1517 search.name = searchName;
1518 search.name.replace( '\\', '/' ); 1518 search.name.replace( '\\', '/' );
1519 search.name.make_lower(); 1519 search.name.make_lower();
1520 1520
1521 1521
1522 core::stringc message; 1522 core::stringc message;
1523 s32 index; 1523 s32 index;
1524 1524
1525 //! is Shader already in cache? 1525 //! is Shader already in cache?
1526 index = Shader.linear_search( search ); 1526 index = Shader.linear_search( search );
1527 if ( index >= 0 ) 1527 if ( index >= 0 )
1528 { 1528 {
1529 if ( LoadParam.verbose > 1 ) 1529 if ( LoadParam.verbose > 1 )
1530 { 1530 {
1531 message = searchName + " found " + Shader[index].name; 1531 message = searchName + " found " + Shader[index].name;
1532 os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); 1532 os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION);
1533 } 1533 }
1534 1534
1535 return &Shader[index]; 1535 return &Shader[index];
1536 } 1536 }
1537 1537
1538 io::path loadFile; 1538 io::path loadFile;
1539 1539
1540 if ( !fileNameIsValid ) 1540 if ( !fileNameIsValid )
1541 { 1541 {
1542 // extract the shader name from the last path component in filename 1542 // extract the shader name from the last path component in filename
1543 // "scripts/[name].shader" 1543 // "scripts/[name].shader"
1544 core::stringc cut( search.name ); 1544 core::stringc cut( search.name );
1545 1545
1546 s32 end = cut.findLast( '/' ); 1546 s32 end = cut.findLast( '/' );
1547 s32 start = cut.findLast( '/', end - 1 ); 1547 s32 start = cut.findLast( '/', end - 1 );
1548 1548
1549 loadFile = LoadParam.scriptDir; 1549 loadFile = LoadParam.scriptDir;
1550 loadFile.append( cut.subString( start, end - start ) ); 1550 loadFile.append( cut.subString( start, end - start ) );
1551 loadFile.append( ".shader" ); 1551 loadFile.append( ".shader" );
1552 } 1552 }
1553 else 1553 else
1554 { 1554 {
1555 loadFile = search.name; 1555 loadFile = search.name;
1556 } 1556 }
1557 1557
1558 // already loaded the file ? 1558 // already loaded the file ?
1559 index = ShaderFile.binary_search( loadFile ); 1559 index = ShaderFile.binary_search( loadFile );
1560 if ( index >= 0 ) 1560 if ( index >= 0 )
1561 return 0; 1561 return 0;
1562 1562
1563 // add file to loaded files 1563 // add file to loaded files
1564 ShaderFile.push_back( loadFile ); 1564 ShaderFile.push_back( loadFile );
1565 1565
1566 if ( !FileSystem->existFile( loadFile.c_str() ) ) 1566 if ( !FileSystem->existFile( loadFile.c_str() ) )
1567 { 1567 {
1568 if ( LoadParam.verbose > 1 ) 1568 if ( LoadParam.verbose > 1 )
1569 { 1569 {
1570 message = loadFile + " for " + searchName + " failed "; 1570 message = loadFile + " for " + searchName + " failed ";
1571 os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); 1571 os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION);
1572 } 1572 }
1573 return 0; 1573 return 0;
1574 } 1574 }
1575 1575
1576 if ( LoadParam.verbose ) 1576 if ( LoadParam.verbose )
1577 { 1577 {
1578 message = loadFile + " for " + searchName; 1578 message = loadFile + " for " + searchName;
1579 os::Printer::log("quake3:getShader Load shader", message.c_str(), ELL_INFORMATION); 1579 os::Printer::log("quake3:getShader Load shader", message.c_str(), ELL_INFORMATION);
1580 } 1580 }
1581 1581
1582 1582
1583 io::IReadFile *file = FileSystem->createAndOpenFile( loadFile.c_str() ); 1583 io::IReadFile *file = FileSystem->createAndOpenFile( loadFile.c_str() );
1584 if ( file ) 1584 if ( file )
1585 { 1585 {
1586 getShader ( file ); 1586 getShader ( file );
1587 file->drop (); 1587 file->drop ();
1588 } 1588 }
1589 1589
1590 1590
1591 // search again 1591 // search again
1592 index = Shader.linear_search( search ); 1592 index = Shader.linear_search( search );
1593 return index >= 0 ? &Shader[index] : 0; 1593 return index >= 0 ? &Shader[index] : 0;
1594} 1594}
1595 1595
1596/*! 1596/*!
1597 loads the shader definition 1597 loads the shader definition
1598*/ 1598*/
1599void CQ3LevelMesh::getShader( io::IReadFile* file ) 1599void CQ3LevelMesh::getShader( io::IReadFile* file )
1600{ 1600{
1601 if ( 0 == file ) 1601 if ( 0 == file )
1602 return; 1602 return;
1603 1603
1604 // load script 1604 // load script
1605 core::array<u8> script; 1605 core::array<u8> script;
1606 const long len = file->getSize(); 1606 const long len = file->getSize();
1607 1607
1608 script.set_used( len + 2 ); 1608 script.set_used( len + 2 );
1609 1609
1610 file->seek( 0 ); 1610 file->seek( 0 );
1611 file->read( script.pointer(), len ); 1611 file->read( script.pointer(), len );
1612 script[ len + 1 ] = 0; 1612 script[ len + 1 ] = 0;
1613 1613
1614 // start a parser instance 1614 // start a parser instance
1615 parser_parse( script.pointer(), len, &CQ3LevelMesh::scriptcallback_shader ); 1615 parser_parse( script.pointer(), len, &CQ3LevelMesh::scriptcallback_shader );
1616} 1616}
1617 1617
1618 1618
1619//! adding default shaders 1619//! adding default shaders
1620void CQ3LevelMesh::InitShader() 1620void CQ3LevelMesh::InitShader()
1621{ 1621{
1622 ReleaseShader(); 1622 ReleaseShader();
1623 1623
1624 IShader element; 1624 IShader element;
1625 1625
1626 SVarGroup group; 1626 SVarGroup group;
1627 SVariable variable ( "noshader" ); 1627 SVariable variable ( "noshader" );
1628 1628
1629 group.Variable.push_back( variable ); 1629 group.Variable.push_back( variable );
1630 1630
1631 element.VarGroup = new SVarGroupList(); 1631 element.VarGroup = new SVarGroupList();
1632 element.VarGroup->VariableGroup.push_back( group ); 1632 element.VarGroup->VariableGroup.push_back( group );
1633 element.VarGroup->VariableGroup.push_back( SVarGroup() ); 1633 element.VarGroup->VariableGroup.push_back( SVarGroup() );
1634 element.name = element.VarGroup->VariableGroup[0].Variable[0].name; 1634 element.name = element.VarGroup->VariableGroup[0].Variable[0].name;
1635 element.ID = Shader.size(); 1635 element.ID = Shader.size();
1636 Shader.push_back( element ); 1636 Shader.push_back( element );
1637 1637
1638 if ( LoadParam.loadAllShaders ) 1638 if ( LoadParam.loadAllShaders )
1639 { 1639 {
1640 io::EFileSystemType current = FileSystem->setFileListSystem ( io::FILESYSTEM_VIRTUAL ); 1640 io::EFileSystemType current = FileSystem->setFileListSystem ( io::FILESYSTEM_VIRTUAL );
1641 io::path save = FileSystem->getWorkingDirectory(); 1641 io::path save = FileSystem->getWorkingDirectory();
1642 1642
1643 io::path newDir; 1643 io::path newDir;
1644 newDir = "/"; 1644 newDir = "/";
1645 newDir += LoadParam.scriptDir; 1645 newDir += LoadParam.scriptDir;
1646 newDir += "/"; 1646 newDir += "/";
1647 FileSystem->changeWorkingDirectoryTo ( newDir.c_str() ); 1647 FileSystem->changeWorkingDirectoryTo ( newDir.c_str() );
1648 1648
1649 core::stringc s; 1649 core::stringc s;
1650 io::IFileList *fileList = FileSystem->createFileList (); 1650 io::IFileList *fileList = FileSystem->createFileList ();
1651 for (u32 i=0; i< fileList->getFileCount(); ++i) 1651 for (u32 i=0; i< fileList->getFileCount(); ++i)
1652 { 1652 {
1653 s = fileList->getFullFileName(i); 1653 s = fileList->getFullFileName(i);
1654 if ( s.find ( ".shader" ) >= 0 ) 1654 if ( s.find ( ".shader" ) >= 0 )
1655 { 1655 {
1656 if ( 0 == LoadParam.loadSkyShader && s.find ( "sky.shader" ) >= 0 ) 1656 if ( 0 == LoadParam.loadSkyShader && s.find ( "sky.shader" ) >= 0 )
1657 { 1657 {
1658 } 1658 }
1659 else 1659 else
1660 { 1660 {
1661 getShader ( s.c_str () ); 1661 getShader ( s.c_str () );
1662 } 1662 }
1663 } 1663 }
1664 } 1664 }
1665 fileList->drop (); 1665 fileList->drop ();
1666 1666
1667 FileSystem->changeWorkingDirectoryTo ( save ); 1667 FileSystem->changeWorkingDirectoryTo ( save );
1668 FileSystem->setFileListSystem ( current ); 1668 FileSystem->setFileListSystem ( current );
1669 } 1669 }
1670} 1670}
1671 1671
1672 1672
1673//! script callback for shaders 1673//! script callback for shaders
1674//! i'm having troubles with the reference counting, during callback.. resorting.. 1674//! i'm having troubles with the reference counting, during callback.. resorting..
1675void CQ3LevelMesh::ReleaseShader() 1675void CQ3LevelMesh::ReleaseShader()
1676{ 1676{
1677 for ( u32 i = 0; i!= Shader.size(); ++i ) 1677 for ( u32 i = 0; i!= Shader.size(); ++i )
1678 { 1678 {
1679 Shader[i].VarGroup->drop(); 1679 Shader[i].VarGroup->drop();
1680 } 1680 }
1681 Shader.clear(); 1681 Shader.clear();
1682 ShaderFile.clear(); 1682 ShaderFile.clear();
1683} 1683}
1684 1684
1685 1685
1686/*! 1686/*!
1687*/ 1687*/
1688void CQ3LevelMesh::ReleaseEntity() 1688void CQ3LevelMesh::ReleaseEntity()
1689{ 1689{
1690 for ( u32 i = 0; i!= Entity.size(); ++i ) 1690 for ( u32 i = 0; i!= Entity.size(); ++i )
1691 { 1691 {
1692 Entity[i].VarGroup->drop(); 1692 Entity[i].VarGroup->drop();
1693 } 1693 }
1694 Entity.clear(); 1694 Entity.clear();
1695} 1695}
1696 1696
1697 1697
1698// config in simple (quake3) and advanced style 1698// config in simple (quake3) and advanced style
1699void CQ3LevelMesh::scriptcallback_config( SVarGroupList *& grouplist, eToken token ) 1699void CQ3LevelMesh::scriptcallback_config( SVarGroupList *& grouplist, eToken token )
1700{ 1700{
1701 IShader element; 1701 IShader element;
1702 1702
1703 if ( token == Q3_TOKEN_END_LIST ) 1703 if ( token == Q3_TOKEN_END_LIST )
1704 { 1704 {
1705 if ( 0 == grouplist->VariableGroup[0].Variable.size() ) 1705 if ( 0 == grouplist->VariableGroup[0].Variable.size() )
1706 return; 1706 return;
1707 1707
1708 element.name = grouplist->VariableGroup[0].Variable[0].name; 1708 element.name = grouplist->VariableGroup[0].Variable[0].name;
1709 } 1709 }
1710 else 1710 else
1711 { 1711 {
1712 if ( grouplist->VariableGroup.size() != 2 ) 1712 if ( grouplist->VariableGroup.size() != 2 )
1713 return; 1713 return;
1714 1714
1715 element.name = "configuration"; 1715 element.name = "configuration";
1716 } 1716 }
1717 1717
1718 grouplist->grab(); 1718 grouplist->grab();
1719 element.VarGroup = grouplist; 1719 element.VarGroup = grouplist;
1720 element.ID = Entity.size(); 1720 element.ID = Entity.size();
1721 Entity.push_back( element ); 1721 Entity.push_back( element );
1722} 1722}
1723 1723
1724 1724
1725// entity only has only one valid level.. and no assoziative name.. 1725// entity only has only one valid level.. and no assoziative name..
1726void CQ3LevelMesh::scriptcallback_entity( SVarGroupList *& grouplist, eToken token ) 1726void CQ3LevelMesh::scriptcallback_entity( SVarGroupList *& grouplist, eToken token )
1727{ 1727{
1728 if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup.size() != 2 ) 1728 if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup.size() != 2 )
1729 return; 1729 return;
1730 1730
1731 grouplist->grab(); 1731 grouplist->grab();
1732 1732
1733 IEntity element; 1733 IEntity element;
1734 element.VarGroup = grouplist; 1734 element.VarGroup = grouplist;
1735 element.ID = Entity.size(); 1735 element.ID = Entity.size();
1736 element.name = grouplist->VariableGroup[1].get( "classname" ); 1736 element.name = grouplist->VariableGroup[1].get( "classname" );
1737 1737
1738 1738
1739 Entity.push_back( element ); 1739 Entity.push_back( element );
1740} 1740}
1741 1741
1742 1742
1743//!. script callback for shaders 1743//!. script callback for shaders
1744void CQ3LevelMesh::scriptcallback_shader( SVarGroupList *& grouplist,eToken token ) 1744void CQ3LevelMesh::scriptcallback_shader( SVarGroupList *& grouplist,eToken token )
1745{ 1745{
1746 if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup[0].Variable.size()==0) 1746 if ( token != Q3_TOKEN_END_LIST || grouplist->VariableGroup[0].Variable.size()==0)
1747 return; 1747 return;
1748 1748
1749 1749
1750 IShader element; 1750 IShader element;
1751 1751
1752 grouplist->grab(); 1752 grouplist->grab();
1753 element.VarGroup = grouplist; 1753 element.VarGroup = grouplist;
1754 element.name = element.VarGroup->VariableGroup[0].Variable[0].name; 1754 element.name = element.VarGroup->VariableGroup[0].Variable[0].name;
1755 element.ID = Shader.size(); 1755 element.ID = Shader.size();
1756/* 1756/*
1757 core::stringc s; 1757 core::stringc s;
1758 dumpShader ( s, &element ); 1758 dumpShader ( s, &element );
1759 printf ( s.c_str () ); 1759 printf ( s.c_str () );
1760*/ 1760*/
1761 Shader.push_back( element ); 1761 Shader.push_back( element );
1762} 1762}
1763 1763
1764 1764
1765/*! 1765/*!
1766 delete all buffers without geometry in it. 1766 delete all buffers without geometry in it.
1767*/ 1767*/
1768void CQ3LevelMesh::cleanMeshes() 1768void CQ3LevelMesh::cleanMeshes()
1769{ 1769{
1770 if ( 0 == LoadParam.cleanUnResolvedMeshes ) 1770 if ( 0 == LoadParam.cleanUnResolvedMeshes )
1771 return; 1771 return;
1772 1772
1773 s32 i; 1773 s32 i;
1774 1774
1775 // First the main level 1775 // First the main level
1776 for (i = 0; i < E_Q3_MESH_SIZE; i++) 1776 for (i = 0; i < E_Q3_MESH_SIZE; i++)
1777 { 1777 {
1778 bool texture0important = ( i == 0 ); 1778 bool texture0important = ( i == 0 );
1779 1779
1780 cleanMesh(Mesh[i], texture0important); 1780 cleanMesh(Mesh[i], texture0important);
1781 } 1781 }
1782 1782
1783 // Then the brush entities 1783 // Then the brush entities
1784 for (i = 1; i < NumModels; i++) 1784 for (i = 1; i < NumModels; i++)
1785 { 1785 {
1786 cleanMesh(BrushEntities[i], true); 1786 cleanMesh(BrushEntities[i], true);
1787 } 1787 }
1788} 1788}
1789 1789
1790void CQ3LevelMesh::cleanMesh(SMesh *m, const bool texture0important) 1790void CQ3LevelMesh::cleanMesh(SMesh *m, const bool texture0important)
1791{ 1791{
1792 // delete all buffers without geometry in it. 1792 // delete all buffers without geometry in it.
1793 u32 run = 0; 1793 u32 run = 0;
1794 u32 remove = 0; 1794 u32 remove = 0;
1795 1795
1796 IMeshBuffer *b; 1796 IMeshBuffer *b;
1797 1797
1798 run = 0; 1798 run = 0;
1799 remove = 0; 1799 remove = 0;
1800 1800
1801 if ( LoadParam.verbose > 0 ) 1801 if ( LoadParam.verbose > 0 )
1802 { 1802 {
1803 LoadParam.startTime = os::Timer::getRealTime(); 1803 LoadParam.startTime = os::Timer::getRealTime();
1804 if ( LoadParam.verbose > 1 ) 1804 if ( LoadParam.verbose > 1 )
1805 { 1805 {
1806 snprintf( buf, sizeof ( buf ), 1806 snprintf( buf, sizeof ( buf ),
1807 "quake3::cleanMeshes start for %d meshes", 1807 "quake3::cleanMeshes start for %d meshes",
1808 m->MeshBuffers.size() 1808 m->MeshBuffers.size()
1809 ); 1809 );
1810 os::Printer::log(buf, ELL_INFORMATION); 1810 os::Printer::log(buf, ELL_INFORMATION);
1811 } 1811 }
1812 } 1812 }
1813 1813
1814 u32 i = 0; 1814 u32 i = 0;
1815 s32 blockstart = -1; 1815 s32 blockstart = -1;
1816 s32 blockcount = 0; 1816 s32 blockcount = 0;
1817 1817
1818 while( i < m->MeshBuffers.size()) 1818 while( i < m->MeshBuffers.size())
1819 { 1819 {
1820 run += 1; 1820 run += 1;
1821 1821
1822 b = m->MeshBuffers[i]; 1822 b = m->MeshBuffers[i];
1823 1823
1824 if ( b->getVertexCount() == 0 || b->getIndexCount() == 0 || 1824 if ( b->getVertexCount() == 0 || b->getIndexCount() == 0 ||
1825 ( texture0important && b->getMaterial().getTexture(0) == 0 ) 1825 ( texture0important && b->getMaterial().getTexture(0) == 0 )
1826 ) 1826 )
1827 { 1827 {
1828 if ( blockstart < 0 ) 1828 if ( blockstart < 0 )
1829 { 1829 {
1830 blockstart = i; 1830 blockstart = i;
1831 blockcount = 0; 1831 blockcount = 0;
1832 } 1832 }
1833 blockcount += 1; 1833 blockcount += 1;
1834 i += 1; 1834 i += 1;
1835 1835
1836 // delete Meshbuffer 1836 // delete Meshbuffer
1837 i -= 1; 1837 i -= 1;
1838 remove += 1; 1838 remove += 1;
1839 b->drop(); 1839 b->drop();
1840 m->MeshBuffers.erase(i); 1840 m->MeshBuffers.erase(i);
1841 } 1841 }
1842 else 1842 else
1843 { 1843 {
1844 // clean blockwise 1844 // clean blockwise
1845 if ( blockstart >= 0 ) 1845 if ( blockstart >= 0 )
1846 { 1846 {
1847 if ( LoadParam.verbose > 1 ) 1847 if ( LoadParam.verbose > 1 )
1848 { 1848 {
1849 snprintf( buf, sizeof ( buf ), 1849 snprintf( buf, sizeof ( buf ),
1850 "quake3::cleanMeshes cleaning mesh %d %d size", 1850 "quake3::cleanMeshes cleaning mesh %d %d size",
1851 blockstart, 1851 blockstart,
1852 blockcount 1852 blockcount
1853 ); 1853 );
1854 os::Printer::log(buf, ELL_INFORMATION); 1854 os::Printer::log(buf, ELL_INFORMATION);
1855 } 1855 }
1856 blockstart = -1; 1856 blockstart = -1;
1857 } 1857 }
1858 i += 1; 1858 i += 1;
1859 } 1859 }
1860 } 1860 }
1861 1861
1862 if ( LoadParam.verbose > 0 ) 1862 if ( LoadParam.verbose > 0 )
1863 { 1863 {
1864 LoadParam.endTime = os::Timer::getRealTime(); 1864 LoadParam.endTime = os::Timer::getRealTime();
1865 snprintf( buf, sizeof ( buf ), 1865 snprintf( buf, sizeof ( buf ),
1866 "quake3::cleanMeshes needed %04d ms to clean %d of %d meshes", 1866 "quake3::cleanMeshes needed %04d ms to clean %d of %d meshes",
1867 LoadParam.endTime - LoadParam.startTime, 1867 LoadParam.endTime - LoadParam.startTime,
1868 remove, 1868 remove,
1869 run 1869 run
1870 ); 1870 );
1871 os::Printer::log(buf, ELL_INFORMATION); 1871 os::Printer::log(buf, ELL_INFORMATION);
1872 } 1872 }
1873} 1873}
1874 1874
1875 1875
1876// recalculate bounding boxes 1876// recalculate bounding boxes
1877void CQ3LevelMesh::calcBoundingBoxes() 1877void CQ3LevelMesh::calcBoundingBoxes()
1878{ 1878{
1879 if ( LoadParam.verbose > 0 ) 1879 if ( LoadParam.verbose > 0 )
1880 { 1880 {
1881 LoadParam.startTime = os::Timer::getRealTime(); 1881 LoadParam.startTime = os::Timer::getRealTime();
1882 1882
1883 if ( LoadParam.verbose > 1 ) 1883 if ( LoadParam.verbose > 1 )
1884 { 1884 {
1885 snprintf( buf, sizeof ( buf ), 1885 snprintf( buf, sizeof ( buf ),
1886 "quake3::calcBoundingBoxes start create %d textures and %d lightmaps", 1886 "quake3::calcBoundingBoxes start create %d textures and %d lightmaps",
1887 NumTextures, 1887 NumTextures,
1888 NumLightMaps 1888 NumLightMaps
1889 ); 1889 );
1890 os::Printer::log(buf, ELL_INFORMATION); 1890 os::Printer::log(buf, ELL_INFORMATION);
1891 } 1891 }
1892 } 1892 }
1893 1893
1894 s32 g; 1894 s32 g;
1895 1895
1896 // create bounding box 1896 // create bounding box
1897 for ( g = 0; g != E_Q3_MESH_SIZE; ++g ) 1897 for ( g = 0; g != E_Q3_MESH_SIZE; ++g )
1898 { 1898 {
1899 for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j) 1899 for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j)
1900 { 1900 {
1901 ((SMeshBufferLightMap*)Mesh[g]->MeshBuffers[j])->recalculateBoundingBox(); 1901 ((SMeshBufferLightMap*)Mesh[g]->MeshBuffers[j])->recalculateBoundingBox();
1902 } 1902 }
1903 1903
1904 Mesh[g]->recalculateBoundingBox(); 1904 Mesh[g]->recalculateBoundingBox();
1905 // Mesh[0] is the main bbox 1905 // Mesh[0] is the main bbox
1906 if (g!=0) 1906 if (g!=0)
1907 Mesh[0]->BoundingBox.addInternalBox(Mesh[g]->getBoundingBox()); 1907 Mesh[0]->BoundingBox.addInternalBox(Mesh[g]->getBoundingBox());
1908 } 1908 }
1909 1909
1910 for (g = 1; g < NumModels; g++) 1910 for (g = 1; g < NumModels; g++)
1911 { 1911 {
1912 for ( u32 j=0; j < BrushEntities[g]->MeshBuffers.size(); ++j) 1912 for ( u32 j=0; j < BrushEntities[g]->MeshBuffers.size(); ++j)
1913 { 1913 {
1914 ((SMeshBufferLightMap*)BrushEntities[g]->MeshBuffers[j])-> 1914 ((SMeshBufferLightMap*)BrushEntities[g]->MeshBuffers[j])->
1915 recalculateBoundingBox(); 1915 recalculateBoundingBox();
1916 } 1916 }
1917 1917
1918 BrushEntities[g]->recalculateBoundingBox(); 1918 BrushEntities[g]->recalculateBoundingBox();
1919 } 1919 }
1920 1920
1921 if ( LoadParam.verbose > 0 ) 1921 if ( LoadParam.verbose > 0 )
1922 { 1922 {
1923 LoadParam.endTime = os::Timer::getRealTime(); 1923 LoadParam.endTime = os::Timer::getRealTime();
1924 1924
1925 snprintf( buf, sizeof ( buf ), 1925 snprintf( buf, sizeof ( buf ),
1926 "quake3::calcBoundingBoxes needed %04d ms to create %d textures and %d lightmaps", 1926 "quake3::calcBoundingBoxes needed %04d ms to create %d textures and %d lightmaps",
1927 LoadParam.endTime - LoadParam.startTime, 1927 LoadParam.endTime - LoadParam.startTime,
1928 NumTextures, 1928 NumTextures,
1929 NumLightMaps 1929 NumLightMaps
1930 ); 1930 );
1931 os::Printer::log( buf, ELL_INFORMATION); 1931 os::Printer::log( buf, ELL_INFORMATION);
1932 } 1932 }
1933} 1933}
1934 1934
1935 1935
1936//! loads the textures 1936//! loads the textures
1937void CQ3LevelMesh::loadTextures() 1937void CQ3LevelMesh::loadTextures()
1938{ 1938{
1939 if (!Driver) 1939 if (!Driver)
1940 return; 1940 return;
1941 1941
1942 if ( LoadParam.verbose > 0 ) 1942 if ( LoadParam.verbose > 0 )
1943 { 1943 {
1944 LoadParam.startTime = os::Timer::getRealTime(); 1944 LoadParam.startTime = os::Timer::getRealTime();
1945 1945
1946 if ( LoadParam.verbose > 1 ) 1946 if ( LoadParam.verbose > 1 )
1947 { 1947 {
1948 snprintf( buf, sizeof ( buf ), 1948 snprintf( buf, sizeof ( buf ),
1949 "quake3::loadTextures start create %d textures and %d lightmaps", 1949 "quake3::loadTextures start create %d textures and %d lightmaps",
1950 NumTextures, 1950 NumTextures,
1951 NumLightMaps 1951 NumLightMaps
1952 ); 1952 );
1953 os::Printer::log( buf, ELL_INFORMATION); 1953 os::Printer::log( buf, ELL_INFORMATION);
1954 } 1954 }
1955 } 1955 }
1956 1956
1957 c8 lightmapname[255]; 1957 c8 lightmapname[255];
1958 s32 t; 1958 s32 t;
1959 1959
1960 // load lightmaps. 1960 // load lightmaps.
1961 Lightmap.set_used(NumLightMaps); 1961 Lightmap.set_used(NumLightMaps);
1962 1962
1963/* 1963/*
1964 bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); 1964 bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
1965 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); 1965 Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
1966*/ 1966*/
1967 core::dimension2d<u32> lmapsize(128,128); 1967 core::dimension2d<u32> lmapsize(128,128);
1968 1968
1969 video::IImage* lmapImg; 1969 video::IImage* lmapImg;
1970 for ( t = 0; t < NumLightMaps ; ++t) 1970 for ( t = 0; t < NumLightMaps ; ++t)
1971 { 1971 {
1972 sprintf(lightmapname, "%s.lightmap.%d", LevelName.c_str(), t); 1972 sprintf(lightmapname, "%s.lightmap.%d", LevelName.c_str(), t);
1973 1973
1974 // lightmap is a CTexture::R8G8B8 format 1974 // lightmap is a CTexture::R8G8B8 format
1975 lmapImg = Driver->createImageFromData( 1975 lmapImg = Driver->createImageFromData(
1976 video::ECF_R8G8B8, lmapsize, 1976 video::ECF_R8G8B8, lmapsize,
1977 LightMaps[t].imageBits, false, true ); 1977 LightMaps[t].imageBits, false, true );
1978 1978
1979 Lightmap[t] = Driver->addTexture( lightmapname, lmapImg ); 1979 Lightmap[t] = Driver->addTexture( lightmapname, lmapImg );
1980 lmapImg->drop(); 1980 lmapImg->drop();
1981 } 1981 }
1982 1982
1983// Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); 1983// Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
1984 1984
1985 // load textures 1985 // load textures
1986 Tex.set_used( NumTextures ); 1986 Tex.set_used( NumTextures );
1987 1987
1988 const IShader* shader; 1988 const IShader* shader;
1989 1989
1990 core::stringc list; 1990 core::stringc list;
1991 io::path check; 1991 io::path check;
1992 tTexArray textureArray; 1992 tTexArray textureArray;
1993 1993
1994 // pre-load shaders 1994 // pre-load shaders
1995 for ( t=0; t< NumTextures; ++t) 1995 for ( t=0; t< NumTextures; ++t)
1996 { 1996 {
1997 shader = getShader(Textures[t].strName, false); 1997 shader = getShader(Textures[t].strName, false);
1998 } 1998 }
1999 1999
2000 for ( t=0; t< NumTextures; ++t) 2000 for ( t=0; t< NumTextures; ++t)
2001 { 2001 {
2002 Tex[t].ShaderID = -1; 2002 Tex[t].ShaderID = -1;
2003 Tex[t].Texture = 0; 2003 Tex[t].Texture = 0;
2004 2004
2005 list = ""; 2005 list = "";
2006 2006
2007 // get a shader ( if one exists ) 2007 // get a shader ( if one exists )
2008 shader = getShader( Textures[t].strName, false); 2008 shader = getShader( Textures[t].strName, false);
2009 if ( shader ) 2009 if ( shader )
2010 { 2010 {
2011 Tex[t].ShaderID = shader->ID; 2011 Tex[t].ShaderID = shader->ID;
2012 2012
2013 // if texture name == stage1 Texture map 2013 // if texture name == stage1 Texture map
2014 const SVarGroup * group; 2014 const SVarGroup * group;
2015 2015
2016 group = shader->getGroup( 2 ); 2016 group = shader->getGroup( 2 );
2017 if ( group ) 2017 if ( group )
2018 { 2018 {
2019 if ( core::cutFilenameExtension( check, group->get( "map" ) ) == Textures[t].strName ) 2019 if ( core::cutFilenameExtension( check, group->get( "map" ) ) == Textures[t].strName )
2020 { 2020 {
2021 list += check; 2021 list += check;
2022 } 2022 }
2023 else 2023 else
2024 if ( check == "$lightmap" ) 2024 if ( check == "$lightmap" )
2025 { 2025 {
2026 // we check if lightmap is in stage 1 and texture in stage 2 2026 // we check if lightmap is in stage 1 and texture in stage 2
2027 group = shader->getGroup( 3 ); 2027 group = shader->getGroup( 3 );
2028 if ( group ) 2028 if ( group )
2029 list += group->get( "map" ); 2029 list += group->get( "map" );
2030 } 2030 }
2031 } 2031 }
2032 } 2032 }
2033 else 2033 else
2034 { 2034 {
2035 // no shader, take it 2035 // no shader, take it
2036 list += Textures[t].strName; 2036 list += Textures[t].strName;
2037 } 2037 }
2038 2038
2039 u32 pos = 0; 2039 u32 pos = 0;
2040 getTextures( textureArray, list, pos, FileSystem, Driver ); 2040 getTextures( textureArray, list, pos, FileSystem, Driver );
2041 2041
2042 Tex[t].Texture = textureArray[0]; 2042 Tex[t].Texture = textureArray[0];
2043 } 2043 }
2044 2044
2045 if ( LoadParam.verbose > 0 ) 2045 if ( LoadParam.verbose > 0 )
2046 { 2046 {
2047 LoadParam.endTime = os::Timer::getRealTime(); 2047 LoadParam.endTime = os::Timer::getRealTime();
2048 2048
2049 snprintf( buf, sizeof ( buf ), 2049 snprintf( buf, sizeof ( buf ),
2050 "quake3::loadTextures needed %04d ms to create %d textures and %d lightmaps", 2050 "quake3::loadTextures needed %04d ms to create %d textures and %d lightmaps",
2051 LoadParam.endTime - LoadParam.startTime, 2051 LoadParam.endTime - LoadParam.startTime,
2052 NumTextures, 2052 NumTextures,
2053 NumLightMaps 2053 NumLightMaps
2054 ); 2054 );
2055 os::Printer::log( buf, ELL_INFORMATION); 2055 os::Printer::log( buf, ELL_INFORMATION);
2056 } 2056 }
2057} 2057}
2058 2058
2059 2059
2060//! Returns an axis aligned bounding box of the mesh. 2060//! Returns an axis aligned bounding box of the mesh.
2061const core::aabbox3d<f32>& CQ3LevelMesh::getBoundingBox() const 2061const core::aabbox3d<f32>& CQ3LevelMesh::getBoundingBox() const
2062{ 2062{
2063 return Mesh[0]->getBoundingBox(); 2063 return Mesh[0]->getBoundingBox();
2064} 2064}
2065 2065
2066 2066
2067void CQ3LevelMesh::setBoundingBox(const core::aabbox3df& box) 2067void CQ3LevelMesh::setBoundingBox(const core::aabbox3df& box)
2068{ 2068{
2069 Mesh[0]->setBoundingBox(box); 2069 Mesh[0]->setBoundingBox(box);
2070} 2070}
2071 2071
2072 2072
2073//! Returns the type of the animated mesh. 2073//! Returns the type of the animated mesh.
2074E_ANIMATED_MESH_TYPE CQ3LevelMesh::getMeshType() const 2074E_ANIMATED_MESH_TYPE CQ3LevelMesh::getMeshType() const
2075{ 2075{
2076 return scene::EAMT_BSP; 2076 return scene::EAMT_BSP;
2077} 2077}
2078 2078
2079} // end namespace scene 2079} // end namespace scene
2080} // end namespace irr 2080} // end namespace irr
2081 2081
2082#endif // _IRR_COMPILE_WITH_BSP_LOADER_ 2082#endif // _IRR_COMPILE_WITH_BSP_LOADER_