1 | /* |
---|
2 | =========================================================================== |
---|
3 | Copyright (C) 2008 Daniel Örstadius |
---|
4 | Copyright (C) 2009 Jared Prince |
---|
5 | |
---|
6 | This file is part of bsp-renderer source code. |
---|
7 | |
---|
8 | bsp-renderer is free software: you can redistribute it and/or modify |
---|
9 | it under the terms of the GNU General Public License as published by |
---|
10 | the Free Software Foundation, either version 3 of the License, or |
---|
11 | (at your option) any later version. |
---|
12 | |
---|
13 | bsp-renderer is distributed in the hope that it will be useful, |
---|
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | GNU General Public License for more details. |
---|
17 | |
---|
18 | You should have received a copy of the GNU General Public License |
---|
19 | along with bsp-renderer. If not, see <http://www.gnu.org/licenses/>. |
---|
20 | |
---|
21 | */ |
---|
22 | |
---|
23 | // Q3Map.cpp -- handles the map data |
---|
24 | |
---|
25 | #include <string> |
---|
26 | #include <math.h> |
---|
27 | |
---|
28 | #include "Q3Map.h" |
---|
29 | #include "Q3Map_misc.h" |
---|
30 | |
---|
31 | |
---|
32 | //temp |
---|
33 | //#include <io.h> |
---|
34 | //#include <fcntl.h> /* Needed only for _O_RDWR definition */ |
---|
35 | //#include <sys/stat.h> |
---|
36 | |
---|
37 | Q3Map::Q3Map() |
---|
38 | { |
---|
39 | m_nDebugA=0 ; |
---|
40 | |
---|
41 | m_nNewCount=0 ; |
---|
42 | |
---|
43 | m_pTexturesOrig=NULL ; |
---|
44 | m_pFaces=NULL ; |
---|
45 | m_pVertices=NULL ; |
---|
46 | m_pMeshVerts=NULL ; |
---|
47 | m_pLeafs=NULL ; |
---|
48 | m_pLeafFaces=NULL ; |
---|
49 | m_pPlanes=NULL ; |
---|
50 | m_pNodes=NULL ; |
---|
51 | |
---|
52 | //m_VisData->vecs=NULL ; // can't NULL this because m_VisData doesn't exist yet! |
---|
53 | m_VisData=NULL ; |
---|
54 | |
---|
55 | m_pBrushes=NULL ; |
---|
56 | m_pLeafBrushes=NULL ; |
---|
57 | m_pBrushSides=NULL ; |
---|
58 | m_pLightMaps=NULL ; |
---|
59 | m_pEntities=NULL ; |
---|
60 | |
---|
61 | m_pSubZones=NULL ; |
---|
62 | m_pPortals=NULL ; |
---|
63 | ////////////////////////////////////////////////////// |
---|
64 | |
---|
65 | // initiallize our triangle memory management |
---|
66 | m_nTriangleSize=0 ; |
---|
67 | m_pTriangleMem=NULL ; |
---|
68 | m_pTriangle=NULL ; |
---|
69 | m_nTriangleMax=0 ; |
---|
70 | m_nTriangleLimit=0 ; |
---|
71 | |
---|
72 | m_nVertexSize=0 ; |
---|
73 | m_pVertexMem=NULL ; |
---|
74 | m_pVertex=NULL ; |
---|
75 | m_nVertexMax=0 ; |
---|
76 | m_nVertexLimit=0 ; |
---|
77 | |
---|
78 | m_nLightSize=0 ; |
---|
79 | m_pLightMem=NULL ; |
---|
80 | m_pLight=NULL ; |
---|
81 | m_nLightMax=0 ; |
---|
82 | m_nLightLimit=0 ; |
---|
83 | m_nMaxMultiZoneLight=0 ; |
---|
84 | |
---|
85 | m_nLampSize=0 ; |
---|
86 | m_pLampMem=NULL ; |
---|
87 | m_pLamp=NULL ; |
---|
88 | m_nLampMax=0 ; |
---|
89 | m_nLampLimit=0 ; |
---|
90 | |
---|
91 | m_nTextureSize=0 ; |
---|
92 | m_pTextureMem=NULL ; |
---|
93 | m_pTexture=NULL ; |
---|
94 | m_nTextureMax=0 ; |
---|
95 | m_nTextureLimit=0 ; |
---|
96 | |
---|
97 | m_nTexLampSize=0 ; |
---|
98 | m_pTexLampMem=NULL ; |
---|
99 | m_pTexLamp=NULL ; |
---|
100 | m_nTexLampMax=0 ; |
---|
101 | m_nTexLampLimit=0 ; |
---|
102 | |
---|
103 | m_BspFaces=NULL; |
---|
104 | |
---|
105 | m_pTransTexture=NULL ; |
---|
106 | |
---|
107 | |
---|
108 | // Q3Bug.LogInit() ; |
---|
109 | |
---|
110 | } |
---|
111 | |
---|
112 | Q3Map::~Q3Map() |
---|
113 | { |
---|
114 | // Q3Bug.LogSave("Q3Bug.log") ; |
---|
115 | |
---|
116 | DELETE_ARRAY(m_pTransTexture) ; |
---|
117 | //DELETE_ARRAY(m_pSubZones) ; |
---|
118 | DELETE_ARRAY(mVisibleFaces) ; |
---|
119 | |
---|
120 | FreeLightMemory() ; |
---|
121 | FreeLampMemory() ; |
---|
122 | FreeVertexMemory() ; |
---|
123 | FreeTriangleMemory() ; |
---|
124 | FreeTextureMemory() ; |
---|
125 | FreeTexLampMemory() ; |
---|
126 | DestroyBspFacesMemory() ; // free up face and patch data. Normally already done if we're just loading a new level or quitting, but we might also be here due to a loading fail or something. |
---|
127 | |
---|
128 | // no need to delete any of the pointers to the lumps since their memory belongs to m_pRawBspFile over in OgreFramework. |
---|
129 | |
---|
130 | |
---|
131 | } |
---|
132 | |
---|
133 | void Q3Map::DestroyBspFacesMemory(void) |
---|
134 | { |
---|
135 | if(m_BspFaces) |
---|
136 | { |
---|
137 | // clean up any memory declared for patches |
---|
138 | for (int i=0; i < m_NumBspFaces; i++) |
---|
139 | if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL)) |
---|
140 | { |
---|
141 | DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ; |
---|
142 | DELETE_POINTER( m_BspFaces[i].patch ) ; |
---|
143 | } |
---|
144 | |
---|
145 | // delete the faces memory |
---|
146 | DELETE_ARRAY( m_BspFaces ) ; |
---|
147 | } |
---|
148 | } |
---|
149 | |
---|
150 | |
---|
151 | |
---|
152 | int Q3Map::parseMap(const char* pMem, size_t Size) |
---|
153 | { |
---|
154 | // we check all lump info to make sure it isn't trying to go out of bounds, |
---|
155 | // in case some mangled bsp is trying to do something devious or is just corrupted |
---|
156 | |
---|
157 | |
---|
158 | |
---|
159 | |
---|
160 | |
---|
161 | m_BspHeader=*((Q3BspHeader_t*)pMem) ; // pointer to the header |
---|
162 | |
---|
163 | // run a check that the total size of all the iLengths plus the header isn't too large |
---|
164 | size_t TotalLength=sizeof(Q3BspHeader_t) ; // initialize to the size of the header |
---|
165 | int nLump=0 ; |
---|
166 | int nOther=0 ; |
---|
167 | int nLumpMin=0 ; |
---|
168 | int nLumpMax=0 ; |
---|
169 | int nOtherMin=0 ; |
---|
170 | int nOtherMax=0 ; |
---|
171 | for(nLump=0 ; nLump<MAX_LUMP ; nLump++) |
---|
172 | { |
---|
173 | if(m_BspHeader.Lumps[nLump].iLength<0) return -1 ; // lumps shouldn't have a negative size. FAIL! |
---|
174 | if(m_BspHeader.Lumps[nLump].iLength>MAX_LUMP_SIZE) return -2 ; // no lump has a right to be this big... FAIL! |
---|
175 | |
---|
176 | |
---|
177 | if( (m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nLump].iOffset<sizeof(Q3BspHeader_t)) ) |
---|
178 | return -3 ; // lump overlaps header, FAIL! |
---|
179 | |
---|
180 | if((m_BspHeader.Lumps[nLump].iLength==0) && (m_BspHeader.Lumps[nLump].iOffset!=0)) |
---|
181 | return -4 ; // lump size is zero and yet offset is not zero??? FAIL! |
---|
182 | |
---|
183 | |
---|
184 | TotalLength+=m_BspHeader.Lumps[nLump].iLength ; |
---|
185 | if(TotalLength>Size) return -5 ;// this file is messed up, the lumps add up to more than the file size. FAIL! |
---|
186 | |
---|
187 | // make sure this lump doesn't overlap any other lumps |
---|
188 | nLumpMin=m_BspHeader.Lumps[nLump].iOffset ; |
---|
189 | nLumpMax=nLumpMin+m_BspHeader.Lumps[nLump].iLength-1 ; |
---|
190 | |
---|
191 | for(nOther=nLump+1 ; nOther<MAX_LUMP ; nOther++) |
---|
192 | if((m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nOther].iLength>0)) // don't check zero sized lumps |
---|
193 | { |
---|
194 | nOtherMin=m_BspHeader.Lumps[nOther].iOffset ; |
---|
195 | nOtherMax=nOtherMin+m_BspHeader.Lumps[nOther].iLength-1 ; |
---|
196 | |
---|
197 | if((nLumpMax>=nOtherMin) && (nLumpMin<=nOtherMax)) |
---|
198 | return -6 ; // lump overlaps another lump, FAIL! |
---|
199 | } |
---|
200 | } |
---|
201 | |
---|
202 | |
---|
203 | |
---|
204 | |
---|
205 | // setup pointers to the lumps |
---|
206 | |
---|
207 | if((m_BspHeader.Lumps[0].iOffset<0) || (m_BspHeader.Lumps[0].iOffset>=Size)) return -7 ; // fail if out of memory bounds |
---|
208 | m_pEntities=(char*)(pMem+m_BspHeader.Lumps[0].iOffset) ; |
---|
209 | |
---|
210 | if((m_BspHeader.Lumps[Faces].iOffset<0) || (m_BspHeader.Lumps[Faces].iOffset>=Size)) return -8 ; // out of bounds |
---|
211 | if(m_BspHeader.Lumps[Faces].iOffset+m_BspHeader.Lumps[Faces].iLength>Size) return -9 ; // out of bounds |
---|
212 | m_iNumFaces = m_BspHeader.Lumps[Faces].iLength / sizeof(Q3BspFace_t); |
---|
213 | m_pFaces=(Q3BspFace_t*)(pMem+m_BspHeader.Lumps[Faces].iOffset) ; |
---|
214 | |
---|
215 | if((m_BspHeader.Lumps[Vertices].iOffset<0) || (m_BspHeader.Lumps[Vertices].iOffset>=Size)) return -10 ; // out of bounds |
---|
216 | if(m_BspHeader.Lumps[Vertices].iOffset+m_BspHeader.Lumps[Vertices].iLength>Size) return -11 ; // out of bounds |
---|
217 | m_iNumVertices = m_BspHeader.Lumps[Vertices].iLength / sizeof(Q3BspVertex); |
---|
218 | m_pVertices=(Q3BspVertex*)(pMem+m_BspHeader.Lumps[Vertices].iOffset) ; |
---|
219 | |
---|
220 | if((m_BspHeader.Lumps[MeshVerts].iOffset<0) || (m_BspHeader.Lumps[MeshVerts].iOffset>=Size)) return -12 ; // out of bounds |
---|
221 | if(m_BspHeader.Lumps[MeshVerts].iOffset+m_BspHeader.Lumps[MeshVerts].iLength>Size) return -13 ; // out of bounds |
---|
222 | m_iNumMeshVerts = m_BspHeader.Lumps[MeshVerts].iLength / sizeof(int); |
---|
223 | m_pMeshVerts=(int*)(pMem+m_BspHeader.Lumps[MeshVerts].iOffset) ; |
---|
224 | |
---|
225 | if((m_BspHeader.Lumps[Leafs].iOffset<0) || (m_BspHeader.Lumps[Leafs].iOffset>=Size)) return -14 ; // out of bounds |
---|
226 | if(m_BspHeader.Lumps[Leafs].iOffset+m_BspHeader.Lumps[Leafs].iLength>Size) return -15 ; // out of bounds |
---|
227 | m_iNumLeafs = m_BspHeader.Lumps[Leafs].iLength / sizeof(Q3BspLeaf); |
---|
228 | m_pLeafs=(Q3BspLeaf*)(pMem+m_BspHeader.Lumps[Leafs].iOffset) ; |
---|
229 | |
---|
230 | if((m_BspHeader.Lumps[LeafFaces].iOffset<0) || (m_BspHeader.Lumps[LeafFaces].iOffset>=Size)) return -16 ; // out of bounds |
---|
231 | if(m_BspHeader.Lumps[LeafFaces].iOffset+m_BspHeader.Lumps[LeafFaces].iLength>Size) return -17 ; // out of bounds |
---|
232 | m_iNumLeafFaces = m_BspHeader.Lumps[LeafFaces].iLength / sizeof(int); |
---|
233 | m_pLeafFaces=(int*)(pMem+m_BspHeader.Lumps[LeafFaces].iOffset) ; |
---|
234 | |
---|
235 | if((m_BspHeader.Lumps[LeafBrushes].iOffset<0) || (m_BspHeader.Lumps[LeafBrushes].iOffset>=Size)) return -18 ; // out of bounds |
---|
236 | if(m_BspHeader.Lumps[LeafBrushes].iOffset+m_BspHeader.Lumps[LeafBrushes].iLength>Size) return -19 ; // out of bounds |
---|
237 | m_iNumLeafBrushes = m_BspHeader.Lumps[LeafBrushes].iLength / sizeof(int); |
---|
238 | m_pLeafBrushes=(int*)(pMem+m_BspHeader.Lumps[LeafBrushes].iOffset) ; |
---|
239 | |
---|
240 | if((m_BspHeader.Lumps[Textures].iOffset<0) || (m_BspHeader.Lumps[Textures].iOffset>=Size)) return -20 ; // out of bounds |
---|
241 | if(m_BspHeader.Lumps[Textures].iOffset+m_BspHeader.Lumps[Textures].iLength>Size) return -21 ; // out of bounds |
---|
242 | m_iNumTexs = m_BspHeader.Lumps[Textures].iLength / sizeof(Q3BspTexture); |
---|
243 | m_pTexturesOrig=(Q3BspTexture*)(pMem+m_BspHeader.Lumps[Textures].iOffset) ; |
---|
244 | |
---|
245 | if((m_BspHeader.Lumps[Planes].iOffset<0) || (m_BspHeader.Lumps[Planes].iOffset>=Size)) return -22 ; // out of bounds |
---|
246 | if(m_BspHeader.Lumps[Planes].iOffset+m_BspHeader.Lumps[Planes].iLength>Size) return -23 ; // out of bounds |
---|
247 | m_iNumPlanes = m_BspHeader.Lumps[Planes].iLength / sizeof(Q3BspPlane); |
---|
248 | m_pPlanes=(Q3BspPlane*)(pMem+m_BspHeader.Lumps[Planes].iOffset) ; |
---|
249 | |
---|
250 | if((m_BspHeader.Lumps[Nodes].iOffset<0) || (m_BspHeader.Lumps[Nodes].iOffset>=Size)) return -24 ; // out of bounds |
---|
251 | if(m_BspHeader.Lumps[Nodes].iOffset+m_BspHeader.Lumps[Nodes].iLength>Size) return -25 ; // out of bounds |
---|
252 | m_iNumNodes = m_BspHeader.Lumps[Nodes].iLength / sizeof(Q3BspNode); |
---|
253 | m_pNodes=(Q3BspNode*)(pMem+m_BspHeader.Lumps[Nodes].iOffset) ; |
---|
254 | |
---|
255 | //m_iNumModels = m_BspHeader.Lumps[Models].iLength / sizeof(Q3BspModel); |
---|
256 | //m_pModels = new Q3BspModel[m_iNumModels]; |
---|
257 | |
---|
258 | // bzn doesn't use lightmaps |
---|
259 | //m_iNumLightMaps = m_BspHeader.Lumps[LightMaps].iLength / sizeof(Q3BspLightMap); |
---|
260 | //m_pLightMaps=(Q3BspLightMap*)(pMem+m_BspHeader.Lumps[LightMaps].iOffset) ; |
---|
261 | |
---|
262 | if((m_BspHeader.Lumps[Brushes].iOffset<0) || (m_BspHeader.Lumps[Brushes].iOffset>=Size)) return -26 ; // out of bounds |
---|
263 | if(m_BspHeader.Lumps[Brushes].iOffset+m_BspHeader.Lumps[Brushes].iLength>Size) return -27 ; // out of bounds |
---|
264 | m_iNumBrushes = m_BspHeader.Lumps[Brushes].iLength / sizeof(Q3BspBrush); |
---|
265 | m_pBrushes=(Q3BspBrush*)(pMem+m_BspHeader.Lumps[Brushes].iOffset) ; |
---|
266 | |
---|
267 | |
---|
268 | if((m_BspHeader.Lumps[BrushSides].iOffset<0) || (m_BspHeader.Lumps[BrushSides].iOffset>=Size)) return -28 ; // out of bounds |
---|
269 | if(m_BspHeader.Lumps[BrushSides].iOffset+m_BspHeader.Lumps[BrushSides].iLength>Size) return -29 ; // out of bounds |
---|
270 | m_iNumBrushSides = m_BspHeader.Lumps[BrushSides].iLength / sizeof(Q3BspBrushSide); |
---|
271 | m_pBrushSides=(Q3BspBrushSide*)(pMem+m_BspHeader.Lumps[BrushSides].iOffset) ; |
---|
272 | |
---|
273 | //m_iNumEffects = m_BspHeader.Lumps[Effects].iLength / sizeof(Q3BspEffect); |
---|
274 | //m_pEffects = new Q3BspEffect[m_iNumEffects]; |
---|
275 | // |
---|
276 | //m_pImages = new BDTexture[m_iNumTexs]; |
---|
277 | |
---|
278 | // bzn doesn't use visdata |
---|
279 | //m_VisData=(Q3BspVisData*)(pMem+m_BspHeader.Lumps[VisData].iOffset) ; |
---|
280 | //m_VisData->vecs=(unsigned char*)(pMem+m_BspHeader.Lumps[VisData].iOffset + 2*sizeof(int)) ; |
---|
281 | |
---|
282 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
283 | |
---|
284 | // bzn specific data |
---|
285 | if((m_BspHeader.Lumps[SubZoneData].iOffset<0) || (m_BspHeader.Lumps[SubZoneData].iOffset>=Size)) return -30 ; // out of bounds |
---|
286 | if(m_BspHeader.Lumps[SubZoneData].iOffset+m_BspHeader.Lumps[SubZoneData].iLength>Size) return -31 ; // out of bounds |
---|
287 | m_iNumSubZones = m_BspHeader.Lumps[SubZoneData].iLength / sizeof(BZN_SubZone_t); |
---|
288 | m_pSubZones=(BZN_SubZone_t*)(pMem+m_BspHeader.Lumps[SubZoneData].iOffset) ; |
---|
289 | |
---|
290 | if((m_BspHeader.Lumps[PortalData].iOffset<0) || (m_BspHeader.Lumps[PortalData].iOffset>=Size)) return -32 ; // out of bounds |
---|
291 | if(m_BspHeader.Lumps[PortalData].iOffset+m_BspHeader.Lumps[PortalData].iLength>Size) return -33 ; // out of bounds |
---|
292 | m_iNumPortals = m_BspHeader.Lumps[PortalData].iLength / sizeof(BZN_Portal_t); |
---|
293 | m_pPortals=(BZN_Portal_t*)(pMem+m_BspHeader.Lumps[PortalData].iOffset) ; |
---|
294 | |
---|
295 | |
---|
296 | |
---|
297 | |
---|
298 | |
---|
299 | |
---|
300 | // fix coords and setup face memory |
---|
301 | swizzleCoords(); |
---|
302 | mVisibleFaces = new int[m_iNumFaces]; |
---|
303 | |
---|
304 | |
---|
305 | // we need a new version of the textures, because when we parse the lights they will have textures to add to it, |
---|
306 | // and we can't expand the texture lump because it's in the middle of a block of memory containing all the lumps. |
---|
307 | |
---|
308 | // copy the texture lump |
---|
309 | int nTexture=0 ; |
---|
310 | for(nTexture=0 ; nTexture<m_iNumTexs ; nTexture++) |
---|
311 | { |
---|
312 | if(!AddTexture(m_pTexturesOrig[nTexture])) return -34 ; // failed to add texture, probably out of memory |
---|
313 | } |
---|
314 | |
---|
315 | return 0 ; |
---|
316 | |
---|
317 | } |
---|
318 | |
---|
319 | |
---|
320 | void Q3Map::swizzleCoords(void) |
---|
321 | { |
---|
322 | //DEBUG_OUTPUT("swizziling data..."); |
---|
323 | // vertices |
---|
324 | for (int i=0; i < m_iNumVertices; i++) |
---|
325 | { |
---|
326 | swizzleFloat3(m_pVertices[i].position); |
---|
327 | swizzleFloat3(m_pVertices[i].normal); |
---|
328 | //m_pVertices[i].texcoord[0][0] = 1.0f - m_pVertices[i].texcoord[0][0]; |
---|
329 | } |
---|
330 | |
---|
331 | // leafs |
---|
332 | for (int i=0; i < m_iNumLeafs; i++) |
---|
333 | { |
---|
334 | swizzleInt3(m_pLeafs[i].maxs); |
---|
335 | swizzleInt3(m_pLeafs[i].mins); |
---|
336 | } |
---|
337 | |
---|
338 | // faces, do lightmaps later... |
---|
339 | for (int i=0; i < m_iNumFaces; i++) |
---|
340 | { |
---|
341 | swizzleFloat3(m_pFaces[i].normal); |
---|
342 | } |
---|
343 | |
---|
344 | // planes |
---|
345 | for (int i=0; i < m_iNumPlanes; i++) |
---|
346 | { |
---|
347 | swizzleFloat3(m_pPlanes[i].normal); |
---|
348 | } |
---|
349 | |
---|
350 | // nodes |
---|
351 | for (int i=0; i < m_iNumNodes; i++) |
---|
352 | { |
---|
353 | swizzleInt3(m_pNodes[i].maxs); |
---|
354 | swizzleInt3(m_pNodes[i].mins); |
---|
355 | } |
---|
356 | |
---|
357 | |
---|
358 | // subzones |
---|
359 | float flTemp=0.0f ; |
---|
360 | for (int i=0; i < m_iNumSubZones; i++) |
---|
361 | { |
---|
362 | swizzleFloat3(m_pSubZones[i].Max); |
---|
363 | swizzleFloat3(m_pSubZones[i].Min); |
---|
364 | |
---|
365 | // swizzling will mix up z max and min due to the sign change, so swap them |
---|
366 | flTemp=m_pSubZones[i].Max[2] ; |
---|
367 | m_pSubZones[i].Max[2]=m_pSubZones[i].Min[2] ; |
---|
368 | m_pSubZones[i].Min[2]=flTemp ; |
---|
369 | |
---|
370 | } |
---|
371 | |
---|
372 | // portals |
---|
373 | for (int i=0; i < m_iNumPortals; i++) |
---|
374 | { |
---|
375 | swizzleFloat3(m_pPortals[i].Max); |
---|
376 | swizzleFloat3(m_pPortals[i].Min); |
---|
377 | |
---|
378 | // swizzling will mix up z max and min due to the sign change, so swap them |
---|
379 | flTemp=m_pPortals[i].Max[2] ; |
---|
380 | m_pPortals[i].Max[2]=m_pPortals[i].Min[2] ; |
---|
381 | m_pPortals[i].Min[2]=flTemp ; |
---|
382 | |
---|
383 | } |
---|
384 | |
---|
385 | |
---|
386 | |
---|
387 | |
---|
388 | } |
---|
389 | |
---|
390 | void Q3Map::swizzleFloat3(float t[3]) |
---|
391 | { |
---|
392 | float temp; |
---|
393 | temp = t[1]; |
---|
394 | t[1] = t[2]; |
---|
395 | t[2] = -temp; |
---|
396 | } |
---|
397 | |
---|
398 | void Q3Map::swizzleInt3(int t[3]) |
---|
399 | { |
---|
400 | int temp; |
---|
401 | temp = t[1]; |
---|
402 | t[1] = t[2]; |
---|
403 | t[2] = -temp; |
---|
404 | } |
---|
405 | |
---|
406 | |
---|
407 | |
---|
408 | Q3BspPatch *Q3Map::handlePatch(int faceIndex) |
---|
409 | { |
---|
410 | Q3BspPatch *q3patch; |
---|
411 | q3patch = new Q3BspPatch; |
---|
412 | |
---|
413 | int patch_size_x = (m_pFaces[faceIndex].size[0] - 1) / 2; |
---|
414 | int patch_size_y = (m_pFaces[faceIndex].size[1] - 1) / 2; |
---|
415 | int num_bezier_patches = patch_size_y * patch_size_x; |
---|
416 | |
---|
417 | q3patch->size = num_bezier_patches; |
---|
418 | q3patch->bezier = new Bezier[q3patch->size]; |
---|
419 | |
---|
420 | int patchIndex = 0; |
---|
421 | int ii, n, j, nn; |
---|
422 | for (ii = 0, n = 0; n < patch_size_x; n++, ii = 2*n) |
---|
423 | { |
---|
424 | for (j=0, nn=0; nn < patch_size_y; nn++, j = 2*nn) |
---|
425 | { |
---|
426 | int index = 0; |
---|
427 | for (int ctr = 0; ctr < 3; ctr++) |
---|
428 | { |
---|
429 | int pos = ctr * m_pFaces[faceIndex].size[0]; |
---|
430 | |
---|
431 | q3patch->bezier[patchIndex].mControls[index++] = |
---|
432 | BspVertex( |
---|
433 | // position |
---|
434 | m_pVertices[m_pFaces[faceIndex].vertex + |
---|
435 | ii + |
---|
436 | m_pFaces[faceIndex].size[0] * j + |
---|
437 | pos].position, |
---|
438 | // texture coordinates |
---|
439 | m_pVertices[m_pFaces[faceIndex].vertex + |
---|
440 | ii + |
---|
441 | m_pFaces[faceIndex].size[0] * j + |
---|
442 | pos].texcoord, |
---|
443 | // normal |
---|
444 | m_pVertices[m_pFaces[faceIndex].vertex + |
---|
445 | ii + |
---|
446 | m_pFaces[faceIndex].size[0] * j + |
---|
447 | pos].normal); |
---|
448 | |
---|
449 | q3patch->bezier[patchIndex].mControls[index++] = |
---|
450 | BspVertex( |
---|
451 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].position, |
---|
452 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].texcoord, |
---|
453 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].normal); |
---|
454 | |
---|
455 | q3patch->bezier[patchIndex].mControls[index++] = |
---|
456 | BspVertex( |
---|
457 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].position, |
---|
458 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].texcoord, |
---|
459 | m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].normal); |
---|
460 | } |
---|
461 | q3patch->bezier[patchIndex].tessellate(5); |
---|
462 | patchIndex++; |
---|
463 | } |
---|
464 | } |
---|
465 | |
---|
466 | return q3patch; |
---|
467 | } |
---|
468 | |
---|
469 | |
---|
470 | int Q3Map::findVisibleFaces(const QVECTOR *camPos, int *facesToRender) |
---|
471 | { |
---|
472 | int leaf; |
---|
473 | int visCluster; |
---|
474 | |
---|
475 | leaf = findLeaf(camPos); |
---|
476 | |
---|
477 | visCluster = m_pLeafs[leaf].cluster; |
---|
478 | |
---|
479 | memset(mVisibleFaces, 0, sizeof(int) * m_iNumFaces); |
---|
480 | |
---|
481 | int faceindex; |
---|
482 | int renderindex=0; |
---|
483 | m_ClusterCount=0 ; |
---|
484 | |
---|
485 | for (int i=0; i < m_iNumLeafs; i++) |
---|
486 | { |
---|
487 | if (isClusterVisible(visCluster, m_pLeafs[i].cluster)) |
---|
488 | { |
---|
489 | m_ClusterCount++ ; |
---|
490 | bool vis=true ;//bool vis = mViewFrustum->checkIfBoxInside(m_pLeafs[i].mins, m_pLeafs[i].maxs); |
---|
491 | |
---|
492 | if (vis) |
---|
493 | { |
---|
494 | for (int k=0; k < m_pLeafs[i].n_leaffaces; k++) |
---|
495 | { |
---|
496 | faceindex = m_pLeafFaces[m_pLeafs[i].leafface + k]; |
---|
497 | if (mVisibleFaces[faceindex] == 0) |
---|
498 | { |
---|
499 | mVisibleFaces[faceindex] = 1; |
---|
500 | facesToRender[renderindex++] = faceindex; |
---|
501 | } |
---|
502 | } |
---|
503 | } |
---|
504 | } |
---|
505 | } |
---|
506 | |
---|
507 | |
---|
508 | facesToRender[renderindex] = -1; |
---|
509 | |
---|
510 | return renderindex; |
---|
511 | } |
---|
512 | |
---|
513 | |
---|
514 | int Q3Map::findLeaf(const QVECTOR *camPos) const |
---|
515 | { |
---|
516 | int index = 0; |
---|
517 | |
---|
518 | while (index >= 0) |
---|
519 | { |
---|
520 | const Q3BspNode *node = &m_pNodes[index]; |
---|
521 | const Q3BspPlane *plane = &m_pPlanes[node->plane]; |
---|
522 | |
---|
523 | // distance from point to plane |
---|
524 | //QVECTOR normal = QVECTOR(plane->normal); |
---|
525 | QVECTOR normal ; |
---|
526 | normal[0]=plane->normal[0] ; |
---|
527 | normal[1]=plane->normal[1] ; |
---|
528 | normal[2]=plane->normal[2] ; |
---|
529 | |
---|
530 | |
---|
531 | //const float distance = D3DXVec3Dot(&normal,camPos) - plane->dist; |
---|
532 | |
---|
533 | const float distance=(normal[0]* *camPos[0] + normal[1]* *camPos[1] + normal[2]* *camPos[2]) - plane->dist ; |
---|
534 | |
---|
535 | if(distance >= 0) |
---|
536 | index = node->children[0]; |
---|
537 | else |
---|
538 | index = node->children[1]; |
---|
539 | } |
---|
540 | |
---|
541 | return -index - 1; |
---|
542 | } |
---|
543 | |
---|
544 | bool Q3Map::isClusterVisible(int visCluster, int testCluster) const |
---|
545 | { |
---|
546 | if (m_VisData == NULL) |
---|
547 | return true; |
---|
548 | |
---|
549 | if ((m_VisData->vecs == NULL) || (visCluster < 0)) |
---|
550 | return true; |
---|
551 | |
---|
552 | int i = (visCluster * m_VisData->sz_vecs) + (testCluster >> 3); |
---|
553 | unsigned char visSet = m_VisData->vecs[i]; |
---|
554 | |
---|
555 | return (visSet & (1 << (testCluster & 7))) != 0; |
---|
556 | } |
---|
557 | |
---|
558 | Q3BspFace_t *Q3Map::getFaces(void) |
---|
559 | { |
---|
560 | return m_pFaces; |
---|
561 | } |
---|
562 | |
---|
563 | |
---|
564 | |
---|
565 | |
---|
566 | |
---|
567 | /***********************************************************************************************************\ |
---|
568 | |
---|
569 | New Parsing and Triangulation Functions |
---|
570 | |
---|
571 | \***********************************************************************************************************/ |
---|
572 | |
---|
573 | |
---|
574 | |
---|
575 | |
---|
576 | // This routine is basically an overview of the entire process that converts the BSP |
---|
577 | // into something our Ogre code can use to construct the map's mesh and level data. |
---|
578 | // In essence, it converts the map geometry into a list of triangles sorted by zone and material, |
---|
579 | // as well as extracting other map info like zone and portal bounding boxes, lights, entities etc. |
---|
580 | |
---|
581 | int Q3Map::ParseAndTriangulateMap(const char* pData, size_t Size) |
---|
582 | { |
---|
583 | |
---|
584 | char chMessage[1024] ; |
---|
585 | int nError=0 ; |
---|
586 | |
---|
587 | // setup pointers to the various lumps and get their quantities |
---|
588 | nError=parseMap( pData, Size ) ; |
---|
589 | if(nError<0) |
---|
590 | { |
---|
591 | //sprintf(chMessage, "Parse Map Error: %i", nError) ; |
---|
592 | //Q3Bug.LogAddCR(chMessage) ; |
---|
593 | return ERROR_ParseMap ; |
---|
594 | } |
---|
595 | |
---|
596 | // extract entities such as lights, monsters, etc |
---|
597 | if(!ParseEntities()) return ERROR_ParseEntities ; |
---|
598 | |
---|
599 | // initial memory allocation for triangles |
---|
600 | m_nVertexMax=0 ; |
---|
601 | if(!AllocateVertexMemory(m_iNumVertices)) return ERROR_AllocateVertex ; |
---|
602 | if(!AllocateTriangleMemory()) return ERROR_AllocateTriangle ; |
---|
603 | if(!initFaces()) return ERROR_InitializeFaces ; |
---|
604 | |
---|
605 | // no new map textures should be added after here, or else SetupTransTextures won't work |
---|
606 | if(!SetupTransTextures()) return ERROR_SetupTransTextures ; |
---|
607 | |
---|
608 | // work out the zones |
---|
609 | SetupZones() ; |
---|
610 | |
---|
611 | // convert faces to triangles |
---|
612 | if(!ConvertFacesToTriangles()) return ERROR_ConvertFaces ; |
---|
613 | |
---|
614 | if(!ConvertPatchesToTriangles()) return ERROR_ConvertPatches ; |
---|
615 | |
---|
616 | if(!ConvertLampsToTriangles()) return ERROR_ConvertLamps ; |
---|
617 | |
---|
618 | if(!ConvertLampsToGlowTriangles()) return ERROR_ConvertLampGlow ; |
---|
619 | |
---|
620 | if(!ConvertLightsToGlowTriangles()) return ERROR_ConvertLightGlow ; |
---|
621 | |
---|
622 | GetTexLampTextureNumbers() ; // find out which textures, if any, are textures/common/bzn_lightnode0 to textures/common/bzn_lightnode3 |
---|
623 | |
---|
624 | // assign triangles to zones, splitting them where necessary |
---|
625 | if(!AssignTrianglesToZones()) return ERROR_AssignTriangles ; |
---|
626 | |
---|
627 | if(!ConvertTexLampsToLampTriangles()) return ERROR_ConvertTexLamp ; |
---|
628 | |
---|
629 | // sort by group and re-range the group numbers |
---|
630 | if(!SortTrianglesIntoGroups()) return ERROR_SortGroups ; |
---|
631 | |
---|
632 | // sort the triangles in order of zone and texture. This will also get rid of any unsubzoned triangles. |
---|
633 | if(!SortTrianglesIntoBatches()) return ERROR_SortTriangles ; |
---|
634 | |
---|
635 | |
---|
636 | |
---|
637 | |
---|
638 | // Setup the portals, lights and various bits of map connectivity |
---|
639 | AssignPortalsToZones() ; // what portals each zone touches |
---|
640 | AssignLightsToZones() ; // what lights each zone touches |
---|
641 | AssignLightsToPortals() ; // what lights each portal touches |
---|
642 | AssignZonesToZones() ; // what zones each zone touches |
---|
643 | |
---|
644 | |
---|
645 | return NOERROR ; |
---|
646 | } |
---|
647 | |
---|
648 | void Q3Map::FreeParseMem(void) |
---|
649 | { |
---|
650 | FreeVertexMemory() ; |
---|
651 | FreeTriangleMemory() ; |
---|
652 | DestroyBspFacesMemory() ; |
---|
653 | } |
---|
654 | |
---|
655 | |
---|
656 | |
---|
657 | |
---|
658 | |
---|
659 | |
---|
660 | |
---|
661 | |
---|
662 | |
---|
663 | |
---|
664 | |
---|
665 | |
---|
666 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
667 | // memory management |
---|
668 | |
---|
669 | int Q3Map::AllocateTriangleMemory(void) |
---|
670 | { |
---|
671 | // memory for the Triangle |
---|
672 | m_nTriangleSize=MEMADD ; // starting memory size |
---|
673 | m_pTriangleMem=malloc(m_nTriangleSize) ; // allocate starting memory space |
---|
674 | m_pTriangle=(triangle_t*)m_pTriangleMem ; // a pointer to the memory cast as a triangle_t |
---|
675 | m_nTriangleMax=0 ; |
---|
676 | m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand |
---|
677 | |
---|
678 | if(m_pTriangleMem==NULL) |
---|
679 | return 0 ; |
---|
680 | |
---|
681 | return 1 ; |
---|
682 | } |
---|
683 | |
---|
684 | void Q3Map::FreeTriangleMemory(void) |
---|
685 | { |
---|
686 | if(m_pTriangleMem) free(m_pTriangleMem) ; |
---|
687 | m_pTriangleMem=NULL ; |
---|
688 | m_pTriangle=NULL ; |
---|
689 | m_nTriangleMax=0 ; |
---|
690 | m_nTriangleLimit=0 ; |
---|
691 | } |
---|
692 | |
---|
693 | // increase size of Triangle memory, return 0 if failed |
---|
694 | int Q3Map::ExpandTriangleMemory(void) |
---|
695 | { |
---|
696 | m_nTriangleSize+=MEMADD ; // increase size |
---|
697 | m_pTriangleMem=realloc(m_pTriangleMem, m_nTriangleSize) ; // reallocate the memory |
---|
698 | if(m_pTriangleMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
699 | |
---|
700 | // if here then memory allocation succeeded |
---|
701 | m_pTriangle=(triangle_t*)m_pTriangleMem ; // pointer to the memory cast as a triangle_t |
---|
702 | m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand |
---|
703 | return 1 ; // ok |
---|
704 | } |
---|
705 | |
---|
706 | int Q3Map::AddTriangle(triangle_t Triangle) |
---|
707 | { |
---|
708 | if(m_nTriangleMax>=m_nTriangleLimit) |
---|
709 | if( !ExpandTriangleMemory() ) |
---|
710 | return 0 ; |
---|
711 | |
---|
712 | m_pTriangle[m_nTriangleMax++]=Triangle ; |
---|
713 | |
---|
714 | return 1 ; |
---|
715 | } |
---|
716 | |
---|
717 | int Q3Map::AllocateVertexMemory(int nVertNum) |
---|
718 | { |
---|
719 | // memory for the Vertex |
---|
720 | m_nVertexSize=nVertNum*sizeof(Q3BspVertex)+MEMADD ; // starting memory size |
---|
721 | m_pVertexMem=malloc(m_nVertexSize) ; // allocate starting memory space |
---|
722 | m_pVertex=(Q3BspVertex*)m_pVertexMem ; // a pointer to the memory cast as a triangle_t |
---|
723 | m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand |
---|
724 | |
---|
725 | if(m_pVertexMem==NULL) |
---|
726 | return 0 ; |
---|
727 | |
---|
728 | return 1 ; |
---|
729 | } |
---|
730 | |
---|
731 | void Q3Map::FreeVertexMemory(void) |
---|
732 | { |
---|
733 | if(m_pVertexMem) free(m_pVertexMem) ; |
---|
734 | m_pVertexMem=NULL ; |
---|
735 | m_pVertex=NULL ; |
---|
736 | m_nVertexMax=0 ; |
---|
737 | m_nVertexLimit=0 ; |
---|
738 | } |
---|
739 | |
---|
740 | // increase size of Vertex memory, return 0 if failed |
---|
741 | int Q3Map::ExpandVertexMemory(void) |
---|
742 | { |
---|
743 | m_nVertexSize+=MEMADD ; // increase size |
---|
744 | m_pVertexMem=realloc(m_pVertexMem, m_nVertexSize) ; // reallocate the memory |
---|
745 | if(m_pVertexMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
746 | |
---|
747 | // if here then memory allocation succeeded |
---|
748 | m_pVertex=(Q3BspVertex*)m_pVertexMem ; // pointer to the memory cast as a triangle_t |
---|
749 | m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand |
---|
750 | return 1 ; // ok |
---|
751 | } |
---|
752 | |
---|
753 | int Q3Map::AddVertex(Q3BspVertex Vertex) |
---|
754 | { |
---|
755 | |
---|
756 | if(m_nVertexMax>=m_nVertexLimit) |
---|
757 | if( !ExpandVertexMemory() ) |
---|
758 | return 0 ; |
---|
759 | |
---|
760 | m_pVertex[m_nVertexMax++]=Vertex ; |
---|
761 | |
---|
762 | return 1 ; |
---|
763 | } |
---|
764 | |
---|
765 | int Q3Map::AllocateLightMemory(void) |
---|
766 | { |
---|
767 | // memory for the Light |
---|
768 | m_nLightSize=MEMADD ; // starting memory size |
---|
769 | m_pLightMem=malloc(m_nLightSize) ; // allocate starting memory space |
---|
770 | m_pLight=(light_t*)m_pLightMem ; // a pointer to the memory cast as a light_t |
---|
771 | m_nLightMax=0 ; |
---|
772 | m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand |
---|
773 | |
---|
774 | if(m_pLightMem==NULL) |
---|
775 | return 0 ; |
---|
776 | |
---|
777 | return 1 ; |
---|
778 | } |
---|
779 | |
---|
780 | void Q3Map::FreeLightMemory(void) |
---|
781 | { |
---|
782 | if(m_pLightMem) free(m_pLightMem) ; |
---|
783 | m_pLightMem=NULL ; |
---|
784 | m_pLight=NULL ; |
---|
785 | m_nLightMax=0 ; |
---|
786 | m_nLightLimit=0 ; |
---|
787 | } |
---|
788 | |
---|
789 | // increase size of Light memory, return 0 if failed |
---|
790 | int Q3Map::ExpandLightMemory(void) |
---|
791 | { |
---|
792 | m_nLightSize+=MEMADD ; // increase size |
---|
793 | m_pLightMem=realloc(m_pLightMem, m_nLightSize) ; // reallocate the memory |
---|
794 | if(m_pLightMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
795 | |
---|
796 | // if here then memory allocation succeeded |
---|
797 | m_pLight=(light_t*)m_pLightMem ; // pointer to the memory cast as a light_t |
---|
798 | m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand |
---|
799 | return 1 ; // ok |
---|
800 | } |
---|
801 | |
---|
802 | int Q3Map::AddLight(light_t Light) |
---|
803 | { |
---|
804 | if(m_nLightLimit==0) // light memory hasn't been allocated yet |
---|
805 | { |
---|
806 | if( !AllocateLightMemory() ) |
---|
807 | return 0 ; |
---|
808 | } |
---|
809 | else |
---|
810 | if(m_nLightMax>=m_nLightLimit) |
---|
811 | if( !ExpandLightMemory() ) |
---|
812 | return 0 ; |
---|
813 | |
---|
814 | m_pLight[m_nLightMax++]=Light ; |
---|
815 | |
---|
816 | return 1 ; |
---|
817 | } |
---|
818 | |
---|
819 | // lamps are deferred shading, non-shadowing point lights |
---|
820 | int Q3Map::AllocateLampMemory(void) |
---|
821 | { |
---|
822 | // memory for the Lamp |
---|
823 | m_nLampSize=MEMADD ; // starting memory size |
---|
824 | m_pLampMem=malloc(m_nLampSize) ; // allocate starting memory space |
---|
825 | m_pLamp=(lamp_t*)m_pLampMem ; // a pointer to the memory cast as a lamp_t |
---|
826 | m_nLampMax=0 ; |
---|
827 | m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand |
---|
828 | |
---|
829 | if(m_pLampMem==NULL) |
---|
830 | return 0 ; |
---|
831 | |
---|
832 | return 1 ; |
---|
833 | } |
---|
834 | |
---|
835 | void Q3Map::FreeLampMemory(void) |
---|
836 | { |
---|
837 | if(m_pLampMem) free(m_pLampMem) ; |
---|
838 | m_pLampMem=NULL ; |
---|
839 | m_pLamp=NULL ; |
---|
840 | m_nLampMax=0 ; |
---|
841 | m_nLampLimit=0 ; |
---|
842 | } |
---|
843 | |
---|
844 | // increase size of Lamp memory, return 0 if failed |
---|
845 | int Q3Map::ExpandLampMemory(void) |
---|
846 | { |
---|
847 | m_nLampSize+=MEMADD ; // increase size |
---|
848 | m_pLampMem=realloc(m_pLampMem, m_nLampSize) ; // reallocate the memory |
---|
849 | if(m_pLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
850 | |
---|
851 | // if here then memory allocation succeeded |
---|
852 | m_pLamp=(lamp_t*)m_pLampMem ; // pointer to the memory cast as a lamp_t |
---|
853 | m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand |
---|
854 | return 1 ; // ok |
---|
855 | } |
---|
856 | |
---|
857 | int Q3Map::AddLamp(lamp_t Lamp) |
---|
858 | { |
---|
859 | if(m_nLampLimit==0) // Lamp memory hasn't been allocated yet |
---|
860 | { |
---|
861 | if( !AllocateLampMemory() ) |
---|
862 | return 0 ; |
---|
863 | } |
---|
864 | else |
---|
865 | if(m_nLampMax>=m_nLampLimit) |
---|
866 | if( !ExpandLampMemory() ) |
---|
867 | return 0 ; |
---|
868 | |
---|
869 | m_pLamp[m_nLampMax++]=Lamp ; |
---|
870 | |
---|
871 | return 1 ; |
---|
872 | } |
---|
873 | |
---|
874 | ////////////// |
---|
875 | // Q3BspTexture textures. We duplicate the loaded texture mem and then add lighting textures to it. |
---|
876 | |
---|
877 | int Q3Map::AllocateTextureMemory(void) |
---|
878 | { |
---|
879 | // memory for the Texture |
---|
880 | m_nTextureSize=MEMADD ; // starting memory size |
---|
881 | m_pTextureMem=malloc(m_nTextureSize) ; // allocate starting memory space |
---|
882 | m_pTexture=(Q3BspTexture*)m_pTextureMem ; // a pointer to the memory cast as a Q3BspTexture |
---|
883 | m_nTextureMax=0 ; |
---|
884 | m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand |
---|
885 | |
---|
886 | if(m_pTextureMem==NULL) |
---|
887 | return 0 ; |
---|
888 | |
---|
889 | return 1 ; |
---|
890 | } |
---|
891 | |
---|
892 | void Q3Map::FreeTextureMemory(void) |
---|
893 | { |
---|
894 | if(m_pTextureMem) free(m_pTextureMem) ; |
---|
895 | m_pTextureMem=NULL ; |
---|
896 | m_pTexture=NULL ; |
---|
897 | m_nTextureMax=0 ; |
---|
898 | m_nTextureLimit=0 ; |
---|
899 | } |
---|
900 | |
---|
901 | // increase size of Texture memory, return 0 if failed |
---|
902 | int Q3Map::ExpandTextureMemory(void) |
---|
903 | { |
---|
904 | m_nTextureSize+=MEMADD ; // increase size |
---|
905 | m_pTextureMem=realloc(m_pTextureMem, m_nTextureSize) ; // reallocate the memory |
---|
906 | if(m_pTextureMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
907 | |
---|
908 | // if here then memory allocation succeeded |
---|
909 | m_pTexture=(Q3BspTexture*)m_pTextureMem ; // pointer to the memory cast as a Q3BspTexture |
---|
910 | m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand |
---|
911 | return 1 ; // ok |
---|
912 | } |
---|
913 | |
---|
914 | int Q3Map::AddTexture(Q3BspTexture Texture) |
---|
915 | { |
---|
916 | if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet |
---|
917 | { |
---|
918 | if( !AllocateTextureMemory() ) |
---|
919 | return 0 ; |
---|
920 | } |
---|
921 | else |
---|
922 | if(m_nTextureMax>=m_nTextureLimit) |
---|
923 | if( !ExpandTextureMemory() ) |
---|
924 | return 0 ; |
---|
925 | |
---|
926 | m_pTexture[m_nTextureMax++]=Texture ; |
---|
927 | |
---|
928 | return 1 ; |
---|
929 | } |
---|
930 | |
---|
931 | // special version of the Add function, will not add if the texture name already exist. |
---|
932 | // Will succeed even if the texture is already on the list, but fails if it can't add a new texture |
---|
933 | // returns texture index, or -1 on fail |
---|
934 | // Q3 texture names can be tricky, I think I've had cases where they ended in spaces instead of nulls, |
---|
935 | // and they might go all the way to the end without either. |
---|
936 | |
---|
937 | int Q3Map::AddTextureUnique(Q3BspTexture Texture) |
---|
938 | { |
---|
939 | if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet |
---|
940 | if( !AllocateTextureMemory() ) |
---|
941 | return ADDTEXTUREUNIQUE_FAIL ; // fail |
---|
942 | |
---|
943 | |
---|
944 | // scan through all the newly added textures so far and see if this one already exists. |
---|
945 | int nTexture=0 ; |
---|
946 | int nPos=0 ; |
---|
947 | |
---|
948 | bool bMatch=false ; |
---|
949 | |
---|
950 | for(nTexture=0 ; nTexture<m_nTextureMax ; nTexture++) |
---|
951 | { |
---|
952 | bMatch=true ; |
---|
953 | // scan through the characters of the texture names, comparing them. We start after the original textures |
---|
954 | //for(nPos=m_iNumTexs ; nPos<Q3NAMESIZE ; nPos++) |
---|
955 | for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++) |
---|
956 | { |
---|
957 | // is it the end of the texture name? |
---|
958 | if( |
---|
959 | ((Texture.name[nPos] ==0) || (Texture.name[nPos] ==' ')) // Texture name end |
---|
960 | &&((m_pTexture[nTexture].name[nPos] ==0) || (m_pTexture[nTexture].name[nPos] ==' ')) // m_pTexture name end |
---|
961 | ) |
---|
962 | break ; |
---|
963 | |
---|
964 | // do the two textures have a difference in the name at this position? |
---|
965 | if(Texture.name[nPos]!=m_pTexture[nTexture].name[nPos]) |
---|
966 | { |
---|
967 | bMatch=false ; |
---|
968 | break ; |
---|
969 | } |
---|
970 | |
---|
971 | }// end scanning name |
---|
972 | |
---|
973 | if(bMatch) // found a match, so return ok but don't add a texture |
---|
974 | { |
---|
975 | return nTexture ; // we don't add any new texture, return this texture's index |
---|
976 | } |
---|
977 | } |
---|
978 | |
---|
979 | // if we got this far, we must have a unique texture |
---|
980 | |
---|
981 | // add the texture, it is unique |
---|
982 | if(m_nTextureMax>=m_nTextureLimit) |
---|
983 | if( !ExpandTextureMemory() ) |
---|
984 | return ADDTEXTUREUNIQUE_FAIL ; // fail |
---|
985 | |
---|
986 | m_pTexture[m_nTextureMax++]=Texture ; |
---|
987 | |
---|
988 | return m_nTextureMax-1 ; // return this new texture's index |
---|
989 | |
---|
990 | } |
---|
991 | |
---|
992 | |
---|
993 | //////////////////////////////////////// |
---|
994 | |
---|
995 | int Q3Map::AllocateTexLampMemory(void) |
---|
996 | { |
---|
997 | // memory for the TexLamp |
---|
998 | m_nTexLampSize=MEMADD ; // starting memory size |
---|
999 | m_pTexLampMem=malloc(m_nTexLampSize) ; // allocate starting memory space |
---|
1000 | m_pTexLamp=(int*)m_pTexLampMem ; // a pointer to the memory cast as an int |
---|
1001 | m_nTexLampMax=0 ; |
---|
1002 | m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand |
---|
1003 | |
---|
1004 | if(m_pTexLampMem==NULL) |
---|
1005 | return 0 ; |
---|
1006 | |
---|
1007 | return 1 ; |
---|
1008 | } |
---|
1009 | |
---|
1010 | void Q3Map::FreeTexLampMemory(void) |
---|
1011 | { |
---|
1012 | if(m_pTexLampMem) free(m_pTexLampMem) ; |
---|
1013 | m_pTexLampMem=NULL ; |
---|
1014 | m_pTexLamp=NULL ; |
---|
1015 | m_nTexLampMax=0 ; |
---|
1016 | m_nTexLampLimit=0 ; |
---|
1017 | } |
---|
1018 | |
---|
1019 | // increase size of TexLamp memory, return 0 if failed |
---|
1020 | int Q3Map::ExpandTexLampMemory(void) |
---|
1021 | { |
---|
1022 | m_nTexLampSize+=MEMADD ; // increase size |
---|
1023 | m_pTexLampMem=realloc(m_pTexLampMem, m_nTexLampSize) ; // reallocate the memory |
---|
1024 | if(m_pTexLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false |
---|
1025 | |
---|
1026 | // if here then memory allocation succeeded |
---|
1027 | m_pTexLamp=(int*)m_pTexLampMem ; // pointer to the memory cast as an int |
---|
1028 | m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand |
---|
1029 | return 1 ; // ok |
---|
1030 | } |
---|
1031 | |
---|
1032 | int Q3Map::AddTexLamp(int TexLamp) |
---|
1033 | { |
---|
1034 | if(m_nTexLampMax>=m_nTexLampLimit) |
---|
1035 | if( !ExpandTexLampMemory() ) |
---|
1036 | return 0 ; |
---|
1037 | |
---|
1038 | m_pTexLamp[m_nTexLampMax++]=TexLamp ; |
---|
1039 | |
---|
1040 | return 1 ; |
---|
1041 | } |
---|
1042 | |
---|
1043 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
1044 | // |
---|
1045 | // extract entities from bsp entities lump |
---|
1046 | int Q3Map::ParseEntities(void) |
---|
1047 | { |
---|
1048 | char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1049 | char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1050 | int nPos=0 ; |
---|
1051 | int nMaxPos=m_BspHeader.Lumps[0].iLength ; |
---|
1052 | int nEntityType=0 ; |
---|
1053 | |
---|
1054 | |
---|
1055 | // reset the spotlight textures |
---|
1056 | m_nMaxSpotlightTexture=0 ; |
---|
1057 | for(nPos=0 ; nPos<MAX_PROJECTORTEX ; nPos++) |
---|
1058 | m_chSpotlightTexture[nPos][0]='\0' ; |
---|
1059 | |
---|
1060 | strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], "spotlight.dds") ; // the default spotlight texture |
---|
1061 | m_nMaxSpotlightTexture++ ; |
---|
1062 | |
---|
1063 | //////////////////////////////////////////////////////////////////////////// |
---|
1064 | // before adding all the entities we need to add some default textures |
---|
1065 | Q3BspTexture Texture ; |
---|
1066 | Texture.contents=0 ; |
---|
1067 | Texture.flags=0 ; |
---|
1068 | |
---|
1069 | // default lamp texture |
---|
1070 | strcpy(Texture.name, "lights/lamp_default") ; |
---|
1071 | m_nDefaultTextureIndexLamp=AddTextureUnique(Texture) ; |
---|
1072 | if(m_nDefaultTextureIndexLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ; |
---|
1073 | |
---|
1074 | // default lamp2Pass texture |
---|
1075 | strcpy(Texture.name, "lights/lamp2pass_default") ; |
---|
1076 | m_nDefaultTextureIndexLamp2Pass=AddTextureUnique(Texture) ; |
---|
1077 | if(m_nDefaultTextureIndexLamp2Pass==ADDTEXTUREUNIQUE_FAIL) return 0 ; |
---|
1078 | |
---|
1079 | // default glow texture |
---|
1080 | strcpy(Texture.name, "GLOW_lamp") ; |
---|
1081 | m_nDefaultTextureIndexGlowLamp=AddTextureUnique(Texture) ; |
---|
1082 | if(m_nDefaultTextureIndexGlowLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ; |
---|
1083 | |
---|
1084 | // default glow texture |
---|
1085 | strcpy(Texture.name, "GLOW_light") ; |
---|
1086 | m_nDefaultTextureIndexGlowLight=AddTextureUnique(Texture) ; |
---|
1087 | if(m_nDefaultTextureIndexGlowLight==ADDTEXTUREUNIQUE_FAIL) return 0 ; |
---|
1088 | |
---|
1089 | |
---|
1090 | // default spotlight texture |
---|
1091 | //strcpy(Texture.name, "lights/light_default") ; |
---|
1092 | //m_nDefaultTextureIndexSpotlight=AddTextureUnique(Texture) ; |
---|
1093 | //if(m_nDefaultTextureIndexSpotlight==ADDTEXTUREUNIQUE_FAIL) return 0 ; |
---|
1094 | |
---|
1095 | // |
---|
1096 | /////////////////////////////////////////////////////////////////////////// |
---|
1097 | |
---|
1098 | |
---|
1099 | nPos=-1 ; |
---|
1100 | while(NextEntity(&nPos, nMaxPos)) |
---|
1101 | { |
---|
1102 | |
---|
1103 | nEntityType=GetEntityType(nPos, nMaxPos) ; // what type of entity is it? |
---|
1104 | |
---|
1105 | |
---|
1106 | switch(nEntityType) |
---|
1107 | { |
---|
1108 | case ENTITY_ERROR: return 0 ; // something is wrong with the entity data |
---|
1109 | |
---|
1110 | case ENTITY_LIGHT: |
---|
1111 | if(!ParseAndAddLight(&nPos, nMaxPos)) |
---|
1112 | return 0 ; // something went wrong with parsing the light |
---|
1113 | break ; |
---|
1114 | }// end switch entity type |
---|
1115 | |
---|
1116 | |
---|
1117 | }// end get next entity |
---|
1118 | |
---|
1119 | |
---|
1120 | |
---|
1121 | // everything is ok. |
---|
1122 | return 1 ; |
---|
1123 | } |
---|
1124 | |
---|
1125 | // move to the beginning of the next entity. |
---|
1126 | // fail if there are no more. |
---|
1127 | int Q3Map::NextEntity(int* pPos, int nMaxPos) |
---|
1128 | { |
---|
1129 | while((++*pPos<nMaxPos) && (m_pEntities[*pPos]!='{')) ; |
---|
1130 | |
---|
1131 | if(*pPos==nMaxPos) |
---|
1132 | return 0 ; |
---|
1133 | |
---|
1134 | return 1 ; |
---|
1135 | } |
---|
1136 | |
---|
1137 | // find out what type of entity this is. |
---|
1138 | // Since the classname might not be at the beginning we have to scan through the whole entity |
---|
1139 | // This function also doesn't update the position like the others do, |
---|
1140 | // since scanning of further key/values will have to start at the beginning of the entity again. |
---|
1141 | int Q3Map::GetEntityType(int nPos, int nMaxPos) |
---|
1142 | { |
---|
1143 | char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1144 | char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1145 | |
---|
1146 | while(nPos<nMaxPos) |
---|
1147 | { |
---|
1148 | if(GetEntityKeyAndValue(&nPos, nMaxPos, chKey, chValue)!=KEY_OK) return ENTITY_ERROR ; // something went wrong, couldn't find any good keys |
---|
1149 | |
---|
1150 | if(strcmp(chKey, "classname")==0) // found the classname key |
---|
1151 | { |
---|
1152 | if(strcmp(chValue, "worldspawn")==0) return ENTITY_WORLDSPAWN ; |
---|
1153 | if(strcmp(chValue, "light")==0) return ENTITY_LIGHT ; |
---|
1154 | |
---|
1155 | // wasn't any entity we recognize |
---|
1156 | return ENTITY_UNKNOWN ; |
---|
1157 | |
---|
1158 | }// end if got entity classname |
---|
1159 | |
---|
1160 | }// end while nPos |
---|
1161 | |
---|
1162 | // didn't find any classname |
---|
1163 | return ENTITY_ERROR ; |
---|
1164 | } |
---|
1165 | |
---|
1166 | // get next entity key and value |
---|
1167 | int Q3Map::GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue) |
---|
1168 | { |
---|
1169 | |
---|
1170 | char* pEntText=m_pEntities ; |
---|
1171 | int nEntPos=*pPos ; |
---|
1172 | int nKeyPos=-1 ; |
---|
1173 | int nValuePos=-1 ; |
---|
1174 | |
---|
1175 | // clear key and value strings |
---|
1176 | pKey[0]='\0' ; |
---|
1177 | pValue[0]='\0' ; |
---|
1178 | |
---|
1179 | ///////////////////////////////////////////////////////////////////////////////////////// |
---|
1180 | // Key |
---|
1181 | |
---|
1182 | // find the next " |
---|
1183 | while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ; |
---|
1184 | |
---|
1185 | // didn't find key, get out |
---|
1186 | if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}')) |
---|
1187 | return KEY_NONE ; |
---|
1188 | |
---|
1189 | |
---|
1190 | // copy key |
---|
1191 | while((++nEntPos<nMaxPos) && (nKeyPos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) |
---|
1192 | pKey[++nKeyPos]=pEntText[nEntPos] ; |
---|
1193 | |
---|
1194 | if((nEntPos==nMaxPos) || (nKeyPos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}')) |
---|
1195 | return KEY_ERROR ; // entity was incomplete or too big |
---|
1196 | |
---|
1197 | pKey[++nKeyPos]='\0' ; |
---|
1198 | |
---|
1199 | ///////////////////////////////////////////////////////////////////////////////////////// |
---|
1200 | // value |
---|
1201 | |
---|
1202 | // find the next " |
---|
1203 | while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ; |
---|
1204 | |
---|
1205 | // didn't find value, get out |
---|
1206 | if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}')) |
---|
1207 | return KEY_ERROR ; |
---|
1208 | |
---|
1209 | // copy value |
---|
1210 | while((++nEntPos<nMaxPos) && (nValuePos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) |
---|
1211 | pValue[++nValuePos]=pEntText[nEntPos] ; |
---|
1212 | |
---|
1213 | if((nEntPos==nMaxPos) || (nValuePos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}')) |
---|
1214 | return KEY_ERROR ; // entity was incomplete or too big |
---|
1215 | |
---|
1216 | pValue[++nValuePos]='\0' ; |
---|
1217 | |
---|
1218 | ///////////////////////////////////////////////////////////////////////////////////////// |
---|
1219 | |
---|
1220 | *pPos=nEntPos+1 ; |
---|
1221 | |
---|
1222 | return KEY_OK ; |
---|
1223 | } |
---|
1224 | |
---|
1225 | |
---|
1226 | // fills array pNumber with the values extracted from pValue, returns how many numbers it got. |
---|
1227 | // float version |
---|
1228 | int Q3Map::GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize) |
---|
1229 | { |
---|
1230 | int nLength=strlen(pValue) ; |
---|
1231 | if(nLength<1) return 0 ; |
---|
1232 | |
---|
1233 | int nPos=-1 ; |
---|
1234 | int nCount=0 ; |
---|
1235 | char chTemp[MAX_TOKENSIZE+1] ; |
---|
1236 | int nTempPos=0 ; |
---|
1237 | |
---|
1238 | do |
---|
1239 | { |
---|
1240 | |
---|
1241 | nPos++ ; |
---|
1242 | |
---|
1243 | if( |
---|
1244 | ((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit |
---|
1245 | || |
---|
1246 | (pValue[nPos]=='.') |
---|
1247 | || |
---|
1248 | (pValue[nPos]=='-') |
---|
1249 | ) |
---|
1250 | { |
---|
1251 | chTemp[nTempPos++]=pValue[nPos] ; |
---|
1252 | if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big |
---|
1253 | } |
---|
1254 | else // anything else means the end of the number |
---|
1255 | { |
---|
1256 | |
---|
1257 | chTemp[nTempPos]='\0' ; |
---|
1258 | pNumber[nCount++]=atof(chTemp) ; |
---|
1259 | nTempPos=0 ; |
---|
1260 | } |
---|
1261 | |
---|
1262 | |
---|
1263 | }while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ; |
---|
1264 | |
---|
1265 | |
---|
1266 | return nCount ; |
---|
1267 | } |
---|
1268 | |
---|
1269 | // integer version |
---|
1270 | int Q3Map::GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize) |
---|
1271 | { |
---|
1272 | int nLength=strlen(pValue) ; |
---|
1273 | if(nLength<1) return 0 ; |
---|
1274 | |
---|
1275 | int nPos=-1 ; |
---|
1276 | int nCount=0 ; |
---|
1277 | char chTemp[MAX_TOKENSIZE+1] ; |
---|
1278 | int nTempPos=0 ; |
---|
1279 | |
---|
1280 | do |
---|
1281 | { |
---|
1282 | |
---|
1283 | nPos++ ; |
---|
1284 | |
---|
1285 | if( |
---|
1286 | ((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit |
---|
1287 | || |
---|
1288 | (pValue[nPos]=='.') |
---|
1289 | || |
---|
1290 | (pValue[nPos]=='-') |
---|
1291 | ) |
---|
1292 | { |
---|
1293 | chTemp[nTempPos++]=pValue[nPos] ; |
---|
1294 | if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big |
---|
1295 | } |
---|
1296 | else // anything else means the end of the number |
---|
1297 | { |
---|
1298 | |
---|
1299 | chTemp[nTempPos]='\0' ; |
---|
1300 | pNumber[nCount++]=atoi(chTemp) ; |
---|
1301 | nTempPos=0 ; |
---|
1302 | } |
---|
1303 | |
---|
1304 | |
---|
1305 | }while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ; |
---|
1306 | |
---|
1307 | |
---|
1308 | return nCount ; |
---|
1309 | } |
---|
1310 | |
---|
1311 | //'' |
---|
1312 | // extracts data for either forward rendered shadow casting spotlights or deferred shading non-shadowing point lights |
---|
1313 | // the point lights ("lamps") will later be changed into map triangles. |
---|
1314 | int Q3Map::ParseAndAddLight(int* pPos, int nMaxPos) |
---|
1315 | { |
---|
1316 | char chMessage[1024] ; |
---|
1317 | |
---|
1318 | |
---|
1319 | char chKey[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1320 | char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator |
---|
1321 | float flOrigin[3]={0.0f, 0.0f, 0.0f} ; |
---|
1322 | float flColour[3]={1.0f, 1.0f, 1.0f} ; |
---|
1323 | float flCentre[3]={0.0f, 0.0f, 0.0f} ; |
---|
1324 | float flAimvec[3]={0.0f, 0.0f, 0.0f} ; |
---|
1325 | float flRadius[3]={0.0f, 0.0f, 0.0f} ; |
---|
1326 | |
---|
1327 | float flTemp[3]={0.0f, 0.0f, 0.0f} ; |
---|
1328 | int nTemp[3] ; |
---|
1329 | |
---|
1330 | float flAngle=0.0f ; |
---|
1331 | float flCutoff=0.0f ; |
---|
1332 | float flLength=0.0f ; |
---|
1333 | float flBrightness=0.0f ; |
---|
1334 | int nLightNode=-1 ; |
---|
1335 | |
---|
1336 | bool bSpotLight=false ; |
---|
1337 | |
---|
1338 | Q3BspTexture Q3Texture ; |
---|
1339 | Q3Texture.flags=0 ; |
---|
1340 | Q3Texture.contents=0 ; |
---|
1341 | Q3Texture.name[0]=0 ; |
---|
1342 | |
---|
1343 | |
---|
1344 | light_t NewLight ; // forward rendered shadow casting spotlight |
---|
1345 | ZeroMemory((void*)&NewLight, sizeof(light_t)) ; |
---|
1346 | |
---|
1347 | lamp_t NewLamp ; // deferred shading non-shadowing point light |
---|
1348 | ZeroMemory((void*)&NewLamp, sizeof(lamp_t)) ; |
---|
1349 | |
---|
1350 | int nKeyReturn=KEY_NONE ; |
---|
1351 | |
---|
1352 | do |
---|
1353 | { |
---|
1354 | nKeyReturn=GetEntityKeyAndValue(pPos, nMaxPos, chKey, chValue) ; |
---|
1355 | |
---|
1356 | if(nKeyReturn==KEY_OK) // found a key |
---|
1357 | { |
---|
1358 | |
---|
1359 | if(strcmp(chKey, "origin")==0) |
---|
1360 | { |
---|
1361 | if(GetNumbersFromValue(chValue, flOrigin, 3)!=3) return 0 ; // extract the numbers |
---|
1362 | swizzleFloat3(flOrigin) ; // fix coordinates |
---|
1363 | } |
---|
1364 | else |
---|
1365 | if(strcmp(chKey, "_color")==0) |
---|
1366 | { |
---|
1367 | if(GetNumbersFromValue(chValue, flColour, 3)!=3) return 0 ; // extract the numbers |
---|
1368 | } |
---|
1369 | else |
---|
1370 | if(strcmp(chKey, "light_center")==0) |
---|
1371 | { |
---|
1372 | if(GetNumbersFromValue(chValue, flCentre, 3)!=3) return 0 ; // extract the numbers |
---|
1373 | swizzleFloat3(flCentre) ; // fix coordinates |
---|
1374 | } |
---|
1375 | else |
---|
1376 | if(strcmp(chKey, "light_target")==0) |
---|
1377 | { |
---|
1378 | if(GetNumbersFromValue(chValue, flAimvec, 3)!=3) return 0 ; // extract the numbers |
---|
1379 | swizzleFloat3(flAimvec) ; // fix coordinates |
---|
1380 | bSpotLight=true ; // if there's a target key, then this must be a spotlight |
---|
1381 | } |
---|
1382 | else |
---|
1383 | if(strcmp(chKey, "light_radius")==0) |
---|
1384 | { |
---|
1385 | if(GetNumbersFromValue(chValue, flRadius, 3)!=3) return 0 ; // extract the numbers |
---|
1386 | swizzleFloat3(flRadius) ; // fix coordinates |
---|
1387 | // make sure all values are positive |
---|
1388 | flRadius[0]=fabs(flRadius[0]) ; |
---|
1389 | flRadius[1]=fabs(flRadius[1]) ; |
---|
1390 | flRadius[2]=fabs(flRadius[2]) ; |
---|
1391 | } |
---|
1392 | else |
---|
1393 | if(strcmp(chKey, "light_abc")==0) |
---|
1394 | { |
---|
1395 | if(GetNumbersFromValue(chValue, flTemp, 3)!=3) return 0 ; // extract the numbers |
---|
1396 | flAngle = flTemp[0] ; |
---|
1397 | flBrightness = flTemp[1] ; |
---|
1398 | flCutoff = flTemp[2] ; |
---|
1399 | } |
---|
1400 | else |
---|
1401 | if(strcmp(chKey, "texture")==0) |
---|
1402 | { |
---|
1403 | strcpy(Q3Texture.name, chValue) ; |
---|
1404 | } |
---|
1405 | if(strcmp(chKey, "light_node")==0) |
---|
1406 | { |
---|
1407 | if(GetNumbersFromValue(chValue, nTemp, 1)!=1) return 0 ; // extract the number |
---|
1408 | nLightNode = nTemp[0] ; |
---|
1409 | if((nLightNode<0) || (nLightNode>3)) return 0 ; // something dodgy about the lightnode number |
---|
1410 | } |
---|
1411 | |
---|
1412 | }// end if key ok |
---|
1413 | |
---|
1414 | |
---|
1415 | |
---|
1416 | }while(nKeyReturn==KEY_OK) ; // end do looping through keys |
---|
1417 | |
---|
1418 | |
---|
1419 | // return a fail if there was a problem with the keys |
---|
1420 | if(nKeyReturn==KEY_ERROR) return 0 ; |
---|
1421 | |
---|
1422 | |
---|
1423 | if(bSpotLight)// found a light_target so this must be a spotlight |
---|
1424 | { |
---|
1425 | // light settings. |
---|
1426 | NewLight.Position[0]=flOrigin[0]+flCentre[0] ; |
---|
1427 | NewLight.Position[1]=flOrigin[1]+flCentre[1] ; |
---|
1428 | NewLight.Position[2]=flOrigin[2]+flCentre[2] ; |
---|
1429 | |
---|
1430 | NewLight.Min[0]=flOrigin[0]-flRadius[0] ; |
---|
1431 | NewLight.Min[1]=flOrigin[1]-flRadius[1] ; |
---|
1432 | NewLight.Min[2]=flOrigin[2]-flRadius[2] ; |
---|
1433 | |
---|
1434 | NewLight.Max[0]=flOrigin[0]+flRadius[0] ; |
---|
1435 | NewLight.Max[1]=flOrigin[1]+flRadius[1] ; |
---|
1436 | NewLight.Max[2]=flOrigin[2]+flRadius[2] ; |
---|
1437 | |
---|
1438 | NewLight.Colour[0]=flColour[0] ; |
---|
1439 | NewLight.Colour[1]=flColour[1] ; |
---|
1440 | NewLight.Colour[2]=flColour[2] ; |
---|
1441 | |
---|
1442 | NewLight.Angle=flAngle ; |
---|
1443 | NewLight.Cutoff=flCutoff ; |
---|
1444 | NewLight.Brightness=flBrightness * BRIGHTNESSTWEAK ; |
---|
1445 | |
---|
1446 | |
---|
1447 | // direction light points, as a normal |
---|
1448 | flLength=sqrt( flAimvec[0]*flAimvec[0] + flAimvec[1]*flAimvec[1] + flAimvec[2]*flAimvec[2] ) ; |
---|
1449 | if(flLength>0.0f) |
---|
1450 | { |
---|
1451 | NewLight.Direction[0]=flAimvec[0]/flLength ; |
---|
1452 | NewLight.Direction[1]=flAimvec[1]/flLength ; |
---|
1453 | NewLight.Direction[2]=flAimvec[2]/flLength ; |
---|
1454 | } |
---|
1455 | else |
---|
1456 | { // default to pointing down |
---|
1457 | NewLight.Direction[0]=0.0f ; |
---|
1458 | NewLight.Direction[1]=1.0f ; |
---|
1459 | NewLight.Direction[2]=0.0f ; |
---|
1460 | } |
---|
1461 | |
---|
1462 | NewLight.ZoneCount=0 ; |
---|
1463 | NewLight.CentreZone=0 ; |
---|
1464 | |
---|
1465 | |
---|
1466 | if(Q3Texture.name[0]==0) |
---|
1467 | strcpy(Q3Texture.name, "spotlight.dds") ; |
---|
1468 | |
---|
1469 | NewLight.Texture=AddSpolightTexture(Q3Texture.name) ; |
---|
1470 | |
---|
1471 | |
---|
1472 | if(NewLight.Texture==ADDSPOTLIGHTTEXTURE_FAIL) |
---|
1473 | return 0 ; // failure |
---|
1474 | |
---|
1475 | //AddTextureUnique(Q3Texture) ; |
---|
1476 | /* |
---|
1477 | // add the light's texture index |
---|
1478 | if(Q3Texture.name[0]==0) |
---|
1479 | NewLight.Texture=m_nDefaultTextureIndexSpotlight ; |
---|
1480 | else |
---|
1481 | { |
---|
1482 | NewLight.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index |
---|
1483 | if(NewLight.Texture==ADDTEXTUREUNIQUE_FAIL) |
---|
1484 | return 0 ; |
---|
1485 | } |
---|
1486 | */ |
---|
1487 | |
---|
1488 | return AddLight(NewLight) ; |
---|
1489 | } |
---|
1490 | else // add a non-shadowing deferred shading point light |
---|
1491 | { |
---|
1492 | // light settings. |
---|
1493 | NewLamp.Position[0]=flOrigin[0]+flCentre[0] ; |
---|
1494 | NewLamp.Position[1]=flOrigin[1]+flCentre[1] ; |
---|
1495 | NewLamp.Position[2]=flOrigin[2]+flCentre[2] ; |
---|
1496 | |
---|
1497 | NewLamp.Min[0]=flOrigin[0]-flRadius[0] ; |
---|
1498 | NewLamp.Min[1]=flOrigin[1]-flRadius[1] ; |
---|
1499 | NewLamp.Min[2]=flOrigin[2]-flRadius[2] ; |
---|
1500 | |
---|
1501 | NewLamp.Max[0]=flOrigin[0]+flRadius[0] ; |
---|
1502 | NewLamp.Max[1]=flOrigin[1]+flRadius[1] ; |
---|
1503 | NewLamp.Max[2]=flOrigin[2]+flRadius[2] ; |
---|
1504 | |
---|
1505 | NewLamp.Colour[0]=flColour[0] ; |
---|
1506 | NewLamp.Colour[1]=flColour[1] ; |
---|
1507 | NewLamp.Colour[2]=flColour[2] ; |
---|
1508 | |
---|
1509 | NewLamp.Brightness=flBrightness * BRIGHTNESSTWEAK ; |
---|
1510 | |
---|
1511 | NewLamp.LightNode=nLightNode ; // typically -1, but may be 0 to 3 if this lamp is the node for some TexLamp freeform deferred shading geometry. |
---|
1512 | |
---|
1513 | |
---|
1514 | // Note that m_pLamp.Zone will be set after we first convert lamps into triangles and then |
---|
1515 | // assign those triangles to zones. At that point, if the assigned triangle is also flagged as |
---|
1516 | // coming from a lamp, then the lamp's list of zones will be updated. |
---|
1517 | |
---|
1518 | // add the light's texture index |
---|
1519 | if(Q3Texture.name[0]==0) |
---|
1520 | { |
---|
1521 | if(nLightNode==-1) |
---|
1522 | NewLamp.Texture=m_nDefaultTextureIndexLamp ; // normal 1 pass deferred shading |
---|
1523 | else |
---|
1524 | NewLamp.Texture=m_nDefaultTextureIndexLamp2Pass ; // special 2 pass deferred shading to texlamps |
---|
1525 | } |
---|
1526 | else |
---|
1527 | { |
---|
1528 | NewLamp.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index |
---|
1529 | if(NewLamp.Texture==ADDTEXTUREUNIQUE_FAIL) |
---|
1530 | return 0 ; |
---|
1531 | } |
---|
1532 | |
---|
1533 | return AddLamp(NewLamp) ; |
---|
1534 | } |
---|
1535 | |
---|
1536 | } |
---|
1537 | |
---|
1538 | // adds a spotlight texture name if it is unique, returns the index to that texture name either way. |
---|
1539 | // returns ADDSPOTLIGHTTEXTURE_FAIL on a fail |
---|
1540 | |
---|
1541 | int Q3Map::AddSpolightTexture(char TEXNAME[]) |
---|
1542 | { |
---|
1543 | if((strlen(TEXNAME)>Q3NAMESIZE) || (m_nMaxSpotlightTexture>=MAX_PROJECTORTEX)) |
---|
1544 | return ADDSPOTLIGHTTEXTURE_FAIL ; |
---|
1545 | |
---|
1546 | |
---|
1547 | // scan through all the newly added textures so far and see if this one already exists. |
---|
1548 | int nTexture=0 ; |
---|
1549 | int nPos=0 ; |
---|
1550 | |
---|
1551 | bool bMatch ; |
---|
1552 | |
---|
1553 | for(nTexture=0 ; nTexture<m_nMaxSpotlightTexture ; nTexture++) |
---|
1554 | { |
---|
1555 | bMatch=true ; |
---|
1556 | // scan through the characters of the texture names, comparing them. |
---|
1557 | for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++) |
---|
1558 | { |
---|
1559 | // do the two textures have a difference in the name at this position? |
---|
1560 | if(m_chSpotlightTexture[nTexture][nPos]!=TEXNAME[nPos]) |
---|
1561 | { |
---|
1562 | bMatch=false ; |
---|
1563 | break ; |
---|
1564 | } |
---|
1565 | |
---|
1566 | // is it the end of the texture name? |
---|
1567 | if(TEXNAME[nPos]=='\0') // end of texture |
---|
1568 | break ; |
---|
1569 | |
---|
1570 | }// end scanning name |
---|
1571 | |
---|
1572 | if(bMatch) // found a match, so return ok but don't add a texture |
---|
1573 | return nTexture ; // we don't add any new texture, return this texture's index |
---|
1574 | } |
---|
1575 | |
---|
1576 | // if we got this far, we must have a unique texture |
---|
1577 | strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], TEXNAME) ; |
---|
1578 | m_nMaxSpotlightTexture++ ; |
---|
1579 | |
---|
1580 | return m_nMaxSpotlightTexture-1 ; // return this new texture's index |
---|
1581 | |
---|
1582 | } |
---|
1583 | |
---|
1584 | |
---|
1585 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
1586 | |
---|
1587 | |
---|
1588 | int Q3Map::initFaces(void) |
---|
1589 | { |
---|
1590 | |
---|
1591 | m_nGroup=0 ; // reset the group counter, used to work out transparent groupings for triangles. |
---|
1592 | |
---|
1593 | Q3BspFace_t *faces = getFaces(); |
---|
1594 | |
---|
1595 | m_BspFaces = new Q3BspFaceRenderer[m_iNumFaces]; |
---|
1596 | if(m_BspFaces==NULL) return 0 ; // fail, out of memory. |
---|
1597 | m_NumBspFaces = m_iNumFaces; |
---|
1598 | |
---|
1599 | |
---|
1600 | for (int i=0; i < m_NumBspFaces; i++) |
---|
1601 | { |
---|
1602 | m_BspFaces[i].lm_index = faces[i].lm_index; |
---|
1603 | m_BspFaces[i].meshvert = faces[i].meshvert; |
---|
1604 | m_BspFaces[i].n_meshverts = faces[i].n_meshverts; |
---|
1605 | m_BspFaces[i].n_vertexes = faces[i].n_vertexes; |
---|
1606 | for (int j=0; j<3; j++) |
---|
1607 | m_BspFaces[i].normal[j] = faces[i].normal[j]; |
---|
1608 | m_BspFaces[i].texture = faces[i].texture; |
---|
1609 | m_BspFaces[i].type = faces[i].type; |
---|
1610 | m_BspFaces[i].vertex = faces[i].vertex; |
---|
1611 | |
---|
1612 | m_BspFaces[i].n_triangles = m_BspFaces[i].n_meshverts / 3; |
---|
1613 | |
---|
1614 | if (m_BspFaces[i].type == PATCH) |
---|
1615 | { |
---|
1616 | m_BspFaces[i].patch = handlePatch(i); |
---|
1617 | } |
---|
1618 | else |
---|
1619 | { |
---|
1620 | m_BspFaces[i].patch = NULL; |
---|
1621 | } |
---|
1622 | |
---|
1623 | |
---|
1624 | } |
---|
1625 | |
---|
1626 | |
---|
1627 | // check patches aren't degenerate |
---|
1628 | int numIndex = 0; |
---|
1629 | int numVertex = 0; |
---|
1630 | |
---|
1631 | |
---|
1632 | for (int i=0; i < m_NumBspFaces; i++) |
---|
1633 | { |
---|
1634 | |
---|
1635 | numIndex = 0; |
---|
1636 | numVertex = 0; |
---|
1637 | |
---|
1638 | if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL)) |
---|
1639 | { |
---|
1640 | for (int j=0; j < m_BspFaces[i].patch->size; j++) |
---|
1641 | { |
---|
1642 | numIndex += m_BspFaces[i].patch->bezier[j].mNumIndex; |
---|
1643 | numVertex += m_BspFaces[i].patch->bezier[j].mNumVertex; |
---|
1644 | } |
---|
1645 | |
---|
1646 | if((numIndex==0) || (numVertex==0)) |
---|
1647 | { |
---|
1648 | DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ; |
---|
1649 | DELETE_POINTER( m_BspFaces[i].patch ) ; |
---|
1650 | } |
---|
1651 | |
---|
1652 | }// end if patch |
---|
1653 | |
---|
1654 | |
---|
1655 | }// end for |
---|
1656 | |
---|
1657 | |
---|
1658 | |
---|
1659 | // copy the vertices over. |
---|
1660 | // We need to work on a copy because we need to create new verts when splitting triangles that cross subzones, and for patches |
---|
1661 | for(int i=0 ; i<m_iNumVertices ; i++) |
---|
1662 | { |
---|
1663 | m_pVertex[i]=m_pVertices[i] ; |
---|
1664 | m_nVertexMax++ ; // need to update this manually since we aren't adding new verts, but filling in the original mem. |
---|
1665 | } |
---|
1666 | |
---|
1667 | |
---|
1668 | return 1 ; |
---|
1669 | |
---|
1670 | } |
---|
1671 | |
---|
1672 | |
---|
1673 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
1674 | // |
---|
1675 | // stuff for assigning triangles to subzones, splitting them where necessary. |
---|
1676 | // |
---|
1677 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
1678 | |
---|
1679 | void Q3Map::SetupZones(void) |
---|
1680 | { |
---|
1681 | int nSubZone=0 ; |
---|
1682 | int nZone=0 ; |
---|
1683 | int nPos=0 ; |
---|
1684 | |
---|
1685 | float flMinX=0.0f ; |
---|
1686 | float flMinY=0.0f ; |
---|
1687 | float flMinZ=0.0f ; |
---|
1688 | float flMaxX=0.0f ; |
---|
1689 | float flMaxY=0.0f ; |
---|
1690 | float flMaxZ=0.0f ; |
---|
1691 | |
---|
1692 | m_nMaxZone=0 ; |
---|
1693 | |
---|
1694 | for(nZone=0 ; nZone<MAX_ZONE ; nZone++) |
---|
1695 | { |
---|
1696 | m_nZone[nZone][INDEX_SUBZONECOUNT]=0 ; |
---|
1697 | m_ZoneBoundary[nZone].Min[0]=MINMAXLIMIT ; |
---|
1698 | m_ZoneBoundary[nZone].Min[1]=MINMAXLIMIT ; |
---|
1699 | m_ZoneBoundary[nZone].Min[2]=MINMAXLIMIT ; |
---|
1700 | m_ZoneBoundary[nZone].Max[0]=-MINMAXLIMIT ; |
---|
1701 | m_ZoneBoundary[nZone].Max[1]=-MINMAXLIMIT ; |
---|
1702 | m_ZoneBoundary[nZone].Max[2]=-MINMAXLIMIT ; |
---|
1703 | } |
---|
1704 | |
---|
1705 | |
---|
1706 | // find the highest used zone number, then +1 to get our limit. |
---|
1707 | for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++) |
---|
1708 | if(m_pSubZones[nSubZone].Zone>m_nMaxZone) |
---|
1709 | m_nMaxZone=m_pSubZones[nSubZone].Zone ; |
---|
1710 | |
---|
1711 | m_nMaxZone++ ; // our limit |
---|
1712 | |
---|
1713 | |
---|
1714 | //char chMessage[1024] ; |
---|
1715 | |
---|
1716 | |
---|
1717 | // fill in what subzones are in each zone |
---|
1718 | for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++) |
---|
1719 | { |
---|
1720 | |
---|
1721 | |
---|
1722 | nZone=m_pSubZones[nSubZone].Zone ; |
---|
1723 | |
---|
1724 | // find next empty slot in this zone |
---|
1725 | nPos=0 ; |
---|
1726 | while((nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT])) |
---|
1727 | nPos++ ; |
---|
1728 | |
---|
1729 | // if there's room, add the subzone to this zone |
---|
1730 | if(nPos<MAX_SUBZONEPERZONE) |
---|
1731 | { |
---|
1732 | m_nZone[nZone][nPos]=nSubZone ; |
---|
1733 | |
---|
1734 | // limits used for cutting up lights (not useful for other boundary stuff, check subzones instead) |
---|
1735 | if(m_pSubZones[nSubZone].Min[0]<m_ZoneBoundary[nZone].Min[0]) |
---|
1736 | m_ZoneBoundary[nZone].Min[0]= m_pSubZones[nSubZone].Min[0] ; |
---|
1737 | if(m_pSubZones[nSubZone].Min[1]<m_ZoneBoundary[nZone].Min[1]) |
---|
1738 | m_ZoneBoundary[nZone].Min[1]= m_pSubZones[nSubZone].Min[1] ; |
---|
1739 | if(m_pSubZones[nSubZone].Min[2]<m_ZoneBoundary[nZone].Min[2]) |
---|
1740 | m_ZoneBoundary[nZone].Min[2]= m_pSubZones[nSubZone].Min[2] ; |
---|
1741 | |
---|
1742 | if(m_pSubZones[nSubZone].Max[0]>m_ZoneBoundary[nZone].Max[0]) |
---|
1743 | m_ZoneBoundary[nZone].Max[0]= m_pSubZones[nSubZone].Max[0] ; |
---|
1744 | if(m_pSubZones[nSubZone].Max[1]>m_ZoneBoundary[nZone].Max[1]) |
---|
1745 | m_ZoneBoundary[nZone].Max[1]= m_pSubZones[nSubZone].Max[1] ; |
---|
1746 | if(m_pSubZones[nSubZone].Max[2]>m_ZoneBoundary[nZone].Max[2]) |
---|
1747 | m_ZoneBoundary[nZone].Max[2]= m_pSubZones[nSubZone].Max[2] ; |
---|
1748 | |
---|
1749 | m_nZone[nZone][INDEX_SUBZONECOUNT]++ ; |
---|
1750 | } |
---|
1751 | |
---|
1752 | |
---|
1753 | } |
---|
1754 | |
---|
1755 | |
---|
1756 | } |
---|
1757 | |
---|
1758 | |
---|
1759 | // work out what zone each triangle is in. |
---|
1760 | // if it is in more than one, cut it up into smaller triangles that are only in one zone each. |
---|
1761 | int Q3Map::AssignTrianglesToZones(void) |
---|
1762 | { |
---|
1763 | int nCurrentTriangle=0 ; |
---|
1764 | int nZone=0 ; |
---|
1765 | |
---|
1766 | |
---|
1767 | /* |
---|
1768 | char chMessage[1024] ; |
---|
1769 | float flPos[3] ; |
---|
1770 | int nTri=0 ; |
---|
1771 | float flVert[3][3] ; |
---|
1772 | |
---|
1773 | |
---|
1774 | for(nTri=0 ; nTri<m_nTriangleMax ; nTri++) |
---|
1775 | { |
---|
1776 | flVert[0][0]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[0] ; |
---|
1777 | flVert[0][1]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[1] ; |
---|
1778 | flVert[0][2]=m_pVertex[ m_pTriangle[nTri].VIndex[0] ].position[2] ; |
---|
1779 | |
---|
1780 | flVert[1][0]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[0] ; |
---|
1781 | flVert[1][1]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[1] ; |
---|
1782 | flVert[1][2]=m_pVertex[ m_pTriangle[nTri].VIndex[1] ].position[2] ; |
---|
1783 | |
---|
1784 | flVert[2][0]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[0] ; |
---|
1785 | flVert[2][1]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[1] ; |
---|
1786 | flVert[2][2]=m_pVertex[ m_pTriangle[nTri].VIndex[2] ].position[2] ; |
---|
1787 | |
---|
1788 | |
---|
1789 | flPos[0]=(flVert[0][0]+flVert[1][0]+flVert[2][0])/3.0f ; |
---|
1790 | flPos[1]=(flVert[0][1]+flVert[1][1]+flVert[2][1])/3.0f ; |
---|
1791 | flPos[2]=(flVert[0][2]+flVert[1][2]+flVert[2][2])/3.0f ; |
---|
1792 | |
---|
1793 | nZone=0 ; |
---|
1794 | while((nZone<m_iNumSubZones) && !PointInZone(flPos, nZone)) |
---|
1795 | nZone++ ; |
---|
1796 | |
---|
1797 | |
---|
1798 | |
---|
1799 | |
---|
1800 | } |
---|
1801 | */ |
---|
1802 | |
---|
1803 | |
---|
1804 | |
---|
1805 | for(nCurrentTriangle=0 ; nCurrentTriangle<m_nTriangleMax ; nCurrentTriangle++) |
---|
1806 | { |
---|
1807 | if(!SetupTriangleZone(nCurrentTriangle)) return 0 ; // what zone completely contains this triangle, if any |
---|
1808 | |
---|
1809 | }// end for current triangle |
---|
1810 | |
---|
1811 | return 1 ; |
---|
1812 | } |
---|
1813 | |
---|
1814 | // return the zone this triangle is in, or -1 if it is not entirely contained by any zone |
---|
1815 | // this is also a convienient spot for us to update Lamp zones when we discover what zones its triangles are in, |
---|
1816 | // and also a handy place to note if the triangle is a TexLamp or not |
---|
1817 | // (TexLamp is free form geometry that is bound to a lamp and gets converted to deferred shading lights, allowing us to do fake shadowing) |
---|
1818 | |
---|
1819 | int Q3Map::FindTriangleZone(int nTriangle) |
---|
1820 | { |
---|
1821 | int nZone=0 ; |
---|
1822 | int nSubZone=0 ; |
---|
1823 | int nPos=0 ; |
---|
1824 | bool bVertInSubZone=false ; |
---|
1825 | int nVert=0 ; |
---|
1826 | bool bTriangleInZone=false ; |
---|
1827 | int nMaxSubZone=m_iNumSubZones ; |
---|
1828 | float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points. |
---|
1829 | // we need the edge points, since it's possible for all the |
---|
1830 | // triangle verts to be in one L shaped zone but the triangle they form not be in that zone. |
---|
1831 | // (such as if there's a vert at the corner and two ends of the "L") |
---|
1832 | |
---|
1833 | |
---|
1834 | flVert[0][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0] ; |
---|
1835 | flVert[0][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1] ; |
---|
1836 | flVert[0][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2] ; |
---|
1837 | |
---|
1838 | flVert[1][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0] ; |
---|
1839 | flVert[1][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1] ; |
---|
1840 | flVert[1][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2] ; |
---|
1841 | |
---|
1842 | flVert[2][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0] ; |
---|
1843 | flVert[2][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1] ; |
---|
1844 | flVert[2][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2] ; |
---|
1845 | |
---|
1846 | flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ; |
---|
1847 | flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ; |
---|
1848 | flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ; |
---|
1849 | |
---|
1850 | flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ; |
---|
1851 | flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ; |
---|
1852 | flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ; |
---|
1853 | |
---|
1854 | flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ; |
---|
1855 | flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ; |
---|
1856 | flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ; |
---|
1857 | |
---|
1858 | |
---|
1859 | // scan through the zones until: |
---|
1860 | // a) we find a zone that completely contains the six vertices |
---|
1861 | // b) we run out of zones. |
---|
1862 | |
---|
1863 | |
---|
1864 | do |
---|
1865 | { |
---|
1866 | nVert=0 ; |
---|
1867 | bTriangleInZone=false ; |
---|
1868 | |
---|
1869 | // scan through the verts until: |
---|
1870 | // a) we find a vert that isn't in this zone |
---|
1871 | // b) we run out of verts |
---|
1872 | |
---|
1873 | do |
---|
1874 | { |
---|
1875 | |
---|
1876 | // scan through the zone's subzones until: |
---|
1877 | // a) we find one that contains this vert, |
---|
1878 | // b) we hit the subzoneperzone limit, |
---|
1879 | // c) this zone runs out of subzones |
---|
1880 | |
---|
1881 | nPos=0 ; |
---|
1882 | do |
---|
1883 | { |
---|
1884 | bVertInSubZone=PointInSubZone(flVert[nVert], m_nZone[nZone][nPos]) ; |
---|
1885 | }while( !bVertInSubZone && (++nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT])) ; |
---|
1886 | |
---|
1887 | // if bVertInSubZone is false, we found a vert that isn't in this zone. |
---|
1888 | |
---|
1889 | }while(bVertInSubZone && (++nVert<6)) ; |
---|
1890 | |
---|
1891 | if(bVertInSubZone) bTriangleInZone=true ; |
---|
1892 | |
---|
1893 | }while(!bTriangleInZone && (++nZone<m_nMaxZone)) ; |
---|
1894 | |
---|
1895 | |
---|
1896 | |
---|
1897 | |
---|
1898 | |
---|
1899 | if(!bTriangleInZone) |
---|
1900 | return -1 ; |
---|
1901 | else |
---|
1902 | { |
---|
1903 | |
---|
1904 | // if this triangle came from a lamp entity, we note in that lamp entity that it touches this zone |
---|
1905 | int nLamp=m_pTriangle[nTriangle].Lamp ; |
---|
1906 | if(nLamp>-1) // if we have a lamp |
---|
1907 | { |
---|
1908 | |
---|
1909 | |
---|
1910 | int nSlot=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ; |
---|
1911 | |
---|
1912 | if(nSlot<MAX_ZONEPERLIGHT) // if the lamp isn't maxed out on zones |
---|
1913 | { |
---|
1914 | // check if we already have this zone recorded |
---|
1915 | int nCheckSlot=0 ; |
---|
1916 | int nFoundDuplicate=0 ; |
---|
1917 | for(nCheckSlot=0 ; nCheckSlot<nSlot ; nCheckSlot++) |
---|
1918 | if(m_pLamp[nLamp].Zone[nCheckSlot]==nZone) |
---|
1919 | { |
---|
1920 | nFoundDuplicate=1 ; |
---|
1921 | break ; |
---|
1922 | } |
---|
1923 | |
---|
1924 | if(!nFoundDuplicate) |
---|
1925 | { |
---|
1926 | m_pLamp[nLamp].Zone[nSlot]=nZone ; // write the zone into this slot |
---|
1927 | m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT]++ ; // note that we have one more zone |
---|
1928 | } |
---|
1929 | |
---|
1930 | } |
---|
1931 | } |
---|
1932 | |
---|
1933 | |
---|
1934 | // if this triangle is a TexLamp triangle (free form deferred lighting shapes) |
---|
1935 | // then we remember this, in order to make assigning it to a lamp faster |
---|
1936 | int nTexture=m_pTriangle[nTriangle].Texture ; |
---|
1937 | if((nTexture==m_nBZN_LightNode0) || (nTexture==m_nBZN_LightNode1) || (nTexture==m_nBZN_LightNode2) || (nTexture==m_nBZN_LightNode3)) |
---|
1938 | if(!AddTexLamp(nTriangle)) |
---|
1939 | return ADDTEXLAMP_FAIL ; //if we failed to note the texlamp (probably out of memory), the whole level load will fail. |
---|
1940 | |
---|
1941 | |
---|
1942 | // finally, return the zone the triangle is in. |
---|
1943 | return nZone ; |
---|
1944 | } |
---|
1945 | } |
---|
1946 | |
---|
1947 | |
---|
1948 | |
---|
1949 | // work out what zone a triangle is in, cut it up if it's in more than one. |
---|
1950 | int Q3Map::SetupTriangleZone(int nTriangle) |
---|
1951 | { |
---|
1952 | |
---|
1953 | |
---|
1954 | int nZone=0 ; |
---|
1955 | |
---|
1956 | nZone=FindTriangleZone(nTriangle) ; |
---|
1957 | |
---|
1958 | if(nZone==ADDTEXLAMP_FAIL) |
---|
1959 | return 0 ; |
---|
1960 | |
---|
1961 | |
---|
1962 | if(nZone!=-1) // triangle was completely in a zone |
---|
1963 | m_pTriangle[nTriangle].Zone=nZone ; |
---|
1964 | else |
---|
1965 | { |
---|
1966 | // This triangle is in more than one zone. (Or no subzone at all) |
---|
1967 | // we chop it up along the edges of every subzone it is in (regardless of whether they are a common zone or not) |
---|
1968 | // so that the resulting triangles will all be in just one subzone, and therefore in only one zone. |
---|
1969 | // this might produce a few extra triangles more than we strictly need, since some will both be in the same zone, |
---|
1970 | // but it is simple and the extra triangles are trivial in number. |
---|
1971 | |
---|
1972 | // As we go to each new cut plane, it must be applied progressively to all newly created triangles too. |
---|
1973 | |
---|
1974 | int nInitialTrianglePos=m_nTriangleMax ; // where we start adding new triangles |
---|
1975 | |
---|
1976 | int nTriLoop=0 ; |
---|
1977 | int nTriangleToCut=0 ; |
---|
1978 | int nMaxTriangle=0 ; |
---|
1979 | int nSide=0 ; |
---|
1980 | int nAxis=0 ; |
---|
1981 | float flCutPos=0.0f ; |
---|
1982 | int nSubZone=0 ; |
---|
1983 | int nMaxSubZone=m_iNumSubZones ; |
---|
1984 | int nVert=0 ; |
---|
1985 | float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points. |
---|
1986 | // we need the edge points, since it's possible for all the |
---|
1987 | // triangle verts to be in one L shaped zone but the triangle they form not be in that zone. |
---|
1988 | // (such as if there's a vert at the corner and two ends of the "L") |
---|
1989 | |
---|
1990 | |
---|
1991 | flVert[0][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0] ; |
---|
1992 | flVert[0][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1] ; |
---|
1993 | flVert[0][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2] ; |
---|
1994 | |
---|
1995 | flVert[1][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0] ; |
---|
1996 | flVert[1][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1] ; |
---|
1997 | flVert[1][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2] ; |
---|
1998 | |
---|
1999 | flVert[2][0]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0] ; |
---|
2000 | flVert[2][1]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1] ; |
---|
2001 | flVert[2][2]=m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2] ; |
---|
2002 | |
---|
2003 | flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ; |
---|
2004 | flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ; |
---|
2005 | flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ; |
---|
2006 | |
---|
2007 | flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ; |
---|
2008 | flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ; |
---|
2009 | flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ; |
---|
2010 | |
---|
2011 | flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ; |
---|
2012 | flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ; |
---|
2013 | flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ; |
---|
2014 | |
---|
2015 | |
---|
2016 | |
---|
2017 | |
---|
2018 | for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++) |
---|
2019 | { |
---|
2020 | // are any of our original verts in this subzone? |
---|
2021 | |
---|
2022 | nVert=0 ; |
---|
2023 | while( !PointInSubZone(flVert[nVert], nSubZone) && (++nVert<6)) ; |
---|
2024 | |
---|
2025 | if(nVert<6) // one of the verts must have been in this subzone. |
---|
2026 | { |
---|
2027 | // cutup all triangles by the sides of this subzone. |
---|
2028 | // we'll need to cut more and more triangles as this progresses. (or at least test if they need to be cut) |
---|
2029 | for(nSide=0 ; nSide<6 ; nSide++) |
---|
2030 | { |
---|
2031 | switch(nSide) |
---|
2032 | { |
---|
2033 | case 0: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Min[0] ; break ; |
---|
2034 | case 1: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Max[0] ; break ; |
---|
2035 | case 2: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Min[1] ; break ; |
---|
2036 | case 3: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Max[1] ; break ; |
---|
2037 | case 4: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Min[2] ; break ; |
---|
2038 | case 5: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Max[2] ; break ; |
---|
2039 | } |
---|
2040 | |
---|
2041 | |
---|
2042 | nMaxTriangle=m_nTriangleMax-nInitialTrianglePos ; // how may new triangles have been created since we first started cutting the original. |
---|
2043 | |
---|
2044 | for(nTriLoop=-1 ; nTriLoop<nMaxTriangle ; nTriLoop++) |
---|
2045 | { |
---|
2046 | // work out if we are cutting up the original triangle or one of the newly created ones. |
---|
2047 | if(nTriLoop==-1) |
---|
2048 | nTriangleToCut=nTriangle ; // the original triangle, perhaps heavily cutup by now. |
---|
2049 | else |
---|
2050 | nTriangleToCut=nInitialTrianglePos+nTriLoop ; // one of the newly created triangles. |
---|
2051 | |
---|
2052 | if(!SplitTriangle(nTriangleToCut, nAxis, flCutPos)) return 0 ; // cut up the triangle, fail if we're out of memory or whatever. |
---|
2053 | |
---|
2054 | |
---|
2055 | }// end for nTriLoop |
---|
2056 | |
---|
2057 | }// end cutting by each side of the subzone |
---|
2058 | |
---|
2059 | }// end if one of the verts was in this subzone |
---|
2060 | |
---|
2061 | }// end going through all subzones |
---|
2062 | |
---|
2063 | |
---|
2064 | // now that the triangle is well and truly chopped up, assign it a zone. |
---|
2065 | // Even though it should be entirely in a subzone by now, there's still the chance that |
---|
2066 | // it might not be inside any subzone at all. If so, it will be assigned -1 zone and |
---|
2067 | // exluded from the manualobjects |
---|
2068 | |
---|
2069 | m_pTriangle[nTriangle].Zone=FindTriangleZone(nTriangle) ; |
---|
2070 | |
---|
2071 | // we don't have to worry about assigning zones to the newly created triangles, |
---|
2072 | // they'll get theirs when the AssignTrianglesToZones loop reaches them at the end. |
---|
2073 | |
---|
2074 | }// end if triangle was in more than one subzone (or no subzone at all) |
---|
2075 | |
---|
2076 | return 1 ; |
---|
2077 | } |
---|
2078 | |
---|
2079 | |
---|
2080 | // cut a triangle along some axial plane, turning into 2 or 3 triangles. |
---|
2081 | // If the plane doesn't go through the triangle then nothing will happen. |
---|
2082 | int Q3Map::SplitTriangle(int nTriangle, int nAxis, float flCutPos) |
---|
2083 | { |
---|
2084 | |
---|
2085 | triangle_t NewTri ; |
---|
2086 | |
---|
2087 | // these will stay -1 if no vert is created, else will be index of the new vert |
---|
2088 | int nABNum=-1 ; |
---|
2089 | int nBCNum=-1 ; |
---|
2090 | int nCANum=-1 ; |
---|
2091 | |
---|
2092 | Q3BspVertex VertA = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[0] ] ; |
---|
2093 | Q3BspVertex VertB = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[1] ] ; |
---|
2094 | Q3BspVertex VertC = m_pVertex[ m_pTriangle[ nTriangle ].VIndex[2] ] ; |
---|
2095 | Q3BspVertex VertexAB ; |
---|
2096 | Q3BspVertex VertexBC ; |
---|
2097 | Q3BspVertex VertexCA ; |
---|
2098 | |
---|
2099 | float flSpan=0.0f ; |
---|
2100 | float flCutSpan=0.0f ; |
---|
2101 | float flPercent=0.0f ; |
---|
2102 | |
---|
2103 | switch(nAxis) |
---|
2104 | { |
---|
2105 | |
---|
2106 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2107 | case AXIS_X: |
---|
2108 | |
---|
2109 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2110 | // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline. |
---|
2111 | if( |
---|
2112 | ((VertA.position[0]<flCutPos-SUBZONE_EPSILON) && (VertB.position[0]>flCutPos+SUBZONE_EPSILON)) |
---|
2113 | || |
---|
2114 | ((VertA.position[0]>flCutPos+SUBZONE_EPSILON) && (VertB.position[0]<flCutPos-SUBZONE_EPSILON)) |
---|
2115 | ) |
---|
2116 | { |
---|
2117 | // work out the span and percentage |
---|
2118 | if(VertA.position[0]<flCutPos) |
---|
2119 | { |
---|
2120 | flSpan=VertB.position[0]-VertA.position[0] ; |
---|
2121 | flCutSpan=flCutPos-VertA.position[0] ; |
---|
2122 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2123 | } |
---|
2124 | else |
---|
2125 | { |
---|
2126 | flSpan=VertA.position[0]-VertB.position[0] ; |
---|
2127 | flCutSpan=flCutPos-VertB.position[0] ; |
---|
2128 | flPercent=flCutSpan/flSpan ; |
---|
2129 | } |
---|
2130 | |
---|
2131 | CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ; |
---|
2132 | nABNum=m_nVertexMax ; |
---|
2133 | if(!AddVertex(VertexAB)) |
---|
2134 | return 0 ; |
---|
2135 | }// end if need create VertexAB |
---|
2136 | |
---|
2137 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2138 | // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline. |
---|
2139 | if( |
---|
2140 | ((VertB.position[0]<flCutPos-SUBZONE_EPSILON) && (VertC.position[0]>flCutPos+SUBZONE_EPSILON)) |
---|
2141 | || |
---|
2142 | ((VertB.position[0]>flCutPos+SUBZONE_EPSILON) && (VertC.position[0]<flCutPos-SUBZONE_EPSILON)) |
---|
2143 | ) |
---|
2144 | { |
---|
2145 | // work out the span and percentage |
---|
2146 | if(VertB.position[0]<flCutPos) |
---|
2147 | { |
---|
2148 | flSpan=VertC.position[0]-VertB.position[0] ; |
---|
2149 | flCutSpan=flCutPos-VertB.position[0] ; |
---|
2150 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2151 | } |
---|
2152 | else |
---|
2153 | { |
---|
2154 | flSpan=VertB.position[0]-VertC.position[0] ; |
---|
2155 | flCutSpan=flCutPos-VertC.position[0] ; |
---|
2156 | flPercent=flCutSpan/flSpan ; |
---|
2157 | } |
---|
2158 | |
---|
2159 | CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ; |
---|
2160 | nBCNum=m_nVertexMax ; |
---|
2161 | if(!AddVertex(VertexBC)) |
---|
2162 | return 0 ; |
---|
2163 | |
---|
2164 | }// end if need create VertexBC |
---|
2165 | |
---|
2166 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2167 | // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline. |
---|
2168 | if( |
---|
2169 | ((VertC.position[0]<flCutPos) && (VertA.position[0]>flCutPos)) |
---|
2170 | || |
---|
2171 | ((VertC.position[0]>flCutPos) && (VertA.position[0]<flCutPos)) |
---|
2172 | ) |
---|
2173 | { |
---|
2174 | // work out the span and percentage |
---|
2175 | if(VertC.position[0]<flCutPos) |
---|
2176 | { |
---|
2177 | flSpan=VertA.position[0]-VertC.position[0] ; |
---|
2178 | flCutSpan=flCutPos-VertC.position[0] ; |
---|
2179 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2180 | } |
---|
2181 | else |
---|
2182 | { |
---|
2183 | flSpan=VertC.position[0]-VertA.position[0] ; |
---|
2184 | flCutSpan=flCutPos-VertA.position[0] ; |
---|
2185 | flPercent=flCutSpan/flSpan ; |
---|
2186 | } |
---|
2187 | |
---|
2188 | CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ; |
---|
2189 | nCANum=m_nVertexMax ; |
---|
2190 | if(!AddVertex(VertexCA)) |
---|
2191 | return 0 ; |
---|
2192 | |
---|
2193 | }// end if need create VertexCA |
---|
2194 | break ; |
---|
2195 | |
---|
2196 | |
---|
2197 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2198 | case AXIS_Y: |
---|
2199 | |
---|
2200 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2201 | // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline. |
---|
2202 | if( |
---|
2203 | ((VertA.position[1]<flCutPos-SUBZONE_EPSILON) && (VertB.position[1]>flCutPos+SUBZONE_EPSILON)) |
---|
2204 | || |
---|
2205 | ((VertA.position[1]>flCutPos+SUBZONE_EPSILON) && (VertB.position[1]<flCutPos-SUBZONE_EPSILON)) |
---|
2206 | ) |
---|
2207 | { |
---|
2208 | // work out the span and percentage |
---|
2209 | if(VertA.position[1]<flCutPos) |
---|
2210 | { |
---|
2211 | flSpan=VertB.position[1]-VertA.position[1] ; |
---|
2212 | flCutSpan=flCutPos-VertA.position[1] ; |
---|
2213 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2214 | } |
---|
2215 | else |
---|
2216 | { |
---|
2217 | flSpan=VertA.position[1]-VertB.position[1] ; |
---|
2218 | flCutSpan=flCutPos-VertB.position[1] ; |
---|
2219 | flPercent=flCutSpan/flSpan ; |
---|
2220 | } |
---|
2221 | |
---|
2222 | CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ; |
---|
2223 | nABNum=m_nVertexMax ; |
---|
2224 | if(!AddVertex(VertexAB)) |
---|
2225 | return 0 ; |
---|
2226 | }// end if need create VertexAB |
---|
2227 | |
---|
2228 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2229 | // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline. |
---|
2230 | if( |
---|
2231 | ((VertB.position[1]<flCutPos-SUBZONE_EPSILON) && (VertC.position[1]>flCutPos+SUBZONE_EPSILON)) |
---|
2232 | || |
---|
2233 | ((VertB.position[1]>flCutPos+SUBZONE_EPSILON) && (VertC.position[1]<flCutPos-SUBZONE_EPSILON)) |
---|
2234 | ) |
---|
2235 | { |
---|
2236 | // work out the span and percentage |
---|
2237 | if(VertB.position[1]<flCutPos) |
---|
2238 | { |
---|
2239 | flSpan=VertC.position[1]-VertB.position[1] ; |
---|
2240 | flCutSpan=flCutPos-VertB.position[1] ; |
---|
2241 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2242 | } |
---|
2243 | else |
---|
2244 | { |
---|
2245 | flSpan=VertB.position[1]-VertC.position[1] ; |
---|
2246 | flCutSpan=flCutPos-VertC.position[1] ; |
---|
2247 | flPercent=flCutSpan/flSpan ; |
---|
2248 | } |
---|
2249 | |
---|
2250 | CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ; |
---|
2251 | nBCNum=m_nVertexMax ; |
---|
2252 | if(!AddVertex(VertexBC)) |
---|
2253 | return 0 ; |
---|
2254 | |
---|
2255 | }// end if need create VertexBC |
---|
2256 | |
---|
2257 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2258 | // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline. |
---|
2259 | if( |
---|
2260 | ((VertC.position[1]<flCutPos) && (VertA.position[1]>flCutPos)) |
---|
2261 | || |
---|
2262 | ((VertC.position[1]>flCutPos) && (VertA.position[1]<flCutPos)) |
---|
2263 | ) |
---|
2264 | { |
---|
2265 | // work out the span and percentage |
---|
2266 | if(VertC.position[1]<flCutPos) |
---|
2267 | { |
---|
2268 | flSpan=VertA.position[1]-VertC.position[1] ; |
---|
2269 | flCutSpan=flCutPos-VertC.position[1] ; |
---|
2270 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2271 | } |
---|
2272 | else |
---|
2273 | { |
---|
2274 | flSpan=VertC.position[1]-VertA.position[1] ; |
---|
2275 | flCutSpan=flCutPos-VertA.position[1] ; |
---|
2276 | flPercent=flCutSpan/flSpan ; |
---|
2277 | } |
---|
2278 | |
---|
2279 | CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ; |
---|
2280 | nCANum=m_nVertexMax ; |
---|
2281 | if(!AddVertex(VertexCA)) |
---|
2282 | return 0 ; |
---|
2283 | |
---|
2284 | }// end if need create VertexCA |
---|
2285 | break ; |
---|
2286 | |
---|
2287 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2288 | case AXIS_Z: |
---|
2289 | |
---|
2290 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2291 | // if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline. |
---|
2292 | if( |
---|
2293 | ((VertA.position[2]<flCutPos-SUBZONE_EPSILON) && (VertB.position[2]>flCutPos+SUBZONE_EPSILON)) |
---|
2294 | || |
---|
2295 | ((VertA.position[2]>flCutPos+SUBZONE_EPSILON) && (VertB.position[2]<flCutPos-SUBZONE_EPSILON)) |
---|
2296 | ) |
---|
2297 | { |
---|
2298 | // work out the span and percentage |
---|
2299 | if(VertA.position[2]<flCutPos) |
---|
2300 | { |
---|
2301 | flSpan=VertB.position[2]-VertA.position[2] ; |
---|
2302 | flCutSpan=flCutPos-VertA.position[2] ; |
---|
2303 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2304 | } |
---|
2305 | else |
---|
2306 | { |
---|
2307 | flSpan=VertA.position[2]-VertB.position[2] ; |
---|
2308 | flCutSpan=flCutPos-VertB.position[2] ; |
---|
2309 | flPercent=flCutSpan/flSpan ; |
---|
2310 | } |
---|
2311 | |
---|
2312 | CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ; |
---|
2313 | nABNum=m_nVertexMax ; |
---|
2314 | if(!AddVertex(VertexAB)) |
---|
2315 | return 0 ; |
---|
2316 | }// end if need create VertexAB |
---|
2317 | |
---|
2318 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2319 | // if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline. |
---|
2320 | if( |
---|
2321 | ((VertB.position[2]<flCutPos-SUBZONE_EPSILON) && (VertC.position[2]>flCutPos+SUBZONE_EPSILON)) |
---|
2322 | || |
---|
2323 | ((VertB.position[2]>flCutPos+SUBZONE_EPSILON) && (VertC.position[2]<flCutPos-SUBZONE_EPSILON)) |
---|
2324 | ) |
---|
2325 | { |
---|
2326 | // work out the span and percentage |
---|
2327 | if(VertB.position[2]<flCutPos) |
---|
2328 | { |
---|
2329 | flSpan=VertC.position[2]-VertB.position[2] ; |
---|
2330 | flCutSpan=flCutPos-VertB.position[2] ; |
---|
2331 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2332 | } |
---|
2333 | else |
---|
2334 | { |
---|
2335 | flSpan=VertB.position[2]-VertC.position[2] ; |
---|
2336 | flCutSpan=flCutPos-VertC.position[2] ; |
---|
2337 | flPercent=flCutSpan/flSpan ; |
---|
2338 | } |
---|
2339 | |
---|
2340 | CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ; |
---|
2341 | nBCNum=m_nVertexMax ; |
---|
2342 | if(!AddVertex(VertexBC)) |
---|
2343 | return 0 ; |
---|
2344 | |
---|
2345 | }// end if need create VertexBC |
---|
2346 | |
---|
2347 | //////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2348 | // if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline. |
---|
2349 | if( |
---|
2350 | ((VertC.position[2]<flCutPos) && (VertA.position[2]>flCutPos)) |
---|
2351 | || |
---|
2352 | ((VertC.position[2]>flCutPos) && (VertA.position[2]<flCutPos)) |
---|
2353 | ) |
---|
2354 | { |
---|
2355 | // work out the span and percentage |
---|
2356 | if(VertC.position[2]<flCutPos) |
---|
2357 | { |
---|
2358 | flSpan=VertA.position[2]-VertC.position[2] ; |
---|
2359 | flCutSpan=flCutPos-VertC.position[2] ; |
---|
2360 | flPercent=1.0f-flCutSpan/flSpan ; |
---|
2361 | } |
---|
2362 | else |
---|
2363 | { |
---|
2364 | flSpan=VertC.position[2]-VertA.position[2] ; |
---|
2365 | flCutSpan=flCutPos-VertA.position[2] ; |
---|
2366 | flPercent=flCutSpan/flSpan ; |
---|
2367 | } |
---|
2368 | |
---|
2369 | CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ; |
---|
2370 | nCANum=m_nVertexMax ; |
---|
2371 | if(!AddVertex(VertexCA)) |
---|
2372 | return 0 ; |
---|
2373 | |
---|
2374 | }// end if need create VertexCA |
---|
2375 | break ; |
---|
2376 | |
---|
2377 | |
---|
2378 | } |
---|
2379 | |
---|
2380 | int nInitialTrianglePos=m_nTriangleMax ; // debugging |
---|
2381 | |
---|
2382 | // default parameters for all new triangles |
---|
2383 | NewTri.Texture = m_pTriangle[ nTriangle ].Texture ; |
---|
2384 | //NewTri.Lightmap = m_pTriangle[ nTriangle ].Lightmap ; // bzn doesn't use lightmaps |
---|
2385 | NewTri.Lamp = m_pTriangle[ nTriangle ].Lamp ; |
---|
2386 | NewTri.Group = m_pTriangle[ nTriangle ].Group ; |
---|
2387 | |
---|
2388 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
2389 | // now we create new triangles depending on the verts we created. |
---|
2390 | if((nABNum!=-1) && (nCANum!=-1)) |
---|
2391 | { |
---|
2392 | // add (AB, B, C) |
---|
2393 | NewTri.VIndex[0]=nABNum ; |
---|
2394 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2395 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2396 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2397 | |
---|
2398 | // add (C, CA, AB) |
---|
2399 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2400 | NewTri.VIndex[1]=nCANum ; |
---|
2401 | NewTri.VIndex[2]=nABNum ; |
---|
2402 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2403 | |
---|
2404 | // overwrite the original triangle with (A, AB, CA) |
---|
2405 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2406 | NewTri.VIndex[1]=nABNum ; |
---|
2407 | NewTri.VIndex[2]=nCANum ; |
---|
2408 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2409 | } |
---|
2410 | else |
---|
2411 | if((nABNum!=-1) && (nBCNum!=-1)) |
---|
2412 | { |
---|
2413 | // add (BC, C, A) |
---|
2414 | NewTri.VIndex[0]=nBCNum ; |
---|
2415 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2416 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2417 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2418 | |
---|
2419 | // add (A, AB, BC) |
---|
2420 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2421 | NewTri.VIndex[1]=nABNum ; |
---|
2422 | NewTri.VIndex[2]=nBCNum ; |
---|
2423 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2424 | |
---|
2425 | // overwrite the original triangle with (B, BC, AB) |
---|
2426 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2427 | NewTri.VIndex[1]=nBCNum ; |
---|
2428 | NewTri.VIndex[2]=nABNum ; |
---|
2429 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2430 | } |
---|
2431 | else |
---|
2432 | if((nBCNum!=-1) && (nCANum!=-1)) |
---|
2433 | { |
---|
2434 | // add (CA, A, B) |
---|
2435 | NewTri.VIndex[0]=nCANum ; |
---|
2436 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2437 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2438 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2439 | |
---|
2440 | // add (B, BC, CA) |
---|
2441 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2442 | NewTri.VIndex[1]=nBCNum ; |
---|
2443 | NewTri.VIndex[2]=nCANum ; |
---|
2444 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2445 | |
---|
2446 | // overwrite the original triangle with (C, CA, BC) |
---|
2447 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2448 | NewTri.VIndex[1]=nCANum ; |
---|
2449 | NewTri.VIndex[2]=nBCNum ; |
---|
2450 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2451 | } |
---|
2452 | else |
---|
2453 | if(nABNum!=-1) |
---|
2454 | { |
---|
2455 | // add (AB, B, C) |
---|
2456 | NewTri.VIndex[0]=nABNum ; |
---|
2457 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2458 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2459 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2460 | |
---|
2461 | // overwrite the original triangle with (A, AB, C) |
---|
2462 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2463 | NewTri.VIndex[1]=nABNum ; |
---|
2464 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2465 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2466 | } |
---|
2467 | else |
---|
2468 | if(nBCNum!=-1) |
---|
2469 | { |
---|
2470 | // add (BC, C, A) |
---|
2471 | NewTri.VIndex[0]=nBCNum ; |
---|
2472 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2473 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2474 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2475 | |
---|
2476 | // overwrite the original triangle with (B, BC, A) |
---|
2477 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2478 | NewTri.VIndex[1]=nBCNum ; |
---|
2479 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2480 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2481 | } |
---|
2482 | else |
---|
2483 | if(nCANum!=-1) |
---|
2484 | { |
---|
2485 | // add (CA, A, B) |
---|
2486 | NewTri.VIndex[0]=nCANum ; |
---|
2487 | NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ; |
---|
2488 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2489 | if(!AddTriangle(NewTri)) return 0 ; |
---|
2490 | |
---|
2491 | // overwrite the original triangle with (C, CA, B) |
---|
2492 | NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ; |
---|
2493 | NewTri.VIndex[1]=nCANum ; |
---|
2494 | NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ; |
---|
2495 | m_pTriangle[ nTriangle ]=NewTri ; |
---|
2496 | } |
---|
2497 | |
---|
2498 | return 1 ; |
---|
2499 | } |
---|
2500 | |
---|
2501 | void Q3Map::CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertexAB) |
---|
2502 | { |
---|
2503 | float flPercent1=1.0f-flPercent0 ; |
---|
2504 | |
---|
2505 | pVertexAB->color[0]=flPercent0*pVertA->color[0] + flPercent1*pVertB->color[0] ; |
---|
2506 | pVertexAB->color[1]=flPercent0*pVertA->color[1] + flPercent1*pVertB->color[1] ; |
---|
2507 | pVertexAB->color[2]=flPercent0*pVertA->color[2] + flPercent1*pVertB->color[2] ; |
---|
2508 | pVertexAB->color[3]=flPercent0*pVertA->color[3] + flPercent1*pVertB->color[3] ; |
---|
2509 | |
---|
2510 | pVertexAB->position[0]=flPercent0*pVertA->position[0] + flPercent1*pVertB->position[0] ; |
---|
2511 | pVertexAB->position[1]=flPercent0*pVertA->position[1] + flPercent1*pVertB->position[1] ; |
---|
2512 | pVertexAB->position[2]=flPercent0*pVertA->position[2] + flPercent1*pVertB->position[2] ; |
---|
2513 | |
---|
2514 | pVertexAB->texcoord[0][0]=flPercent0*pVertA->texcoord[0][0] + flPercent1*pVertB->texcoord[0][0] ; |
---|
2515 | pVertexAB->texcoord[0][1]=flPercent0*pVertA->texcoord[0][1] + flPercent1*pVertB->texcoord[0][1] ; |
---|
2516 | pVertexAB->texcoord[1][0]=flPercent0*pVertA->texcoord[1][0] + flPercent1*pVertB->texcoord[1][0] ; |
---|
2517 | pVertexAB->texcoord[1][1]=flPercent0*pVertA->texcoord[1][1] + flPercent1*pVertB->texcoord[1][1] ; |
---|
2518 | |
---|
2519 | pVertexAB->normal[0]=flPercent0*pVertA->normal[0] + flPercent1*pVertB->normal[0] ; |
---|
2520 | pVertexAB->normal[1]=flPercent0*pVertA->normal[1] + flPercent1*pVertB->normal[1] ; |
---|
2521 | pVertexAB->normal[2]=flPercent0*pVertA->normal[2] + flPercent1*pVertB->normal[2] ; |
---|
2522 | // normalize |
---|
2523 | float flLen=sqrt(pVertexAB->normal[0]*pVertexAB->normal[0] + pVertexAB->normal[1]*pVertexAB->normal[1] + pVertexAB->normal[2]*pVertexAB->normal[2]) ; |
---|
2524 | if(flLen!=0.0f) // don't divide by zero... but normal is messed up. |
---|
2525 | { |
---|
2526 | pVertexAB->normal[0]/=flLen ; |
---|
2527 | pVertexAB->normal[1]/=flLen ; |
---|
2528 | pVertexAB->normal[2]/=flLen ; |
---|
2529 | } |
---|
2530 | else |
---|
2531 | { |
---|
2532 | // default a messed up normal to point upward |
---|
2533 | pVertexAB->normal[0]=0.0f ; |
---|
2534 | pVertexAB->normal[1]=1.0f ; |
---|
2535 | pVertexAB->normal[2]=0.0f ; |
---|
2536 | } |
---|
2537 | } |
---|
2538 | |
---|
2539 | // returns the next subzone a point is in after the start subzone, or -1 if there are no more subzones |
---|
2540 | int Q3Map::GetNextSubZone(float *flPoint, int nStart, int nMax) |
---|
2541 | { |
---|
2542 | while(++nStart<nMax) |
---|
2543 | if(PointInSubZone(flPoint, nStart)) |
---|
2544 | break ; |
---|
2545 | |
---|
2546 | if(nStart==nMax) |
---|
2547 | return -1 ; |
---|
2548 | else |
---|
2549 | return nStart ; |
---|
2550 | } |
---|
2551 | |
---|
2552 | // returns true if a point is in a subzone. |
---|
2553 | bool Q3Map::PointInSubZone(float *flPoint, int nSubZone) |
---|
2554 | { |
---|
2555 | if( |
---|
2556 | (flPoint[0]>=m_pSubZones[nSubZone].Min[0]-SUBZONE_EPSILON) && (flPoint[0]<=m_pSubZones[nSubZone].Max[0]+SUBZONE_EPSILON) |
---|
2557 | &&(flPoint[1]>=m_pSubZones[nSubZone].Min[1]-SUBZONE_EPSILON) && (flPoint[1]<=m_pSubZones[nSubZone].Max[1]+SUBZONE_EPSILON) |
---|
2558 | &&(flPoint[2]>=m_pSubZones[nSubZone].Min[2]-SUBZONE_EPSILON) && (flPoint[2]<=m_pSubZones[nSubZone].Max[2]+SUBZONE_EPSILON) |
---|
2559 | ) |
---|
2560 | return true ; |
---|
2561 | |
---|
2562 | return false ; |
---|
2563 | } |
---|
2564 | |
---|
2565 | // returns true if a point is in a zone. |
---|
2566 | bool Q3Map::PointInZone(float *flPos, int nZone) |
---|
2567 | { |
---|
2568 | int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ; |
---|
2569 | |
---|
2570 | for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++) |
---|
2571 | if(PointInSubZone(flPos, m_nZone[nZone][nSubZoneIndex])) |
---|
2572 | return true ; |
---|
2573 | |
---|
2574 | return false ; |
---|
2575 | } |
---|
2576 | |
---|
2577 | // returns true if an axis aligned bounding box touches a subzone. |
---|
2578 | bool Q3Map::AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone) |
---|
2579 | { |
---|
2580 | // if test AABB overlaps the subzone AABB |
---|
2581 | if( |
---|
2582 | (m_pSubZones[nSubZone].Min[0]<flPointMax[0]) && (m_pSubZones[nSubZone].Max[0]>flPointMin[0]) |
---|
2583 | && (m_pSubZones[nSubZone].Min[1]<flPointMax[1]) && (m_pSubZones[nSubZone].Max[1]>flPointMin[1]) |
---|
2584 | && (m_pSubZones[nSubZone].Min[2]<flPointMax[2]) && (m_pSubZones[nSubZone].Max[2]>flPointMin[2]) |
---|
2585 | ) |
---|
2586 | return true ; |
---|
2587 | |
---|
2588 | return false ; |
---|
2589 | } |
---|
2590 | |
---|
2591 | // returns true if an axis aligned bounding box touches a zone. |
---|
2592 | bool Q3Map::AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone) |
---|
2593 | { |
---|
2594 | int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ; |
---|
2595 | |
---|
2596 | for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++) |
---|
2597 | if(AABBTouchesSubZone(flPosMin, flPosMax, m_nZone[nZone][nSubZoneIndex])) |
---|
2598 | return true ; |
---|
2599 | |
---|
2600 | return false ; |
---|
2601 | } |
---|
2602 | |
---|
2603 | // take the faces from the BSP and add them to our list of triangles. |
---|
2604 | int Q3Map::ConvertFacesToTriangles(void) |
---|
2605 | { |
---|
2606 | int nFaceIndex = 0 ; |
---|
2607 | |
---|
2608 | int nVertex=0 ; |
---|
2609 | int nVertexMax=0 ; |
---|
2610 | int nTriangle=0 ; |
---|
2611 | int nTriangleMax=0 ; |
---|
2612 | |
---|
2613 | float flPosX=0.0f ; |
---|
2614 | float flPosY=0.0f ; |
---|
2615 | float flPosZ=0.0f ; |
---|
2616 | float flNormX=0.0f ; |
---|
2617 | float flNormY=0.0f ; |
---|
2618 | float flNormZ=0.0f ; |
---|
2619 | float flTexU=0.0f ; |
---|
2620 | float flTexV=0.0f ; |
---|
2621 | int nMeshVert=0 ; |
---|
2622 | int nMeshVertA=0 ; |
---|
2623 | int nMeshVertB=0 ; |
---|
2624 | int nMeshVertC=0 ; |
---|
2625 | |
---|
2626 | Q3BspVertex *vertices = m_pVertices ; |
---|
2627 | int *meshverts = m_pMeshVerts ; |
---|
2628 | |
---|
2629 | QVECTOR junk ; |
---|
2630 | junk[0]=0.0f ; |
---|
2631 | junk[1]=0.0f ; |
---|
2632 | junk[2]=0.0f ; |
---|
2633 | |
---|
2634 | |
---|
2635 | nFaceIndex = 0 ; |
---|
2636 | while(nFaceIndex<m_iNumFaces) |
---|
2637 | { |
---|
2638 | |
---|
2639 | switch (m_BspFaces[nFaceIndex].type) |
---|
2640 | { |
---|
2641 | case MESH: |
---|
2642 | case POLYGON: |
---|
2643 | |
---|
2644 | nTriangleMax=m_BspFaces[nFaceIndex].n_triangles ; |
---|
2645 | nMeshVert=m_BspFaces[nFaceIndex].meshvert ; |
---|
2646 | |
---|
2647 | for(nTriangle=0 ; nTriangle<nTriangleMax ; nTriangle++) |
---|
2648 | { |
---|
2649 | |
---|
2650 | // if we are out of memory, grow it. If we can't grow it, fail |
---|
2651 | if(m_nTriangleMax>=m_nTriangleLimit) |
---|
2652 | if(!ExpandTriangleMemory()) |
---|
2653 | return 0 ; |
---|
2654 | |
---|
2655 | |
---|
2656 | |
---|
2657 | m_pTriangle[ m_nTriangleMax ].Texture= m_BspFaces[nFaceIndex].texture ; |
---|
2658 | //m_pTriangle[ m_nTriangleMax ].Lightmap= m_BspFaces[nFaceIndex].lm_index ; // bzn doesn't use lightmaps |
---|
2659 | m_pTriangle[ m_nTriangleMax ].VIndex[0]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ; |
---|
2660 | m_pTriangle[ m_nTriangleMax ].VIndex[1]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ; |
---|
2661 | m_pTriangle[ m_nTriangleMax ].VIndex[2]= meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ; |
---|
2662 | |
---|
2663 | m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later |
---|
2664 | |
---|
2665 | m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ; // increment group number. |
---|
2666 | |
---|
2667 | m_nTriangleMax++ ; |
---|
2668 | }// end for nTriangle |
---|
2669 | m_nGroup++ ; // increment group. Every face is a new group. |
---|
2670 | |
---|
2671 | break ; |
---|
2672 | |
---|
2673 | }// end switch |
---|
2674 | |
---|
2675 | nFaceIndex++; |
---|
2676 | } // end while |
---|
2677 | |
---|
2678 | return 1 ; |
---|
2679 | |
---|
2680 | } |
---|
2681 | |
---|
2682 | |
---|
2683 | // convert the patch info from the BSP into bezier curved triangle meshes and add to our triangle list. |
---|
2684 | int Q3Map::ConvertPatchesToTriangles(void) |
---|
2685 | { |
---|
2686 | |
---|
2687 | float flPosX=0.0f ; |
---|
2688 | float flPosY=0.0f ; |
---|
2689 | float flPosZ=0.0f ; |
---|
2690 | float flNormX=0.0f ; |
---|
2691 | float flNormY=0.0f ; |
---|
2692 | float flNormZ=0.0f ; |
---|
2693 | float flTexU=0.0f ; |
---|
2694 | float flTexV=0.0f ; |
---|
2695 | int nMeshVert=0 ; |
---|
2696 | int nMeshVertA=0 ; |
---|
2697 | int nMeshVertB=0 ; |
---|
2698 | int nMeshVertC=0 ; |
---|
2699 | |
---|
2700 | |
---|
2701 | int nTriPerRow=0 ; |
---|
2702 | int nRow=0 ; |
---|
2703 | |
---|
2704 | int nFirstVertex=m_nVertexMax ; |
---|
2705 | |
---|
2706 | int nVertCount=nFirstVertex ; |
---|
2707 | int nPatchCount=0 ; |
---|
2708 | |
---|
2709 | int* pIndexBuffer=NULL ; |
---|
2710 | |
---|
2711 | Q3BspVertex NewVert ; |
---|
2712 | |
---|
2713 | |
---|
2714 | |
---|
2715 | |
---|
2716 | int nCount=0 ; |
---|
2717 | int nCountB=0 ; |
---|
2718 | |
---|
2719 | |
---|
2720 | |
---|
2721 | |
---|
2722 | int indexBufferindex = 0; |
---|
2723 | |
---|
2724 | int vertexBufferindex = 0; |
---|
2725 | |
---|
2726 | for (int faceIndex=0; faceIndex < m_iNumFaces; faceIndex++) |
---|
2727 | { |
---|
2728 | |
---|
2729 | nCount++ ; |
---|
2730 | if(nCount==1) |
---|
2731 | { |
---|
2732 | nCountB+=nCount ; |
---|
2733 | nCount=0 ; |
---|
2734 | } |
---|
2735 | |
---|
2736 | |
---|
2737 | if (m_BspFaces[faceIndex].type == PATCH) |
---|
2738 | { |
---|
2739 | Q3BspPatch *patch = m_BspFaces[faceIndex].patch; |
---|
2740 | |
---|
2741 | if (patch != NULL) |
---|
2742 | { |
---|
2743 | |
---|
2744 | for (int bezierIndex=0; bezierIndex < patch->size; bezierIndex++) |
---|
2745 | { |
---|
2746 | indexBufferindex = 0; |
---|
2747 | pIndexBuffer = new int[patch->bezier[bezierIndex].mNumIndex] ; |
---|
2748 | if(pIndexBuffer==NULL) return 0 ; // ran out of memory |
---|
2749 | |
---|
2750 | |
---|
2751 | for (int index=0; index < patch->bezier[bezierIndex].mNumIndex; index++) |
---|
2752 | { |
---|
2753 | pIndexBuffer[indexBufferindex] = patch->bezier[bezierIndex].mIndex[index]; |
---|
2754 | indexBufferindex++; |
---|
2755 | } |
---|
2756 | |
---|
2757 | for (int vertex=0; vertex < patch->bezier[bezierIndex].mNumVertex; vertex++) |
---|
2758 | { |
---|
2759 | |
---|
2760 | BspVertex *bspVertex = &patch->bezier[bezierIndex].mVertex[vertex]; |
---|
2761 | |
---|
2762 | NewVert.position[0]=bspVertex->mPosition[0] ; |
---|
2763 | NewVert.position[1]=bspVertex->mPosition[1] ; |
---|
2764 | NewVert.position[2]=bspVertex->mPosition[2] ; |
---|
2765 | NewVert.normal[0]=bspVertex->mNormal[0] ; |
---|
2766 | NewVert.normal[1]=bspVertex->mNormal[1] ; |
---|
2767 | NewVert.normal[2]=bspVertex->mNormal[2] ; |
---|
2768 | NewVert.texcoord[0][0]=bspVertex->mTexcoord[0][0] ; |
---|
2769 | NewVert.texcoord[0][1]=bspVertex->mTexcoord[0][1] ; |
---|
2770 | |
---|
2771 | |
---|
2772 | |
---|
2773 | // if we are out of memory, grow it. If we can't grow it, fail |
---|
2774 | if(m_nVertexMax>=m_nVertexLimit) |
---|
2775 | if(!ExpandVertexMemory()) |
---|
2776 | { |
---|
2777 | if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ; |
---|
2778 | return 0 ; |
---|
2779 | } |
---|
2780 | |
---|
2781 | |
---|
2782 | if(!AddVertex(NewVert)) |
---|
2783 | { |
---|
2784 | if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ; |
---|
2785 | return 0 ; |
---|
2786 | } |
---|
2787 | |
---|
2788 | nVertCount++ ; |
---|
2789 | vertexBufferindex++; |
---|
2790 | |
---|
2791 | }// end for vertex |
---|
2792 | |
---|
2793 | |
---|
2794 | for (int j=0; j < 5; j++) |
---|
2795 | { |
---|
2796 | nRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mRowIndex[j] ; |
---|
2797 | nTriPerRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mTrianglesPerRow[j] ; |
---|
2798 | |
---|
2799 | nMeshVertA=pIndexBuffer[nRow+0]+nFirstVertex ; |
---|
2800 | nMeshVertB=pIndexBuffer[nRow+1]+nFirstVertex ; |
---|
2801 | |
---|
2802 | for(int nVert=2 ; nVert<nTriPerRow ; nVert++) |
---|
2803 | { |
---|
2804 | // if we are out of memory, grow it. If we can't grow it, fail |
---|
2805 | if(m_nTriangleMax>=m_nTriangleLimit) |
---|
2806 | if(!ExpandTriangleMemory()) |
---|
2807 | { |
---|
2808 | if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ; |
---|
2809 | return 0 ; |
---|
2810 | } |
---|
2811 | |
---|
2812 | m_pTriangle[ m_nTriangleMax ].Texture= m_BspFaces[faceIndex].texture ; |
---|
2813 | //m_pTriangle[ m_nTriangleMax ].Lightmap= m_BspFaces[faceIndex].lm_index ; // bzn doesn't use lightmaps |
---|
2814 | |
---|
2815 | |
---|
2816 | |
---|
2817 | nMeshVertC=pIndexBuffer[nRow+nVert]+nFirstVertex ; |
---|
2818 | |
---|
2819 | |
---|
2820 | if(nVert&1) |
---|
2821 | { |
---|
2822 | m_pTriangle[ m_nTriangleMax ].VIndex[0]= nMeshVertB ; |
---|
2823 | m_pTriangle[ m_nTriangleMax ].VIndex[1]= nMeshVertA ; |
---|
2824 | m_pTriangle[ m_nTriangleMax ].VIndex[2]= nMeshVertC ; |
---|
2825 | } |
---|
2826 | else |
---|
2827 | { |
---|
2828 | m_pTriangle[ m_nTriangleMax ].VIndex[0]= nMeshVertA ; |
---|
2829 | m_pTriangle[ m_nTriangleMax ].VIndex[1]= nMeshVertB ; |
---|
2830 | m_pTriangle[ m_nTriangleMax ].VIndex[2]= nMeshVertC ; |
---|
2831 | } |
---|
2832 | |
---|
2833 | m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later |
---|
2834 | |
---|
2835 | |
---|
2836 | m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ; |
---|
2837 | |
---|
2838 | |
---|
2839 | m_nTriangleMax++ ; |
---|
2840 | |
---|
2841 | nMeshVertA=nMeshVertB ; |
---|
2842 | nMeshVertB=nMeshVertC ; |
---|
2843 | } |
---|
2844 | |
---|
2845 | |
---|
2846 | } |
---|
2847 | |
---|
2848 | |
---|
2849 | // finished with the index buffer |
---|
2850 | if(pIndexBuffer) |
---|
2851 | DELETE_ARRAY( pIndexBuffer ) ; |
---|
2852 | |
---|
2853 | nFirstVertex=nVertCount ; |
---|
2854 | }// end for bezier index |
---|
2855 | |
---|
2856 | |
---|
2857 | m_nGroup++ ; // increment the group number. Each patch is treated as a single group. |
---|
2858 | |
---|
2859 | }// end if patch not null |
---|
2860 | }// end if patch |
---|
2861 | }// end for faceIndex |
---|
2862 | |
---|
2863 | return 1 ; |
---|
2864 | |
---|
2865 | } |
---|
2866 | |
---|
2867 | //'' |
---|
2868 | // some triangles might be designed to be deferred shading shapes inside of Lamp entities. |
---|
2869 | // If so, change their material to the deferred shading configuration for that lamp entity. |
---|
2870 | int Q3Map::ConvertTexLampsToLampTriangles(void) |
---|
2871 | { |
---|
2872 | |
---|
2873 | float flCentreX=0.0f ; |
---|
2874 | float flCentreY=0.0f ; |
---|
2875 | float flCentreZ=0.0f ; |
---|
2876 | |
---|
2877 | float flMinX=0.0f ; |
---|
2878 | float flMinY=0.0f ; |
---|
2879 | float flMinZ=0.0f ; |
---|
2880 | float flMaxX=0.0f ; |
---|
2881 | float flMaxY=0.0f ; |
---|
2882 | float flMaxZ=0.0f ; |
---|
2883 | |
---|
2884 | float flNormX=0.0f ; |
---|
2885 | float flNormY=0.0f ; |
---|
2886 | float flNormZ=0.0f ; |
---|
2887 | float flTexU=0.0f ; |
---|
2888 | float flTexV=0.0f ; |
---|
2889 | |
---|
2890 | float flColR=0.0f ; |
---|
2891 | float flColG=0.0f ; |
---|
2892 | float flColB=0.0f ; |
---|
2893 | |
---|
2894 | float flBrightness=0.0f ; |
---|
2895 | |
---|
2896 | int nLamp=0 ; |
---|
2897 | int nTriangle=0 ; |
---|
2898 | int nTexLampListPos=0 ; |
---|
2899 | int nLightNode=0 ; |
---|
2900 | int nTexture=0 ; |
---|
2901 | int nZone=0 ; |
---|
2902 | int nLampZone=0 ; |
---|
2903 | int nMaxLampZone=0 ; |
---|
2904 | int nZoneMatch=0 ; |
---|
2905 | |
---|
2906 | |
---|
2907 | for(nTexLampListPos=0 ; nTexLampListPos<m_nTexLampMax ; nTexLampListPos++) |
---|
2908 | { |
---|
2909 | nTriangle=m_pTexLamp[nTexLampListPos] ; |
---|
2910 | |
---|
2911 | nZone=m_pTriangle[nTriangle].Zone ; |
---|
2912 | |
---|
2913 | nTexture=m_pTriangle[nTriangle].Texture ; |
---|
2914 | |
---|
2915 | if(nTexture==m_nBZN_LightNode0) |
---|
2916 | nLightNode=0 ; |
---|
2917 | else |
---|
2918 | if(nTexture==m_nBZN_LightNode1) |
---|
2919 | nLightNode=1 ; |
---|
2920 | else |
---|
2921 | if(nTexture==m_nBZN_LightNode2) |
---|
2922 | nLightNode=2 ; |
---|
2923 | else |
---|
2924 | if(nTexture==m_nBZN_LightNode3) |
---|
2925 | nLightNode=3 ; |
---|
2926 | else |
---|
2927 | return 0 ; // didn't match any lightnode, something went wrong. |
---|
2928 | |
---|
2929 | |
---|
2930 | // scan through all the lamps, finding the ones that touch the same zone as this triangle and that have the same lightnode number |
---|
2931 | for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++) |
---|
2932 | { |
---|
2933 | // skip if the lightnode doesn't match |
---|
2934 | if(m_pLamp[nLamp].LightNode!=nLightNode) |
---|
2935 | continue ; |
---|
2936 | |
---|
2937 | |
---|
2938 | /* |
---|
2939 | // lightnode matches, check if lamp touches the same zone (lamps can touch multiple zones so we have to check them all) |
---|
2940 | nZoneMatch=0 ; |
---|
2941 | nMaxLampZone=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ; |
---|
2942 | for(nLampZone=0 ; nLampZone<nMaxLampZone ; nLampZone++) |
---|
2943 | { |
---|
2944 | if(m_pLamp[nLamp].Zone[nLampZone]==nZone) |
---|
2945 | { |
---|
2946 | nZoneMatch=1 ; |
---|
2947 | break ; |
---|
2948 | } |
---|
2949 | } |
---|
2950 | |
---|
2951 | |
---|
2952 | // if the zone didn't match, continue |
---|
2953 | if(!nZoneMatch) continue ; |
---|
2954 | |
---|
2955 | */ |
---|
2956 | |
---|
2957 | |
---|
2958 | |
---|
2959 | // check if all three vertices of this triangle fall within the bounds of this lamp |
---|
2960 | if( |
---|
2961 | // first vert |
---|
2962 | (m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0]>=m_pLamp[nLamp].Min[0]) |
---|
2963 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[0]<=m_pLamp[nLamp].Max[0]) |
---|
2964 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1]>=m_pLamp[nLamp].Min[1]) |
---|
2965 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[1]<=m_pLamp[nLamp].Max[1]) |
---|
2966 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2]>=m_pLamp[nLamp].Min[2]) |
---|
2967 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].position[2]<=m_pLamp[nLamp].Max[2]) |
---|
2968 | && |
---|
2969 | // second vert |
---|
2970 | (m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0]>=m_pLamp[nLamp].Min[0]) |
---|
2971 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[0]<=m_pLamp[nLamp].Max[0]) |
---|
2972 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1]>=m_pLamp[nLamp].Min[1]) |
---|
2973 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[1]<=m_pLamp[nLamp].Max[1]) |
---|
2974 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2]>=m_pLamp[nLamp].Min[2]) |
---|
2975 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].position[2]<=m_pLamp[nLamp].Max[2]) |
---|
2976 | && |
---|
2977 | // third vert |
---|
2978 | (m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0]>=m_pLamp[nLamp].Min[0]) |
---|
2979 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[0]<=m_pLamp[nLamp].Max[0]) |
---|
2980 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1]>=m_pLamp[nLamp].Min[1]) |
---|
2981 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[1]<=m_pLamp[nLamp].Max[1]) |
---|
2982 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2]>=m_pLamp[nLamp].Min[2]) |
---|
2983 | &&(m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].position[2]<=m_pLamp[nLamp].Max[2]) |
---|
2984 | |
---|
2985 | ) |
---|
2986 | { |
---|
2987 | |
---|
2988 | |
---|
2989 | m_pTriangle[nTriangle].Texture=m_pLamp[nLamp].Texture ; |
---|
2990 | m_pTriangle[nTriangle].Lamp=nLamp ; |
---|
2991 | |
---|
2992 | flCentreX = m_pLamp[nLamp].Position[0] ; |
---|
2993 | flCentreY = m_pLamp[nLamp].Position[1] ; |
---|
2994 | flCentreZ = m_pLamp[nLamp].Position[2] ; |
---|
2995 | flColR = m_pLamp[nLamp].Colour[0]*255.0f ; |
---|
2996 | flColG = m_pLamp[nLamp].Colour[1]*255.0f ; |
---|
2997 | flColB = m_pLamp[nLamp].Colour[2]*255.0f ; |
---|
2998 | flBrightness= m_pLamp[nLamp].Brightness ; |
---|
2999 | |
---|
3000 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[0][0]=flCentreX ; |
---|
3001 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[0][1]=flCentreY ; |
---|
3002 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[1][0]=flCentreZ ; |
---|
3003 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].texcoord[1][1]=flBrightness ; |
---|
3004 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[0]=flColR ; |
---|
3005 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[1]=flColG ; |
---|
3006 | m_pVertex[ m_pTriangle[nTriangle].VIndex[0] ].color[2]=flColB ; |
---|
3007 | |
---|
3008 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[0][0]=flCentreX ; |
---|
3009 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[0][1]=flCentreY ; |
---|
3010 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[1][0]=flCentreZ ; |
---|
3011 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].texcoord[1][1]=flBrightness ; |
---|
3012 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[0]=flColR ; |
---|
3013 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[1]=flColG ; |
---|
3014 | m_pVertex[ m_pTriangle[nTriangle].VIndex[1] ].color[2]=flColB ; |
---|
3015 | |
---|
3016 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[0][0]=flCentreX ; |
---|
3017 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[0][1]=flCentreY ; |
---|
3018 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[1][0]=flCentreZ ; |
---|
3019 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].texcoord[1][1]=flBrightness ; |
---|
3020 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[0]=flColR ; |
---|
3021 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[1]=flColG ; |
---|
3022 | m_pVertex[ m_pTriangle[nTriangle].VIndex[2] ].color[2]=flColB ; |
---|
3023 | |
---|
3024 | |
---|
3025 | m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ; |
---|
3026 | |
---|
3027 | |
---|
3028 | }// end triangle is in bounds of lamp |
---|
3029 | |
---|
3030 | |
---|
3031 | m_nGroup++ ; // increment group number. Every texture lamp is a group. |
---|
3032 | |
---|
3033 | |
---|
3034 | }// end for nLamp |
---|
3035 | |
---|
3036 | |
---|
3037 | } |
---|
3038 | |
---|
3039 | |
---|
3040 | |
---|
3041 | return 1 ; |
---|
3042 | } |
---|
3043 | |
---|
3044 | |
---|
3045 | // convert lamps into boxes. Lamps are deferred shading non-shadowing lights, and are rendered as triangles |
---|
3046 | // The texture coords are actually the light centre point, the spot the shaders calculate as the source of the lighting, |
---|
3047 | // and also the brightness |
---|
3048 | // The triangles created will remember the lamp they came from, via Triangle.Lamp |
---|
3049 | |
---|
3050 | int Q3Map::ConvertLampsToTriangles(void) |
---|
3051 | { |
---|
3052 | float flCentreX=0.0f ; |
---|
3053 | float flCentreY=0.0f ; |
---|
3054 | float flCentreZ=0.0f ; |
---|
3055 | |
---|
3056 | float flMinX=0.0f ; |
---|
3057 | float flMinY=0.0f ; |
---|
3058 | float flMinZ=0.0f ; |
---|
3059 | float flMaxX=0.0f ; |
---|
3060 | float flMaxY=0.0f ; |
---|
3061 | float flMaxZ=0.0f ; |
---|
3062 | |
---|
3063 | float flNormX=0.0f ; |
---|
3064 | float flNormY=0.0f ; |
---|
3065 | float flNormZ=0.0f ; |
---|
3066 | float flTexU=0.0f ; |
---|
3067 | float flTexV=0.0f ; |
---|
3068 | |
---|
3069 | float flColR=0.0f ; |
---|
3070 | float flColG=0.0f ; |
---|
3071 | float flColB=0.0f ; |
---|
3072 | |
---|
3073 | float flBrightness=0.0f ; |
---|
3074 | |
---|
3075 | int nLamp=0 ; |
---|
3076 | |
---|
3077 | // lower case = min, upper case = max |
---|
3078 | Q3BspVertex Vert_xyz ; |
---|
3079 | Q3BspVertex Vert_Xyz ; |
---|
3080 | Q3BspVertex Vert_xYz ; |
---|
3081 | Q3BspVertex Vert_XYz ; |
---|
3082 | Q3BspVertex Vert_xyZ ; |
---|
3083 | Q3BspVertex Vert_XyZ ; |
---|
3084 | Q3BspVertex Vert_xYZ ; |
---|
3085 | Q3BspVertex Vert_XYZ ; |
---|
3086 | |
---|
3087 | int n_xyz=0 ; |
---|
3088 | int n_Xyz=0 ; |
---|
3089 | int n_xYz=0 ; |
---|
3090 | int n_XYz=0 ; |
---|
3091 | int n_xyZ=0 ; |
---|
3092 | int n_XyZ=0 ; |
---|
3093 | int n_xYZ=0 ; |
---|
3094 | int n_XYZ=0 ; |
---|
3095 | |
---|
3096 | int nFirstVertex=0 ; |
---|
3097 | |
---|
3098 | triangle_t Triangle ; |
---|
3099 | ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ; |
---|
3100 | |
---|
3101 | for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++) |
---|
3102 | { |
---|
3103 | if(m_pLamp[nLamp].LightNode>-1) continue ; // lamps that are lightnodes don't add their own triangles. They just exist as information for TexLamps. |
---|
3104 | |
---|
3105 | |
---|
3106 | flCentreX = m_pLamp[nLamp].Position[0] ; |
---|
3107 | flCentreY = m_pLamp[nLamp].Position[1] ; |
---|
3108 | flCentreZ = m_pLamp[nLamp].Position[2] ; |
---|
3109 | |
---|
3110 | flMinX = m_pLamp[nLamp].Min[0] ; |
---|
3111 | flMinY = m_pLamp[nLamp].Min[1] ; |
---|
3112 | flMinZ = m_pLamp[nLamp].Min[2] ; |
---|
3113 | |
---|
3114 | flMaxX = m_pLamp[nLamp].Max[0] ; |
---|
3115 | flMaxY = m_pLamp[nLamp].Max[1] ; |
---|
3116 | flMaxZ = m_pLamp[nLamp].Max[2] ; |
---|
3117 | |
---|
3118 | flColR = m_pLamp[nLamp].Colour[0]*255.0f ; |
---|
3119 | flColG = m_pLamp[nLamp].Colour[1]*255.0f ; |
---|
3120 | flColB = m_pLamp[nLamp].Colour[2]*255.0f ; |
---|
3121 | |
---|
3122 | flBrightness= m_pLamp[nLamp].Brightness ; |
---|
3123 | |
---|
3124 | ////////////////////////////////////// |
---|
3125 | // setup our 8 vertices. Normal isn't that important, I just approximate regardless of actual box shape |
---|
3126 | |
---|
3127 | |
---|
3128 | nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles |
---|
3129 | |
---|
3130 | // vertex numbers |
---|
3131 | n_xyz=nFirstVertex+0 ; |
---|
3132 | n_Xyz=nFirstVertex+1 ; |
---|
3133 | n_xYz=nFirstVertex+2 ; |
---|
3134 | n_XYz=nFirstVertex+3 ; |
---|
3135 | n_xyZ=nFirstVertex+4 ; |
---|
3136 | n_XyZ=nFirstVertex+5 ; |
---|
3137 | n_xYZ=nFirstVertex+6 ; |
---|
3138 | n_XYZ=nFirstVertex+7 ; |
---|
3139 | |
---|
3140 | |
---|
3141 | Vert_xyz.position[0]=flMinX ; |
---|
3142 | Vert_xyz.position[1]=flMinY ; |
---|
3143 | Vert_xyz.position[2]=flMinZ ; |
---|
3144 | Vert_xyz.normal[0]=-0.5773502691896 ; |
---|
3145 | Vert_xyz.normal[1]=-0.5773502691896 ; |
---|
3146 | Vert_xyz.normal[2]=-0.5773502691896 ; |
---|
3147 | Vert_xyz.texcoord[0][0]=flCentreX ; |
---|
3148 | Vert_xyz.texcoord[0][1]=flCentreY ; |
---|
3149 | Vert_xyz.texcoord[1][0]=flCentreZ ; |
---|
3150 | Vert_xyz.texcoord[1][1]=flBrightness ; |
---|
3151 | Vert_xyz.color[0]=flColR ; |
---|
3152 | Vert_xyz.color[1]=flColG ; |
---|
3153 | Vert_xyz.color[2]=flColB ; |
---|
3154 | if(!AddVertex(Vert_xyz)) return 0 ; |
---|
3155 | |
---|
3156 | |
---|
3157 | Vert_Xyz.position[0]=flMaxX ; |
---|
3158 | Vert_Xyz.position[1]=flMinY ; |
---|
3159 | Vert_Xyz.position[2]=flMinZ ; |
---|
3160 | Vert_Xyz.normal[0]= 0.5773502691896 ; |
---|
3161 | Vert_Xyz.normal[1]=-0.5773502691896 ; |
---|
3162 | Vert_Xyz.normal[2]=-0.5773502691896 ; |
---|
3163 | Vert_Xyz.texcoord[0][0]=flCentreX ; |
---|
3164 | Vert_Xyz.texcoord[0][1]=flCentreY ; |
---|
3165 | Vert_Xyz.texcoord[1][0]=flCentreZ ; |
---|
3166 | Vert_Xyz.texcoord[1][1]=flBrightness ; |
---|
3167 | Vert_Xyz.color[0]=flColR ; |
---|
3168 | Vert_Xyz.color[1]=flColG ; |
---|
3169 | Vert_Xyz.color[2]=flColB ; |
---|
3170 | if(!AddVertex(Vert_Xyz)) return 0 ; |
---|
3171 | |
---|
3172 | Vert_xYz.position[0]=flMinX ; |
---|
3173 | Vert_xYz.position[1]=flMaxY ; |
---|
3174 | Vert_xYz.position[2]=flMinZ ; |
---|
3175 | Vert_xYz.normal[0]=-0.5773502691896 ; |
---|
3176 | Vert_xYz.normal[1]= 0.5773502691896 ; |
---|
3177 | Vert_xYz.normal[2]=-0.5773502691896 ; |
---|
3178 | Vert_xYz.texcoord[0][0]=flCentreX ; |
---|
3179 | Vert_xYz.texcoord[0][1]=flCentreY ; |
---|
3180 | Vert_xYz.texcoord[1][0]=flCentreZ ; |
---|
3181 | Vert_xYz.texcoord[1][1]=flBrightness ; |
---|
3182 | Vert_xYz.color[0]=flColR ; |
---|
3183 | Vert_xYz.color[1]=flColG ; |
---|
3184 | Vert_xYz.color[2]=flColB ; |
---|
3185 | if(!AddVertex(Vert_xYz)) return 0 ; |
---|
3186 | |
---|
3187 | Vert_XYz.position[0]=flMaxX ; |
---|
3188 | Vert_XYz.position[1]=flMaxY ; |
---|
3189 | Vert_XYz.position[2]=flMinZ ; |
---|
3190 | Vert_XYz.normal[0]= 0.5773502691896 ; |
---|
3191 | Vert_XYz.normal[1]= 0.5773502691896 ; |
---|
3192 | Vert_XYz.normal[2]=-0.5773502691896 ; |
---|
3193 | Vert_XYz.texcoord[0][0]=flCentreX ; |
---|
3194 | Vert_XYz.texcoord[0][1]=flCentreY ; |
---|
3195 | Vert_XYz.texcoord[1][0]=flCentreZ ; |
---|
3196 | Vert_XYz.texcoord[1][1]=flBrightness ; |
---|
3197 | Vert_XYz.color[0]=flColR ; |
---|
3198 | Vert_XYz.color[1]=flColG ; |
---|
3199 | Vert_XYz.color[2]=flColB ; |
---|
3200 | if(!AddVertex(Vert_XYz)) return 0 ; |
---|
3201 | |
---|
3202 | ////////////////////////////////////// |
---|
3203 | |
---|
3204 | Vert_xyZ.position[0]=flMinX ; |
---|
3205 | Vert_xyZ.position[1]=flMinY ; |
---|
3206 | Vert_xyZ.position[2]=flMaxZ ; |
---|
3207 | Vert_xyZ.normal[0]=-0.5773502691896 ; |
---|
3208 | Vert_xyZ.normal[1]=-0.5773502691896 ; |
---|
3209 | Vert_xyZ.normal[2]= 0.5773502691896 ; |
---|
3210 | Vert_xyZ.texcoord[0][0]=flCentreX ; |
---|
3211 | Vert_xyZ.texcoord[0][1]=flCentreY ; |
---|
3212 | Vert_xyZ.texcoord[1][0]=flCentreZ ; |
---|
3213 | Vert_xyZ.texcoord[1][1]=flBrightness ; |
---|
3214 | Vert_xyZ.color[0]=flColR ; |
---|
3215 | Vert_xyZ.color[1]=flColG ; |
---|
3216 | Vert_xyZ.color[2]=flColB ; |
---|
3217 | if(!AddVertex(Vert_xyZ)) return 0 ; |
---|
3218 | |
---|
3219 | Vert_XyZ.position[0]=flMaxX ; |
---|
3220 | Vert_XyZ.position[1]=flMinY ; |
---|
3221 | Vert_XyZ.position[2]=flMaxZ ; |
---|
3222 | Vert_XyZ.normal[0]= 0.5773502691896 ; |
---|
3223 | Vert_XyZ.normal[1]=-0.5773502691896 ; |
---|
3224 | Vert_XyZ.normal[2]= 0.5773502691896 ; |
---|
3225 | Vert_XyZ.texcoord[0][0]=flCentreX ; |
---|
3226 | Vert_XyZ.texcoord[0][1]=flCentreY ; |
---|
3227 | Vert_XyZ.texcoord[1][0]=flCentreZ ; |
---|
3228 | Vert_XyZ.texcoord[1][1]=flBrightness ; |
---|
3229 | Vert_XyZ.color[0]=flColR ; |
---|
3230 | Vert_XyZ.color[1]=flColG ; |
---|
3231 | Vert_XyZ.color[2]=flColB ; |
---|
3232 | if(!AddVertex(Vert_XyZ)) return 0 ; |
---|
3233 | |
---|
3234 | Vert_xYZ.position[0]=flMinX ; |
---|
3235 | Vert_xYZ.position[1]=flMaxY ; |
---|
3236 | Vert_xYZ.position[2]=flMaxZ ; |
---|
3237 | Vert_xYZ.normal[0]=-0.5773502691896 ; |
---|
3238 | Vert_xYZ.normal[1]= 0.5773502691896 ; |
---|
3239 | Vert_xYZ.normal[2]= 0.5773502691896 ; |
---|
3240 | Vert_xYZ.texcoord[0][0]=flCentreX ; |
---|
3241 | Vert_xYZ.texcoord[0][1]=flCentreY ; |
---|
3242 | Vert_xYZ.texcoord[1][0]=flCentreZ ; |
---|
3243 | Vert_xYZ.texcoord[1][1]=flBrightness ; |
---|
3244 | Vert_xYZ.color[0]=flColR ; |
---|
3245 | Vert_xYZ.color[1]=flColG ; |
---|
3246 | Vert_xYZ.color[2]=flColB ; |
---|
3247 | if(!AddVertex(Vert_xYZ)) return 0 ; |
---|
3248 | |
---|
3249 | Vert_XYZ.position[0]=flMaxX ; |
---|
3250 | Vert_XYZ.position[1]=flMaxY ; |
---|
3251 | Vert_XYZ.position[2]=flMaxZ ; |
---|
3252 | Vert_XYZ.normal[0]= 0.5773502691896 ; |
---|
3253 | Vert_XYZ.normal[1]= 0.5773502691896 ; |
---|
3254 | Vert_XYZ.normal[2]= 0.5773502691896 ; |
---|
3255 | Vert_XYZ.texcoord[0][0]=flCentreX ; |
---|
3256 | Vert_XYZ.texcoord[0][1]=flCentreY ; |
---|
3257 | Vert_XYZ.texcoord[1][0]=flCentreZ ; |
---|
3258 | Vert_XYZ.texcoord[1][1]=flBrightness ; |
---|
3259 | Vert_XYZ.color[0]=flColR ; |
---|
3260 | Vert_XYZ.color[1]=flColG ; |
---|
3261 | Vert_XYZ.color[2]=flColB ; |
---|
3262 | if(!AddVertex(Vert_XYZ)) return 0 ; |
---|
3263 | |
---|
3264 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3265 | |
---|
3266 | Triangle.Texture=m_pLamp[nLamp].Texture ; |
---|
3267 | Triangle.Lamp=nLamp ; |
---|
3268 | Triangle.Group=m_nGroup ; |
---|
3269 | |
---|
3270 | ///////////////////////////////////// |
---|
3271 | |
---|
3272 | Triangle.VIndex[2]=n_xyz ; |
---|
3273 | Triangle.VIndex[1]=n_xyZ ; |
---|
3274 | Triangle.VIndex[0]=n_xYZ ; |
---|
3275 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3276 | |
---|
3277 | Triangle.VIndex[2]=n_xYZ ; |
---|
3278 | Triangle.VIndex[1]=n_xYz ; |
---|
3279 | Triangle.VIndex[0]=n_xyz ; |
---|
3280 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3281 | |
---|
3282 | ///////////////////////////////////// |
---|
3283 | |
---|
3284 | Triangle.VIndex[0]=n_Xyz ; |
---|
3285 | Triangle.VIndex[1]=n_XyZ ; |
---|
3286 | Triangle.VIndex[2]=n_XYZ ; |
---|
3287 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3288 | |
---|
3289 | Triangle.VIndex[0]=n_XYZ ; |
---|
3290 | Triangle.VIndex[1]=n_XYz ; |
---|
3291 | Triangle.VIndex[2]=n_Xyz ; |
---|
3292 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3293 | |
---|
3294 | ///////////////////////////////////// |
---|
3295 | |
---|
3296 | Triangle.VIndex[2]=n_xyz ; |
---|
3297 | Triangle.VIndex[1]=n_xYz ; |
---|
3298 | Triangle.VIndex[0]=n_XYz ; |
---|
3299 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3300 | |
---|
3301 | Triangle.VIndex[2]=n_XYz ; |
---|
3302 | Triangle.VIndex[1]=n_Xyz ; |
---|
3303 | Triangle.VIndex[0]=n_xyz ; |
---|
3304 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3305 | |
---|
3306 | ///////////////////////////////////// |
---|
3307 | |
---|
3308 | Triangle.VIndex[0]=n_xyZ ; |
---|
3309 | Triangle.VIndex[1]=n_xYZ ; |
---|
3310 | Triangle.VIndex[2]=n_XYZ ; |
---|
3311 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3312 | |
---|
3313 | Triangle.VIndex[0]=n_XYZ ; |
---|
3314 | Triangle.VIndex[1]=n_XyZ ; |
---|
3315 | Triangle.VIndex[2]=n_xyZ ; |
---|
3316 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3317 | |
---|
3318 | ///////////////////////////////////// |
---|
3319 | |
---|
3320 | Triangle.VIndex[0]=n_xyz ; |
---|
3321 | Triangle.VIndex[1]=n_xyZ ; |
---|
3322 | Triangle.VIndex[2]=n_XyZ ; |
---|
3323 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3324 | |
---|
3325 | Triangle.VIndex[0]=n_XyZ ; |
---|
3326 | Triangle.VIndex[1]=n_Xyz ; |
---|
3327 | Triangle.VIndex[2]=n_xyz ; |
---|
3328 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3329 | |
---|
3330 | ///////////////////////////////////// |
---|
3331 | |
---|
3332 | Triangle.VIndex[2]=n_xYz ; |
---|
3333 | Triangle.VIndex[1]=n_xYZ ; |
---|
3334 | Triangle.VIndex[0]=n_XYZ ; |
---|
3335 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3336 | |
---|
3337 | Triangle.VIndex[2]=n_XYZ ; |
---|
3338 | Triangle.VIndex[1]=n_XYz ; |
---|
3339 | Triangle.VIndex[0]=n_xYz ; |
---|
3340 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3341 | |
---|
3342 | m_nGroup++ ; // increment group once for every lamp |
---|
3343 | } |
---|
3344 | |
---|
3345 | |
---|
3346 | |
---|
3347 | return 1 ; |
---|
3348 | } |
---|
3349 | |
---|
3350 | |
---|
3351 | int Q3Map::ConvertLampsToGlowTriangles(void) |
---|
3352 | { |
---|
3353 | float flCentreX=0.0f ; |
---|
3354 | float flCentreY=0.0f ; |
---|
3355 | float flCentreZ=0.0f ; |
---|
3356 | |
---|
3357 | float flMinX=0.0f ; |
---|
3358 | float flMinY=0.0f ; |
---|
3359 | float flMinZ=0.0f ; |
---|
3360 | float flMaxX=0.0f ; |
---|
3361 | float flMaxY=0.0f ; |
---|
3362 | float flMaxZ=0.0f ; |
---|
3363 | |
---|
3364 | float flNormX=0.0f ; |
---|
3365 | float flNormY=0.0f ; |
---|
3366 | float flNormZ=0.0f ; |
---|
3367 | float flTexU=0.0f ; |
---|
3368 | float flTexV=0.0f ; |
---|
3369 | |
---|
3370 | float flColR=0.0f ; |
---|
3371 | float flColG=0.0f ; |
---|
3372 | float flColB=0.0f ; |
---|
3373 | |
---|
3374 | float flBrightness=0.0f ; |
---|
3375 | |
---|
3376 | int nLamp=0 ; |
---|
3377 | |
---|
3378 | |
---|
3379 | Q3BspVertex Vert_L ; |
---|
3380 | Q3BspVertex Vert_R ; |
---|
3381 | Q3BspVertex Vert_F ; |
---|
3382 | Q3BspVertex Vert_B ; |
---|
3383 | Q3BspVertex Vert_U ; |
---|
3384 | Q3BspVertex Vert_D ; |
---|
3385 | |
---|
3386 | |
---|
3387 | int n_L=0 ; |
---|
3388 | int n_R=0 ; |
---|
3389 | int n_F=0 ; |
---|
3390 | int n_B=0 ; |
---|
3391 | int n_U=0 ; |
---|
3392 | int n_D=0 ; |
---|
3393 | |
---|
3394 | int nFirstVertex=0 ; |
---|
3395 | |
---|
3396 | float flBaseGlowSize=0.15f ;//0.2f;//0.001f ; |
---|
3397 | float flGlowSize=0.0f ; |
---|
3398 | |
---|
3399 | |
---|
3400 | |
---|
3401 | triangle_t Triangle ; |
---|
3402 | ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ; |
---|
3403 | |
---|
3404 | for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++) |
---|
3405 | { |
---|
3406 | |
---|
3407 | flGlowSize=flBaseGlowSize*m_pLamp[nLamp].Brightness ; |
---|
3408 | |
---|
3409 | flCentreX = m_pLamp[nLamp].Position[0] ; |
---|
3410 | flCentreY = m_pLamp[nLamp].Position[1] ; |
---|
3411 | flCentreZ = m_pLamp[nLamp].Position[2] ; |
---|
3412 | |
---|
3413 | flMinX = flCentreX-flGlowSize ; |
---|
3414 | flMinY = flCentreY-flGlowSize ; |
---|
3415 | flMinZ = flCentreZ-flGlowSize ; |
---|
3416 | |
---|
3417 | flMaxX = flCentreX+flGlowSize ; |
---|
3418 | flMaxY = flCentreY+flGlowSize ; |
---|
3419 | flMaxZ = flCentreZ+flGlowSize ; |
---|
3420 | |
---|
3421 | flColR = m_pLamp[nLamp].Colour[0]*255.0f ; |
---|
3422 | flColG = m_pLamp[nLamp].Colour[1]*255.0f ; |
---|
3423 | flColB = m_pLamp[nLamp].Colour[2]*255.0f ; |
---|
3424 | |
---|
3425 | flBrightness= m_pLamp[nLamp].Brightness*4.0f ; |
---|
3426 | |
---|
3427 | ////////////////////////////////////// |
---|
3428 | // setup our 8 vertices. Normal isn't that important, I just approximate regardless of actual box shape |
---|
3429 | |
---|
3430 | |
---|
3431 | nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles |
---|
3432 | |
---|
3433 | // vertex numbers |
---|
3434 | n_L=nFirstVertex+0 ; |
---|
3435 | n_R=nFirstVertex+1 ; |
---|
3436 | n_F=nFirstVertex+2 ; |
---|
3437 | n_B=nFirstVertex+3 ; |
---|
3438 | n_U=nFirstVertex+4 ; |
---|
3439 | n_D=nFirstVertex+5 ; |
---|
3440 | |
---|
3441 | |
---|
3442 | |
---|
3443 | Vert_L.position[0]=flMinX ; |
---|
3444 | Vert_L.position[1]=flCentreY ; |
---|
3445 | Vert_L.position[2]=flCentreZ ; |
---|
3446 | Vert_L.normal[0]=-1.0 ; |
---|
3447 | Vert_L.normal[1]=0.0 ; |
---|
3448 | Vert_L.normal[2]=0.0 ; |
---|
3449 | Vert_L.texcoord[0][0]=flCentreX ; |
---|
3450 | Vert_L.texcoord[0][1]=flCentreY ; |
---|
3451 | Vert_L.texcoord[1][0]=flCentreZ ; |
---|
3452 | Vert_L.texcoord[1][1]=flBrightness ; |
---|
3453 | Vert_L.color[0]=flColR ; |
---|
3454 | Vert_L.color[1]=flColG ; |
---|
3455 | Vert_L.color[2]=flColB ; |
---|
3456 | if(!AddVertex(Vert_L)) return 0 ; |
---|
3457 | |
---|
3458 | Vert_R.position[0]=flMaxX ; |
---|
3459 | Vert_R.position[1]=flCentreY ; |
---|
3460 | Vert_R.position[2]=flCentreZ ; |
---|
3461 | Vert_R.normal[0]=1.0 ; |
---|
3462 | Vert_R.normal[1]=0.0 ; |
---|
3463 | Vert_R.normal[2]=0.0 ; |
---|
3464 | Vert_R.texcoord[0][0]=flCentreX ; |
---|
3465 | Vert_R.texcoord[0][1]=flCentreY ; |
---|
3466 | Vert_R.texcoord[1][0]=flCentreZ ; |
---|
3467 | Vert_R.texcoord[1][1]=flBrightness ; |
---|
3468 | Vert_R.color[0]=flColR ; |
---|
3469 | Vert_R.color[1]=flColG ; |
---|
3470 | Vert_R.color[2]=flColB ; |
---|
3471 | if(!AddVertex(Vert_R)) return 0 ; |
---|
3472 | |
---|
3473 | Vert_F.position[0]=flCentreX ; |
---|
3474 | Vert_F.position[1]=flCentreY ; |
---|
3475 | Vert_F.position[2]=flMinZ ; |
---|
3476 | Vert_F.normal[0]=0.0 ; |
---|
3477 | Vert_F.normal[1]=0.0 ; |
---|
3478 | Vert_F.normal[2]=-1.0 ; |
---|
3479 | Vert_F.texcoord[0][0]=flCentreX ; |
---|
3480 | Vert_F.texcoord[0][1]=flCentreY ; |
---|
3481 | Vert_F.texcoord[1][0]=flCentreZ ; |
---|
3482 | Vert_F.texcoord[1][1]=flBrightness ; |
---|
3483 | Vert_F.color[0]=flColR ; |
---|
3484 | Vert_F.color[1]=flColG ; |
---|
3485 | Vert_F.color[2]=flColB ; |
---|
3486 | if(!AddVertex(Vert_F)) return 0 ; |
---|
3487 | |
---|
3488 | Vert_B.position[0]=flCentreX ; |
---|
3489 | Vert_B.position[1]=flCentreY ; |
---|
3490 | Vert_B.position[2]=flMaxZ ; |
---|
3491 | Vert_B.normal[0]=0.0 ; |
---|
3492 | Vert_B.normal[1]=0.0 ; |
---|
3493 | Vert_B.normal[2]=1.0 ; |
---|
3494 | Vert_B.texcoord[0][0]=flCentreX ; |
---|
3495 | Vert_B.texcoord[0][1]=flCentreY ; |
---|
3496 | Vert_B.texcoord[1][0]=flCentreZ ; |
---|
3497 | Vert_B.texcoord[1][1]=flBrightness ; |
---|
3498 | Vert_B.color[0]=flColR ; |
---|
3499 | Vert_B.color[1]=flColG ; |
---|
3500 | Vert_B.color[2]=flColB ; |
---|
3501 | if(!AddVertex(Vert_B)) return 0 ; |
---|
3502 | |
---|
3503 | Vert_U.position[0]=flCentreX ; |
---|
3504 | Vert_U.position[1]=flMaxY ; |
---|
3505 | Vert_U.position[2]=flCentreZ ; |
---|
3506 | Vert_U.normal[0]=0.0 ; |
---|
3507 | Vert_U.normal[1]=1.0 ; |
---|
3508 | Vert_U.normal[2]=0.0 ; |
---|
3509 | Vert_U.texcoord[0][0]=flCentreX ; |
---|
3510 | Vert_U.texcoord[0][1]=flCentreY ; |
---|
3511 | Vert_U.texcoord[1][0]=flCentreZ ; |
---|
3512 | Vert_U.texcoord[1][1]=flBrightness ; |
---|
3513 | Vert_U.color[0]=flColR ; |
---|
3514 | Vert_U.color[1]=flColG ; |
---|
3515 | Vert_U.color[2]=flColB ; |
---|
3516 | if(!AddVertex(Vert_U)) return 0 ; |
---|
3517 | |
---|
3518 | Vert_D.position[0]=flCentreX ; |
---|
3519 | Vert_D.position[1]=flMinY ; |
---|
3520 | Vert_D.position[2]=flCentreZ ; |
---|
3521 | Vert_D.normal[0]=0.0 ; |
---|
3522 | Vert_D.normal[1]=-1.0 ; |
---|
3523 | Vert_D.normal[2]=0.0 ; |
---|
3524 | Vert_D.texcoord[0][0]=flCentreX ; |
---|
3525 | Vert_D.texcoord[0][1]=flCentreY ; |
---|
3526 | Vert_D.texcoord[1][0]=flCentreZ ; |
---|
3527 | Vert_D.texcoord[1][1]=flBrightness ; |
---|
3528 | Vert_D.color[0]=flColR ; |
---|
3529 | Vert_D.color[1]=flColG ; |
---|
3530 | Vert_D.color[2]=flColB ; |
---|
3531 | if(!AddVertex(Vert_D)) return 0 ; |
---|
3532 | |
---|
3533 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3534 | |
---|
3535 | Triangle.Texture=m_nDefaultTextureIndexGlowLamp ; |
---|
3536 | Triangle.Lamp=-1 ; |
---|
3537 | Triangle.Group=m_nGroup ; |
---|
3538 | |
---|
3539 | ///////////////////////////////////// |
---|
3540 | |
---|
3541 | Triangle.VIndex[0]=n_U ; |
---|
3542 | Triangle.VIndex[1]=n_L ; |
---|
3543 | Triangle.VIndex[2]=n_F ; |
---|
3544 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3545 | |
---|
3546 | Triangle.VIndex[0]=n_U ; |
---|
3547 | Triangle.VIndex[1]=n_F ; |
---|
3548 | Triangle.VIndex[2]=n_R ; |
---|
3549 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3550 | |
---|
3551 | Triangle.VIndex[0]=n_U ; |
---|
3552 | Triangle.VIndex[1]=n_R ; |
---|
3553 | Triangle.VIndex[2]=n_B ; |
---|
3554 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3555 | |
---|
3556 | Triangle.VIndex[0]=n_U ; |
---|
3557 | Triangle.VIndex[1]=n_B ; |
---|
3558 | Triangle.VIndex[2]=n_L ; |
---|
3559 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3560 | |
---|
3561 | ////////////////////////////////////// |
---|
3562 | |
---|
3563 | Triangle.VIndex[2]=n_D ; |
---|
3564 | Triangle.VIndex[1]=n_L ; |
---|
3565 | Triangle.VIndex[0]=n_F ; |
---|
3566 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3567 | |
---|
3568 | Triangle.VIndex[2]=n_D ; |
---|
3569 | Triangle.VIndex[1]=n_F ; |
---|
3570 | Triangle.VIndex[0]=n_R ; |
---|
3571 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3572 | |
---|
3573 | Triangle.VIndex[2]=n_D ; |
---|
3574 | Triangle.VIndex[1]=n_R ; |
---|
3575 | Triangle.VIndex[0]=n_B ; |
---|
3576 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3577 | |
---|
3578 | Triangle.VIndex[2]=n_D ; |
---|
3579 | Triangle.VIndex[1]=n_B ; |
---|
3580 | Triangle.VIndex[0]=n_L ; |
---|
3581 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3582 | |
---|
3583 | m_nGroup++ ; // increment group once for each glow |
---|
3584 | |
---|
3585 | } |
---|
3586 | |
---|
3587 | |
---|
3588 | |
---|
3589 | return 1 ; |
---|
3590 | } |
---|
3591 | |
---|
3592 | ///////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3593 | |
---|
3594 | |
---|
3595 | int Q3Map::ConvertLightsToGlowTriangles(void) |
---|
3596 | { |
---|
3597 | float flCentreX=0.0f ; |
---|
3598 | float flCentreY=0.0f ; |
---|
3599 | float flCentreZ=0.0f ; |
---|
3600 | |
---|
3601 | float flMinX=0.0f ; |
---|
3602 | float flMinY=0.0f ; |
---|
3603 | float flMinZ=0.0f ; |
---|
3604 | float flMaxX=0.0f ; |
---|
3605 | float flMaxY=0.0f ; |
---|
3606 | float flMaxZ=0.0f ; |
---|
3607 | |
---|
3608 | float flNormX=0.0f ; |
---|
3609 | float flNormY=0.0f ; |
---|
3610 | float flNormZ=0.0f ; |
---|
3611 | float flTexU=0.0f ; |
---|
3612 | float flTexV=0.0f ; |
---|
3613 | |
---|
3614 | float flColR=0.0f ; |
---|
3615 | float flColG=0.0f ; |
---|
3616 | float flColB=0.0f ; |
---|
3617 | |
---|
3618 | float flBrightness=0.0f ; |
---|
3619 | |
---|
3620 | int nLight=0 ; |
---|
3621 | |
---|
3622 | Q3BspVertex Vert_Or ; |
---|
3623 | Q3BspVertex Vert_A0 ; |
---|
3624 | Q3BspVertex Vert_A1 ; |
---|
3625 | Q3BspVertex Vert_B0 ; |
---|
3626 | Q3BspVertex Vert_B1 ; |
---|
3627 | |
---|
3628 | |
---|
3629 | int n_Or=0 ; |
---|
3630 | int n_A0=0 ; |
---|
3631 | int n_A1=0 ; |
---|
3632 | int n_B0=0 ; |
---|
3633 | int n_B1=0 ; |
---|
3634 | |
---|
3635 | int nFirstVertex=0 ; |
---|
3636 | |
---|
3637 | float flBaseGlowSize=0.2f ;//0.001f ; |
---|
3638 | float flGlowSize=0.0f ; |
---|
3639 | |
---|
3640 | char chMessage[1024] ; |
---|
3641 | |
---|
3642 | |
---|
3643 | |
---|
3644 | triangle_t Triangle ; |
---|
3645 | ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ; |
---|
3646 | |
---|
3647 | for(nLight=0 ; nLight<m_nLightMax ; nLight++) |
---|
3648 | //for(nLight=0 ; nLight<1 ; nLight++) |
---|
3649 | { |
---|
3650 | //if(m_pLight[nLight].LightNode>-1) continue ; // Lights that are lightnodes don't add their own triangles. They just exist as information for TexLights. |
---|
3651 | |
---|
3652 | flGlowSize=flBaseGlowSize*m_pLight[nLight].Brightness ; |
---|
3653 | |
---|
3654 | flCentreX = m_pLight[nLight].Position[0] ; |
---|
3655 | flCentreY = m_pLight[nLight].Position[1] ; |
---|
3656 | flCentreZ = m_pLight[nLight].Position[2] ; |
---|
3657 | |
---|
3658 | flMinX = flCentreX-flGlowSize ; |
---|
3659 | flMinY = flCentreY-flGlowSize ; |
---|
3660 | flMinZ = flCentreZ-flGlowSize ; |
---|
3661 | |
---|
3662 | flMaxX = flCentreX+flGlowSize ; |
---|
3663 | flMaxY = flCentreY+flGlowSize ; |
---|
3664 | flMaxZ = flCentreZ+flGlowSize ; |
---|
3665 | |
---|
3666 | flColR = m_pLight[nLight].Colour[0]*255.0f ; |
---|
3667 | flColG = m_pLight[nLight].Colour[1]*255.0f ; |
---|
3668 | flColB = m_pLight[nLight].Colour[2]*255.0f ; |
---|
3669 | |
---|
3670 | flBrightness= m_pLight[nLight].Brightness * 0.75 ;//*2.0 ; |
---|
3671 | |
---|
3672 | ////////////////////////////////////// |
---|
3673 | // setup our 5 vertices. |
---|
3674 | |
---|
3675 | |
---|
3676 | nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles |
---|
3677 | |
---|
3678 | // vertex numbers |
---|
3679 | n_Or=nFirstVertex+0 ; |
---|
3680 | n_A0=nFirstVertex+1 ; |
---|
3681 | n_A1=nFirstVertex+2 ; |
---|
3682 | n_B0=nFirstVertex+3 ; |
---|
3683 | n_B1=nFirstVertex+4 ; |
---|
3684 | |
---|
3685 | |
---|
3686 | |
---|
3687 | |
---|
3688 | |
---|
3689 | |
---|
3690 | |
---|
3691 | |
---|
3692 | |
---|
3693 | |
---|
3694 | |
---|
3695 | |
---|
3696 | |
---|
3697 | |
---|
3698 | |
---|
3699 | |
---|
3700 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3701 | |
---|
3702 | |
---|
3703 | |
---|
3704 | |
---|
3705 | float flHALFPI = 1.5707963 ; |
---|
3706 | float flTWOPI = 6.2831853 ; |
---|
3707 | float flPI = 3.1415926 ; |
---|
3708 | float flAngle=(m_pLight[nLight].Angle/360.0f*flTWOPI)/2.0 ; |
---|
3709 | float flCutoff=32.0f ;//m_pLight[nLight].Brightness ; |
---|
3710 | |
---|
3711 | Q3BspVertex color ; |
---|
3712 | |
---|
3713 | Q3BspVertex NormalVert ; |
---|
3714 | SetVertex(&NormalVert, m_pLight[nLight].Direction[0], m_pLight[nLight].Direction[1], m_pLight[nLight].Direction[2]) ; |
---|
3715 | NormalVert=GetNormalised(&NormalVert) ; |
---|
3716 | |
---|
3717 | Q3BspVertex normal ; |
---|
3718 | SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ; |
---|
3719 | |
---|
3720 | Q3BspVertex adjust=normal ; |
---|
3721 | VertexScale(&adjust, 0.5) ; |
---|
3722 | |
---|
3723 | Q3BspVertex start ; SetVertex(&start, flCentreX, flCentreY, flCentreZ) ; |
---|
3724 | Q3BspVertex end ; SetVertex(&end, flCentreX+normal.position[0], flCentreY+normal.position[1], flCentreZ+normal.position[2]) ; |
---|
3725 | |
---|
3726 | Q3BspVertex xaxis ; SetVertex(&xaxis, 1,0,0) ; |
---|
3727 | Q3BspVertex xaxisneg ; SetVertex(&xaxisneg, -1,0,0) ; |
---|
3728 | Q3BspVertex yaxis ; SetVertex(&yaxis, 0,1,0) ; |
---|
3729 | Q3BspVertex Origin ; SetVertex(&Origin, 0,0,0) ; |
---|
3730 | Q3BspVertex tangentA ; |
---|
3731 | Q3BspVertex tangentB ; |
---|
3732 | Q3BspVertex tangentStart ; |
---|
3733 | Q3BspVertex tangentEnd ; |
---|
3734 | Q3BspVertex tangentEndA0 ; |
---|
3735 | Q3BspVertex tangentEndA1 ; |
---|
3736 | Q3BspVertex tangentEndB0 ; |
---|
3737 | Q3BspVertex tangentEndB1 ; |
---|
3738 | |
---|
3739 | Q3BspVertex tangentANorm ; |
---|
3740 | Q3BspVertex tangentBNorm ; |
---|
3741 | |
---|
3742 | Q3BspVertex raytangent ; |
---|
3743 | |
---|
3744 | Q3BspVertex ray ; |
---|
3745 | float theta=0.0f ; |
---|
3746 | float adjacent=0.0f ; |
---|
3747 | SetVertex(&color, 0.66, 0.66, 0.66) ; |
---|
3748 | |
---|
3749 | if(flAngle<0.0001) return 0 ; |
---|
3750 | |
---|
3751 | if(flAngle>flPI-0.01) // near on 180 degrees |
---|
3752 | flAngle=flPI-0.01 ; |
---|
3753 | |
---|
3754 | |
---|
3755 | Q3BspVertex backshift ; |
---|
3756 | backshift=normal ; |
---|
3757 | VertexScale(&backshift, 0.95) ; |
---|
3758 | |
---|
3759 | |
---|
3760 | if( !VectorsAreEqual(&NormalVert, &xaxis) && !VectorsAreEqual(&NormalVert, &xaxisneg) ) |
---|
3761 | tangentA=NormalizedCrossProduct(Origin, normal, xaxis) ; |
---|
3762 | else |
---|
3763 | tangentA=NormalizedCrossProduct(Origin, normal, yaxis) ; |
---|
3764 | |
---|
3765 | tangentB=NormalizedCrossProduct(Origin, normal, tangentA) ; |
---|
3766 | |
---|
3767 | tangentANorm=tangentA ; |
---|
3768 | tangentBNorm=tangentB ; |
---|
3769 | |
---|
3770 | |
---|
3771 | |
---|
3772 | theta=flHALFPI-flAngle ; // angle between adjacent and hypotenuse (the normal is the "opposite" side, and we know there's a right angle) |
---|
3773 | adjacent=VertexDistance(&Origin, &normal)/tan(theta) ; |
---|
3774 | |
---|
3775 | ////////////////////////////////////////////////////////////////////// |
---|
3776 | |
---|
3777 | Vert_Or.position[0]=end.position[0]-backshift.position[0] ; |
---|
3778 | Vert_Or.position[1]=end.position[1]-backshift.position[1] ; |
---|
3779 | Vert_Or.position[2]=end.position[2]-backshift.position[2] ; |
---|
3780 | Vert_Or.normal[0]= NormalVert.position[0] ; |
---|
3781 | Vert_Or.normal[1]= NormalVert.position[1] ; |
---|
3782 | Vert_Or.normal[2]= NormalVert.position[2] ; |
---|
3783 | Vert_Or.texcoord[0][0]=flCentreX ; |
---|
3784 | Vert_Or.texcoord[0][1]=flCentreY ; |
---|
3785 | Vert_Or.texcoord[1][0]=flCentreZ ; |
---|
3786 | Vert_Or.texcoord[1][1]=flBrightness ; |
---|
3787 | Vert_Or.color[0]=flColR ; |
---|
3788 | Vert_Or.color[1]=flColG ; |
---|
3789 | Vert_Or.color[2]=flColB ; |
---|
3790 | if(!AddVertex(Vert_Or)) return 0 ; |
---|
3791 | |
---|
3792 | |
---|
3793 | |
---|
3794 | |
---|
3795 | ////////////////////////////////////////////////////////////////////// |
---|
3796 | |
---|
3797 | flColR=0.0f ; |
---|
3798 | flColG=0.0f ; |
---|
3799 | flColB=0.0f ; |
---|
3800 | |
---|
3801 | tangentA=GetNormalised(&tangentA) ; |
---|
3802 | VertexScale(&tangentA, adjacent) ; |
---|
3803 | |
---|
3804 | tangentStart=start ; |
---|
3805 | tangentEnd=VectorSubtract(&end, &tangentA) ; |
---|
3806 | ray=VectorSubtract(&tangentEnd, &tangentStart) ; |
---|
3807 | ray=GetNormalised(&ray) ; |
---|
3808 | VertexScale(&ray, flCutoff) ; |
---|
3809 | tangentStart=start ; |
---|
3810 | tangentEndA0=VectorAdd(&start, &ray) ; |
---|
3811 | |
---|
3812 | raytangent=VectorSubtract(&end, &tangentEndA0) ; |
---|
3813 | raytangent=VectorAdd(&raytangent, &adjust) ; |
---|
3814 | raytangent=GetNormalised(&raytangent) ; |
---|
3815 | |
---|
3816 | |
---|
3817 | |
---|
3818 | tangentEndA0=VectorSubtract(&tangentEndA0, &backshift) ; |
---|
3819 | Vert_A0.position[0]=tangentEndA0.position[0] ; |
---|
3820 | Vert_A0.position[1]=tangentEndA0.position[1] ; |
---|
3821 | Vert_A0.position[2]=tangentEndA0.position[2] ; |
---|
3822 | Vert_A0.normal[0]= -raytangent.position[0] ; |
---|
3823 | Vert_A0.normal[1]= -raytangent.position[1] ; |
---|
3824 | Vert_A0.normal[2]= -raytangent.position[2] ; |
---|
3825 | Vert_A0.texcoord[0][0]=flCentreX ; |
---|
3826 | Vert_A0.texcoord[0][1]=flCentreY ; |
---|
3827 | Vert_A0.texcoord[1][0]=flCentreZ ; |
---|
3828 | Vert_A0.texcoord[1][1]=flBrightness ; |
---|
3829 | Vert_A0.color[0]=flColR ;//abs(Vert_A0.normal[0])*255 ;//0.0f ; |
---|
3830 | Vert_A0.color[1]=flColG ;//abs(Vert_A0.normal[1])*255 ;//0.0f ; |
---|
3831 | Vert_A0.color[2]=flColB ;//abs(Vert_A0.normal[2])*255 ;//0.0f ; |
---|
3832 | if(!AddVertex(Vert_A0)) return 0 ; |
---|
3833 | |
---|
3834 | |
---|
3835 | tangentStart=start ; |
---|
3836 | tangentEnd=VectorAdd(&end, &tangentA) ; |
---|
3837 | ray=VectorSubtract(&tangentEnd, &tangentStart) ; |
---|
3838 | ray=GetNormalised(&ray) ; |
---|
3839 | VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ; |
---|
3840 | tangentStart=start ; |
---|
3841 | tangentEndA1=VectorAdd(&start, &ray) ; |
---|
3842 | |
---|
3843 | raytangent=VectorSubtract(&end, &tangentEndA1) ; |
---|
3844 | raytangent=VectorAdd(&raytangent, &adjust) ; |
---|
3845 | raytangent=GetNormalised(&raytangent) ; |
---|
3846 | |
---|
3847 | tangentEndA1=VectorSubtract(&tangentEndA1, &backshift) ; |
---|
3848 | Vert_A1.position[0]=tangentEndA1.position[0] ; |
---|
3849 | Vert_A1.position[1]=tangentEndA1.position[1] ; |
---|
3850 | Vert_A1.position[2]=tangentEndA1.position[2] ; |
---|
3851 | Vert_A1.normal[0]= -raytangent.position[0] ; |
---|
3852 | Vert_A1.normal[1]= -raytangent.position[1] ; |
---|
3853 | Vert_A1.normal[2]= -raytangent.position[2] ; |
---|
3854 | Vert_A1.texcoord[0][0]=flCentreX ; |
---|
3855 | Vert_A1.texcoord[0][1]=flCentreY ; |
---|
3856 | Vert_A1.texcoord[1][0]=flCentreZ ; |
---|
3857 | Vert_A1.texcoord[1][1]=flBrightness ; |
---|
3858 | Vert_A1.color[0]=flColR ;//abs(Vert_A1.normal[0])*255 ;//0.0f ; |
---|
3859 | Vert_A1.color[1]=flColG ;//abs(Vert_A1.normal[1])*255 ;//0.0f ; |
---|
3860 | Vert_A1.color[2]=flColB ;//abs(Vert_A1.normal[2])*255 ;//0.0f ; |
---|
3861 | if(!AddVertex(Vert_A1)) return 0 ; |
---|
3862 | |
---|
3863 | ////////////////////////////////////////////////////////////////////// |
---|
3864 | |
---|
3865 | tangentB=GetNormalised(&tangentB) ; |
---|
3866 | VertexScale(&tangentB, adjacent) ; //tangentB.getScaledBy(adjacent) ; |
---|
3867 | |
---|
3868 | tangentStart=start ; |
---|
3869 | tangentEnd=VectorSubtract(&end, &tangentB) ; |
---|
3870 | ray=VectorSubtract(&tangentEnd, &tangentStart) ; |
---|
3871 | ray=GetNormalised(&ray) ; |
---|
3872 | VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ; |
---|
3873 | tangentStart=start ; |
---|
3874 | tangentEndB0=VectorAdd(&start, &ray) ; |
---|
3875 | |
---|
3876 | raytangent=VectorSubtract(&end, &tangentEndB0) ; |
---|
3877 | raytangent=VectorAdd(&raytangent, &adjust) ; |
---|
3878 | raytangent=GetNormalised(&raytangent) ; |
---|
3879 | |
---|
3880 | tangentEndB0=VectorSubtract(&tangentEndB0, &backshift) ; |
---|
3881 | Vert_B0.position[0]=tangentEndB0.position[0] ; |
---|
3882 | Vert_B0.position[1]=tangentEndB0.position[1] ; |
---|
3883 | Vert_B0.position[2]=tangentEndB0.position[2] ; |
---|
3884 | Vert_B0.normal[0]= -raytangent.position[0] ; |
---|
3885 | Vert_B0.normal[1]= -raytangent.position[1] ; |
---|
3886 | Vert_B0.normal[2]= -raytangent.position[2] ; |
---|
3887 | Vert_B0.texcoord[0][0]=flCentreX ; |
---|
3888 | Vert_B0.texcoord[0][1]=flCentreY ; |
---|
3889 | Vert_B0.texcoord[1][0]=flCentreZ ; |
---|
3890 | Vert_B0.texcoord[1][1]=flBrightness ; |
---|
3891 | Vert_B0.color[0]=flColR ;//abs(Vert_B0.normal[0])*255 ;//0.0f ; |
---|
3892 | Vert_B0.color[1]=flColG ;//abs(Vert_B0.normal[1])*255 ;//0.0f ; |
---|
3893 | Vert_B0.color[2]=flColB ;//abs(Vert_B0.normal[2])*255 ;//0.0f ; |
---|
3894 | if(!AddVertex(Vert_B0)) return 0 ; |
---|
3895 | |
---|
3896 | tangentStart=start ; |
---|
3897 | tangentEnd=VectorAdd(&end, &tangentB) ; |
---|
3898 | ray=VectorSubtract(&tangentEnd, &tangentStart) ; |
---|
3899 | ray=GetNormalised(&ray) ; |
---|
3900 | VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ; |
---|
3901 | tangentStart=start ; |
---|
3902 | tangentEndB1=VectorAdd(&start, &ray) ; |
---|
3903 | |
---|
3904 | raytangent=VectorSubtract(&end, &tangentEndB1) ; |
---|
3905 | raytangent=VectorAdd(&raytangent, &adjust) ; |
---|
3906 | raytangent=GetNormalised(&raytangent) ; |
---|
3907 | |
---|
3908 | tangentEndB1=VectorSubtract(&tangentEndB1, &backshift) ; |
---|
3909 | Vert_B1.position[0]=tangentEndB1.position[0] ; |
---|
3910 | Vert_B1.position[1]=tangentEndB1.position[1] ; |
---|
3911 | Vert_B1.position[2]=tangentEndB1.position[2] ; |
---|
3912 | Vert_B1.normal[0]= -raytangent.position[0] ; |
---|
3913 | Vert_B1.normal[1]= -raytangent.position[1] ; |
---|
3914 | Vert_B1.normal[2]= -raytangent.position[2] ; |
---|
3915 | Vert_B1.texcoord[0][0]=flCentreX ; |
---|
3916 | Vert_B1.texcoord[0][1]=flCentreY ; |
---|
3917 | Vert_B1.texcoord[1][0]=flCentreZ ; |
---|
3918 | Vert_B1.texcoord[1][1]=flBrightness ; |
---|
3919 | Vert_B1.color[0]=flColR ;//abs(Vert_B1.normal[0])*255 ;//0.0f ; |
---|
3920 | Vert_B1.color[1]=flColG ;//abs(Vert_B1.normal[1])*255 ;//0.0f ; |
---|
3921 | Vert_B1.color[2]=flColB ;//abs(Vert_B1.normal[2])*255 ;//0.0f ; |
---|
3922 | if(!AddVertex(Vert_B1)) return 0 ; |
---|
3923 | |
---|
3924 | ///////////////////////////////////////////////////////////////////// |
---|
3925 | |
---|
3926 | |
---|
3927 | |
---|
3928 | |
---|
3929 | // the four verts are position correctly to make the large end of a cone (or rather, pyramid) that would be consistent |
---|
3930 | // with the angle and their distance from the origin. However we cheat and move them back on top of the origin |
---|
3931 | // so that map lights come out looking better. |
---|
3932 | |
---|
3933 | /* |
---|
3934 | SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ; |
---|
3935 | |
---|
3936 | tangentEndA0=VectorSubtract(&tangentEndA0, &normal) ; |
---|
3937 | Vert_A0.position[0]=tangentEndA0.position[0] ; |
---|
3938 | Vert_A0.position[1]=tangentEndA0.position[1] ; |
---|
3939 | Vert_A0.position[2]=tangentEndA0.position[2] ; |
---|
3940 | |
---|
3941 | tangentEndA1=VectorSubtract(&tangentEndA1, &normal) ; |
---|
3942 | Vert_A1.position[0]=tangentEndA1.position[0] ; |
---|
3943 | Vert_A1.position[1]=tangentEndA1.position[1] ; |
---|
3944 | Vert_A1.position[2]=tangentEndA1.position[2] ; |
---|
3945 | |
---|
3946 | tangentEndB0=VectorSubtract(&tangentEndB0, &normal) ; |
---|
3947 | Vert_A0.position[0]=tangentEndB0.position[0] ; |
---|
3948 | Vert_A0.position[1]=tangentEndB0.position[1] ; |
---|
3949 | Vert_A0.position[2]=tangentEndB0.position[2] ; |
---|
3950 | |
---|
3951 | tangentEndB1=VectorSubtract(&tangentEndB1, &normal) ; |
---|
3952 | Vert_A1.position[0]=tangentEndB1.position[0] ; |
---|
3953 | Vert_A1.position[1]=tangentEndB1.position[1] ; |
---|
3954 | Vert_A1.position[2]=tangentEndB1.position[2] ; |
---|
3955 | */ |
---|
3956 | |
---|
3957 | |
---|
3958 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3959 | |
---|
3960 | Triangle.Texture=m_nDefaultTextureIndexGlowLight ; |
---|
3961 | Triangle.Lamp=-1 ; |
---|
3962 | Triangle.Group=m_nGroup ; |
---|
3963 | |
---|
3964 | ///////////////////////////////////// |
---|
3965 | |
---|
3966 | Triangle.VIndex[0]=n_Or ; |
---|
3967 | Triangle.VIndex[2]=n_A0 ; |
---|
3968 | Triangle.VIndex[1]=n_B1 ; |
---|
3969 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3970 | |
---|
3971 | Triangle.VIndex[0]=n_Or ; |
---|
3972 | Triangle.VIndex[2]=n_B1 ; |
---|
3973 | Triangle.VIndex[1]=n_A1 ; |
---|
3974 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3975 | |
---|
3976 | Triangle.VIndex[0]=n_Or ; |
---|
3977 | Triangle.VIndex[2]=n_A1 ; |
---|
3978 | Triangle.VIndex[1]=n_B0 ; |
---|
3979 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3980 | |
---|
3981 | Triangle.VIndex[0]=n_Or ; |
---|
3982 | Triangle.VIndex[2]=n_B0 ; |
---|
3983 | Triangle.VIndex[1]=n_A0 ; |
---|
3984 | if(!AddTriangle(Triangle)) return 0 ; |
---|
3985 | |
---|
3986 | m_nGroup++ ; // increment group once for each glow |
---|
3987 | |
---|
3988 | } |
---|
3989 | |
---|
3990 | return 1 ; |
---|
3991 | } |
---|
3992 | |
---|
3993 | |
---|
3994 | |
---|
3995 | |
---|
3996 | ///////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
3997 | // some vertex manipulation functions used for setting up the light disk. |
---|
3998 | // They only work on the position, so other parts of the struct need to be setup seperately |
---|
3999 | |
---|
4000 | |
---|
4001 | void Q3Map::SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos) |
---|
4002 | { |
---|
4003 | pVert->position[0]=flXPos ; |
---|
4004 | pVert->position[1]=flYPos ; |
---|
4005 | pVert->position[2]=flZPos ; |
---|
4006 | } |
---|
4007 | |
---|
4008 | // this doesn't test exact equivalence, but rather within the range of an epsilon VERYSMALL |
---|
4009 | bool Q3Map::VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB) |
---|
4010 | { |
---|
4011 | if( fabs(pVecA->position[0] - pVecB->position[0])>VERYSMALL ) return false ; |
---|
4012 | if( fabs(pVecA->position[1] - pVecB->position[1])>VERYSMALL ) return false ; |
---|
4013 | if( fabs(pVecA->position[2] - pVecB->position[2])>VERYSMALL ) return false ; |
---|
4014 | |
---|
4015 | return true ; |
---|
4016 | } |
---|
4017 | |
---|
4018 | // VertA is the origin of VertB and VertC |
---|
4019 | Q3BspVertex Q3Map::NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC) |
---|
4020 | { |
---|
4021 | |
---|
4022 | |
---|
4023 | Q3BspVertex Cross ; |
---|
4024 | |
---|
4025 | // edge vectors |
---|
4026 | float flVecXA_CP = VertA.position[0] - VertB.position[0] ; |
---|
4027 | float flVecYA_CP = VertA.position[1] - VertB.position[1] ; |
---|
4028 | float flVecZA_CP = VertA.position[2] - VertB.position[2] ; |
---|
4029 | float flVecXB_CP = VertA.position[0] - VertC.position[0] ; |
---|
4030 | float flVecYB_CP = VertA.position[1] - VertC.position[1] ; |
---|
4031 | float flVecZB_CP = VertA.position[2] - VertC.position[2] ; |
---|
4032 | |
---|
4033 | // cross product |
---|
4034 | float flCpx_CP = (flVecZA_CP * flVecYB_CP) - (flVecYA_CP * flVecZB_CP); |
---|
4035 | float flCpy_CP = (flVecXA_CP * flVecZB_CP) - (flVecZA_CP * flVecXB_CP); |
---|
4036 | float flCpz_CP = (flVecYA_CP * flVecXB_CP) - (flVecXA_CP * flVecYB_CP); |
---|
4037 | |
---|
4038 | // Normalize |
---|
4039 | float flR_CP = sqrt(flCpx_CP * flCpx_CP + flCpy_CP * flCpy_CP + flCpz_CP * flCpz_CP); |
---|
4040 | |
---|
4041 | Cross.position[0] = flCpx_CP / flR_CP; |
---|
4042 | Cross.position[1] = flCpy_CP / flR_CP; |
---|
4043 | Cross.position[2] = flCpz_CP / flR_CP; |
---|
4044 | |
---|
4045 | return Cross ; |
---|
4046 | } |
---|
4047 | |
---|
4048 | float Q3Map::VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB) |
---|
4049 | { |
---|
4050 | float flXDis=VertA->position[0]-VertB->position[0] ; |
---|
4051 | float flYDis=VertA->position[1]-VertB->position[1] ; |
---|
4052 | float flZDis=VertA->position[2]-VertB->position[2] ; |
---|
4053 | |
---|
4054 | return sqrt(flXDis*flXDis+flYDis*flYDis+flZDis*flZDis) ; |
---|
4055 | } |
---|
4056 | |
---|
4057 | void Q3Map::VertexScale(Q3BspVertex* pVert, float flScale) |
---|
4058 | { |
---|
4059 | pVert->position[0]*=flScale ; |
---|
4060 | pVert->position[1]*=flScale ; |
---|
4061 | pVert->position[2]*=flScale ; |
---|
4062 | } |
---|
4063 | |
---|
4064 | Q3BspVertex Q3Map::GetNormalised(Q3BspVertex* pVector) |
---|
4065 | { |
---|
4066 | float flLength=sqrt((pVector->position[0]*pVector->position[0])+(pVector->position[1]*pVector->position[1])+(pVector->position[2]*pVector->position[2])) ; |
---|
4067 | |
---|
4068 | Q3BspVertex Vector=*pVector ; |
---|
4069 | |
---|
4070 | Vector.position[0]/=flLength ; |
---|
4071 | Vector.position[1]/=flLength ; |
---|
4072 | Vector.position[2]/=flLength ; |
---|
4073 | |
---|
4074 | return Vector ; |
---|
4075 | } |
---|
4076 | |
---|
4077 | Q3BspVertex Q3Map::VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB) |
---|
4078 | { |
---|
4079 | Q3BspVertex Vector ; |
---|
4080 | |
---|
4081 | Vector.position[0]=pVecA->position[0] + pVecB->position[0] ; |
---|
4082 | Vector.position[1]=pVecA->position[1] + pVecB->position[1] ; |
---|
4083 | Vector.position[2]=pVecA->position[2] + pVecB->position[2] ; |
---|
4084 | |
---|
4085 | return Vector ; |
---|
4086 | } |
---|
4087 | |
---|
4088 | Q3BspVertex Q3Map::VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB) |
---|
4089 | { |
---|
4090 | Q3BspVertex Vector ; |
---|
4091 | |
---|
4092 | Vector.position[0]=pVecA->position[0] - pVecB->position[0] ; |
---|
4093 | Vector.position[1]=pVecA->position[1] - pVecB->position[1] ; |
---|
4094 | Vector.position[2]=pVecA->position[2] - pVecB->position[2] ; |
---|
4095 | |
---|
4096 | return Vector ; |
---|
4097 | } |
---|
4098 | |
---|
4099 | Q3BspVertex Q3Map::VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB) |
---|
4100 | { |
---|
4101 | Q3BspVertex Vector ; |
---|
4102 | |
---|
4103 | Vector.position[0]=pVecA->position[0] * pVecB->position[0] ; |
---|
4104 | Vector.position[1]=pVecA->position[1] * pVecB->position[1] ; |
---|
4105 | Vector.position[2]=pVecA->position[2] * pVecB->position[2] ; |
---|
4106 | |
---|
4107 | return Vector ; |
---|
4108 | } |
---|
4109 | |
---|
4110 | |
---|
4111 | |
---|
4112 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
4113 | |
---|
4114 | |
---|
4115 | |
---|
4116 | |
---|
4117 | void Q3Map::GetTexLampTextureNumbers() |
---|
4118 | { |
---|
4119 | m_nBZN_LightNode0=-1 ; |
---|
4120 | m_nBZN_LightNode1=-1 ; |
---|
4121 | m_nBZN_LightNode2=-1 ; |
---|
4122 | m_nBZN_LightNode3=-1 ; |
---|
4123 | |
---|
4124 | int nTex=0; |
---|
4125 | char chTexName[1024] ; |
---|
4126 | int nLen=0 ; |
---|
4127 | int nPos=0 ; |
---|
4128 | |
---|
4129 | int nMatch=0 ; |
---|
4130 | |
---|
4131 | strcpy(chTexName, "textures/common/bzn_lightnode") ; |
---|
4132 | nLen=strlen(chTexName) ; |
---|
4133 | |
---|
4134 | for(nTex=0 ; nTex<m_nTextureMax ; nTex++) |
---|
4135 | { |
---|
4136 | nMatch=1 ; |
---|
4137 | for(nPos=nLen-1 ; nPos>=0 ; nPos--) // faster to check backwards since lots of textures will start with "textures/common/" |
---|
4138 | if(m_pTexture[nTex].name[nPos]!=chTexName[nPos]) |
---|
4139 | { |
---|
4140 | nMatch=0 ; |
---|
4141 | break ; |
---|
4142 | } |
---|
4143 | |
---|
4144 | if(nMatch) |
---|
4145 | { |
---|
4146 | // what is the last character? |
---|
4147 | if(m_pTexture[nTex].name[nLen]=='0') |
---|
4148 | m_nBZN_LightNode0=nTex ; |
---|
4149 | else |
---|
4150 | if(m_pTexture[nTex].name[nLen]=='1') |
---|
4151 | m_nBZN_LightNode1=nTex ; |
---|
4152 | else |
---|
4153 | if(m_pTexture[nTex].name[nLen]=='2') |
---|
4154 | m_nBZN_LightNode2=nTex ; |
---|
4155 | else |
---|
4156 | if(m_pTexture[nTex].name[nLen]=='3') |
---|
4157 | m_nBZN_LightNode3=nTex ; |
---|
4158 | |
---|
4159 | }// end if match |
---|
4160 | |
---|
4161 | |
---|
4162 | }// end for nTex |
---|
4163 | |
---|
4164 | } |
---|
4165 | |
---|
4166 | int Q3Map::SortTrianglesIntoGroups(void) |
---|
4167 | { |
---|
4168 | |
---|
4169 | |
---|
4170 | int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number. |
---|
4171 | |
---|
4172 | ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ; |
---|
4173 | if(pFaceOrder==NULL) return 0 ; // out of memory. |
---|
4174 | |
---|
4175 | // temporary copy of m_pTriangles to make sorting easier |
---|
4176 | triangle_t *TempTriangle = new triangle_t[m_nTriangleMax]; |
---|
4177 | if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory |
---|
4178 | memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ; |
---|
4179 | |
---|
4180 | // create the initial face "value" by setting the most significant bits to it's criteria number |
---|
4181 | for (int i=0; i < m_nTriangleMax; i++) |
---|
4182 | if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles |
---|
4183 | pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<GROUPSORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<GROUPSORT_GROUP_SHIFT ) + i ; |
---|
4184 | |
---|
4185 | // sort the ULONGLONGs, this will order things according to our criteria |
---|
4186 | // sorting is based firstly on subzone, secondly on texture. |
---|
4187 | // So all triangles in a subzone will be grouped together, |
---|
4188 | // and within that group all triangles with the same material will be grouped together. |
---|
4189 | |
---|
4190 | qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareGroups); |
---|
4191 | |
---|
4192 | // copy the sorted faces back to the original |
---|
4193 | for (int i=0; i < nNewSize; i++) |
---|
4194 | m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ; |
---|
4195 | |
---|
4196 | // update m_nTriangleMax to show that there may now be less triangles |
---|
4197 | m_nTriangleMax=nNewSize ; |
---|
4198 | |
---|
4199 | // clean up the memory we used |
---|
4200 | DELETE_ARRAY( pFaceOrder ) ; |
---|
4201 | DELETE_ARRAY( TempTriangle ) ; |
---|
4202 | |
---|
4203 | |
---|
4204 | // now that the triangles are sorting according to zone and group, |
---|
4205 | // re-assign the group numbers per zone, from 0 to FACESORT_GROUP_LIMIT-1 |
---|
4206 | // All non-trans triangles will be group 0, trans triangles will be 1 to FACESORT_GROUP_LIMIT-1 |
---|
4207 | |
---|
4208 | int nTri=0 ; |
---|
4209 | int nZone=-1 ; |
---|
4210 | int nGroup=-1 ; |
---|
4211 | int nNewGroup=0 ; |
---|
4212 | |
---|
4213 | //char chMessage[1024] ; |
---|
4214 | |
---|
4215 | for(nTri=0 ; nTri<m_nTriangleMax ; nTri++) |
---|
4216 | { |
---|
4217 | // reset the newgroup if we've got a new zone |
---|
4218 | if(m_pTriangle[nTri].Zone!=nZone) |
---|
4219 | { |
---|
4220 | nZone=m_pTriangle[nTri].Zone ; |
---|
4221 | nGroup=-1 ; |
---|
4222 | nNewGroup=0 ; |
---|
4223 | } |
---|
4224 | |
---|
4225 | // if we have a new group, increment the newgroup number, fail if we have too many |
---|
4226 | if(m_pTriangle[nTri].Group!=nGroup) |
---|
4227 | { |
---|
4228 | // if this is a trans triangle, inc the newgroup |
---|
4229 | if(m_pTransTexture[ m_pTriangle[nTri].Texture ]) |
---|
4230 | { |
---|
4231 | nNewGroup++ ; // will always be at least 1 |
---|
4232 | if(nNewGroup>=FACESORT_GROUP_LIMIT) return 0 ; // too many groups in a zone. |
---|
4233 | } |
---|
4234 | |
---|
4235 | nGroup=m_pTriangle[nTri].Group ; |
---|
4236 | } |
---|
4237 | |
---|
4238 | if(m_pTransTexture[ m_pTriangle[nTri].Texture ]==0) |
---|
4239 | m_pTriangle[nTri].Group=0 ; |
---|
4240 | else |
---|
4241 | m_pTriangle[nTri].Group=nNewGroup ; |
---|
4242 | |
---|
4243 | |
---|
4244 | |
---|
4245 | }// end for tri |
---|
4246 | |
---|
4247 | return 1 ; |
---|
4248 | } |
---|
4249 | |
---|
4250 | |
---|
4251 | // static function for sorting groups, required by qsort |
---|
4252 | int Q3Map::compareGroups( const void *arg1, const void *arg2 ) |
---|
4253 | { |
---|
4254 | ULONGLONG FaceA= *(ULONGLONG*)arg1 ; |
---|
4255 | ULONGLONG FaceB= *(ULONGLONG*)arg2 ; |
---|
4256 | |
---|
4257 | if(FaceA < FaceB) |
---|
4258 | return -1 ; |
---|
4259 | else |
---|
4260 | if(FaceA > FaceB) |
---|
4261 | return 1 ; |
---|
4262 | |
---|
4263 | return 0 ; |
---|
4264 | } |
---|
4265 | |
---|
4266 | |
---|
4267 | |
---|
4268 | // sort faces so that we can batch effectively when constructing our manualobjects |
---|
4269 | // Currently grouped according to zone and texture. |
---|
4270 | // Triangles not in any subzone will be dropped at this stage. |
---|
4271 | int Q3Map::SortTrianglesIntoBatches(void) |
---|
4272 | { |
---|
4273 | |
---|
4274 | |
---|
4275 | int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number. |
---|
4276 | |
---|
4277 | ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ; |
---|
4278 | if(pFaceOrder==NULL) return 0 ; // out of memory. |
---|
4279 | |
---|
4280 | // temporary copy of m_pTriangles to make sorting easier |
---|
4281 | triangle_t *TempTriangle = new triangle_t[m_nTriangleMax]; |
---|
4282 | if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory |
---|
4283 | memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ; |
---|
4284 | |
---|
4285 | // create the initial face "value" by setting the most significant bits to it's criteria number |
---|
4286 | for (int i=0; i < m_nTriangleMax; i++) |
---|
4287 | if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles |
---|
4288 | pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<FACESORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<FACESORT_TEXTURE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Group)<<FACESORT_GROUP_SHIFT ) + i ; |
---|
4289 | |
---|
4290 | // sort the ULONGLONGs, this will order things according to our criteria |
---|
4291 | // sorting is based firstly on subzone, secondly on texture. |
---|
4292 | // So all triangles in a subzone will be grouped together, |
---|
4293 | // and within that group all triangles with the same material will be grouped together. |
---|
4294 | |
---|
4295 | qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareTriangles); |
---|
4296 | |
---|
4297 | // copy the sorted faces back to the original |
---|
4298 | for (int i=0; i < nNewSize; i++) |
---|
4299 | m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ; |
---|
4300 | |
---|
4301 | // update m_nTriangleMax to show that there may now be less triangles |
---|
4302 | m_nTriangleMax=nNewSize ; |
---|
4303 | |
---|
4304 | // clean up the memory we used |
---|
4305 | DELETE_ARRAY( pFaceOrder ) ; |
---|
4306 | DELETE_ARRAY( TempTriangle ) ; |
---|
4307 | |
---|
4308 | return 1 ; |
---|
4309 | } |
---|
4310 | |
---|
4311 | // static function for sorting triangles, required by qsort |
---|
4312 | int Q3Map::compareTriangles( const void *arg1, const void *arg2 ) |
---|
4313 | { |
---|
4314 | ULONGLONG FaceA= *(ULONGLONG*)arg1 ; |
---|
4315 | ULONGLONG FaceB= *(ULONGLONG*)arg2 ; |
---|
4316 | |
---|
4317 | if(FaceA < FaceB) |
---|
4318 | return -1 ; |
---|
4319 | else |
---|
4320 | if(FaceA > FaceB) |
---|
4321 | return 1 ; |
---|
4322 | |
---|
4323 | return 0 ; |
---|
4324 | } |
---|
4325 | |
---|
4326 | |
---|
4327 | |
---|
4328 | |
---|
4329 | // note which texture numbers correspond to textures that have transparency. |
---|
4330 | // needed for when we work out transparency groups and related stuff |
---|
4331 | int Q3Map::SetupTransTextures(void) |
---|
4332 | { |
---|
4333 | int nMaterial=0 ; |
---|
4334 | int nPos=0 ; |
---|
4335 | char chMaterial[1024] ; |
---|
4336 | |
---|
4337 | // create the memory for the transtextures |
---|
4338 | m_pTransTexture = new int[m_nTextureMax] ; |
---|
4339 | if(m_pTransTexture==NULL) return 0 ; // out of memory. |
---|
4340 | |
---|
4341 | for(nMaterial=0 ; nMaterial<m_nTextureMax ; nMaterial++) |
---|
4342 | { |
---|
4343 | // copy the material name. |
---|
4344 | // q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated. They have no extension either. |
---|
4345 | nPos=-1 ; |
---|
4346 | while((++nPos<Q3NAMESIZE) && (m_pTexture[nMaterial].name[nPos]!=' ') && (m_pTexture[nMaterial].name[nPos]!='\0')) |
---|
4347 | chMaterial[nPos]=m_pTexture[nMaterial].name[nPos] ; |
---|
4348 | |
---|
4349 | // make sure name is null terminated |
---|
4350 | chMaterial[nPos]='\0' ; |
---|
4351 | |
---|
4352 | |
---|
4353 | // is the texture a type we need to flag as transparent? |
---|
4354 | if(strstr(chMaterial, "GEL")!=NULL) |
---|
4355 | m_pTransTexture[nMaterial]=1 ; |
---|
4356 | else |
---|
4357 | m_pTransTexture[nMaterial]=0 ; |
---|
4358 | |
---|
4359 | }// end for nMaterial |
---|
4360 | |
---|
4361 | return 1 ; |
---|
4362 | |
---|
4363 | } |
---|
4364 | |
---|
4365 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
4366 | |
---|
4367 | int Q3Map::AssignPortalsToZones(void) |
---|
4368 | { |
---|
4369 | int nZone=0 ; |
---|
4370 | float flMinX=0.0f ; |
---|
4371 | float flMaxX=0.0f ; |
---|
4372 | float flMinY=0.0f ; |
---|
4373 | float flMaxY=0.0f ; |
---|
4374 | float flMinZ=0.0f ; |
---|
4375 | float flMaxZ=0.0f ; |
---|
4376 | int nMaxSubZone=m_iNumSubZones ; |
---|
4377 | int nSubZone=0 ; |
---|
4378 | int nMaxPortal=m_iNumPortals ; |
---|
4379 | int nPortal=0 ; |
---|
4380 | int nIndex=0 ; |
---|
4381 | int nPos=0 ; |
---|
4382 | |
---|
4383 | |
---|
4384 | |
---|
4385 | // clear the portal settings. |
---|
4386 | for(nZone=0 ; nZone<m_nMaxZone ; nZone++) |
---|
4387 | m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]=0 ; |
---|
4388 | |
---|
4389 | for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++) |
---|
4390 | m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]=0 ; |
---|
4391 | |
---|
4392 | |
---|
4393 | |
---|
4394 | // now test each subzone against each portal to see what zones each portal contains. |
---|
4395 | for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++) |
---|
4396 | { |
---|
4397 | nZone=m_pSubZones[nSubZone].Zone ; |
---|
4398 | flMinX=m_pSubZones[nSubZone].Min[0] ; |
---|
4399 | flMaxX=m_pSubZones[nSubZone].Max[0] ; |
---|
4400 | flMinY=m_pSubZones[nSubZone].Min[1] ; |
---|
4401 | flMaxY=m_pSubZones[nSubZone].Max[1] ; |
---|
4402 | flMinZ=m_pSubZones[nSubZone].Min[2] ; |
---|
4403 | flMaxZ=m_pSubZones[nSubZone].Max[2] ; |
---|
4404 | |
---|
4405 | // test all the portals to see if any overlap this subzone |
---|
4406 | for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++) |
---|
4407 | { |
---|
4408 | |
---|
4409 | // if AABB overlap |
---|
4410 | if( |
---|
4411 | (flMinX<m_pPortals[nPortal].Max[0]) && (flMaxX>m_pPortals[nPortal].Min[0]) |
---|
4412 | && (flMinY<m_pPortals[nPortal].Max[1]) && (flMaxY>m_pPortals[nPortal].Min[1]) |
---|
4413 | && (flMinZ<m_pPortals[nPortal].Max[2]) && (flMaxZ>m_pPortals[nPortal].Min[2]) |
---|
4414 | ) |
---|
4415 | { |
---|
4416 | |
---|
4417 | // add this portal to the zone's portal list |
---|
4418 | nIndex=m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ; |
---|
4419 | if(nIndex<MAX_PORTALPERZONE) // only add if we aren't already maxed out. |
---|
4420 | { |
---|
4421 | // we need to check this portal isn't already on the list. |
---|
4422 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4423 | nPos=-1 ; |
---|
4424 | while((++nPos<nIndex) && (m_nZoneTouchesPortal[nZone][nPos]!=nPortal)) ; |
---|
4425 | |
---|
4426 | if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list |
---|
4427 | { |
---|
4428 | m_nZoneTouchesPortal[nZone][nIndex]=nPortal ; |
---|
4429 | m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]++ ; |
---|
4430 | } |
---|
4431 | } |
---|
4432 | |
---|
4433 | // add this zone to the portal's list |
---|
4434 | nIndex=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ; |
---|
4435 | if(nIndex<MAX_ZONEPERPORTAL) |
---|
4436 | { |
---|
4437 | // we need to check this zone isn't already on the list. |
---|
4438 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4439 | nPos=-1 ; |
---|
4440 | while((++nPos<nIndex) && (m_nPortalTouchesZone[nPortal][nPos]!=nZone)) ; |
---|
4441 | |
---|
4442 | if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list |
---|
4443 | { |
---|
4444 | m_nPortalTouchesZone[nPortal][nIndex]=nZone ; |
---|
4445 | m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]++ ; |
---|
4446 | } |
---|
4447 | } |
---|
4448 | |
---|
4449 | }// end if portal overlaps subzone |
---|
4450 | |
---|
4451 | }// end for portal |
---|
4452 | |
---|
4453 | }// end for subzone |
---|
4454 | |
---|
4455 | return 1 ; |
---|
4456 | } |
---|
4457 | |
---|
4458 | int Q3Map::AssignLightsToZones(void) |
---|
4459 | { |
---|
4460 | int nZone=0 ; |
---|
4461 | float flMinX=0.0f ; |
---|
4462 | float flMaxX=0.0f ; |
---|
4463 | float flMinY=0.0f ; |
---|
4464 | float flMaxY=0.0f ; |
---|
4465 | float flMinZ=0.0f ; |
---|
4466 | float flMaxZ=0.0f ; |
---|
4467 | int nMaxSubZone=m_iNumSubZones ; |
---|
4468 | int nSubZone=0 ; |
---|
4469 | int nMaxLight=m_nLightMax ; |
---|
4470 | int nLight=0 ; |
---|
4471 | int nIndex=0 ; |
---|
4472 | int nPos=0 ; |
---|
4473 | |
---|
4474 | |
---|
4475 | |
---|
4476 | // clear the light settings. |
---|
4477 | for(nZone=0 ; nZone<m_nMaxZone ; nZone++) |
---|
4478 | m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ; |
---|
4479 | |
---|
4480 | for(nLight=0 ; nLight<nMaxLight ; nLight++) |
---|
4481 | m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]=0 ; |
---|
4482 | |
---|
4483 | |
---|
4484 | |
---|
4485 | |
---|
4486 | // now test each subzone against each light what contains/touches what |
---|
4487 | for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++) |
---|
4488 | { |
---|
4489 | nZone=m_pSubZones[nSubZone].Zone ; |
---|
4490 | flMinX=m_pSubZones[nSubZone].Min[0] ; |
---|
4491 | flMaxX=m_pSubZones[nSubZone].Max[0] ; |
---|
4492 | flMinY=m_pSubZones[nSubZone].Min[1] ; |
---|
4493 | flMaxY=m_pSubZones[nSubZone].Max[1] ; |
---|
4494 | flMinZ=m_pSubZones[nSubZone].Min[2] ; |
---|
4495 | flMaxZ=m_pSubZones[nSubZone].Max[2] ; |
---|
4496 | |
---|
4497 | // test all the lights to see if any have centers inside this subzone |
---|
4498 | for(nLight=0 ; nLight<nMaxLight ; nLight++) |
---|
4499 | { |
---|
4500 | |
---|
4501 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
4502 | |
---|
4503 | // if light center is in this subzone |
---|
4504 | if( |
---|
4505 | (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX) |
---|
4506 | && (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY) |
---|
4507 | && (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ) |
---|
4508 | ) |
---|
4509 | { |
---|
4510 | |
---|
4511 | // add this light to the zone's light list |
---|
4512 | nIndex=m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT] ; |
---|
4513 | if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out. |
---|
4514 | { |
---|
4515 | // we need to check this light isn't already on the list. |
---|
4516 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4517 | nPos=-1 ; |
---|
4518 | while((++nPos<nIndex) && (m_nZoneContainsLightCentre[nZone][nPos]!=nLight)) ; |
---|
4519 | |
---|
4520 | if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list |
---|
4521 | { |
---|
4522 | m_nZoneContainsLightCentre[nZone][nIndex]=nLight ; |
---|
4523 | m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]++ ; |
---|
4524 | |
---|
4525 | // assign this zone as the light's centre. We only allow one zone to be the light's centre zone, |
---|
4526 | // so this will get overwritten if the light is on the border. |
---|
4527 | m_pLight[nLight].CentreZone=nZone ; |
---|
4528 | } |
---|
4529 | } |
---|
4530 | |
---|
4531 | }// end if light centre contained by subzone |
---|
4532 | |
---|
4533 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
4534 | |
---|
4535 | // if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later) |
---|
4536 | // if light AABB overlaps the zone AABB |
---|
4537 | if( |
---|
4538 | (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0]) |
---|
4539 | && (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1]) |
---|
4540 | && (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2]) |
---|
4541 | ) |
---|
4542 | { |
---|
4543 | // add this light to the zone's light list |
---|
4544 | nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ; |
---|
4545 | if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out. |
---|
4546 | { |
---|
4547 | // we need to check this light isn't already on the list. |
---|
4548 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4549 | nPos=-1 ; |
---|
4550 | while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nLight)) ; |
---|
4551 | |
---|
4552 | if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list |
---|
4553 | { |
---|
4554 | m_nZoneTouchesSubLight[nZone][nIndex]=nLight ; |
---|
4555 | m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ; |
---|
4556 | } |
---|
4557 | } |
---|
4558 | |
---|
4559 | // add this zone to the light's list |
---|
4560 | nIndex=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; |
---|
4561 | if(nIndex<MAX_ZONEPERLIGHT) |
---|
4562 | { |
---|
4563 | // we need to check this zone isn't already on the list. |
---|
4564 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4565 | nPos=-1 ; |
---|
4566 | while((++nPos<nIndex) && (m_nLightTouchesZone[nLight][nPos]!=nZone)) ; |
---|
4567 | |
---|
4568 | if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list |
---|
4569 | { |
---|
4570 | m_nLightTouchesZone[nLight][nIndex]=nZone ; |
---|
4571 | m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]++ ; |
---|
4572 | } |
---|
4573 | } |
---|
4574 | |
---|
4575 | }// end if light touches contained by subzone |
---|
4576 | |
---|
4577 | ///////////////////////////////////////////////////////////////////////////////////// |
---|
4578 | |
---|
4579 | |
---|
4580 | |
---|
4581 | |
---|
4582 | }// end for light |
---|
4583 | |
---|
4584 | }// end for subzone |
---|
4585 | |
---|
4586 | |
---|
4587 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
4588 | // |
---|
4589 | // work out the sublights. These are cut up boxes made from the light boxes, one per zone. |
---|
4590 | // Most lights will just become a single sublight, but multizone lights will be cut up into |
---|
4591 | // multiple sublights. These are used for calculating light visibility. |
---|
4592 | // |
---|
4593 | |
---|
4594 | m_nSubLightMax=0 ; |
---|
4595 | int nMaxZone=0 ; |
---|
4596 | int nZoneIndex=0 ; |
---|
4597 | int nSubLightCentre=0 ; |
---|
4598 | sublight_t TempSubLight ; |
---|
4599 | for(nLight=0 ; nLight<nMaxLight ; nLight++) |
---|
4600 | { |
---|
4601 | |
---|
4602 | m_pLight[nLight].ZoneCount=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; // in the light, note how many zones it touches |
---|
4603 | |
---|
4604 | if((m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]>1) && (m_nMaxMultiZoneLight<MAX_LIGHT))// this is a multizone light |
---|
4605 | m_nMultiZoneLight[m_nMaxMultiZoneLight++]=nLight ; |
---|
4606 | |
---|
4607 | |
---|
4608 | m_pLight[nLight].SubLightStart=m_nSubLightMax ; // where this light's cut up sublights start in m_SubLight |
---|
4609 | |
---|
4610 | |
---|
4611 | // break the light up into it's different sublights, cut by zones. |
---|
4612 | nMaxZone=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; |
---|
4613 | for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++) |
---|
4614 | { |
---|
4615 | nZone=m_nLightTouchesZone[nLight][nZoneIndex] ; |
---|
4616 | |
---|
4617 | flMinX= m_pLight[nLight].Min[0]<m_ZoneBoundary[nZone].Min[0] ? m_ZoneBoundary[nZone].Min[0] : m_pLight[nLight].Min[0] ; |
---|
4618 | flMinY= m_pLight[nLight].Min[1]<m_ZoneBoundary[nZone].Min[1] ? m_ZoneBoundary[nZone].Min[1] : m_pLight[nLight].Min[1] ; |
---|
4619 | flMinZ= m_pLight[nLight].Min[2]<m_ZoneBoundary[nZone].Min[2] ? m_ZoneBoundary[nZone].Min[2] : m_pLight[nLight].Min[2] ; |
---|
4620 | |
---|
4621 | flMaxX= m_pLight[nLight].Max[0]>m_ZoneBoundary[nZone].Max[0] ? m_ZoneBoundary[nZone].Max[0] : m_pLight[nLight].Max[0] ; |
---|
4622 | flMaxY= m_pLight[nLight].Max[1]>m_ZoneBoundary[nZone].Max[1] ? m_ZoneBoundary[nZone].Max[1] : m_pLight[nLight].Max[1] ; |
---|
4623 | flMaxZ= m_pLight[nLight].Max[2]>m_ZoneBoundary[nZone].Max[2] ? m_ZoneBoundary[nZone].Max[2] : m_pLight[nLight].Max[2] ; |
---|
4624 | |
---|
4625 | // add the cut down light as a sublight |
---|
4626 | m_SubLight[m_nSubLightMax].Light=nLight ; |
---|
4627 | m_SubLight[m_nSubLightMax].Zone=nZone ; |
---|
4628 | m_SubLight[m_nSubLightMax].Min[0]=flMinX ; |
---|
4629 | m_SubLight[m_nSubLightMax].Min[1]=flMinY ; |
---|
4630 | m_SubLight[m_nSubLightMax].Min[2]=flMinZ ; |
---|
4631 | m_SubLight[m_nSubLightMax].Max[0]=flMaxX ; |
---|
4632 | m_SubLight[m_nSubLightMax].Max[1]=flMaxY ; |
---|
4633 | m_SubLight[m_nSubLightMax].Max[2]=flMaxZ ; |
---|
4634 | |
---|
4635 | // remember which sublight is the centre |
---|
4636 | if( |
---|
4637 | (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX) |
---|
4638 | && (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY) |
---|
4639 | && (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ) |
---|
4640 | ) |
---|
4641 | nSubLightCentre=m_nSubLightMax ; |
---|
4642 | |
---|
4643 | |
---|
4644 | m_nSubLightMax++ ; // we don't have to worry about bound checking this, because we've already checked there aren't too many lights. |
---|
4645 | |
---|
4646 | }// end for zoneindex |
---|
4647 | |
---|
4648 | // move the sublight that contains the centre to the beginning of the sublights for this light. |
---|
4649 | // We always want the first sublight to contain the centre to make the culling algos work better. |
---|
4650 | TempSubLight=m_SubLight[ m_pLight[nLight].SubLightStart ] ; |
---|
4651 | m_SubLight[ m_pLight[nLight].SubLightStart ] = m_SubLight[ nSubLightCentre ] ; |
---|
4652 | m_SubLight[ nSubLightCentre ] = TempSubLight ; |
---|
4653 | |
---|
4654 | |
---|
4655 | |
---|
4656 | }// end for light |
---|
4657 | |
---|
4658 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
---|
4659 | // |
---|
4660 | // recalculate m_nZoneTouchesSubLight using the newly created sublights |
---|
4661 | // (instead of the complete lights that were originally used) |
---|
4662 | // |
---|
4663 | |
---|
4664 | int nSubLight=0 ; |
---|
4665 | |
---|
4666 | |
---|
4667 | // clear the light settings. |
---|
4668 | for(nZone=0 ; nZone<m_nMaxZone ; nZone++) |
---|
4669 | m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ; |
---|
4670 | |
---|
4671 | for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++) |
---|
4672 | { |
---|
4673 | nZone=m_pSubZones[nSubZone].Zone ; |
---|
4674 | flMinX=m_pSubZones[nSubZone].Min[0] ; |
---|
4675 | flMaxX=m_pSubZones[nSubZone].Max[0] ; |
---|
4676 | flMinY=m_pSubZones[nSubZone].Min[1] ; |
---|
4677 | flMaxY=m_pSubZones[nSubZone].Max[1] ; |
---|
4678 | flMinZ=m_pSubZones[nSubZone].Min[2] ; |
---|
4679 | flMaxZ=m_pSubZones[nSubZone].Max[2] ; |
---|
4680 | |
---|
4681 | // test all the lights to see if any have centers inside this subzone |
---|
4682 | for(nSubLight=0 ; nSubLight<m_nSubLightMax ; nSubLight++) |
---|
4683 | { |
---|
4684 | // if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later) |
---|
4685 | // if light AABB overlaps the zone AABB |
---|
4686 | if( |
---|
4687 | (flMinX<m_SubLight[nSubLight].Max[0]) && (flMaxX>m_SubLight[nSubLight].Min[0]) |
---|
4688 | && (flMinY<m_SubLight[nSubLight].Max[1]) && (flMaxY>m_SubLight[nSubLight].Min[1]) |
---|
4689 | && (flMinZ<m_SubLight[nSubLight].Max[2]) && (flMaxZ>m_SubLight[nSubLight].Min[2]) |
---|
4690 | ) |
---|
4691 | { |
---|
4692 | // add this light to the zone's light list |
---|
4693 | nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ; |
---|
4694 | if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out. |
---|
4695 | { |
---|
4696 | // we need to check this light isn't already on the list. |
---|
4697 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4698 | nPos=-1 ; |
---|
4699 | while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nSubLight)) ; |
---|
4700 | |
---|
4701 | if(nPos==nIndex) // this can only be true if we didn't already find nSubLight in the list |
---|
4702 | { |
---|
4703 | m_nZoneTouchesSubLight[nZone][nIndex]=nSubLight ; |
---|
4704 | m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ; |
---|
4705 | } |
---|
4706 | |
---|
4707 | } |
---|
4708 | |
---|
4709 | }// end if overlap |
---|
4710 | |
---|
4711 | }// end for nSubLight |
---|
4712 | |
---|
4713 | }// end for nSubZone |
---|
4714 | |
---|
4715 | |
---|
4716 | |
---|
4717 | |
---|
4718 | |
---|
4719 | return 1 ; |
---|
4720 | } |
---|
4721 | |
---|
4722 | |
---|
4723 | int Q3Map::AssignLightsToPortals(void) |
---|
4724 | { |
---|
4725 | float flMinX=0.0f ; |
---|
4726 | float flMaxX=0.0f ; |
---|
4727 | float flMinY=0.0f ; |
---|
4728 | float flMaxY=0.0f ; |
---|
4729 | float flMinZ=0.0f ; |
---|
4730 | float flMaxZ=0.0f ; |
---|
4731 | int nMaxPortal=m_iNumPortals ; |
---|
4732 | int nPortal=0 ; |
---|
4733 | int nMaxLight=m_nLightMax ; |
---|
4734 | int nLight=0 ; |
---|
4735 | int nIndex=0 ; |
---|
4736 | int nPos=0 ; |
---|
4737 | |
---|
4738 | |
---|
4739 | |
---|
4740 | // clear the light settings. |
---|
4741 | for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++) |
---|
4742 | m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]=0 ; |
---|
4743 | |
---|
4744 | // now test each portal against each light to see if they touch |
---|
4745 | for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++) |
---|
4746 | { |
---|
4747 | flMinX=m_pPortals[nPortal].Min[0] ; |
---|
4748 | flMaxX=m_pPortals[nPortal].Max[0] ; |
---|
4749 | flMinY=m_pPortals[nPortal].Min[1] ; |
---|
4750 | flMaxY=m_pPortals[nPortal].Max[1] ; |
---|
4751 | flMinZ=m_pPortals[nPortal].Min[2] ; |
---|
4752 | flMaxZ=m_pPortals[nPortal].Max[2] ; |
---|
4753 | |
---|
4754 | // test all the lights to see if any touch this portal |
---|
4755 | for(nLight=0 ; nLight<nMaxLight ; nLight++) |
---|
4756 | { |
---|
4757 | |
---|
4758 | // if light AABB overlaps the portal AABB |
---|
4759 | if( |
---|
4760 | (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0]) |
---|
4761 | && (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1]) |
---|
4762 | && (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2]) |
---|
4763 | ) |
---|
4764 | { |
---|
4765 | |
---|
4766 | // add this light to the portal's light list |
---|
4767 | nIndex=m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ; |
---|
4768 | if(nIndex<MAX_LIGHTPERPORTAL) // only add if we aren't already maxed out. |
---|
4769 | { |
---|
4770 | // we need to check this light isn't already on the list. |
---|
4771 | // it might have gotten on by another subzone, since a zone can have multiple subzones. |
---|
4772 | nPos=-1 ; |
---|
4773 | while((++nPos<nIndex) && (m_nPortalTouchesLight[nPortal][nPos]!=nLight)) ; |
---|
4774 | |
---|
4775 | if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list |
---|
4776 | { |
---|
4777 | m_nPortalTouchesLight[nPortal][nIndex]=nLight ; |
---|
4778 | m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]++ ; |
---|
4779 | } |
---|
4780 | } |
---|
4781 | |
---|
4782 | // we don't keep a list of the portals that a light touches, we don't use such a thing. |
---|
4783 | |
---|
4784 | }// end if light touches portal |
---|
4785 | |
---|
4786 | }// end for light |
---|
4787 | |
---|
4788 | }// end for portal |
---|
4789 | |
---|
4790 | return 1 ; |
---|
4791 | } |
---|
4792 | |
---|
4793 | // work out all the other zones each zone touches, via portals |
---|
4794 | int Q3Map::AssignZonesToZones(void) |
---|
4795 | { |
---|
4796 | |
---|
4797 | |
---|
4798 | int nCentralZone=0 ; |
---|
4799 | int nPortalZone=0 ; |
---|
4800 | int nMaxPortalZone=0 ; |
---|
4801 | int nPortalZoneIndex=0 ; |
---|
4802 | int nPortal=0 ; |
---|
4803 | int nPortalIndex=0 ; |
---|
4804 | int nMaxPortal=0 ; |
---|
4805 | |
---|
4806 | int nTouchZoneIndex=0 ; |
---|
4807 | int nMaxTouchZone=0 ; |
---|
4808 | int nAddZone=0 ; |
---|
4809 | |
---|
4810 | |
---|
4811 | // scan through all the zones (consider them "central zones") |
---|
4812 | for(nCentralZone=0 ; nCentralZone<m_nMaxZone ; nCentralZone++) |
---|
4813 | { |
---|
4814 | nMaxTouchZone=0 ; |
---|
4815 | |
---|
4816 | // scan through all the portals in this centralzone. |
---|
4817 | nMaxPortal=m_nZoneTouchesPortal[nCentralZone][INDEX_PORTALCOUNT] ; |
---|
4818 | for(nPortalIndex=0 ; nPortalIndex<nMaxPortal; nPortalIndex++) |
---|
4819 | { |
---|
4820 | nPortal=m_nZoneTouchesPortal[nCentralZone][nPortalIndex] ; |
---|
4821 | |
---|
4822 | // scan through all the zones this portal touches and add then to the central zone's list |
---|
4823 | nMaxPortalZone=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ; |
---|
4824 | for(nPortalZoneIndex=0 ; nPortalZoneIndex<nMaxPortalZone ; nPortalZoneIndex++) |
---|
4825 | { |
---|
4826 | nPortalZone=m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ; |
---|
4827 | |
---|
4828 | // we've got a portal zone. |
---|
4829 | if(nPortalZone==nCentralZone) continue ; // if it's the central zone, skip it. |
---|
4830 | |
---|
4831 | // check we don't already have it listed. |
---|
4832 | nAddZone=1 ; |
---|
4833 | for(nTouchZoneIndex=0 ; nTouchZoneIndex<nMaxTouchZone ; nTouchZoneIndex++) |
---|
4834 | { |
---|
4835 | if(m_nZoneTouchesPortal[nCentralZone][nTouchZoneIndex]==nPortalZone) |
---|
4836 | { |
---|
4837 | nAddZone=0 ; |
---|
4838 | break ; |
---|
4839 | }// end if |
---|
4840 | }// end for nTouchZoneIndex |
---|
4841 | |
---|
4842 | if(nAddZone) |
---|
4843 | { |
---|
4844 | m_nZoneTouchesZone[nCentralZone][nMaxTouchZone]=nPortalZone ; |
---|
4845 | nMaxTouchZone++ ; |
---|
4846 | if(nMaxTouchZone>=MAX_ZONEPERZONE) |
---|
4847 | nMaxTouchZone=MAX_ZONEPERZONE-1 ; |
---|
4848 | |
---|
4849 | |
---|
4850 | } |
---|
4851 | |
---|
4852 | |
---|
4853 | }// end for portal zone index |
---|
4854 | |
---|
4855 | |
---|
4856 | }// end for portal index |
---|
4857 | |
---|
4858 | // set the maximum |
---|
4859 | m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT]=nMaxTouchZone ; |
---|
4860 | |
---|
4861 | /* |
---|
4862 | sprintf(m_chBug, "CentralZone %i, TouchedZoneCount %i", nCentralZone, m_nZoneTouchesPortal[nCentralZone][INDEX_ZONEPERZONECOUNT]) ; |
---|
4863 | Q3Bug.LogAddCR(m_chBug) ; |
---|
4864 | for(nTouchZoneIndex=0 ; nTouchZoneIndex<m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT] ; nTouchZoneIndex++) |
---|
4865 | { |
---|
4866 | sprintf(m_chBug, " TouchedZone %i", m_nZoneTouchesZone[nCentralZone][nTouchZoneIndex]) ; |
---|
4867 | Q3Bug.LogAddCR(m_chBug) ; |
---|
4868 | } |
---|
4869 | */ |
---|
4870 | |
---|
4871 | |
---|
4872 | }// end for central zone |
---|
4873 | |
---|
4874 | |
---|
4875 | |
---|
4876 | |
---|
4877 | return 1 ; |
---|
4878 | } |
---|
4879 | |
---|
4880 | |
---|
4881 | |
---|