Mercurial > mm7
comparison Engine/Graphics/Vis.cpp @ 2496:5abd8fc8f1c6
for ITEM_ARTIFACT_LADYS_ESCORT
author | Ritor1 |
---|---|
date | Thu, 18 Sep 2014 17:38:54 +0600 |
parents | |
children | 68cdef6879a0 |
comparison
equal
deleted
inserted
replaced
2495:7b076fe64f23 | 2496:5abd8fc8f1c6 |
---|---|
1 #define _CRTDBG_MAP_ALLOC | |
2 #include <stdlib.h> | |
3 #include <crtdbg.h> | |
4 | |
5 #define _CRT_SECURE_NO_WARNINGS | |
6 #include "Vis.h" | |
7 #include "Sprites.h" | |
8 #include "Lod.h" | |
9 #include "Outdoor.h" | |
10 #include "Game.h" | |
11 #include "Actor.h" | |
12 #include "Viewport.h" | |
13 #include "OurMath.h" | |
14 #include "Log.h" | |
15 #include "ErrorHandling.h" | |
16 | |
17 #include "MM7.h" | |
18 #include "Engine/Graphics/Level/Decoration.h" | |
19 | |
20 | |
21 static Vis_SelectionList Vis_static_sub_4C1944_stru_F8BDE8; | |
22 | |
23 Vis_SelectionFilter vis_sprite_filter_1 = {VisObjectType_Sprite, OBJECT_Decoration, 0, 0, 2}; // 00F93E1C | |
24 Vis_SelectionFilter vis_sprite_filter_2 = {VisObjectType_Sprite, OBJECT_Decoration, 0, 0, 2}; // 00F93E30 | |
25 Vis_SelectionFilter vis_face_filter = {VisObjectType_Face, OBJECT_Any, -1, 0, 0}; // 00F93E44 | |
26 Vis_SelectionFilter vis_door_filter = {VisObjectType_Face, OBJECT_BLVDoor, -1, 0x100000, 0}; // 00F93E58 | |
27 Vis_SelectionFilter vis_sprite_filter_3 = {VisObjectType_Sprite, OBJECT_Decoration, -1, 0, 4}; // 00F93E6C | |
28 Vis_SelectionFilter vis_sprite_filter_4 = {VisObjectType_Any, OBJECT_Item, -1, 0, 0}; // static to sub_44EEA7 | |
29 | |
30 | |
31 | |
32 //----- (004C1026) -------------------------------------------------------- | |
33 Vis_ObjectInfo *Vis::DetermineFacetIntersection(BLVFace *face, unsigned int pid, float pick_depth) | |
34 { | |
35 // char *v4; // eax@4 | |
36 // signed int v5; // ecx@4 | |
37 RenderVertexSoft pRay[2]; // [sp+20h] [bp-70h]@17 | |
38 // int v20; // [sp+84h] [bp-Ch]@10 | |
39 | |
40 static Vis_SelectionList SelectedPointersList;//stru_F8FE00 | |
41 SelectedPointersList.uNumPointers = 0; | |
42 | |
43 static bool _init_flag = false; | |
44 static RenderVertexSoft static_DetermineFacetIntersection_array_F8F200[64]; | |
45 if (!_init_flag) | |
46 { | |
47 _init_flag = true; | |
48 for (uint i = 0; i < 64; ++i) | |
49 static_DetermineFacetIntersection_array_F8F200[i].flt_2C = 0.0f; | |
50 } | |
51 | |
52 if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
53 { | |
54 if ( (signed int)face->uNumVertices > 0 ) | |
55 { | |
56 for ( int i = 0; i < face->uNumVertices; i++) | |
57 { | |
58 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.x = (double)pIndoor->pVertices[face->pVertexIDs[i]].x; | |
59 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.y = (double)pIndoor->pVertices[face->pVertexIDs[i]].y; | |
60 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.z = (double)pIndoor->pVertices[face->pVertexIDs[i]].z; | |
61 } | |
62 } | |
63 } | |
64 else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor) | |
65 { | |
66 uint bmodel_id = pid >> 9; | |
67 Vec3_int_* v = (Vec3_int_ *)pOutdoor->pBModels[bmodel_id].pVertices.pVertices; | |
68 for (uint i = 0; i < face->uNumVertices; ++i) | |
69 { | |
70 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.x = v[face->pVertexIDs[i]].x; | |
71 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.y = v[face->pVertexIDs[i]].y; | |
72 static_DetermineFacetIntersection_array_F8F200[i].vWorldPosition.z = v[face->pVertexIDs[i]].z; | |
73 } | |
74 } | |
75 else assert(false); | |
76 | |
77 pGame->pIndoorCameraD3D->ViewTransform(static_DetermineFacetIntersection_array_F8F200, face->uNumVertices); | |
78 pGame->pIndoorCameraD3D->Project(static_DetermineFacetIntersection_array_F8F200, face->uNumVertices, 1); | |
79 | |
80 SortVectors_x(static_DetermineFacetIntersection_array_F8F200, 0, face->uNumVertices - 1); | |
81 if (static_DetermineFacetIntersection_array_F8F200[0].vWorldViewPosition.x > pick_depth) | |
82 return nullptr; | |
83 | |
84 float screenspace_center_x, | |
85 screenspace_center_y; | |
86 GetPolygonScreenSpaceCenter(static_DetermineFacetIntersection_array_F8F200, face->uNumVertices, &screenspace_center_x, &screenspace_center_y); | |
87 if (IsPolygonOccludedByBillboard(static_DetermineFacetIntersection_array_F8F200, face->uNumVertices, screenspace_center_x, screenspace_center_y)) | |
88 return nullptr; | |
89 | |
90 CastPickRay(pRay, screenspace_center_x, screenspace_center_y, pick_depth); | |
91 | |
92 if (uCurrentlyLoadedLevelType == LEVEL_Outdoor) | |
93 PickOutdoorFaces_Mouse(pick_depth, pRay, &SelectedPointersList, &vis_face_filter, true); | |
94 else if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
95 PickIndoorFaces_Mouse(pick_depth, pRay, &SelectedPointersList, &vis_face_filter); | |
96 else assert(false); | |
97 | |
98 SelectedPointersList.create_object_pointers(); | |
99 sort_object_pointers(SelectedPointersList.object_pointers, 0, SelectedPointersList.uNumPointers - 1); | |
100 if (!SelectedPointersList.uNumPointers) | |
101 return nullptr; | |
102 | |
103 if (!SelectedPointersList.SelectionPointers(VisObjectType_Face, pid)) | |
104 return nullptr; | |
105 | |
106 if (SelectedPointersList.uNumPointers) | |
107 return SelectedPointersList.object_pointers[0]; | |
108 else return nullptr; | |
109 } | |
110 // F91E08: using guessed type char static_DetermineFacetIntersection_byte_F91E08__init_flags; | |
111 | |
112 //----- (004C12C3) -------------------------------------------------------- | |
113 bool Vis::IsPolygonOccludedByBillboard(RenderVertexSoft *vertices, int num_vertices, float x, float y) | |
114 { | |
115 int v13 = -1; | |
116 //v5 = 0; | |
117 | |
118 //v6 = pRenderer->pBillboardRenderListD3D; | |
119 for (uint i = 0; i < pRenderer->uNumBillboardsToDraw; ++i) | |
120 { | |
121 RenderBillboardD3D* billboard = &pRenderer->pBillboardRenderListD3D[i]; | |
122 if (IsPointInsideD3DBillboard(billboard, x, y)) | |
123 { | |
124 if (v13 == -1) | |
125 v13 = i; | |
126 else if (pBillboardRenderList[billboard->sParentBillboardID].sZValue < | |
127 pBillboardRenderList[pRenderer->pBillboardRenderListD3D[v13].sParentBillboardID].sZValue) | |
128 v13 = i; | |
129 } | |
130 } | |
131 | |
132 if ( v13 == -1 ) | |
133 return false; | |
134 | |
135 // //Bounding rectangle(Ограничивающий прямоугольник)------------------------- | |
136 //v7 = 3.4028235e38; | |
137 float min_x = FLT_MAX; | |
138 //a4a = 3.4028235e38; | |
139 float min_y = FLT_MAX; | |
140 //a3a = -3.4028235e38; | |
141 float max_x = -FLT_MAX; | |
142 //thisb = -3.4028235e38; | |
143 float max_y = -FLT_MAX; | |
144 for (int i = 0; i < num_vertices; ++i) | |
145 { | |
146 RenderVertexSoft* v = &vertices[i]; | |
147 | |
148 if (v->vWorldViewProjX < min_x) | |
149 min_x = v->vWorldViewProjX; | |
150 if (v->vWorldViewProjX > max_x) | |
151 max_x = v->vWorldViewProjX; | |
152 | |
153 if (v->vWorldViewProjY < min_y) | |
154 min_y = v->vWorldViewProjY; | |
155 if (v->vWorldViewProjY > max_y) | |
156 max_y = v->vWorldViewProjY; | |
157 } | |
158 // //-------------------------------- | |
159 | |
160 if (min_x < pRenderer->pBillboardRenderListD3D[v13].pQuads[0].pos.x || pRenderer->pBillboardRenderListD3D[v13].pQuads[0].pos.y > min_y || | |
161 pRenderer->pBillboardRenderListD3D[v13].pQuads[3].pos.x < max_x || pRenderer->pBillboardRenderListD3D[v13].pQuads[1].pos.y < max_y) | |
162 return false; | |
163 | |
164 return true; | |
165 } | |
166 | |
167 //----- (004C1417) -------------------------------------------------------- | |
168 void Vis::GetPolygonCenter(RenderVertexD3D3 *pVertices, unsigned int uNumVertices, float *pCenterX, float *pCenterY) | |
169 { | |
170 static RenderVertexD3D3 unk_F8EA00[64]; | |
171 | |
172 memcpy(unk_F8EA00, pVertices, 32 * uNumVertices); | |
173 | |
174 SortVerticesByX(unk_F8EA00, 0, uNumVertices - 1); | |
175 *pCenterX = (unk_F8EA00[uNumVertices - 1].pos.x - unk_F8EA00[0].pos.x) * 0.5 + unk_F8EA00[0].pos.x; | |
176 | |
177 SortVerticesByY(unk_F8EA00, 0, uNumVertices - 1); | |
178 *pCenterY = (unk_F8EA00[uNumVertices - 1].pos.y - unk_F8EA00[0].pos.y) * 0.5 + unk_F8EA00[0].pos.y; | |
179 } | |
180 | |
181 //----- (004C1495) -------------------------------------------------------- | |
182 void Vis::GetPolygonScreenSpaceCenter(RenderVertexSoft *vertices, int num_vertices, float *out_center_x, float *out_center_y) | |
183 { | |
184 // char *v5; // eax@2 | |
185 // signed int v6; // ecx@2 | |
186 // float *result; // eax@5 | |
187 | |
188 static RenderVertexSoft static_sub_4C1495_array_F8DDF8[64]; | |
189 | |
190 memcpy(static_sub_4C1495_array_F8DDF8, vertices, 48 * num_vertices); | |
191 | |
192 SortByScreenSpaceX(static_sub_4C1495_array_F8DDF8, 0, num_vertices - 1); | |
193 *out_center_x = (static_sub_4C1495_array_F8DDF8[num_vertices - 1].vWorldViewProjX - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX) * 0.5 + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjX; | |
194 | |
195 SortByScreenSpaceY(static_sub_4C1495_array_F8DDF8, 0, num_vertices - 1); | |
196 *out_center_y = (static_sub_4C1495_array_F8DDF8[num_vertices - 1].vWorldViewProjY - static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY) * 0.5 + static_sub_4C1495_array_F8DDF8[0].vWorldViewProjY; | |
197 } | |
198 | |
199 //----- (004C1542) -------------------------------------------------------- | |
200 void Vis::PickBillboards_Mouse(float fPickDepth, float fX, float fY, Vis_SelectionList *list, Vis_SelectionFilter *filter) | |
201 { | |
202 for (uint i = 0; i < pRenderer->uNumBillboardsToDraw; ++i) | |
203 { | |
204 RenderBillboardD3D* d3d_billboard = &pRenderer->pBillboardRenderListD3D[i]; | |
205 if (is_part_of_selection((void *)i, filter) && IsPointInsideD3DBillboard(d3d_billboard, fX, fY)) | |
206 { | |
207 if (DoesRayIntersectBillboard(fPickDepth, i)) | |
208 { | |
209 RenderBillboard* billboard = &pBillboardRenderList[d3d_billboard->sParentBillboardID]; | |
210 | |
211 list->AddObject((void *)d3d_billboard->sParentBillboardID, VisObjectType_Sprite, billboard->sZValue); | |
212 } | |
213 } | |
214 } | |
215 } | |
216 | |
217 | |
218 //----- (004C1607) -------------------------------------------------------- | |
219 bool Vis::IsPointInsideD3DBillboard(RenderBillboardD3D *a1, float x, float y) | |
220 { | |
221 /*Not the original implementation. | |
222 This function is redone to use Grayface's mouse pick implementation to take only the visible | |
223 parts of billboards into account - I don't really have too much of an idea how it actually works*/ | |
224 float drX; // st7@2 | |
225 float drY; // ecx@2 | |
226 float drH; // [sp+4h] [bp-8h]@2 | |
227 float drW; // [sp+14h] [bp+8h]@2 | |
228 | |
229 if ( a1->sParentBillboardID == -1 ) | |
230 return false; | |
231 | |
232 drX = a1->pQuads[0].pos.x; | |
233 drW = a1->pQuads[3].pos.x - drX; | |
234 drY = a1->pQuads[0].pos.y; | |
235 drH = a1->pQuads[1].pos.y - drY; | |
236 | |
237 Sprite* ownerSprite = nullptr; | |
238 for (int i = 0; i < pSprites_LOD->uNumLoadedSprites; ++i) | |
239 { | |
240 if (pSprites_LOD->pHardwareSprites[i].pTexture == a1->pTexture) | |
241 { | |
242 ownerSprite = &pSprites_LOD->pHardwareSprites[i]; | |
243 break; | |
244 } | |
245 } | |
246 | |
247 if (ownerSprite == nullptr) | |
248 return false; | |
249 | |
250 int i = ownerSprite->uAreaX + int(ownerSprite->uAreaWidth * (x - drX) / drW); | |
251 int j = ownerSprite->uAreaY + int(ownerSprite->uAreaHeight * (y - drY) / drH); | |
252 | |
253 | |
254 LODSprite* spriteHeader = nullptr; | |
255 | |
256 for (int i = 0; i < MAX_LOD_SPRITES; ++i) | |
257 { | |
258 if (strcmp(pSprites_LOD->pSpriteHeaders[i].pName, ownerSprite->pName) == 0) | |
259 { | |
260 spriteHeader = &pSprites_LOD->pSpriteHeaders[i]; | |
261 break; | |
262 } | |
263 } | |
264 | |
265 if (j < 0 || j >= spriteHeader->uHeight) | |
266 return false; | |
267 | |
268 if (spriteHeader->pSpriteLines[j].a1 < 0 || i > spriteHeader->pSpriteLines[j].a2 || i < spriteHeader->pSpriteLines[j].a1) | |
269 { | |
270 return false; | |
271 } | |
272 return *(spriteHeader->pSpriteLines[j].pos + i - spriteHeader->pSpriteLines[j].a1) != 0; | |
273 } | |
274 | |
275 //----- (004C16B4) -------------------------------------------------------- | |
276 void Vis::PickIndoorFaces_Mouse(float fDepth, RenderVertexSoft *pRay, Vis_SelectionList *list, Vis_SelectionFilter *filter) | |
277 { | |
278 int v5; // eax@1 | |
279 signed int pFaceID; // edi@2 | |
280 int v9; // eax@7 | |
281 unsigned int *pNumPointers; // eax@7 | |
282 Vis_ObjectInfo *v12; // edi@7 | |
283 RenderVertexSoft a1; // [sp+Ch] [bp-44h]@1 | |
284 void *v15; // [sp+40h] [bp-10h]@7 | |
285 int v17; // [sp+48h] [bp-8h]@1 | |
286 | |
287 v5 = 0; | |
288 v17 = 0; | |
289 for ( a1.flt_2C = 0.0; v17 < (signed int)pBspRenderer->num_faces; ++v17 ) | |
290 { | |
291 pFaceID = pBspRenderer->faces[v5].uFaceID; | |
292 if ( pFaceID >= 0 ) | |
293 { | |
294 if ( pFaceID < (signed int)pIndoor->uNumFaces ) | |
295 { | |
296 BLVFace* face = &pIndoor->pFaces[pFaceID]; | |
297 if ( is_part_of_selection(face, filter) ) | |
298 { | |
299 if ( !pGame->pIndoorCameraD3D->IsCulled(face) ) | |
300 { | |
301 if ( Intersect_Ray_Face(pRay, pRay + 1, &fDepth, &a1, face, 0xFFFFFFFFu) ) | |
302 { | |
303 pGame->pIndoorCameraD3D->ViewTransform(&a1, 1); | |
304 v9 = fixpoint_from_float(/*v8, */a1.vWorldViewPosition.x); | |
305 LOWORD(v9) = 0; | |
306 v15 = (void *)((PID(OBJECT_BModel,pFaceID)) + v9); | |
307 pNumPointers = &list->uNumPointers; | |
308 v12 = &list->object_pool[list->uNumPointers]; | |
309 v12->object = &pIndoor->pFaces[pFaceID]; | |
310 v12 = (Vis_ObjectInfo *) &v12->sZValue; | |
311 v12->object = v15; | |
312 v12->sZValue = 2; | |
313 ++*pNumPointers; | |
314 } | |
315 } | |
316 } | |
317 | |
318 if (face->uAttributes & FACE_PICKED) | |
319 face->uAttributes |= FACE_OUTLINED; | |
320 else | |
321 face->uAttributes &= ~FACE_OUTLINED; | |
322 face->uAttributes &= ~FACE_PICKED; | |
323 } | |
324 } | |
325 v5 = v17 + 1; | |
326 } | |
327 } | |
328 | |
329 //----- (004C17CF) -------------------------------------------------------- | |
330 void Vis::PickOutdoorFaces_Mouse(float fDepth, RenderVertexSoft *pRay, Vis_SelectionList *list, Vis_SelectionFilter *filter, bool only_reachable) | |
331 { | |
332 if (!pOutdoor) | |
333 return; | |
334 | |
335 for (int i = 0; i < pOutdoor->uNumBModels; ++i) | |
336 { | |
337 int reachable; | |
338 if (!IsBModelVisible(i, &reachable)) | |
339 continue; | |
340 if (!reachable && only_reachable) | |
341 continue; | |
342 | |
343 BSPModel* bmodel = &pOutdoor->pBModels[i]; | |
344 for (int j = 0; j < bmodel->uNumFaces; ++j) | |
345 { | |
346 ODMFace* face = &bmodel->pFaces[j]; | |
347 if (is_part_of_selection(face, filter)) | |
348 { | |
349 BLVFace blv_face; | |
350 blv_face.FromODM(face); | |
351 | |
352 RenderVertexSoft intersection; | |
353 if (Intersect_Ray_Face(pRay, pRay + 1, &fDepth, &intersection, &blv_face, i)) | |
354 { | |
355 pGame->pIndoorCameraD3D->ViewTransform(&intersection, 1); | |
356 int v13 = fixpoint_from_float(/*v12, */intersection.vWorldViewPosition.x); | |
357 v13 &= 0xFFFF0000; | |
358 v13 += PID(OBJECT_BModel, j | (i << 6)); | |
359 | |
360 list->AddObject(face, VisObjectType_Face, v13); | |
361 } | |
362 | |
363 if (blv_face.uAttributes & FACE_PICKED) | |
364 face->uAttributes |= FACE_OUTLINED; | |
365 else | |
366 face->uAttributes &= ~FACE_OUTLINED; | |
367 blv_face.uAttributes &= ~FACE_PICKED; | |
368 } | |
369 } | |
370 } | |
371 } | |
372 | |
373 //----- (004C1930) -------------------------------------------------------- | |
374 //bool Vis::j_DoesRayIntersectBillboard(float fDepth, unsigned int uD3DBillboardIdx) | |
375 //{return DoesRayIntersectBillboard(fDepth, uD3DBillboardIdx);} | |
376 | |
377 //----- (004C1944) -------------------------------------------------------- | |
378 int Vis::PickClosestActor(int object_id, unsigned int pick_depth, int a4, int a5, int a6) | |
379 { | |
380 Vis_SelectionFilter v8; // [sp+18h] [bp-20h]@3 | |
381 | |
382 static Vis_SelectionList Vis_static_sub_4C1944_stru_F8BDE8; | |
383 | |
384 v8.object_type = VisObjectType_Sprite; | |
385 v8.object_id = object_id; | |
386 v8.at_ai_state = a6; | |
387 v8.no_at_ai_state = a5; | |
388 v8.select_flags = a4; | |
389 Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers = 0; | |
390 PickBillboards_Keyboard(pick_depth, &Vis_static_sub_4C1944_stru_F8BDE8, &v8); | |
391 Vis_static_sub_4C1944_stru_F8BDE8.create_object_pointers(Vis_SelectionList::Unique); | |
392 sort_object_pointers(Vis_static_sub_4C1944_stru_F8BDE8.object_pointers, 0, Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers - 1); | |
393 | |
394 if (!Vis_static_sub_4C1944_stru_F8BDE8.uNumPointers) | |
395 return -1; | |
396 return Vis_static_sub_4C1944_stru_F8BDE8.object_pointers[0]->sZValue; | |
397 } | |
398 | |
399 //----- (004C1A02) -------------------------------------------------------- | |
400 void Vis::_4C1A02() | |
401 { | |
402 RenderVertexSoft v1; // [sp+8h] [bp-C0h]@1 | |
403 RenderVertexSoft v2; // [sp+38h] [bp-90h]@1 | |
404 RenderVertexSoft v3; // [sp+68h] [bp-60h]@1 | |
405 RenderVertexSoft v4; // [sp+98h] [bp-30h]@1 | |
406 | |
407 v4.flt_2C = 0.0; | |
408 v4.vWorldPosition.x = 0.0; | |
409 v4.vWorldPosition.y = 65536.0; | |
410 v4.vWorldPosition.z = 0.0; | |
411 v3.flt_2C = 0.0; | |
412 v3.vWorldPosition.x = 65536.0; | |
413 v3.vWorldPosition.y = 0.0; | |
414 v3.vWorldPosition.z = 0.0; | |
415 memcpy(&v1, &v3, sizeof(v1)); | |
416 v3.flt_2C = 0.0; | |
417 v3.vWorldPosition.x = 0.0; | |
418 v3.vWorldPosition.y = 65536.0; | |
419 v3.vWorldPosition.z = 0.0; | |
420 memcpy(&v2, &v4, sizeof(v2)); | |
421 v4.flt_2C = 0.0; | |
422 v4.vWorldPosition.x = 65536.0; | |
423 v4.vWorldPosition.y = 0.0; | |
424 v4.vWorldPosition.z = 0.0; | |
425 memcpy(&this->stru_200C, &v1, 0x60u); | |
426 memcpy(&v1, &v4, sizeof(v1)); | |
427 memcpy(&v2, &v3, sizeof(v2)); | |
428 memcpy(&this->stru_206C, &v1, 0x60u); | |
429 } | |
430 | |
431 //----- (004C1ABA) -------------------------------------------------------- | |
432 void Vis::SortVectors_x(RenderVertexSoft *pArray, int start, int end) | |
433 { | |
434 int left_sort_index; // ebx@2 | |
435 int right_sort_index; // ecx@2 | |
436 RenderVertexSoft temp_array; // [sp+4h] [bp-6Ch]@8 | |
437 RenderVertexSoft max_array; // [sp+34h] [bp-3Ch]@2 | |
438 | |
439 if ( end > start ) | |
440 { | |
441 left_sort_index = start - 1; | |
442 right_sort_index = end; | |
443 memcpy(&max_array, &pArray[end], sizeof(max_array)); | |
444 while ( 1 ) | |
445 { | |
446 do | |
447 { | |
448 ++left_sort_index; | |
449 } | |
450 while ( pArray[left_sort_index].vWorldViewPosition.x < (double)max_array.vWorldViewPosition.x ); | |
451 do | |
452 { | |
453 --right_sort_index; | |
454 } | |
455 while ( pArray[right_sort_index].vWorldViewPosition.x > (double)max_array.vWorldViewPosition.x ); | |
456 if ( left_sort_index >= right_sort_index ) | |
457 break; | |
458 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
459 memcpy(&pArray[left_sort_index], &pArray[right_sort_index], sizeof(pArray[left_sort_index])); | |
460 memcpy(&pArray[right_sort_index], &temp_array, sizeof(pArray[right_sort_index])); | |
461 } | |
462 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
463 memcpy(&pArray[left_sort_index], &pArray[end], sizeof(pArray[left_sort_index])); | |
464 memcpy(&pArray[end], &temp_array, sizeof(pArray[end])); | |
465 SortVectors_x(pArray, start, left_sort_index - 1); | |
466 SortVectors_x(pArray, left_sort_index + 1, end); | |
467 } | |
468 } | |
469 | |
470 //----- (004C1BAA) -------------------------------------------------------- | |
471 int Vis::get_object_zbuf_val(Vis_ObjectInfo *info) | |
472 { | |
473 switch (info->object_type) | |
474 { | |
475 case VisObjectType_Sprite: | |
476 case VisObjectType_Face: | |
477 return info->sZValue; | |
478 | |
479 default: | |
480 MessageBoxW(nullptr, L"Undefined type requested for: CVis::get_object_zbuf_val()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1037", 0); | |
481 return -1; | |
482 } | |
483 } | |
484 | |
485 //----- (004C1BF1) -------------------------------------------------------- | |
486 int Vis::get_picked_object_zbuf_val() | |
487 { | |
488 if (!default_list.uNumPointers) | |
489 return -1; | |
490 | |
491 return get_object_zbuf_val(default_list.object_pointers[0]); | |
492 } | |
493 | |
494 //----- (004C1C0C) -------------------------------------------------------- | |
495 bool Vis::Intersect_Ray_Face(RenderVertexSoft *pRayStart, RenderVertexSoft *pRayEnd, float *pDepth, RenderVertexSoft *Intersection, BLVFace *pFace, signed int pBModelID) | |
496 { | |
497 float c1; // st5@6 | |
498 float c2; // st7@11 | |
499 Vec3_short_ IntersectPoint; // ST04_6@11 | |
500 | |
501 | |
502 if (pFace->Portal() || pFace->Invisible()) | |
503 return false; | |
504 | |
505 int ray_dir_x = pRayEnd->vWorldPosition.x - pRayStart->vWorldPosition.x,//calculate the direction vector of the line(вычислим вектор направления линий) | |
506 ray_dir_y = pRayEnd->vWorldPosition.y - pRayStart->vWorldPosition.y, | |
507 ray_dir_z = pRayEnd->vWorldPosition.z - pRayStart->vWorldPosition.z; | |
508 | |
509 //c1 = -d-(n*p0) | |
510 c1 = -pFace->pFacePlane.dist -(pFace->pFacePlane.vNormal.x * pRayStart->vWorldPosition.x | |
511 + pFace->pFacePlane.vNormal.y * pRayStart->vWorldPosition.y | |
512 + pFace->pFacePlane.vNormal.z * pRayStart->vWorldPosition.z); | |
513 if (c1 > 0) | |
514 return false; | |
515 #define EPSILON 1e-6 | |
516 //c2 = n*u | |
517 c2 = pFace->pFacePlane.vNormal.x * ray_dir_y// get length of the line(Это дает нам длину линии) | |
518 + pFace->pFacePlane.vNormal.y * ray_dir_x | |
519 + pFace->pFacePlane.vNormal.z * ray_dir_z; | |
520 if (c2 > -EPSILON && c2 < EPSILON) // ray faces face's normal ( > 0) or parallel ( == 0) | |
521 return false; | |
522 | |
523 //t = -d-(n*p0)/n*u | |
524 float t = c1 / c2;//How far is crossing the line in percent for 0 to 1(Как далеко пересечение линии в процентах от 0 до 1 ) | |
525 | |
526 if (t < 0 || t > 1) | |
527 return false; | |
528 | |
529 // p(t) = p0 + tu; | |
530 Intersection->vWorldPosition.x = pRayStart->vWorldPosition.x + t * ray_dir_y;// add the interest to the start line(прибавляем процент линии к линии старта) | |
531 Intersection->vWorldPosition.y = pRayStart->vWorldPosition.y + t * ray_dir_x; | |
532 Intersection->vWorldPosition.z = pRayStart->vWorldPosition.z + t * ray_dir_z; | |
533 | |
534 IntersectPoint.x = Intersection->vWorldPosition.x; | |
535 IntersectPoint.y = Intersection->vWorldPosition.y; | |
536 IntersectPoint.z = Intersection->vWorldPosition.z; | |
537 | |
538 if ( !CheckIntersectBModel(pFace, IntersectPoint, pBModelID) ) | |
539 return false; | |
540 | |
541 *pDepth = t;//Record the distance from the origin of the ray (Записываем дистанцию от начала луча) | |
542 return true; | |
543 } | |
544 | |
545 //----- (004C1D2B) -------------------------------------------------------- | |
546 bool Vis::CheckIntersectBModel(BLVFace *pFace, Vec3_short_ IntersectPoint, signed int sModelID) | |
547 { | |
548 int v5; // esi@10 | |
549 bool v6; // edi@10 | |
550 signed int v10; // ebx@14 | |
551 // int v15; // [sp+10h] [bp-Ch]@10 | |
552 signed int v16; // [sp+18h] [bp-4h]@10 | |
553 | |
554 int a = 0, b = 0; | |
555 | |
556 if (IntersectPoint.x < pFace->pBounding.x1 || IntersectPoint.x > pFace->pBounding.x2 || | |
557 IntersectPoint.y < pFace->pBounding.y1 || IntersectPoint.y > pFace->pBounding.y2 || | |
558 IntersectPoint.z < pFace->pBounding.z1 || IntersectPoint.z > pFace->pBounding.z2 ) | |
559 return false; | |
560 | |
561 if (sModelID != -1) | |
562 ODM_CreateIntersectFacesVertexCoordList(&a, &b, intersect_face_vertex_coords_list_a.data(), intersect_face_vertex_coords_list_b.data(), | |
563 &IntersectPoint, pFace, sModelID); | |
564 else | |
565 BLV_CreateIntersectFacesVertexCoordList(&a, &b, intersect_face_vertex_coords_list_a.data(), intersect_face_vertex_coords_list_b.data(), | |
566 &IntersectPoint, pFace); | |
567 v5 = 2 * pFace->uNumVertices; | |
568 v16 = 0; | |
569 intersect_face_vertex_coords_list_a[v5] = intersect_face_vertex_coords_list_a[0]; | |
570 intersect_face_vertex_coords_list_b[v5] = intersect_face_vertex_coords_list_b[0]; | |
571 v6 = intersect_face_vertex_coords_list_b[0] >= b; | |
572 if (v5 <= 0) | |
573 return false; | |
574 for ( int i = 0; i < v5; ++i ) | |
575 { | |
576 if ( v16 >= 2 ) | |
577 break; | |
578 if ( v6 ^ (intersect_face_vertex_coords_list_b[i + 1] >= b) ) | |
579 { | |
580 if ( intersect_face_vertex_coords_list_a[i + 1] >= a ) | |
581 v10 = 0; | |
582 else | |
583 v10 = 2; | |
584 v10 |= intersect_face_vertex_coords_list_a[i] < a ? 1 : 0; | |
585 if ( v10 != 3 ) | |
586 { | |
587 if ( !v10) | |
588 ++v16; | |
589 else | |
590 { | |
591 int _v1 = fixpoint_div(intersect_face_vertex_coords_list_a[i + 1] - intersect_face_vertex_coords_list_a[i], | |
592 intersect_face_vertex_coords_list_b[i + 1] - intersect_face_vertex_coords_list_b[i]); | |
593 int _v2 = fixpoint_mul(b - intersect_face_vertex_coords_list_b[i], _v1) + 32768; | |
594 | |
595 if (intersect_face_vertex_coords_list_a[i] + (_v2 >> 16) >= a) | |
596 ++v16; | |
597 } | |
598 } | |
599 } | |
600 v6 = intersect_face_vertex_coords_list_b[i + 1] >= b; | |
601 } | |
602 | |
603 if ( v16 != 1 ) | |
604 return false; | |
605 | |
606 if ( show_picked_face ) | |
607 pFace->uAttributes |= FACE_PICKED; | |
608 return true; | |
609 /* | |
610 int v5; // esi@10 | |
611 bool v6; // edi@10 | |
612 signed int v10; // ebx@14 | |
613 int v11; // edi@16 | |
614 signed int v12; // ST28_4@18 | |
615 signed __int64 v13; // qtt@18 | |
616 signed int result; // eax@21 | |
617 int v15; // [sp+10h] [bp-Ch]@10 | |
618 signed int v16; // [sp+18h] [bp-4h]@10 | |
619 | |
620 int a = 0, b = 0; | |
621 | |
622 if (IntersectPoint.x < pFace->pBounding.x1 || IntersectPoint.x > pFace->pBounding.x2 || | |
623 IntersectPoint.y < pFace->pBounding.y1 || IntersectPoint.y > pFace->pBounding.y2 || | |
624 IntersectPoint.z < pFace->pBounding.z1 || IntersectPoint.z > pFace->pBounding.z2 ) | |
625 return false; | |
626 | |
627 pFace->uAttributes |= 0x80000000; | |
628 | |
629 if (uModelID != -1) | |
630 ODM_CreateIntersectFacesVertexCoordList(&a, &b, intersect_face_vertex_coords_list_a, intersect_face_vertex_coords_list_b, | |
631 &IntersectPoint, pFace, uModelID); | |
632 else | |
633 BLV_CreateIntersectFacesVertexCoordList(&a, &b, intersect_face_vertex_coords_list_a, intersect_face_vertex_coords_list_b, | |
634 &IntersectPoint, pFace); | |
635 v5 = 2 * pFace->uNumVertices; | |
636 v16 = 0; | |
637 intersect_face_vertex_coords_list_a[v5] = intersect_face_vertex_coords_list_a[0]; | |
638 intersect_face_vertex_coords_list_b[v5] = intersect_face_vertex_coords_list_b[0]; | |
639 v6 = intersect_face_vertex_coords_list_b[0] >= b; | |
640 if (v5 <= 0) | |
641 return false; | |
642 for ( uint i = 0; i < v5; ++i ) | |
643 { | |
644 if ( v16 >= 2 ) | |
645 break; | |
646 if ( v6 ^ intersect_face_vertex_coords_list_b[i + 1] >= b ) | |
647 { | |
648 if ( intersect_face_vertex_coords_list_a[i + 1] >= a ) | |
649 v10 = 0; | |
650 else | |
651 v10 = 2; | |
652 v11 = v10 | intersect_face_vertex_coords_list_a[i] < a; | |
653 if ( v11 != 3 ) | |
654 { | |
655 if ( !v11 | |
656 || (v12 = intersect_face_vertex_coords_list_a[i + 1] - intersect_face_vertex_coords_list_a[i], | |
657 LODWORD(v13) = v12 << 16, | |
658 HIDWORD(v13) = v12 >> 16, | |
659 intersect_face_vertex_coords_list_a[i] | |
660 + ((signed int)(((unsigned __int64)(v13 / (intersect_face_vertex_coords_list_b[i + 1] - intersect_face_vertex_coords_list_b[i]) | |
661 * (signed int)((b - intersect_face_vertex_coords_list_b[i]) << 16)) >> 16) + 32768) >> 16) >= a) ) | |
662 ++v16; | |
663 } | |
664 } | |
665 v6 = intersect_face_vertex_coords_list_b[i + 1] >= b; | |
666 } | |
667 result = true; | |
668 if ( v16 != 1 ) | |
669 result = false; | |
670 return result; | |
671 }*/ | |
672 } | |
673 | |
674 //----- (004C1EE5) -------------------------------------------------------- | |
675 void Vis::BLV_CreateIntersectFacesVertexCoordList(int *a, int *b, __int16 *intersect_face_vertex_coords_list_a, | |
676 __int16 *intersect_face_vertex_coords_list_b, | |
677 Vec3_short_ *IntersectPoint, BLVFace *pFace) | |
678 { | |
679 if (pFace->uAttributes & FACE_XY_PLANE) | |
680 { | |
681 *a = IntersectPoint->x; | |
682 *b = IntersectPoint->y; | |
683 | |
684 for (uint i = 0; i < pFace->uNumVertices; ++i) | |
685 { | |
686 intersect_face_vertex_coords_list_a[2 * i] = pFace->pXInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].x; | |
687 intersect_face_vertex_coords_list_a[2 * i + 1] = pFace->pXInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].x; | |
688 | |
689 intersect_face_vertex_coords_list_b[2 * i] = pFace->pYInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].y; | |
690 intersect_face_vertex_coords_list_b[2 * i + 1] = pFace->pYInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].y; | |
691 } | |
692 } | |
693 else if (pFace->uAttributes & FACE_XZ_PLANE) | |
694 { | |
695 *a = IntersectPoint->x; | |
696 *b = IntersectPoint->z; | |
697 | |
698 for (uint i = 0; i < pFace->uNumVertices; ++i) | |
699 { | |
700 intersect_face_vertex_coords_list_a[2 * i] = pFace->pXInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].x; | |
701 intersect_face_vertex_coords_list_a[2 * i + 1] = pFace->pXInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].x; | |
702 | |
703 intersect_face_vertex_coords_list_b[2 * i] = pFace->pZInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].z; | |
704 intersect_face_vertex_coords_list_b[2 * i + 1] = pFace->pZInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].z; | |
705 } | |
706 } | |
707 else if (pFace->uAttributes & FACE_YZ_PLANE) | |
708 { | |
709 *a = IntersectPoint->y; | |
710 *b = IntersectPoint->z; | |
711 | |
712 for (uint i = 0; i < pFace->uNumVertices; ++i) | |
713 { | |
714 intersect_face_vertex_coords_list_a[2 * i] = pFace->pYInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].y; | |
715 intersect_face_vertex_coords_list_a[2 * i + 1] = pFace->pYInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].y; | |
716 | |
717 intersect_face_vertex_coords_list_b[2 * i] = pFace->pZInterceptDisplacements[i] + pIndoor->pVertices[pFace->pVertexIDs[i]].z; | |
718 intersect_face_vertex_coords_list_b[2 * i + 1] = pFace->pZInterceptDisplacements[i + 1] + pIndoor->pVertices[pFace->pVertexIDs[i + 1]].z; | |
719 } | |
720 } | |
721 else assert(false); | |
722 } | |
723 | |
724 //----- (004C2186) -------------------------------------------------------- | |
725 void Vis::ODM_CreateIntersectFacesVertexCoordList(int *a, int *b, __int16 *intersect_face_vertex_coords_list_a, | |
726 __int16 *intersect_face_vertex_coords_list_b, | |
727 Vec3_short_ *IntersectPoint, BLVFace *pFace, unsigned int uModelID) | |
728 { | |
729 if (pFace->uAttributes & FACE_XY_PLANE) | |
730 { | |
731 *a = IntersectPoint->x; | |
732 *b = IntersectPoint->y; | |
733 | |
734 for (int i = 0; i < pFace->uNumVertices; ++i) | |
735 { | |
736 intersect_face_vertex_coords_list_a[2 * i] = pFace->pXInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].x; | |
737 intersect_face_vertex_coords_list_a[i * 2 + 1] = pFace->pXInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].x; | |
738 | |
739 intersect_face_vertex_coords_list_b[2 * i] = pFace->pYInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].y; | |
740 intersect_face_vertex_coords_list_b[i * 2 + 1] = pFace->pYInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].y; | |
741 } | |
742 } | |
743 else if (pFace->uAttributes & FACE_XZ_PLANE) | |
744 { | |
745 *a = IntersectPoint->x; | |
746 *b = IntersectPoint->z; | |
747 | |
748 for (int i = 0; i < pFace->uNumVertices; ++i) | |
749 { | |
750 intersect_face_vertex_coords_list_a[2 * i] = pFace->pXInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].x; | |
751 intersect_face_vertex_coords_list_a[i * 2 + 1] = pFace->pXInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].x; | |
752 | |
753 intersect_face_vertex_coords_list_b[2 * i] = pFace->pZInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].z; | |
754 intersect_face_vertex_coords_list_b[i * 2 + 1] = pFace->pZInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].z; | |
755 } | |
756 } | |
757 else if (pFace->uAttributes & FACE_YZ_PLANE) | |
758 { | |
759 *a = IntersectPoint->y; | |
760 *b = IntersectPoint->z; | |
761 | |
762 for (int i = 0; i < pFace->uNumVertices; ++i) | |
763 { | |
764 intersect_face_vertex_coords_list_a[2 * i] = pFace->pYInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].y; | |
765 intersect_face_vertex_coords_list_a[i * 2 + 1] = pFace->pYInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].y; | |
766 | |
767 intersect_face_vertex_coords_list_b[2 * i] = pFace->pZInterceptDisplacements[i] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i]].z; | |
768 intersect_face_vertex_coords_list_b[i * 2 + 1] = pFace->pZInterceptDisplacements[i + 1] + pOutdoor->pBModels[uModelID].pVertices.pVertices[pFace->pVertexIDs[i + 1]].z; | |
769 } | |
770 } | |
771 else assert(false); | |
772 } | |
773 | |
774 //----- (0046A0A1) -------------------------------------------------------- | |
775 int UnprojectX(int x) | |
776 { | |
777 int v3; // [sp-4h] [bp-8h]@5 | |
778 | |
779 if ( uCurrentlyLoadedLevelType == LEVEL_Indoor ) | |
780 { | |
781 //if ( pRenderer->pRenderD3D ) | |
782 v3 = pGame->pIndoorCameraD3D->fov; | |
783 //else | |
784 // v3 = pIndoorCamera->fov_rad; | |
785 } | |
786 else | |
787 { | |
788 v3 = pODMRenderParams->int_fov_rad; | |
789 } | |
790 return stru_5C6E00->Atan2(x - pViewport->uScreenCenterX, v3) - stru_5C6E00->uIntegerHalfPi; | |
791 } | |
792 | |
793 //----- (0046A0F6) -------------------------------------------------------- | |
794 int UnprojectY(int y) | |
795 { | |
796 int v3; // [sp-4h] [bp-8h]@5 | |
797 | |
798 if ( uCurrentlyLoadedLevelType == LEVEL_Indoor ) | |
799 { | |
800 //if ( pRenderer->pRenderD3D ) | |
801 v3 = pGame->pIndoorCameraD3D->fov; | |
802 //else | |
803 // v3 = pIndoorCamera->fov_rad; | |
804 } | |
805 else | |
806 { | |
807 v3 = pODMRenderParams->int_fov_rad; | |
808 } | |
809 return stru_5C6E00->Atan2(y - pViewport->uScreenCenterY, v3) - stru_5C6E00->uIntegerHalfPi; | |
810 } | |
811 | |
812 //----- (004C248E) -------------------------------------------------------- | |
813 void Vis::CastPickRay(RenderVertexSoft *pRay, float fMouseX, float fMouseY, float fPickDepth) | |
814 { | |
815 int pRotY; // esi@1 | |
816 Vec3_int_ pStartR; // ST08_12@1 | |
817 int pRotX; // ST04_4@1 | |
818 int pDepth; // eax@1 | |
819 RenderVertexSoft v11[2]; // [sp+2Ch] [bp-74h]@1 | |
820 int outx; | |
821 int outz; // [sp+94h] [bp-Ch]@1 | |
822 int outy; // [sp+98h] [bp-8h]@1 | |
823 | |
824 pRotY = pGame->pIndoorCameraD3D->sRotationY + UnprojectX(fMouseX); | |
825 pRotX = pGame->pIndoorCameraD3D->sRotationX + UnprojectY(fMouseY); | |
826 | |
827 pStartR.z = pGame->pIndoorCameraD3D->vPartyPos.z; | |
828 pStartR.x = pGame->pIndoorCameraD3D->vPartyPos.x; | |
829 pStartR.y = pGame->pIndoorCameraD3D->vPartyPos.y; | |
830 | |
831 v11[1].vWorldPosition.x = (double)pGame->pIndoorCameraD3D->vPartyPos.x; | |
832 v11[1].vWorldPosition.y = (double)pGame->pIndoorCameraD3D->vPartyPos.y; | |
833 v11[1].vWorldPosition.z = (double)pGame->pIndoorCameraD3D->vPartyPos.z; | |
834 | |
835 pDepth = fixpoint_from_float(fPickDepth); | |
836 Vec3_int_::Rotate(pDepth, pRotY, pRotX, pStartR, &outx, &outy, &outz); | |
837 | |
838 v11[0].vWorldPosition.x = (double)outx; | |
839 v11[0].vWorldPosition.y = (double)outy; | |
840 v11[0].vWorldPosition.z = (double)outz; | |
841 | |
842 memcpy(pRay + 0, &v11[1], sizeof(RenderVertexSoft)); | |
843 memcpy(pRay + 1, &v11[0], sizeof(RenderVertexSoft)); | |
844 } | |
845 | |
846 //----- (004C2551) -------------------------------------------------------- | |
847 Vis_ObjectInfo *Vis_SelectionList::SelectionPointers(int pVisObjectType, int pid) | |
848 { | |
849 //unsigned int v3; // esi@1 | |
850 //signed int v4; // edx@1 | |
851 //char *v5; // eax@2 | |
852 //Vis_ObjectInfo *result; // eax@6 | |
853 | |
854 //v3 = this->uNumPointers; | |
855 if ( this->uNumPointers > 0 ) | |
856 { | |
857 for ( uint i = 0; i < this->uNumPointers; ++i ) | |
858 { | |
859 if ( this->object_pool[i].object_type == pVisObjectType && (this->object_pool[i].sZValue & 0xFFFF) == pid ) | |
860 return &this->object_pool[i]; | |
861 } | |
862 } | |
863 return nullptr; | |
864 /*v4 = 0; | |
865 if ( this->uNumPointers <= 0 ) | |
866 return false; | |
867 else | |
868 { | |
869 //v5 = (char *)&this->object_pool[0].sZValue; | |
870 while ( this->object_pool[v4].object_type != a2 || (this->object_pool[v4].sZValue & 0xFFFF) != a3 ) | |
871 { | |
872 ++v4; | |
873 //v5 += 12; | |
874 if ( v4 >= this->uNumPointers ) | |
875 return false; | |
876 } | |
877 result = &this->object_pool[v4]; | |
878 } | |
879 return result;*/ | |
880 } | |
881 | |
882 //----- (004C2591) -------------------------------------------------------- | |
883 void Vis_SelectionList::create_object_pointers(PointerCreationType type) | |
884 { | |
885 switch (type) | |
886 { | |
887 case All: | |
888 { | |
889 for (uint i = 0; i < uNumPointers; ++i) | |
890 object_pointers[i] = &object_pool[i]; | |
891 } | |
892 break; | |
893 | |
894 case Unique: // seems quite retarted; the inner if condition will never trigger, since we compare pointers, not values. pointers will always be unique | |
895 { // but it may be decompilation error thou | |
896 bool create = true; | |
897 | |
898 for (uint i = 0; i < uNumPointers; ++i) | |
899 { | |
900 for (uint j = 0; j < i; ++j) | |
901 { | |
902 if (object_pointers[j] == &object_pool[i]) | |
903 { | |
904 create = false; | |
905 break; | |
906 } | |
907 } | |
908 | |
909 if (create) | |
910 object_pointers[i] = &object_pool[i]; | |
911 } | |
912 } | |
913 break; | |
914 | |
915 default: | |
916 MessageBoxW(nullptr, L"Unknown pointer creation flag passed to ::create_object_pointers()", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:1358", 0); | |
917 } | |
918 } | |
919 | |
920 //----- (004C264A) -------------------------------------------------------- | |
921 void Vis::sort_object_pointers( Vis_ObjectInfo **pPointers, int start, int end )//сортировка | |
922 { | |
923 int sort_start; // edx@1 | |
924 int forward_sort_index; // esi@2 | |
925 signed int backward_sort_index; // ecx@2 | |
926 unsigned int last_z_val; // eax@3 | |
927 unsigned int more_lz_val; // ebx@4 | |
928 unsigned int less_lz_val; // ebx@6 | |
929 Vis_ObjectInfo *temp_pointer; // eax@7 | |
930 // Vis_ObjectInfo *a3a; // [sp+14h] [bp+Ch]@2 | |
931 | |
932 sort_start = start; | |
933 | |
934 if ( end > start ) | |
935 { | |
936 do | |
937 { | |
938 forward_sort_index = sort_start - 1; | |
939 backward_sort_index = end; | |
940 do | |
941 { | |
942 last_z_val = pPointers[end]->sZValue & 0xFFFF0000; | |
943 do | |
944 { | |
945 ++forward_sort_index; | |
946 more_lz_val = pPointers[forward_sort_index]->sZValue & 0xFFFF0000; | |
947 } | |
948 while ( more_lz_val < last_z_val ); | |
949 | |
950 do | |
951 { | |
952 if ( backward_sort_index < 1 ) | |
953 break; | |
954 --backward_sort_index; | |
955 less_lz_val = pPointers[backward_sort_index]->sZValue & 0xFFFF0000; | |
956 } | |
957 while ( less_lz_val > last_z_val ); | |
958 | |
959 temp_pointer = pPointers[forward_sort_index]; | |
960 if ( forward_sort_index >= backward_sort_index ) | |
961 { | |
962 pPointers[forward_sort_index] = pPointers[end]; | |
963 pPointers[end] = temp_pointer; | |
964 } | |
965 else | |
966 { | |
967 pPointers[forward_sort_index] = pPointers[backward_sort_index]; | |
968 pPointers[backward_sort_index] = temp_pointer; | |
969 } | |
970 | |
971 } while ( forward_sort_index < backward_sort_index ); | |
972 | |
973 sort_object_pointers(pPointers, sort_start, forward_sort_index - 1); | |
974 sort_start = forward_sort_index + 1; | |
975 } | |
976 while ( end > forward_sort_index + 1 ); | |
977 } | |
978 } | |
979 | |
980 //----- (004C26D0) -------------------------------------------------------- | |
981 void Vis::SortVerticesByX(RenderVertexD3D3 *pArray, unsigned int uStart, unsigned int uEnd) | |
982 { | |
983 unsigned int left_sort_index; // ebx@2 | |
984 RenderVertexD3D3 temp_array; // [sp+4h] [bp-4Ch]@8 | |
985 RenderVertexD3D3 max_array; // [sp+24h] [bp-2Ch]@2 | |
986 unsigned int right_sort_index; // [sp+4Ch] [bp-4h]@2 | |
987 | |
988 if ( (signed int)uEnd > (signed int)uStart ) | |
989 { | |
990 left_sort_index = uStart - 1; | |
991 right_sort_index = uEnd; | |
992 while ( 1 ) | |
993 { | |
994 memcpy(&max_array, &pArray[uEnd], sizeof(max_array)); | |
995 do | |
996 { | |
997 ++left_sort_index; | |
998 } | |
999 while ( pArray[left_sort_index].pos.x < (double)max_array.pos.x ); | |
1000 do | |
1001 { | |
1002 --right_sort_index; | |
1003 } | |
1004 while ( pArray[right_sort_index].pos.x > (double)max_array.pos.x ); | |
1005 if ( (signed int)left_sort_index >= (signed int)right_sort_index ) | |
1006 break; | |
1007 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1008 memcpy(&pArray[left_sort_index], &pArray[right_sort_index], sizeof(pArray[left_sort_index])); | |
1009 memcpy(&pArray[right_sort_index], &temp_array, sizeof(pArray[right_sort_index])); | |
1010 } | |
1011 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1012 memcpy(&pArray[left_sort_index], &pArray[uEnd], sizeof(pArray[left_sort_index])); | |
1013 memcpy(&pArray[uEnd], &temp_array, sizeof(pArray[uEnd])); | |
1014 SortVerticesByX(pArray, uStart, left_sort_index - 1); | |
1015 SortVerticesByX(pArray, left_sort_index + 1, uEnd); | |
1016 } | |
1017 } | |
1018 | |
1019 //----- (004C27AD) -------------------------------------------------------- | |
1020 void Vis::SortVerticesByY(RenderVertexD3D3 *pArray, unsigned int uStart, unsigned int uEnd) | |
1021 { | |
1022 unsigned int left_sort_index; // ebx@2 | |
1023 RenderVertexD3D3 temp_array; // [sp+4h] [bp-4Ch]@8 | |
1024 RenderVertexD3D3 max_array; // [sp+24h] [bp-2Ch]@2 | |
1025 unsigned int right_sort_index; // [sp+4Ch] [bp-4h]@2 | |
1026 | |
1027 if ( (signed int)uEnd > (signed int)uStart ) | |
1028 { | |
1029 left_sort_index = uStart - 1; | |
1030 right_sort_index = uEnd; | |
1031 while ( 1 ) | |
1032 { | |
1033 memcpy(&max_array, &pArray[uEnd], sizeof(max_array)); | |
1034 do | |
1035 { | |
1036 ++left_sort_index; | |
1037 } | |
1038 while ( pArray[left_sort_index].pos.y < (double)max_array.pos.y ); | |
1039 do | |
1040 { | |
1041 --right_sort_index; | |
1042 } | |
1043 while ( pArray[right_sort_index].pos.y > (double)max_array.pos.y ); | |
1044 if ( (signed int)left_sort_index >= (signed int)right_sort_index ) | |
1045 break; | |
1046 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1047 memcpy(&pArray[left_sort_index], &pArray[right_sort_index], sizeof(pArray[left_sort_index])); | |
1048 memcpy(&pArray[right_sort_index], &temp_array, sizeof(pArray[right_sort_index])); | |
1049 } | |
1050 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1051 memcpy(&pArray[left_sort_index], &pArray[uEnd], sizeof(pArray[left_sort_index])); | |
1052 memcpy(&pArray[uEnd], &temp_array, sizeof(pArray[uEnd])); | |
1053 SortVerticesByY(pArray, uStart, left_sort_index - 1); | |
1054 SortVerticesByY(pArray, left_sort_index + 1, uEnd); | |
1055 } | |
1056 } | |
1057 | |
1058 //----- (004C288E) -------------------------------------------------------- | |
1059 void Vis::SortByScreenSpaceX(RenderVertexSoft *pArray, int start, int end)//сортировка по возрастанию экранных координат х | |
1060 { | |
1061 int left_sort_index; // ebx@2 | |
1062 int right_sort_index; // ecx@2 | |
1063 RenderVertexSoft temp_array; // [sp+4h] [bp-6Ch]@8 | |
1064 RenderVertexSoft max_array; // [sp+34h] [bp-3Ch]@2 | |
1065 | |
1066 if ( end > start ) | |
1067 { | |
1068 left_sort_index = start - 1; | |
1069 right_sort_index = end; | |
1070 memcpy(&max_array, &pArray[end], sizeof(max_array)); | |
1071 while ( 1 ) | |
1072 { | |
1073 do | |
1074 { | |
1075 ++left_sort_index; | |
1076 } | |
1077 while ( pArray[left_sort_index].vWorldViewProjX < (double)max_array.vWorldViewProjX ); | |
1078 do | |
1079 { | |
1080 --right_sort_index; | |
1081 } | |
1082 while ( pArray[right_sort_index].vWorldViewProjX > (double)max_array.vWorldViewProjX ); | |
1083 if ( left_sort_index >= right_sort_index ) | |
1084 break; | |
1085 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1086 memcpy(&pArray[left_sort_index], &pArray[right_sort_index], sizeof(pArray[left_sort_index])); | |
1087 memcpy(&pArray[right_sort_index], &temp_array, sizeof(pArray[right_sort_index])); | |
1088 } | |
1089 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1090 memcpy(&pArray[left_sort_index], &pArray[end], sizeof(pArray[left_sort_index])); | |
1091 memcpy(&pArray[end], &temp_array, sizeof(pArray[end])); | |
1092 Vis::SortByScreenSpaceX(pArray, start, left_sort_index - 1); | |
1093 Vis::SortByScreenSpaceX(pArray, left_sort_index + 1, end); | |
1094 } | |
1095 } | |
1096 | |
1097 //----- (004C297E) -------------------------------------------------------- | |
1098 void Vis::SortByScreenSpaceY(RenderVertexSoft *pArray, int start, int end) | |
1099 { | |
1100 int left_sort_index; // ebx@2 | |
1101 int right_sort_index; // ecx@2 | |
1102 RenderVertexSoft temp_array; // [sp+4h] [bp-6Ch]@8 | |
1103 RenderVertexSoft max_array; // [sp+34h] [bp-3Ch]@2 | |
1104 | |
1105 if ( end > start ) | |
1106 { | |
1107 left_sort_index = start - 1; | |
1108 right_sort_index = end; | |
1109 memcpy(&max_array, &pArray[end], sizeof(max_array)); | |
1110 while ( 1 ) | |
1111 { | |
1112 do | |
1113 { | |
1114 ++left_sort_index; | |
1115 } | |
1116 while ( pArray[left_sort_index].vWorldViewProjY < (double)max_array.vWorldViewProjY ); | |
1117 do | |
1118 { | |
1119 --right_sort_index; | |
1120 } | |
1121 while ( pArray[right_sort_index].vWorldViewProjY > (double)max_array.vWorldViewProjY ); | |
1122 if ( left_sort_index >= right_sort_index ) | |
1123 break; | |
1124 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1125 memcpy(&pArray[left_sort_index], &pArray[right_sort_index], sizeof(pArray[left_sort_index])); | |
1126 memcpy(&pArray[right_sort_index], &temp_array, sizeof(pArray[right_sort_index])); | |
1127 } | |
1128 memcpy(&temp_array, &pArray[left_sort_index], sizeof(temp_array)); | |
1129 memcpy(&pArray[left_sort_index], &pArray[end], sizeof(pArray[left_sort_index])); | |
1130 memcpy(&pArray[end], &temp_array, sizeof(pArray[end])); | |
1131 Vis::SortByScreenSpaceY(pArray, start, left_sort_index - 1); | |
1132 Vis::SortByScreenSpaceY(pArray, left_sort_index + 1, end); | |
1133 } | |
1134 } | |
1135 | |
1136 //----- (004C04AF) -------------------------------------------------------- | |
1137 Vis::Vis() | |
1138 { | |
1139 RenderVertexSoft v3; // [sp+Ch] [bp-60h]@1 | |
1140 RenderVertexSoft v4; // [sp+3Ch] [bp-30h]@1 | |
1141 | |
1142 v3.flt_2C = 0.0; | |
1143 v3.vWorldPosition.x = 0.0; | |
1144 v3.vWorldPosition.y = 65536.0; | |
1145 v3.vWorldPosition.z = 0.0; | |
1146 v4.flt_2C = 0.0; | |
1147 v4.vWorldPosition.x = 65536.0; | |
1148 v4.vWorldPosition.y = 0.0; | |
1149 v4.vWorldPosition.z = 0.0; | |
1150 memcpy(&stru_200C, &v4, sizeof(stru_200C)); | |
1151 | |
1152 v4.flt_2C = 0.0; | |
1153 v4.vWorldPosition.x = 0.0; | |
1154 v4.vWorldPosition.y = 65536.0; | |
1155 v4.vWorldPosition.z = 0.0; | |
1156 memcpy(&stru_203C, &v3, sizeof(stru_203C)); | |
1157 | |
1158 v3.flt_2C = 0.0; | |
1159 v3.vWorldPosition.x = 65536.0; | |
1160 v3.vWorldPosition.y = 0.0; | |
1161 v3.vWorldPosition.z = 0.0; | |
1162 memcpy(&stru_206C, &v3, sizeof(stru_206C)); | |
1163 memcpy(&stru_209C, &v4, sizeof(stru_209C)); | |
1164 | |
1165 keyboard_pick_depth = 512; | |
1166 } | |
1167 | |
1168 //----- (004C055C) -------------------------------------------------------- | |
1169 Vis_SelectionList::Vis_SelectionList() | |
1170 { | |
1171 for (uint i = 0; i < 512; ++i) | |
1172 { | |
1173 object_pool[i].object = nullptr; | |
1174 object_pool[i].sZValue = -1; | |
1175 object_pool[i].object_type = VisObjectType_Any; | |
1176 } | |
1177 uNumPointers = 0; | |
1178 } | |
1179 | |
1180 //----- (004C05CC) -------------------------------------------------------- | |
1181 bool Vis::PickKeyboard(Vis_SelectionList *list, Vis_SelectionFilter *sprite_filter, Vis_SelectionFilter *face_filter) | |
1182 { | |
1183 if (!list) | |
1184 list = &default_list; | |
1185 list->uNumPointers = 0; | |
1186 | |
1187 PickBillboards_Keyboard(keyboard_pick_depth, list, sprite_filter); | |
1188 if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
1189 PickIndoorFaces_Keyboard(keyboard_pick_depth, list, face_filter); | |
1190 else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor) | |
1191 PickOutdoorFaces_Keyboard(keyboard_pick_depth, list, face_filter); | |
1192 else | |
1193 assert(false); | |
1194 | |
1195 list->create_object_pointers(Vis_SelectionList::Unique); | |
1196 sort_object_pointers(list->object_pointers, 0, list->uNumPointers - 1); | |
1197 | |
1198 return true; | |
1199 } | |
1200 | |
1201 //----- (004C0646) -------------------------------------------------------- | |
1202 bool Vis::PickMouse(float fDepth, float fMouseX, float fMouseY, Vis_SelectionFilter *sprite_filter, Vis_SelectionFilter *face_filter) | |
1203 { | |
1204 RenderVertexSoft pMouseRay[2]; // [sp+1Ch] [bp-60h]@1 | |
1205 | |
1206 default_list.uNumPointers = 0; | |
1207 CastPickRay(pMouseRay, fMouseX, fMouseY, fDepth); | |
1208 PickBillboards_Mouse(fDepth, fMouseX, fMouseY, &default_list, sprite_filter); | |
1209 if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
1210 PickIndoorFaces_Mouse(fDepth, pMouseRay, &default_list, face_filter); | |
1211 else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor) | |
1212 PickOutdoorFaces_Mouse(fDepth, pMouseRay, &default_list, face_filter, false); | |
1213 else | |
1214 { | |
1215 Log::Warning(L"Picking mouse in undefined level"); // picking in main menu is default (buggy) game behaviour. should've returned false in Game::PickMouse | |
1216 return false; | |
1217 } | |
1218 default_list.create_object_pointers(Vis_SelectionList::All); | |
1219 sort_object_pointers(default_list.object_pointers, 0, default_list.uNumPointers - 1); | |
1220 | |
1221 return true; | |
1222 } | |
1223 | |
1224 //----- (004C06F8) -------------------------------------------------------- | |
1225 void Vis::PickBillboards_Keyboard(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter) | |
1226 { | |
1227 for (uint i = 0; i < pRenderer->uNumBillboardsToDraw; ++i) | |
1228 { | |
1229 RenderBillboardD3D* d3d_billboard = &pRenderer->pBillboardRenderListD3D[i]; | |
1230 | |
1231 if (is_part_of_selection((void *)i, filter)) | |
1232 { | |
1233 if (DoesRayIntersectBillboard(pick_depth, i)) | |
1234 { | |
1235 RenderBillboard* billboard = &pBillboardRenderList[d3d_billboard->sParentBillboardID]; | |
1236 | |
1237 list->AddObject((void *)d3d_billboard->sParentBillboardID, VisObjectType_Sprite, billboard->sZValue); | |
1238 } | |
1239 } | |
1240 } | |
1241 } | |
1242 | |
1243 | |
1244 // tests the object against selection filter to determine whether it can be picked or not | |
1245 //----- (004C0791) -------------------------------------------------------- | |
1246 bool Vis::is_part_of_selection(void *uD3DBillboardIdx_or_pBLVFace_or_pODMFace, Vis_SelectionFilter *filter) | |
1247 { | |
1248 //stru157 *v3; // esi@1 | |
1249 //int result; // eax@1 | |
1250 //int v5; // edx@2 | |
1251 //int v6; // ecx@2 | |
1252 //char v7; // zf@3 | |
1253 //int v8; // esi@5 | |
1254 // std::string *v9; // ecx@7 | |
1255 //Actor *v10; // edi@18 | |
1256 //const char *v12; // [sp-20h] [bp-2Ch]@7 | |
1257 // int v13; // [sp-1Ch] [bp-28h]@7 | |
1258 //std::string v14; // [sp-18h] [bp-24h]@7 | |
1259 //const char *v15; // [sp-8h] [bp-14h]@7 | |
1260 // int v16; // [sp-4h] [bp-10h]@7 | |
1261 | |
1262 switch (filter->object_type) | |
1263 { | |
1264 case VisObjectType_Any: | |
1265 return true; | |
1266 | |
1267 case VisObjectType_Sprite: | |
1268 { | |
1269 //v5 = filter->select_flags; | |
1270 int object_idx = PID_ID(pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].sParentBillboardID].object_pid); | |
1271 int object_type = PID_TYPE(pBillboardRenderList[pRenderer->pBillboardRenderListD3D[(int)uD3DBillboardIdx_or_pBLVFace_or_pODMFace].sParentBillboardID].object_pid); | |
1272 if ( filter->select_flags & 2 ) | |
1273 { | |
1274 if (object_type == filter->object_id) | |
1275 return false; | |
1276 return true; | |
1277 } | |
1278 if ( filter->select_flags & 4 ) | |
1279 { | |
1280 //v8 = filter->object_id; | |
1281 if ( object_type != filter->object_id) | |
1282 return true; | |
1283 if (filter->object_id != OBJECT_Decoration) | |
1284 { | |
1285 MessageBoxA(nullptr, "Unsupported \"exclusion if no event\" type in CVis::is_part_of_selection", "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:207", 0); | |
1286 return true; | |
1287 } | |
1288 if (pLevelDecorations[object_idx].uCog || pLevelDecorations[object_idx].uEventID) | |
1289 return true; | |
1290 return pLevelDecorations[object_idx].IsInteractive(); | |
1291 } | |
1292 if (object_type == filter->object_id) | |
1293 { | |
1294 if (object_type != OBJECT_Actor) | |
1295 { | |
1296 MessageBoxA(nullptr, "Default case reached in VIS", "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Vis.cpp:245", 0); | |
1297 return true; | |
1298 } | |
1299 | |
1300 //v10 = &pActors[object_idx]; | |
1301 int result = 1 << LOBYTE(pActors[object_idx].uAIState); | |
1302 if ( result & filter->no_at_ai_state | |
1303 || !(result & filter->at_ai_state) | |
1304 || filter->select_flags & 8 && (result = MonsterStats::BelongsToSupertype(pActors[object_idx].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD)) == 0 ) | |
1305 return false; | |
1306 if ( !(filter->select_flags & 1) ) | |
1307 return true; | |
1308 | |
1309 result = pActors[object_idx].GetActorsRelation(nullptr); | |
1310 if (result == 0) | |
1311 return false; | |
1312 return true; | |
1313 } | |
1314 return false; | |
1315 } | |
1316 | |
1317 case VisObjectType_Face: | |
1318 { | |
1319 uint face_attrib = 0; | |
1320 bool no_event = true; | |
1321 if (uCurrentlyLoadedLevelType == LEVEL_Outdoor) | |
1322 { | |
1323 ODMFace* face = (ODMFace *)uD3DBillboardIdx_or_pBLVFace_or_pODMFace; | |
1324 no_event = face->sCogTriggeredID == 0; | |
1325 face_attrib = face->uAttributes; | |
1326 } | |
1327 else if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
1328 { | |
1329 BLVFace* face = (BLVFace *)uD3DBillboardIdx_or_pBLVFace_or_pODMFace; | |
1330 no_event = pIndoor->pFaceExtras[face->uFaceExtraID].uEventID == 0; | |
1331 face_attrib = face->uAttributes; | |
1332 } | |
1333 else | |
1334 assert(false); | |
1335 | |
1336 if (filter->object_id != OBJECT_BLVDoor) | |
1337 return true; | |
1338 if (no_event || face_attrib & filter->no_at_ai_state)//face_attrib = 0x2009408 incorrect | |
1339 return false; | |
1340 return (face_attrib & filter->at_ai_state) != 0; | |
1341 } | |
1342 | |
1343 default: | |
1344 assert(false); | |
1345 } | |
1346 } | |
1347 | |
1348 //----- (004C091D) -------------------------------------------------------- | |
1349 bool Vis::DoesRayIntersectBillboard(float fDepth, unsigned int uD3DBillboardIdx) | |
1350 { | |
1351 int v3; // eax@3 | |
1352 //signed int v5; // ecx@4 | |
1353 //float v6; // ST04_4@6 | |
1354 //float v7; // ST00_4@7 | |
1355 //int v8; // eax@10 | |
1356 //unsigned int v9; // eax@12 | |
1357 // int v10; // eax@17 | |
1358 // double v11; // st6@18 | |
1359 // double v12; // st7@18 | |
1360 // double v13; // st4@18 | |
1361 // float v14; // ST0C_4@22 | |
1362 // float v15; // ST08_4@22 | |
1363 //float v16; // ST04_4@23 | |
1364 //float v17; // ST00_4@24 | |
1365 //signed int v18; // eax@27 | |
1366 //unsigned int v19; // eax@29 | |
1367 // double v20; // st6@32 | |
1368 // double v21; // st7@32 | |
1369 // int v22; // eax@32 | |
1370 // double v23; // st7@36 | |
1371 //void *v24; // esi@40 | |
1372 // float v25; // ST08_4@40 | |
1373 //float v26; // ST04_4@41 | |
1374 //float v27; // ST00_4@42 | |
1375 // int v28; // eax@45 | |
1376 // unsigned int v29; // eax@47 | |
1377 // char result; // al@48 | |
1378 struct RenderVertexSoft pPickingRay[2]; | |
1379 //int v31; // [sp+20h] [bp-DCh]@5 | |
1380 struct RenderVertexSoft local_80[2]; | |
1381 | |
1382 float test_x; | |
1383 float test_y; | |
1384 | |
1385 float t1_x; | |
1386 float t1_y; | |
1387 float t2_x; | |
1388 float t2_y; | |
1389 float swap_temp; | |
1390 // int v37; // [sp+F0h] [bp-Ch]@5 | |
1391 | |
1392 signed int v40; // [sp+108h] [bp+Ch]@17 | |
1393 | |
1394 | |
1395 static Vis_SelectionList Vis_static_stru_F91E10; | |
1396 Vis_static_stru_F91E10.uNumPointers = 0; | |
1397 v3 = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].sParentBillboardID; | |
1398 if (v3 == -1) | |
1399 return false; | |
1400 | |
1401 if (pBillboardRenderList[v3].GetFloatZ() > fDepth) | |
1402 return false; | |
1403 | |
1404 | |
1405 GetPolygonCenter(pRenderer->pBillboardRenderListD3D[v3].pQuads, 4, &test_x, &test_y); | |
1406 CastPickRay(pPickingRay, test_x, test_y, fDepth); | |
1407 if (uCurrentlyLoadedLevelType == LEVEL_Indoor) | |
1408 PickIndoorFaces_Mouse(fDepth, pPickingRay, &Vis_static_stru_F91E10, &vis_face_filter); | |
1409 else | |
1410 PickOutdoorFaces_Mouse(fDepth, pPickingRay, &Vis_static_stru_F91E10, &vis_face_filter, false); | |
1411 Vis_static_stru_F91E10.create_object_pointers(); | |
1412 sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1); | |
1413 if (Vis_static_stru_F91E10.uNumPointers) | |
1414 { | |
1415 if (Vis_static_stru_F91E10.object_pointers[0]->actual_z > pBillboardRenderList[v3].actual_z) | |
1416 return true; | |
1417 } | |
1418 else if ((double)(pViewport->uScreen_TL_X) <= test_x && | |
1419 (double)pViewport->uScreen_BR_X >= test_x && | |
1420 (double)pViewport->uScreen_TL_Y <= test_y && | |
1421 (double)pViewport->uScreen_BR_Y >= test_y) | |
1422 return true; | |
1423 | |
1424 for (v40 = 0; v40 < 4; ++v40) | |
1425 { | |
1426 test_x=pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[v40].pos.x; | |
1427 test_y= pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[v40].pos.y; | |
1428 if ((double)(pViewport->uScreen_TL_X) <= test_x && | |
1429 (double)pViewport->uScreen_BR_X >= test_x && | |
1430 (double)pViewport->uScreen_TL_Y <= test_y && | |
1431 (double)pViewport->uScreen_BR_Y >= test_y) | |
1432 { | |
1433 CastPickRay(local_80, test_x, test_y, fDepth); | |
1434 if ( uCurrentlyLoadedLevelType == LEVEL_Indoor ) | |
1435 PickIndoorFaces_Mouse(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter); | |
1436 else | |
1437 PickOutdoorFaces_Mouse(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter, false); | |
1438 Vis_static_stru_F91E10.create_object_pointers(); | |
1439 sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1); | |
1440 if ( !Vis_static_stru_F91E10.uNumPointers ) | |
1441 return true; | |
1442 if (Vis_static_stru_F91E10.object_pointers[0]->actual_z > pBillboardRenderList[v3].actual_z) | |
1443 return true; | |
1444 } | |
1445 | |
1446 } | |
1447 | |
1448 if ( v40 >= 4 ) | |
1449 { | |
1450 if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor ) | |
1451 return false; | |
1452 t1_x = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[0].pos.x; | |
1453 t2_x = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[3].pos.x; | |
1454 | |
1455 t1_y = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[0].pos.y; | |
1456 t2_y = pRenderer->pBillboardRenderListD3D[uD3DBillboardIdx].pQuads[1].pos.y; | |
1457 if ( t1_x > t2_x ) | |
1458 { | |
1459 swap_temp = t1_x; | |
1460 t1_x = t2_x; | |
1461 t2_x = swap_temp; | |
1462 } | |
1463 if ( t1_y > t2_y ) | |
1464 test_y = t1_y; | |
1465 else | |
1466 test_y = t2_y; | |
1467 | |
1468 Vis_static_stru_F91E10.uNumPointers = 0; | |
1469 | |
1470 test_x = (t2_x - t1_x) * 0.5; | |
1471 if ((double)(pViewport->uScreen_TL_X) <= test_x && | |
1472 (double)pViewport->uScreen_BR_X >= test_x && | |
1473 (double)pViewport->uScreen_TL_Y <= test_y && | |
1474 (double)pViewport->uScreen_BR_Y >= test_y) | |
1475 { | |
1476 CastPickRay(local_80, test_x, test_y, fDepth); | |
1477 if ( uCurrentlyLoadedLevelType == LEVEL_Indoor ) | |
1478 PickIndoorFaces_Mouse(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter); | |
1479 else | |
1480 PickOutdoorFaces_Mouse(fDepth, local_80, &Vis_static_stru_F91E10, &vis_face_filter, false); | |
1481 Vis_static_stru_F91E10.create_object_pointers(); | |
1482 sort_object_pointers(Vis_static_stru_F91E10.object_pointers, 0, Vis_static_stru_F91E10.uNumPointers - 1); | |
1483 if ( !Vis_static_stru_F91E10.uNumPointers ) | |
1484 return true; | |
1485 if (Vis_static_stru_F91E10.object_pointers[0]->actual_z > pBillboardRenderList[v3].actual_z) | |
1486 return true; | |
1487 | |
1488 } | |
1489 | |
1490 } | |
1491 return false; | |
1492 } | |
1493 // F93E18: using guessed type char static_byte_F93E18_init; | |
1494 | |
1495 //----- (004C0D32) -------------------------------------------------------- | |
1496 void Vis::PickIndoorFaces_Keyboard(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter) | |
1497 { | |
1498 int result; // eax@1 | |
1499 signed int pFaceID; // esi@2 | |
1500 BLVFace *pFace; // edi@4 | |
1501 //unsigned int v7; // eax@6 | |
1502 Vis_ObjectInfo *v8; // eax@6 | |
1503 signed int i; // [sp+18h] [bp-8h]@1 | |
1504 | |
1505 result = 0; | |
1506 for ( i = 0; i < (signed int)pBspRenderer->num_faces; ++i ) | |
1507 { | |
1508 pFaceID = pBspRenderer->faces[result].uFaceID; | |
1509 if ( pFaceID >= 0 ) | |
1510 { | |
1511 if ( pFaceID < (signed int)pIndoor->uNumFaces ) | |
1512 { | |
1513 pFace = &pIndoor->pFaces[pFaceID]; | |
1514 if ( !pGame->pIndoorCameraD3D->IsCulled(&pIndoor->pFaces[pFaceID]) ) | |
1515 { | |
1516 if ( is_part_of_selection(pFace, filter) ) | |
1517 { | |
1518 v8 = DetermineFacetIntersection(pFace, PID(OBJECT_BModel, pFaceID), pick_depth); | |
1519 if ( v8 ) | |
1520 list->AddObject(v8->object, v8->object_type, v8->sZValue); | |
1521 } | |
1522 } | |
1523 } | |
1524 } | |
1525 result = i + 1; | |
1526 } | |
1527 } | |
1528 | |
1529 //----- (004C0DEA) -------------------------------------------------------- | |
1530 void Vis::PickOutdoorFaces_Keyboard(float pick_depth, Vis_SelectionList *list, Vis_SelectionFilter *filter) | |
1531 { | |
1532 for (int i = 0; i < pOutdoor->uNumBModels; ++i) | |
1533 { | |
1534 int v17; | |
1535 if (!IsBModelVisible(i, &v17)) | |
1536 continue; | |
1537 if (!v17) | |
1538 continue; | |
1539 | |
1540 BSPModel* bmodel = &pOutdoor->pBModels[i]; | |
1541 for (int j = 0; j < bmodel->uNumFaces; ++j) | |
1542 { | |
1543 //ODMFace* face = &bmodel->pFaces[j]; | |
1544 | |
1545 if (is_part_of_selection(&bmodel->pFaces[j], filter) ) | |
1546 { | |
1547 BLVFace blv_face; | |
1548 blv_face.FromODM(&bmodel->pFaces[j]); | |
1549 | |
1550 int pid = PID(OBJECT_BModel, j | (i << 6)); | |
1551 if (Vis_ObjectInfo* object_info = DetermineFacetIntersection(&blv_face, pid, pick_depth)) | |
1552 list->AddObject(object_info->object, object_info->object_type, object_info->sZValue); | |
1553 } | |
1554 } | |
1555 } | |
1556 } |