1 /*
2 * Copyright 2011-2012 Arx Libertatis Team (see the AUTHORS file)
3 *
4 * This file is part of Arx Libertatis.
5 *
6 * Arx Libertatis is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Arx Libertatis is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Arx Libertatis. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /* Based on:
20 ===========================================================================
21 ARX FATALIS GPL Source Code
22 Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
23
24 This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
25
26 Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
27 License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
28
29 Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
30 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see
33 <http://www.gnu.org/licenses/>.
34
35 In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
36 additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
37 Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
38
39 If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
40 ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
41 ===========================================================================
42 */
43
44 #include "animation/AnimationRender.h"
45
46 #include <stddef.h>
47 #include <cstdlib>
48 #include <cstring>
49 #include <algorithm>
50
51 #include "animation/Animation.h"
52
53 #include "core/Application.h"
54 #include "core/GameTime.h"
55 #include "core/Core.h"
56
57 #include "game/Damage.h"
58 #include "game/Equipment.h"
59 #include "game/EntityManager.h"
60 #include "game/NPC.h"
61 #include "game/Player.h"
62 #include "game/Spells.h"
63
64 #include "graphics/BaseGraphicsTypes.h"
65 #include "graphics/GraphicsTypes.h"
66 #include "graphics/Draw.h"
67 #include "graphics/Math.h"
68 #include "graphics/Renderer.h"
69 #include "graphics/Vertex.h"
70 #include "graphics/data/Mesh.h"
71 #include "graphics/data/MeshManipulation.h"
72 #include "graphics/data/TextureContainer.h"
73 #include "graphics/particle/ParticleEffects.h"
74
75 #include "math/Angle.h"
76 #include "math/Vector3.h"
77
78 #include "physics/Collisions.h"
79
80 #include "platform/Platform.h"
81
82 #include "scene/Light.h"
83 #include "scene/GameSound.h"
84 #include "scene/Scene.h"
85 #include "scene/Interactive.h"
86
87 using std::min;
88 using std::max;
89
90 unsigned char * grps = NULL;
91 static long max_grps = 0;
92 extern long FORCE_NO_HIDE;
93 extern long USEINTERNORM;
94 extern long INTER_DRAW;
95
96 extern float dists[];
97 extern long BH_MODE;
98 extern int iHighLight;
99
100 extern TextureContainer TexSpecialColor;
101
102 extern long TSU_TEST_NB;
103 extern long TSU_TEST_NB_LIGHT;
104
105 //#define USE_SOFTWARE_CLIPPING
106 #ifdef USE_SOFTWARE_CLIPPING
107 float SOFTNEARCLIPPZ=1.f;
108 #endif
109
110 /* Init bounding box */
Cedric_ResetBoundingBox(Entity * io)111 inline static void Cedric_ResetBoundingBox(Entity * io)
112 {
113 // resets 2D Bounding Box
114 BBOXMIN.y = BBOXMIN.x = 32000;
115 BBOXMAX.y = BBOXMAX.x = -32000;
116 // Resets 3D Bounding Box
117 ResetBBox3D(io);
118 }
119
120 extern float INVISIBILITY_OVERRIDE;
121 extern long EXTERNALVIEW;
Cedric_GetScale(float & scale,float & invisibility,Entity * io)122 static void Cedric_GetScale(float & scale, float & invisibility, Entity * io)
123 {
124 if (io)
125 {
126 invisibility = io->invisibility;
127
128 if (invisibility > 1.f) invisibility -= 1.f;
129
130 if ((io != entities.player()) && (invisibility > 0.f) && (!EXTERNALVIEW))
131 {
132 long num = ARX_SPELLS_GetSpellOn(io, SPELL_INVISIBILITY);
133
134 if (num >= 0)
135 {
136 if (player.Full_Skill_Intuition > spells[num].caster_level * 10)
137 {
138 invisibility -= (float)player.Full_Skill_Intuition * ( 1.0f / 100 ) + (float)spells[num].caster_level * ( 1.0f / 10 );
139
140 if (invisibility < 0.1f) invisibility = 0.1f;
141 else if (invisibility > 1.f) invisibility = 1.f;
142 }
143 }
144 }
145
146 // Scaling Value for this object (Movements will also be scaled)
147 scale = io->scale;
148 }
149 else
150 {
151 if (INVISIBILITY_OVERRIDE != 0.f)
152 {
153 invisibility = INVISIBILITY_OVERRIDE;
154
155 if (invisibility > 1.f) invisibility -= 1.f;
156 }
157 else
158 {
159 invisibility = 0.f;
160 }
161
162 scale = 1.f;
163 }
164 }
165
Cedric_GetTime(float & timm,Entity * io)166 static void Cedric_GetTime(float & timm, Entity * io) {
167
168 if(!io || !io->nb_lastanimvertex) {
169 timm = 0.f;
170 return;
171 }
172
173 timm = (arxtime.get_frame_time() - io->lastanimtime) + 0.0001f;
174
175 if(timm >= 300.f) {
176 timm = 0.f;
177 io->nb_lastanimvertex = 0;
178 } else {
179 timm *= ( 1.0f / 300 );
180 if(timm >= 1.f) {
181 timm = 0.f;
182 } else if(timm < 0.f) {
183 timm = 0.f;
184 }
185 }
186 }
187
188 /* Evaluate main entity translation */
Cedric_AnimCalcTranslation(Entity * io,ANIM_USE * animuse,float scale,Vec3f & ftr,bool update_movement)189 static void Cedric_AnimCalcTranslation(Entity * io, ANIM_USE * animuse, float scale,
190 Vec3f & ftr, bool update_movement) {
191
192 // Resets Frame Translate
193 ftr = Vec3f::ZERO;
194 Vec3f ftr2 = Vec3f::ZERO;
195
196
197 // Fill frame translate values with multi-layer translate informations...
198 for (int count = MAX_ANIM_LAYERS - 1; count >= 0; count--)
199 {
200 EERIE_ANIM * eanim;
201
202 if (!io)
203 {
204 count = -1;
205 }
206 else
207 {
208 animuse = &io->animlayer[count];
209 }
210
211 if (!animuse) continue;
212
213 if (!animuse->cur_anim) continue;
214
215 eanim = animuse->cur_anim->anims[animuse->altidx_cur];
216
217 if (!eanim) continue;
218
219 //Avoiding impossible cases
220 if (animuse->fr < 0)
221 {
222 animuse->fr = 0;
223 animuse->pour = 0.f;
224 }
225 else if (animuse->fr >= eanim->nb_key_frames - 1)
226 {
227 animuse->fr = eanim->nb_key_frames - 2;
228 animuse->pour = 1.f;
229 }
230 else if (animuse->pour > 1.f) animuse->pour = 1.f;
231 else if (animuse->pour < 0.f) animuse->pour = 0.f;
232
233
234 // FRAME TRANSLATE : Gives the Virtual pos of Main Object
235 if (((eanim->frames[animuse->fr].f_translate) && (!(animuse->flags & EA_STATICANIM))))
236 {
237 EERIE_FRAME * sFrame = &eanim->frames[animuse->fr];
238 EERIE_FRAME * eFrame = &eanim->frames[animuse->fr+1];
239
240 // Linear interpolation of object translation (MOVE)
241 ftr = sFrame->translate + (eFrame->translate - sFrame->translate) * animuse->pour;
242
243 if(io && update_movement) {
244
245 ftr *= scale;
246
247 float temp = radians(MAKEANGLE(180.f - io->angle.b));
248
249 if (io == entities.player()) temp = radians(MAKEANGLE(180.f - player.angle.b));
250
251 YRotatePoint(&ftr, &ftr2, (float)EEcos(temp), (float)EEsin(temp));
252
253 // stores Translations for a later use
254 io->move = ftr2;
255 }
256 }
257 }
258
259 if(io && io->animlayer[0].cur_anim && update_movement) {
260
261 // Use calculated value to notify the Movement engine of the translation to do
262 if(io->ioflags & IO_NPC) {
263 ftr = Vec3f::ZERO;
264 io->move -= io->lastmove;
265 } else if (io->gameFlags & GFLAG_ELEVATOR) {
266 // Must recover translations for NON-NPC IO
267 PushIO_ON_Top(io, io->move.y - io->lastmove.y);
268 }
269
270 io->lastmove = ftr2;
271 }
272 }
273
274
275 // Animate skeleton
Cedric_AnimateObject(Entity * io,EERIE_3DOBJ * eobj,ANIM_USE * animuse)276 static void Cedric_AnimateObject(Entity * io, EERIE_3DOBJ * eobj, ANIM_USE * animuse)
277 {
278 int j, l;
279 EERIE_C_DATA * obj = eobj->c_data;
280
281 for (long count = MAX_ANIM_LAYERS - 1; count >= 0; count--)
282 {
283 EERIE_QUAT t, temp;
284 Vec3f vect;
285 Vec3f scale;
286
287 if(!io) {
288 count = -1;
289 } else {
290 animuse = &io->animlayer[count];
291 }
292
293 if(!animuse) {
294 continue;
295 }
296
297 if(!animuse->cur_anim) {
298 continue;
299 }
300
301 EERIE_ANIM * eanim = animuse->cur_anim->anims[animuse->altidx_cur];
302
303 if (!eanim) continue;
304
305 if (animuse->fr < 0)
306 {
307 animuse->fr = 0;
308 animuse->pour = 0.f;
309 }
310 else if (animuse->fr >= eanim->nb_key_frames - 1)
311 {
312 animuse->fr = eanim->nb_key_frames - 2;
313 animuse->pour = 1.f;
314 }
315 else if (animuse->pour > 1.f) animuse->pour = 1.f;
316 else if (animuse->pour < 0.f) animuse->pour = 0.f;
317
318 // Now go for groups rotation/translation/scaling, And transform Linked objects by the way
319 l = min(eobj->nbgroups - 1, eanim->nb_groups - 1);
320
321 for (j = l; j >= 0; j--)
322 {
323 if (grps[j])
324 continue;
325
326 EERIE_GROUP * sGroup = &eanim->groups[j+(animuse->fr*eanim->nb_groups)];
327 EERIE_GROUP * eGroup = &eanim->groups[j+(animuse->fr*eanim->nb_groups)+eanim->nb_groups];
328
329 if (!eanim->voidgroups[j])
330 grps[j] = 1;
331
332 if (eanim->nb_key_frames != 1)
333 {
334 Quat_Slerp(&t, &sGroup->quat, &eGroup->quat, animuse->pour);
335 Quat_Copy(&temp, &obj->bones[j].quatinit);
336 Quat_Multiply(&obj->bones[j].quatinit, &temp, &t);
337
338 vect = sGroup->translate + (eGroup->translate - sGroup->translate) * animuse->pour;
339 obj->bones[j].transinit = vect + obj->bones[j].transinit_global;
340
341 scale = sGroup->zoom + (eGroup->zoom - sGroup->zoom) * animuse->pour;
342 if(BH_MODE && j == eobj->fastaccess.head_group) {
343 scale += Vec3f::ONE;
344 }
345
346 obj->bones[j].scaleinit = scale;
347 }
348 }
349 }
350 }
351
352
353
354 /* Apply transformations on all bones */
Cedric_ConcatenateTM(Entity * io,EERIE_C_DATA * obj,Anglef * angle,Vec3f * pos,Vec3f & ftr,float g_scale)355 static void Cedric_ConcatenateTM(Entity * io, EERIE_C_DATA * obj, Anglef * angle, Vec3f * pos, Vec3f & ftr, float g_scale)
356 {
357 int i;
358
359 if (!obj)
360 return;
361
362 for (i = 0; i != obj->nb_bones; i++)
363 {
364 EERIE_QUAT qt2;
365
366 if (obj->bones[i].father >= 0) // Child Bones
367 {
368 // Rotation
369 Quat_Multiply(&obj->bones[i].quatanim, &obj->bones[obj->bones[i].father].quatanim, &obj->bones[i].quatinit);
370
371 // Translation
372 obj->bones[i].transanim = obj->bones[i].transinit * obj->bones[obj->bones[i].father].scaleanim;
373 TransformVertexQuat(&obj->bones[obj->bones[i].father].quatanim, &obj->bones[i].transanim, &obj->bones[i].transanim);
374 obj->bones[i].transanim = obj->bones[obj->bones[i].father].transanim + obj->bones[i].transanim;
375
376 /* Scale */
377 obj->bones[i].scaleanim = (obj->bones[i].scaleinit + Vec3f::ONE) * obj->bones[obj->bones[i].father].scaleanim;
378
379 }
380 else // Root Bone
381 {
382 // Rotation
383 if ((io) && !(io->ioflags & IO_NPC))
384 {
385 // To correct invalid angle in Animated FIX/ITEMS
386 Anglef ang = *angle;
387 ang.a = (360 - ang.a);
388 ang.b = (ang.b);
389 ang.g = (ang.g);
390 EERIEMATRIX mat;
391 Vec3f vect(0, 0, 1);
392 Vec3f up(0, 1, 0);
393 VRotateY(&vect, ang.b);
394 VRotateX(&vect, ang.a);
395 VRotateZ(&vect, ang.g);
396 VRotateY(&up, ang.b);
397 VRotateX(&up, ang.a);
398 VRotateZ(&up, ang.g);
399 MatrixSetByVectors(&mat, &vect, &up);
400 QuatFromMatrix(qt2, mat);
401 Quat_Multiply(&obj->bones[i].quatanim, &qt2, &obj->bones[i].quatinit);
402 }
403 else
404 {
405 Anglef vt1 = Anglef(radians(angle->a), radians(angle->b), radians(angle->g));
406 QuatFromAngles(&qt2, &vt1);
407 Quat_Multiply(&obj->bones[i].quatanim, &qt2, &obj->bones[i].quatinit);
408 }
409
410 // Translation
411 Vec3f vt1 = obj->bones[i].transinit + ftr;
412 TransformVertexQuat(&qt2, &vt1, &obj->bones[i].transanim);
413 obj->bones[i].transanim *= g_scale;
414 obj->bones[i].transanim = *pos + obj->bones[i].transanim;
415
416 // Compute Global Object Scale AND Global Animation Scale
417 obj->bones[i].scaleanim = (obj->bones[i].scaleinit + Vec3f::ONE) * g_scale;
418 }
419 }
420 }
421
422 void EE_RT(TexturedVertex * in, Vec3f * out);
423 void EE_P(Vec3f * in, TexturedVertex * out);
424 void EE_P2(TexturedVertex * in, TexturedVertex * out);
425
426 /* Transform object vertices */
Cedric_TransformVerts(Entity * io,EERIE_3DOBJ * eobj,EERIE_C_DATA * obj,Vec3f * pos)427 int Cedric_TransformVerts(Entity * io, EERIE_3DOBJ * eobj, EERIE_C_DATA * obj,
428 Vec3f * pos) {
429 int v;
430
431 EERIE_3DPAD * inVert;
432 EERIE_VERTEX * outVert;
433
434 /* Transform & project all vertices */
435 for (long i = 0; i != obj->nb_bones; i++)
436 {
437 EERIEMATRIX matrix;
438
439 MatrixFromQuat(&matrix, &obj->bones[i].quatanim);
440 Vec3f vector = obj->bones[i].transanim;
441
442 // Apply Scale
443 matrix._11 *= obj->bones[i].scaleanim.x;
444 matrix._12 *= obj->bones[i].scaleanim.x;
445 matrix._13 *= obj->bones[i].scaleanim.x;
446
447 matrix._21 *= obj->bones[i].scaleanim.y;
448 matrix._22 *= obj->bones[i].scaleanim.y;
449 matrix._23 *= obj->bones[i].scaleanim.y;
450
451 matrix._31 *= obj->bones[i].scaleanim.z;
452 matrix._32 *= obj->bones[i].scaleanim.z;
453 matrix._33 *= obj->bones[i].scaleanim.z;
454
455 for(v = 0; v != obj->bones[i].nb_idxvertices; v++) {
456 inVert = &eobj->vertexlocal[obj->bones[i].idxvertices[v]];
457 outVert = &eobj->vertexlist3[obj->bones[i].idxvertices[v]];
458 TransformVertexMatrix(&matrix, inVert, &outVert->v);
459 outVert->v += vector;
460 outVert->vert.p = outVert->v;
461 }
462 }
463
464 if(eobj->cdata && eobj->sdata) {
465 for(size_t i = 0; i < eobj->vertexlist.size(); i++) {
466 eobj->vertexlist[i].vert.p = eobj->vertexlist3[i].v - *pos;
467 }
468 }
469
470 for (size_t i = 0; i < eobj->vertexlist.size(); i++)
471 {
472 outVert = &eobj->vertexlist3[i];
473 AddToBBox3D(io, &outVert->v);
474 EE_RT(&outVert->vert, &outVert->vworld);
475 EE_P(&outVert->vworld, &outVert->vert);
476
477 // Updates 2D Bounding Box
478 if (outVert->vert.rhw > 0.f)
479 {
480 BBOXMIN.x = min(BBOXMIN.x, outVert->vert.p.x);
481 BBOXMAX.x = max(BBOXMAX.x, outVert->vert.p.x);
482 BBOXMIN.y = min(BBOXMIN.y, outVert->vert.p.y);
483 BBOXMAX.y = max(BBOXMAX.y, outVert->vert.p.y);
484 }
485 }
486
487 if ((io)
488 && (io->ioflags & IO_NPC)
489 && (io->_npcdata->behavior & BEHAVIOUR_FIGHT)
490 && (distSqr(io->pos, player.pos) < square(240.f)))
491 return true;
492
493 if ((io != entities.player())
494 && (!EXTERNALVIEW)
495 && (!eobj->cdata)
496 && ((BBOXMIN.x >= DANAESIZX - 1)
497 || (BBOXMAX.x <= 1)
498 || (BBOXMIN.y >= DANAESIZY - 1)
499 || (BBOXMAX.y <= 1))
500 )
501 {
502 return false;
503 }
504
505 if (ARX_SCENE_PORTAL_ClipIO(io, pos))
506 return false;
507
508 return true;
509 }
510 extern Entity * DESTROYED_DURING_RENDERING;
511 long special_color_flag = 0;
512 Color3f special_color;
513 extern long TRAP_DETECT;
514 extern long TRAP_SECRET;
515 extern long FRAME_COUNT;
516
517 extern float GLOBAL_LIGHT_FACTOR;
518
519 /* Object dynamic lighting */
Cedric_ApplyLighting(EERIE_3DOBJ * eobj,EERIE_C_DATA * obj,Entity * io,Vec3f * pos)520 static bool Cedric_ApplyLighting(EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, Entity * io, Vec3f * pos) {
521
522 Color3f infra = Color3f::black;
523 int i, v, l;
524 Vec3f tv;
525 Vec3f vTLights[32]; /* Same as above but in bone space (for faster calculation) */
526
527
528
529 special_color_flag = 0;
530
531 if (io)
532 {
533 float poisonpercent = 0.f;
534 float trappercent = 0.f;
535 float secretpercent = 0.f;
536
537 if (io->ioflags & IO_NPC)
538 {
539 if (io->_npcdata->poisonned > 0.f)
540 {
541 poisonpercent = io->_npcdata->poisonned * ( 1.0f / 20 );
542
543 if (poisonpercent > 1.f) poisonpercent = 1.f;
544 }
545 }
546
547 if ((io->ioflags & IO_ITEM) && (io->poisonous > 0.f) && (io->poisonous_count != 0))
548 {
549 poisonpercent = (float)io->poisonous * ( 1.0f / 20 );
550
551 if (poisonpercent > 1.f) poisonpercent = 1.f;
552 }
553
554 if ((io->ioflags & IO_FIX) && (io->_fixdata->trapvalue > -1))
555 {
556 trappercent = (float)TRAP_DETECT - (float)io->_fixdata->trapvalue;
557
558 if (trappercent > 0.f)
559 {
560 trappercent = 0.6f + trappercent * ( 1.0f / 100 );
561
562 if (trappercent < 0.6f) trappercent = 0.6f;
563
564 if (trappercent > 1.f) trappercent = 1.f;
565 }
566 }
567
568 if ((io->ioflags & IO_FIX) && (io->secretvalue > -1))
569 {
570 secretpercent = (float)TRAP_SECRET - (float)io->secretvalue;
571
572 if (secretpercent > 0.f)
573 {
574 secretpercent = 0.6f + secretpercent * ( 1.0f / 100 );
575 if (secretpercent < 0.6f) secretpercent = 0.6f;
576 else if (secretpercent > 1.f) secretpercent = 1.f;
577 }
578 }
579
580 if (poisonpercent > 0.f)
581 {
582 special_color_flag = 1;
583 special_color.r = 0.f;
584 special_color.g = 1.f;
585 special_color.b = 0.f;
586 }
587
588 if (trappercent > 0.f)
589 {
590 special_color_flag = 1;
591 special_color.r = trappercent;
592 special_color.g = 1.f - trappercent;
593 special_color.b = 1.f - trappercent;
594 }
595
596 if (secretpercent > 0.f)
597 {
598 special_color_flag = 1;
599 special_color.r = 1.f - secretpercent;
600 special_color.g = 1.f - secretpercent;
601 special_color.b = secretpercent;
602 }
603
604 if (io->ioflags & IO_FREEZESCRIPT)
605 {
606 special_color_flag = 1;
607 special_color.r = 0.f;
608 special_color.g = 0.f;
609 special_color.b = 1.f;
610 }
611
612 if (io->sfx_flag & SFX_TYPE_YLSIDE_DEATH)
613 {
614 if (io->show == SHOW_FLAG_TELEPORTING)
615 {
616
617 float fTime = io->sfx_time + FrameDiff;
618 io->sfx_time = checked_range_cast<unsigned long>(fTime);
619
620 if (io->sfx_time >= (unsigned long)(arxtime))
621 io->sfx_time = (unsigned long)(arxtime);
622
623
624 }
625 else
626 {
627 special_color_flag = 1;
628 float elapsed = float(arxtime) - io->sfx_time;
629
630 if (elapsed > 0.f)
631 {
632 if (elapsed < 3000.f) // 5 seconds to red
633 {
634 float ratio = elapsed * ( 1.0f / 3000 );
635 special_color.r = 1.f;
636 special_color.g = 1.f - ratio;
637 special_color.b = 1.f - ratio;
638 AddRandomSmoke(io, 1);
639 }
640 else if (elapsed < 6000.f) // 5 seconds to White
641 {
642 float ratio = (elapsed - 3000.f) * ( 1.0f / 3000 );
643 special_color.r = ratio;
644 special_color_flag = 2;
645 AddRandomSmoke(io, 2);
646 }
647 else // SFX finish
648 {
649 special_color_flag = 0;
650
651 io->sfx_time = 0;
652
653 if (io->ioflags & IO_NPC)
654 {
655 MakePlayerAppearsFX(io);
656 AddRandomSmoke(io, 50);
657 Color3f rgb = io->_npcdata->blood_color.to<float>();
658 EERIE_SPHERE sp;
659 sp.origin = io->pos;
660 sp.radius = 200.f;
661 long count = 6;
662
663 while (count--)
664 {
665 SpawnGroundSplat(&sp, &rgb, rnd() * 30.f + 30.f, 1);
666 sp.origin.y -= rnd() * 150.f;
667
668 ARX_PARTICLES_Spawn_Splat(sp.origin, 200.f, io->_npcdata->blood_color);
669
670 sp.origin.x = io->pos.x + rnd() * 200.f - 100.f;
671 sp.origin.y = io->pos.y + rnd() * 20.f - 10.f;
672 sp.origin.z = io->pos.z + rnd() * 200.f - 100.f;
673 sp.radius = rnd() * 100.f + 100.f;
674 }
675
676 long nn = GetFreeDynLight();
677
678 if (nn >= 0)
679 {
680 DynLight[nn].exist = 1;
681 DynLight[nn].intensity = 0.7f + 2.f * rnd();
682 DynLight[nn].fallend = 600.f;
683 DynLight[nn].fallstart = 400.f;
684 DynLight[nn].rgb.r = 1.0f;
685 DynLight[nn].rgb.g = 0.8f;
686 DynLight[nn].rgb.b = .0f;
687 DynLight[nn].pos.x = io->pos.x;
688 DynLight[nn].pos.y = io->pos.y - 80.f;
689 DynLight[nn].pos.z = io->pos.z;
690 DynLight[nn].duration = 600;
691 }
692
693 if (io->sfx_flag & SFX_TYPE_INCINERATE)
694 {
695 io->sfx_flag &= ~SFX_TYPE_INCINERATE;
696 io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH;
697 long num = ARX_SPELLS_GetSpellOn(io, SPELL_INCINERATE);
698
699 if (num < 0)
700 num = ARX_SPELLS_GetSpellOn(io, SPELL_MASS_INCINERATE);
701
702 if (num >= 0)
703 {
704 spells[num].tolive = 0;
705 float damages = 20 * spells[num].caster_level;
706 damages = ARX_SPELLS_ApplyFireProtection(io, damages);
707
708 if (ValidIONum(spells[num].caster))
709 ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &entities[spells[num].caster]->pos);
710 else
711 ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &io->pos);
712
713 ARX_SOUND_PlaySFX(SND_SPELL_FIRE_HIT, &io->pos);
714 }
715 }
716 else
717 {
718 io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH;
719 ARX_INTERACTIVE_DestroyIO(io);
720 DESTROYED_DURING_RENDERING = io;
721 return false;
722 }
723 }
724 }
725 }
726 }
727 }
728 }
729
730 if(eobj->drawflags & DRAWFLAG_HIGHLIGHT) {
731 special_color_flag = 4;
732 special_color = Color3f::gray(float(iHighLight));
733 }
734
735 if(FRAME_COUNT > 0) {
736 return true;
737 }
738
739 if(Project.improve) {
740 infra = (io) ? io->infracolor : Color3f(0.6f, 0.f, 1.f);
741 }
742
743 /* Get nearest lights */
744 tv = *pos;
745
746 if ((io) && (io->obj->fastaccess.view_attach >= 0) && (io->obj->fastaccess.head_group_origin != -1))
747 {
748 tv.y = io->obj->vertexlist3[io->obj->fastaccess.head_group_origin].v.y + 10;
749 }
750 else tv.y -= 90.f;
751
752 llightsInit();
753
754 for (i = 0; i < TOTIOPDL; i++)
755 {
756 if (IO_PDL[i]->fallend + 500.f < 0)
757 continue;
758
759 Insertllight(IO_PDL[i], dist(IO_PDL[i]->pos, tv));
760 }
761
762 for (i = 0; i < TOTPDL; i++)
763 {
764 if (PDL[i]->fallend + 500.f < 0)
765 continue;
766
767 Insertllight(PDL[i], dist(PDL[i]->pos, tv));
768 }
769
770 if (!USEINTERNORM)
771 {
772 /* Apply light on all vertices */
773 for (i = 0; i != obj->nb_bones; i++)
774 {
775 /* Get light value for each vertex */
776 for (v = 0; v != obj->bones[i].nb_idxvertices; v++)
777 {
778 Vec3f * posVert;
779 float r, g, b;
780 long ir, ig, ib;
781
782 if(io) {
783 posVert = &io->obj->vertexlist3[obj->bones[i].idxvertices[v]].v;
784 } else {
785 posVert = &eobj->vertexlist3[obj->bones[i].idxvertices[v]].v;
786 }
787
788 /* Ambient light */
789 if ((io) && (io->ioflags & (IO_NPC | IO_ITEM)))
790 {
791 r = g = b = NPC_ITEMS_AMBIENT_VALUE_255;
792 }
793 else
794 {
795 r = ACTIVEBKG->ambient255.r;
796 g = ACTIVEBKG->ambient255.g;
797 b = ACTIVEBKG->ambient255.b;
798 }
799
800 /* Dynamic lights */
801 for (l = 0 ; l != MAX_LLIGHTS; l++)
802 {
803 EERIE_LIGHT * Cur_llights = llights[l];
804
805 if (Cur_llights)
806 {
807 // tsu
808 if (Cur_llights->fallend < 0)
809 {
810 TSU_TEST_NB_LIGHT ++;
811 continue;
812 }
813
814 float cosangle;
815 float distance = fdist(Cur_llights->pos, *posVert);
816
817 /* Evaluate its intensity depending on the distance Light<->Object */
818 if (distance <= Cur_llights->fallstart)
819 cosangle = Cur_llights->intensity * GLOBAL_LIGHT_FACTOR;
820 else
821 {
822 float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul);
823
824 if (p <= 0.f)
825 cosangle = 0.f;
826 else
827 cosangle = p * Cur_llights->precalc;
828 }
829
830 r += Cur_llights->rgb255.r * cosangle;
831 g += Cur_llights->rgb255.g * cosangle;
832 b += Cur_llights->rgb255.b * cosangle;
833 }
834 else
835 break;
836 }
837
838 if (special_color_flag)
839 {
840 if (special_color_flag & 1)
841 {
842 r *= special_color.r;
843 g *= special_color.g;
844 b *= special_color.b;
845 }
846 else if (special_color_flag & 2)
847 {
848 r = 1.f;
849 g = 0.f;
850 b = 0.f;
851 }
852 else if (special_color_flag & 4) // HIGHLIGHT
853 {
854 r += special_color.r;
855 g += special_color.g;
856 b += special_color.b;
857 }
858 }
859
860 /* PACK color */
861 ir = clipByte255(r);
862 ig = clipByte255(g);
863 ib = clipByte255(b);
864
865 eobj->vertexlist3[obj->bones[i].idxvertices[v]].vert.color = (0xFF000000L | ((ir) << 16) | ((ig) << 8) | (ib));
866 }
867 }
868 }
869
870 else
871 {
872 /* Apply light on all vertices */
873 for (i = 0; i != obj->nb_bones; i++)
874 {
875 EERIE_QUAT qt1;
876
877 EERIEMATRIX matrix;//,omatrix;
878 Quat_Copy(&qt1, &obj->bones[i].quatanim);
879 Quat_Reverse(&qt1);
880 MatrixFromQuat(&matrix, &qt1);
881 // FMatrixInvert(matrix,omatrix);
882
883 /* Get light value for each vertex */
884 for (v = 0; v != obj->bones[i].nb_idxvertices; v++)
885 {
886 EERIE_3DPAD * inVert;
887
888 float r, g, b;
889 long ir, ig, ib;
890
891 inVert = (EERIE_3DPAD *)&eobj->vertexlist[obj->bones[i].idxvertices[v]].norm;
892
893 /* Ambient light */
894 if ((io) && (io->ioflags & (IO_NPC | IO_ITEM)))
895 {
896 r = g = b = NPC_ITEMS_AMBIENT_VALUE_255;
897 }
898 else
899 {
900 r = ACTIVEBKG->ambient255.r;
901 g = ACTIVEBKG->ambient255.g;
902 b = ACTIVEBKG->ambient255.b;
903 }
904
905
906 /* Dynamic lights */
907 for (l = 0 ; l != MAX_LLIGHTS; l++)
908 {
909 EERIE_LIGHT * Cur_llights = llights[l];
910
911 if (Cur_llights)
912 {
913 Vec3f & Cur_vTLights = vTLights[l];
914 Vec3f tl;
915 tl = (Cur_llights->pos - eobj->vertexlist3[obj->bones[i].idxvertices[v]].v);
916 float dista = ffsqrt(tl.lengthSqr());
917
918 if(dista < Cur_llights->fallend) {
919
920 tl *= 1.f / dista;
921
922 VectorMatrixMultiply(&Cur_vTLights, &tl, &matrix);
923
924 float cosangle = dot(*inVert, Cur_vTLights);
925
926 /* If light visible */
927 if (cosangle > 0.0f)
928 {
929 /* Evaluate its intensity depending on the distance Light<->Object */
930 if (dista <= Cur_llights->fallstart)
931 cosangle *= Cur_llights->precalc;
932 else
933 {
934 float p = ((Cur_llights->fallend - dista) * Cur_llights->falldiffmul);
935
936 if (p <= 0.f)
937 cosangle = 0.f;
938 else
939 cosangle *= p * Cur_llights->precalc;
940 }
941
942 r += Cur_llights->rgb255.r * cosangle;
943 g += Cur_llights->rgb255.g * cosangle;
944 b += Cur_llights->rgb255.b * cosangle;
945 }
946 }
947 }
948 else
949 break;
950 }
951
952 /* Fake adjust */
953 if (Project.improve)
954 {
955 r *= infra.r;
956 g *= infra.g;
957 b *= infra.b;
958 }
959
960 if (special_color_flag)
961 {
962 if (special_color_flag & 1)
963 {
964 r *= special_color.r;
965 g *= special_color.g;
966 b *= special_color.b;
967 }
968 else if (special_color_flag & 2)
969 {
970 r = 1.f;
971 g = 0.f;
972 b = 0.f;
973 }
974 else if (special_color_flag & 4) // HIGHLIGHT
975 {
976 r += special_color.r;
977 g += special_color.g;
978 b += special_color.b;
979 }
980 }
981
982 /* PACK color */
983 ir = clipByte255(r);
984 ig = clipByte255(g);
985 ib = clipByte255(b);
986
987 eobj->vertexlist3[obj->bones[i].idxvertices[v]].vert.color = (0xFF000000L | ((ir) << 16) | ((ig) << 8) | (ib));
988 }
989 }
990 }
991
992 return true;
993 }
994
Cedric_PrepareHalo(EERIE_3DOBJ * eobj,EERIE_C_DATA * obj)995 void Cedric_PrepareHalo(EERIE_3DOBJ * eobj, EERIE_C_DATA * obj) {
996 Vec3f cam_vector, t_vector;
997 cam_vector.x = -EEsin(radians(ACTIVECAM->angle.b)) * EEcos(radians(ACTIVECAM->angle.a));
998 cam_vector.y = EEsin(radians(ACTIVECAM->angle.a));
999 cam_vector.z = EEcos(radians(ACTIVECAM->angle.b)) * EEcos(radians(ACTIVECAM->angle.a));
1000
1001 /* Apply light on all vertices */
1002 for (long i = 0; i != obj->nb_bones; i++)
1003 {
1004 EERIE_QUAT qt1;
1005 Quat_Copy(&qt1, &obj->bones[i].quatanim);
1006 TransformInverseVertexQuat(&qt1, &cam_vector, &t_vector);
1007
1008 /* Get light value for each vertex */
1009 for (long v = 0; v != obj->bones[i].nb_idxvertices; v++)
1010 {
1011 EERIE_3DPAD * inVert;
1012 //inVert = &eobj->normallocal[obj->bones[i].idxvertices[v]];
1013 inVert = (EERIE_3DPAD *)&eobj->vertexlist[obj->bones[i].idxvertices[v]].norm;
1014 /* Get cos angle between light and vertex norm */
1015 eobj->vertexlist3[obj->bones[i].idxvertices[v]].norm.z =
1016 (inVert->x * t_vector.x + inVert->y * t_vector.y + inVert->z * t_vector.z);
1017
1018 }
1019 }
1020 }
1021
1022 #ifdef USE_SOFTWARE_CLIPPING
1023 //-----------------------------------------------------------------------------
ARX_ClippZ(TexturedVertex * _pA,TexturedVertex * _pB,EERIE_VERTEX * _pVertexA,EERIE_VERTEX * _pVertexB,TexturedVertex * _pOut)1024 void ARX_ClippZ(TexturedVertex * _pA, TexturedVertex * _pB, EERIE_VERTEX * _pVertexA, EERIE_VERTEX * _pVertexB, TexturedVertex * _pOut)
1025 {
1026 Vec3f e3dTemp;
1027
1028 float fDenom = (SOFTNEARCLIPPZ - _pVertexB->vworld.z) / (_pVertexA->vworld.z - _pVertexB->vworld.z);
1029 e3dTemp.x = (_pVertexA->vworld.x - _pVertexB->vworld.x) * fDenom + _pVertexB->vworld.x;
1030 e3dTemp.y = (_pVertexA->vworld.y - _pVertexB->vworld.y) * fDenom + _pVertexB->vworld.y;
1031 e3dTemp.z = SOFTNEARCLIPPZ ;
1032
1033 float fRA, fGA, fBA;
1034 float fRB, fGB, fBB;
1035
1036 fRA = checked_range_cast<float>((_pA->color >> 16) & 255);
1037 fGA = checked_range_cast<float>((_pA->color >> 8) & 255);
1038 fBA = checked_range_cast<float>(_pA->color & 255);
1039 fRB = checked_range_cast<float>((_pB->color >> 16) & 255);
1040 fGB = checked_range_cast<float>((_pB->color >> 8) & 255);
1041 fBB = checked_range_cast<float>(_pB->color & 255);
1042
1043 float fRC, fGC, fBC;
1044 fRC = (fRA - fRB) * fDenom + fRB;
1045 fGC = (fGA - fGB) * fDenom + fGB;
1046 fBC = (fBA - fBB) * fDenom + fBB;
1047
1048 _pOut->color = (((int)fRC) << 16) | (((int)fGC) << 8) | ((int)fBC);
1049 _pOut->uv = (_pA->uv - _pB->uv) * fDenom + _pB->uv;
1050
1051 EE_P(&e3dTemp, _pOut);
1052 }
1053
1054 //-----------------------------------------------------------------------------
1055 void ARX_DrawPrimitive_ClippZ(TexturedVertex * _pVertexA, TexturedVertex * _pVertexB, TexturedVertex * _pOut, float _fAdd = 0.f);
ARX_DrawPrimitive_ClippZ(TexturedVertex * _pVertexA,TexturedVertex * _pVertexB,TexturedVertex * _pOut,float _fAdd)1056 void ARX_DrawPrimitive_ClippZ(TexturedVertex * _pVertexA, TexturedVertex * _pVertexB, TexturedVertex * _pOut, float _fAdd)
1057 {
1058 Vec3f e3dTemp;
1059 float fDenom = ((SOFTNEARCLIPPZ + _fAdd) - _pVertexB->p.z) / (_pVertexA->p.z - _pVertexB->p.z);
1060 e3dTemp.x = (_pVertexA->p.x - _pVertexB->p.x) * fDenom + _pVertexB->p.x;
1061 e3dTemp.y = (_pVertexA->p.y - _pVertexB->p.y) * fDenom + _pVertexB->p.y;
1062 e3dTemp.z = SOFTNEARCLIPPZ + _fAdd;
1063
1064 float fRA, fGA, fBA;
1065 float fRB, fGB, fBB;
1066
1067 fRA = checked_range_cast<float>((_pVertexA->color >> 16) & 255);
1068 fGA = checked_range_cast<float>((_pVertexA->color >> 8) & 255);
1069 fBA = checked_range_cast<float>(_pVertexA->color & 255);
1070 fRB = checked_range_cast<float>((_pVertexB->color >> 16) & 255);
1071 fGB = checked_range_cast<float>((_pVertexB->color >> 8) & 255);
1072 fBB = checked_range_cast<float>(_pVertexB->color & 255);
1073
1074 float fRC, fGC, fBC;
1075 fRC = (fRA - fRB) * fDenom + fRB;
1076 fGC = (fGA - fGB) * fDenom + fGB;
1077 fBC = (fBA - fBB) * fDenom + fBB;
1078
1079 _pOut->color = (((int) fRC) << 16) | (((int)fGC) << 8) | ((int) fBC);
1080 _pOut->uv = (_pVertexA->uv - _pVertexB->uv) * fDenom + _pVertexB->uv;
1081
1082 EE_P(&e3dTemp, _pOut);
1083 }
1084 #endif
1085
1086 //-----------------------------------------------------------------------------
GetNewVertexList(EERIE_FACE * _pFace,float _fInvisibility,TextureContainer * _pTex)1087 TexturedVertex * GetNewVertexList(EERIE_FACE * _pFace, float _fInvisibility, TextureContainer * _pTex) {
1088
1089 if(!(_pFace->facetype & POLY_TRANS) && !(_fInvisibility > 0.f)) {
1090 return PushVertexInTableCull(_pTex);
1091 }
1092
1093 float fTransp;
1094
1095 if(_fInvisibility > 0.f) {
1096 fTransp = 2.f - _fInvisibility;
1097 } else {
1098 fTransp = _pFace->transval;
1099 }
1100
1101 if(fTransp >= 2.f) { //MULTIPLICATIVE
1102 return PushVertexInTableCull_TMultiplicative(_pTex);
1103 } else if(fTransp >= 1.f) { //ADDITIVE
1104 return PushVertexInTableCull_TAdditive(_pTex);
1105 } else if(fTransp > 0.f) { //NORMAL TRANS
1106 return PushVertexInTableCull_TNormalTrans(_pTex);
1107 } else { //SUBTRACTIVE
1108 return PushVertexInTableCull_TSubstractive(_pTex);
1109 }
1110 }
1111
1112 #ifdef USE_SOFTWARE_CLIPPING
1113
ARX_SoftClippZ(EERIE_VERTEX * _pVertex1,EERIE_VERTEX * _pVertex2,EERIE_VERTEX * _pVertex3,TexturedVertex ** _ptV,EERIE_FACE * _pFace,float _fInvibility,TextureContainer * _pTex,bool _bZMapp,EERIE_3DOBJ * _pObj,int _iNumFace,long * _pInd,Entity * _pioInteractive,bool _bNPC,long _lSpecialColorFlag,Color3f * _pRGB)1114 int ARX_SoftClippZ(EERIE_VERTEX * _pVertex1, EERIE_VERTEX * _pVertex2, EERIE_VERTEX * _pVertex3, TexturedVertex ** _ptV, EERIE_FACE * _pFace, float _fInvibility, TextureContainer * _pTex, bool _bZMapp, EERIE_3DOBJ * _pObj, int _iNumFace, long * _pInd, Entity * _pioInteractive, bool _bNPC, long _lSpecialColorFlag, Color3f * _pRGB) {
1115
1116 int iPointAdd = 3;
1117 int iClipp = 0;
1118
1119 if ((_pVertex1->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 1;
1120
1121 if ((_pVertex2->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 2;
1122
1123 if ((_pVertex3->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 4;
1124
1125 TexturedVertex ClippZ1, ClippZ2;
1126 TexturedVertex * pPointAdd = NULL;
1127 TexturedVertex * ptV = *_ptV;
1128
1129 switch (iClipp)
1130 {
1131 case 1: //pt1 outside
1132 ARX_ClippZ(&ptV[0], &ptV[1], _pVertex1, _pVertex2, &ClippZ1);
1133 ARX_ClippZ(&ptV[0], &ptV[2], _pVertex1, _pVertex3, &ClippZ2);
1134 pPointAdd = GetNewVertexList(_pFace,
1135 _fInvibility,
1136 _pTex);
1137 ptV = pPointAdd - 3;
1138
1139 if (pPointAdd)
1140 {
1141 pPointAdd[0] = ClippZ1;
1142 pPointAdd[1] = ptV[1];
1143 pPointAdd[2] = ClippZ2;
1144 }
1145
1146 ptV[0] = ClippZ2;
1147 iPointAdd = 6;
1148 break;
1149 case 2: //pt2 outside
1150 ARX_ClippZ(&ptV[1], &ptV[2], _pVertex2, _pVertex3, &ClippZ1);
1151 ARX_ClippZ(&ptV[1], &ptV[0], _pVertex2, _pVertex1, &ClippZ2);
1152 pPointAdd = GetNewVertexList(_pFace,
1153 _fInvibility,
1154 _pTex);
1155 ptV = pPointAdd - 3;
1156
1157 if (pPointAdd)
1158 {
1159 pPointAdd[0] = ptV[2];
1160 pPointAdd[1] = ClippZ1;
1161 pPointAdd[2] = ClippZ2;
1162 }
1163
1164 ptV[1] = ClippZ2;
1165 iPointAdd = 6;
1166 break;
1167 case 4: //pt3 outside
1168 ARX_ClippZ(&ptV[2], &ptV[0], _pVertex3, _pVertex1, &ClippZ1);
1169 ARX_ClippZ(&ptV[2], &ptV[1], _pVertex3, _pVertex2, &ClippZ2);
1170 pPointAdd = GetNewVertexList(_pFace,
1171 _fInvibility,
1172 _pTex);
1173 ptV = pPointAdd - 3;
1174
1175 if (pPointAdd)
1176 {
1177 pPointAdd[0] = ptV[0];
1178 pPointAdd[1] = ClippZ2;
1179 pPointAdd[2] = ClippZ1;
1180 }
1181
1182 ptV[2] = ClippZ2;
1183 iPointAdd = 6;
1184 break;
1185 case 3: //pt1_2 outside
1186 ARX_ClippZ(&ptV[0], &ptV[2], _pVertex1, _pVertex3, &ClippZ1);
1187 ARX_ClippZ(&ptV[1], &ptV[2], _pVertex2, _pVertex3, &ClippZ2);
1188 ptV[0] = ClippZ1;
1189 ptV[1] = ClippZ2;
1190 break;
1191 case 5: //pt1_3 outside
1192 ARX_ClippZ(&ptV[0], &ptV[1], _pVertex1, _pVertex2, &ClippZ1);
1193 ARX_ClippZ(&ptV[2], &ptV[1], _pVertex3, _pVertex2, &ClippZ2);
1194 ptV[0] = ClippZ1;
1195 ptV[2] = ClippZ2;
1196 break;
1197 case 6: //pt2_3 outside
1198 ARX_ClippZ(&ptV[2], &ptV[0], _pVertex3, _pVertex1, &ClippZ1);
1199 ARX_ClippZ(&ptV[1], &ptV[0], _pVertex2, _pVertex1, &ClippZ2);
1200 ptV[1] = ClippZ1;
1201 ptV[2] = ClippZ2;
1202 break;
1203 case 7:
1204 return 0;
1205 }
1206
1207 if (pPointAdd)
1208 {
1209 *_ptV = ptV;
1210
1211 if (_bZMapp)
1212 {
1213 CalculateInterZMapp(_pObj, _iNumFace, _pInd, _pTex, pPointAdd);
1214 }
1215 }
1216
1217 return iPointAdd;
1218 }
1219 #endif
1220
1221 extern long IsInGroup(EERIE_3DOBJ * obj, long vert, long tw);
1222
ARX_DrawPrimitive(TexturedVertex * _pVertex1,TexturedVertex * _pVertex2,TexturedVertex * _pVertex3,float _fAddZ)1223 void ARX_DrawPrimitive(TexturedVertex * _pVertex1, TexturedVertex * _pVertex2, TexturedVertex * _pVertex3, float _fAddZ) {
1224
1225 #ifdef USE_SOFTWARE_CLIPPING
1226 int iClipp = 0;
1227
1228 if (_pVertex1->p.z < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 1;
1229
1230 if (_pVertex2->p.z < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 2;
1231
1232 if (_pVertex3->p.z < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 4;
1233
1234 TexturedVertex ClippZ1, ClippZ2;
1235 TexturedVertex pPointAdd[6];
1236 int iNbTotVertex = 3;
1237
1238 switch (iClipp)
1239 {
1240 case 0: {
1241 EE_P(&_pVertex1->p, &pPointAdd[0]);
1242 EE_P(&_pVertex2->p, &pPointAdd[1]);
1243 EE_P(&_pVertex3->p, &pPointAdd[2]);
1244 pPointAdd[0].color = _pVertex1->color;
1245 pPointAdd[0].specular = _pVertex1->specular;
1246 pPointAdd[0].uv = _pVertex1->uv;
1247 pPointAdd[1].specular = _pVertex2->specular;
1248 pPointAdd[1].uv = _pVertex2->uv;
1249 pPointAdd[2].color = _pVertex3->color;
1250 pPointAdd[2].specular = _pVertex3->specular;
1251 pPointAdd[2].uv = _pVertex3->uv;
1252 break;
1253 }
1254 case 1: //pt1 outside
1255 ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex2, &ClippZ1, _fAddZ);
1256 ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex3, &ClippZ2, _fAddZ);
1257 pPointAdd[0] = ClippZ2;
1258 pPointAdd[1] = *_pVertex2;
1259 EE_P2(&pPointAdd[1], &pPointAdd[1]);
1260 pPointAdd[2] = *_pVertex3;
1261 EE_P2(&pPointAdd[2], &pPointAdd[2]);
1262 pPointAdd[3] = ClippZ1;
1263 pPointAdd[4] = pPointAdd[1];
1264 pPointAdd[5] = ClippZ2;
1265 iNbTotVertex = 6;
1266 break;
1267 case 2: //pt2 outside
1268 ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex3, &ClippZ1, _fAddZ);
1269 ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex1, &ClippZ2, _fAddZ);
1270 pPointAdd[0] = *_pVertex1;
1271 EE_P2(&pPointAdd[0], &pPointAdd[0]);
1272 pPointAdd[1] = ClippZ2;
1273 pPointAdd[2] = *_pVertex3;
1274 EE_P2(&pPointAdd[2], &pPointAdd[2]);
1275 pPointAdd[3] = pPointAdd[2];
1276 pPointAdd[4] = ClippZ1;
1277 pPointAdd[5] = ClippZ2;
1278 iNbTotVertex = 6;
1279 break;
1280 case 4: //pt3 outside
1281 ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex1, &ClippZ1, _fAddZ);
1282 ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex2, &ClippZ2, _fAddZ);
1283 pPointAdd[0] = *_pVertex1;
1284 EE_P2(&pPointAdd[0], &pPointAdd[0]);
1285 pPointAdd[1] = *_pVertex2;
1286 EE_P2(&pPointAdd[1], &pPointAdd[1]);
1287 pPointAdd[2] = ClippZ2;
1288 pPointAdd[3] = pPointAdd[0];
1289 pPointAdd[4] = ClippZ2;
1290 pPointAdd[5] = ClippZ1;
1291 iNbTotVertex = 6;
1292 break;
1293 case 3: //pt1_2 outside
1294 ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex3, &ClippZ1, _fAddZ);
1295 ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex3, &ClippZ2, _fAddZ);
1296 pPointAdd[0] = ClippZ1;
1297 pPointAdd[1] = ClippZ2;
1298 pPointAdd[2] = *_pVertex3;
1299 EE_P2(&pPointAdd[2], &pPointAdd[2]);
1300 break;
1301 case 5: //pt1_3 outside
1302 ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex2, &ClippZ1, _fAddZ);
1303 ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex2, &ClippZ2, _fAddZ);
1304 pPointAdd[0] = ClippZ1;
1305 pPointAdd[1] = *_pVertex2;
1306 EE_P2(&pPointAdd[1], &pPointAdd[1]);
1307 pPointAdd[2] = ClippZ2;
1308 break;
1309 case 6: //pt2_3 outside
1310 ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex1, &ClippZ1, _fAddZ);
1311 ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex1, &ClippZ2, _fAddZ);
1312 pPointAdd[0] = *_pVertex1;
1313 EE_P2(&pPointAdd[0], &pPointAdd[0]);
1314 pPointAdd[1] = ClippZ1;
1315 pPointAdd[2] = ClippZ2;
1316 break;
1317 case 7:
1318 return;
1319 }
1320 #else
1321
1322 ARX_UNUSED(_fAddZ);
1323
1324 TexturedVertex pPointAdd[3];
1325 EE_P(&_pVertex1->p, &pPointAdd[0]);
1326 EE_P(&_pVertex2->p, &pPointAdd[1]);
1327 EE_P(&_pVertex3->p, &pPointAdd[2]);
1328 pPointAdd[0].color = _pVertex1->color;
1329 pPointAdd[0].specular = _pVertex1->specular;
1330 pPointAdd[0].uv = _pVertex1->uv;
1331 pPointAdd[1].color = _pVertex2->color;
1332 pPointAdd[1].specular = _pVertex2->specular;
1333 pPointAdd[1].uv = _pVertex2->uv;
1334 pPointAdd[2].color = _pVertex3->color;
1335 pPointAdd[2].specular = _pVertex3->specular;
1336 pPointAdd[2].uv = _pVertex3->uv;
1337 #endif
1338
1339 EERIEDRAWPRIM(Renderer::TriangleList, pPointAdd);
1340 }
1341
1342 long FORCE_FRONT_DRAW = 0;
1343
1344 //-----------------------------------------------------------------------------
1345 extern long IN_BOOK_DRAW;
1346
1347 /* Render object */
Cedric_RenderObject(EERIE_3DOBJ * eobj,EERIE_C_DATA * obj,Entity * io,Vec3f * pos,Vec3f & ftr,float invisibility)1348 static void Cedric_RenderObject(EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, Entity * io, Vec3f * pos, Vec3f & ftr, float invisibility) {
1349
1350 float MAX_ZEDE = 0.f;
1351
1352 // Sets IO BBox to calculated BBox :)
1353 if (io)
1354 {
1355 io->bbox1.x = (short) BBOXMIN.x;
1356 io->bbox2.x = (short) BBOXMAX.x;
1357 io->bbox1.y = (short) BBOXMIN.y;
1358 io->bbox2.y = (short) BBOXMAX.y;
1359 }
1360
1361 if (invisibility == 1.f)
1362 return;
1363
1364 float ddist = 0.f;
1365 long need_halo;
1366
1367 need_halo = 0;
1368
1369 Entity * hio_helmet = NULL;
1370 Entity * hio_armor = NULL;
1371 Entity * hio_leggings = NULL;
1372 Entity * hio_player = NULL;
1373 Entity * use_io = io;
1374
1375 if ((!io)
1376 && (IN_BOOK_DRAW)
1377 && (eobj == entities.player()->obj))
1378 use_io = entities.player();
1379
1380 if (use_io)
1381 {
1382 if (use_io == entities.player())
1383 {
1384 if ((player.equiped[EQUIP_SLOT_HELMET] != 0)
1385 && ValidIONum(player.equiped[EQUIP_SLOT_HELMET]))
1386 {
1387 Entity * tio = entities[player.equiped[EQUIP_SLOT_HELMET]];
1388
1389 if (tio->halo.flags & HALO_ACTIVE)
1390 hio_helmet = tio;
1391 }
1392
1393 if ((player.equiped[EQUIP_SLOT_ARMOR] != 0)
1394 && ValidIONum(player.equiped[EQUIP_SLOT_ARMOR]))
1395 {
1396 Entity * tio = entities[player.equiped[EQUIP_SLOT_ARMOR]];
1397
1398 if (tio->halo.flags & HALO_ACTIVE)
1399 hio_armor = tio;
1400 }
1401
1402 if ((player.equiped[EQUIP_SLOT_LEGGINGS] != 0)
1403 && ValidIONum(player.equiped[EQUIP_SLOT_LEGGINGS]))
1404 {
1405 Entity * tio = entities[player.equiped[EQUIP_SLOT_LEGGINGS]];
1406
1407 if (tio->halo.flags & HALO_ACTIVE)
1408 hio_leggings = tio;
1409 }
1410
1411 if (use_io->halo.flags & HALO_ACTIVE)
1412 hio_player = use_io;
1413 }
1414
1415 if (hio_player
1416 || hio_armor
1417 || hio_leggings
1418 || hio_helmet
1419 || (use_io->halo.flags & HALO_ACTIVE))
1420 {
1421
1422 float mdist = ACTIVECAM->cdepth * ( 1.0f / 2 );
1423
1424 ddist = mdist - fdist(*pos + ftr, ACTIVECAM->pos);
1425
1426 ddist = (ddist / mdist); //*0.1f;
1427 ddist *= ddist * ddist * ddist * ddist * ddist;
1428
1429 if (ddist <= 0.25f) ddist = 0.25f;
1430
1431 else if (ddist > 0.9f) ddist = 0.9f;
1432
1433 Cedric_PrepareHalo(eobj, obj);
1434 need_halo = 1;
1435 MAX_ZEDE = 0.f;
1436
1437 for (size_t i = 0 ; i < eobj->vertexlist.size() ; i++)
1438 {
1439 if (eobj->vertexlist3[i].vert.rhw > 0.f)
1440 MAX_ZEDE = max(eobj->vertexlist3[i].vert.p.z, MAX_ZEDE);
1441 }
1442
1443 }
1444 }
1445
1446 {
1447 for (size_t i = 0 ; i < eobj->facelist.size() ; i++)
1448 {
1449 TexturedVertex * tv = NULL;
1450
1451
1452 EERIE_FACE * eface;
1453 long paf[3];
1454
1455 eface = &eobj->facelist[i];
1456
1457 if ((eface->facetype & POLY_HIDE) && (!FORCE_NO_HIDE))
1458 continue;
1459
1460 //CULL3D
1461 Vec3f nrm = eobj->vertexlist3[eface->vid[0]].v - ACTIVECAM->pos;
1462
1463 if(!(eface->facetype & POLY_DOUBLESIDED)) {
1464 Vec3f normV10;
1465 Vec3f normV20;
1466 normV10 = eobj->vertexlist3[eface->vid[1]].v - eobj->vertexlist3[eface->vid[0]].v;
1467 normV20 = eobj->vertexlist3[eface->vid[2]].v - eobj->vertexlist3[eface->vid[0]].v;
1468 Vec3f normFace;
1469 normFace.x = (normV10.y * normV20.z) - (normV10.z * normV20.y);
1470 normFace.y = (normV10.z * normV20.x) - (normV10.x * normV20.z);
1471 normFace.z = (normV10.x * normV20.y) - (normV10.y * normV20.x);
1472
1473 if ((dot(normFace , nrm) > 0.f)) continue;
1474 }
1475
1476 TextureContainer * pTex;
1477
1478 if(eobj->facelist[i].texid < 0)
1479 continue;
1480
1481 pTex = eobj->texturecontainer[eobj->facelist[i].texid];
1482 if(!pTex)
1483 continue;
1484
1485 float fTransp = 0;
1486
1487 if((eobj->facelist[i].facetype & POLY_TRANS) || invisibility > 0.f) {
1488
1489 fTransp = (invisibility > 0.f) ? 2.f - invisibility : eobj->facelist[i].transval;
1490
1491 if(fTransp >= 2.f) {
1492 //MULTIPLICATIVE
1493 fTransp *= (1.f/2);
1494 fTransp += .5f;
1495 tv = PushVertexInTableCull_TMultiplicative(pTex);
1496 } else if(fTransp >= 1.f) {
1497 //ADDITIVE
1498 fTransp -= 1.f;
1499 tv = PushVertexInTableCull_TAdditive(pTex);
1500 } else if(fTransp > 0.f) {
1501 //NORMAL TRANS
1502 fTransp = 1.f - fTransp;
1503 tv = PushVertexInTableCull_TNormalTrans(pTex);
1504 } else {
1505 //SUBTRACTIVE
1506 fTransp = 1.f - fTransp;
1507 tv = PushVertexInTableCull_TSubstractive(pTex);
1508 }
1509 } else {
1510 tv = PushVertexInTableCull(pTex);
1511 }
1512
1513 for(long n = 0 ; n < 3 ; n++) {
1514 paf[n] = eface->vid[n];
1515 tv[n].p = eobj->vertexlist3[paf[n]].vert.p;
1516
1517 // Nuky - this code takes 20% of the whole game performance O_O
1518 // AFAIK it allows to correctly display the blue magic effects
1519 // when one's hands are inside a wall. I've only managed to do that
1520 // while in combat mode, looking straight down, and touching a wall
1521 // So, for the greater good I think it's best to simply skip this test
1522 //const float IN_FRONT_DIVIDER = 0.75f;
1523 //const float IN_FRONT_DIVIDER_FEET = 0.998f;
1524 //if (FORCE_FRONT_DRAW)
1525 //{
1526 // if (IsInGroup(eobj, paf[n], 1) != -1)
1527 // tv[n].sz *= IN_FRONT_DIVIDER;
1528 // else
1529 // tv[n].sz *= IN_FRONT_DIVIDER_FEET;
1530 //}
1531
1532 tv[n].rhw = eobj->vertexlist3[paf[n]].vert.rhw;
1533 tv[n].uv.x = eface->u[n];
1534 tv[n].uv.y = eface->v[n];
1535 tv[n].color = eobj->vertexlist3[paf[n]].vert.color;
1536 }
1537
1538 if (special_color_flag)
1539 {
1540 if (special_color_flag & 1)
1541 {
1542 for (long j = 0 ; j < 3 ; j++)
1543 {
1544 tv[j].color = 0xFF000000L
1545 | (((long)((float)((long)((tv[j].color >> 16) & 255)) * (special_color.r)) & 255) << 16)
1546 | (((long)((float)((long)((tv[j].color >> 8) & 255)) * special_color.g) & 255) << 8)
1547 | ((long)((float)((long)(tv[j].color & 255)) * (special_color.b)) & 255);
1548 }
1549 }
1550 else if (special_color_flag & 2)
1551 {
1552 for (long j = 0 ; j < 3 ; j++)
1553 {
1554 tv[j].color = 0xFFFF0000;
1555 }
1556 }
1557 }
1558
1559 if((eobj->facelist[i].facetype & POLY_TRANS) || invisibility > 0.f) {
1560 tv[0].color = tv[1].color = tv[2].color = Color::gray(fTransp).toBGR();
1561 }
1562
1563 #ifdef USE_SOFTWARE_CLIPPING
1564 if (!(ARX_SoftClippZ(&eobj->vertexlist3[paf[0]],
1565 &eobj->vertexlist3[paf[1]],
1566 &eobj->vertexlist3[paf[2]],
1567 &tv,
1568 eface,
1569 invisibility,
1570 pTex,
1571 (io) && (io->ioflags & IO_ZMAP),
1572 eobj,
1573 i,
1574 paf,
1575 NULL,
1576 true,
1577 special_color_flag,
1578 &special_color)))
1579 {
1580 continue;
1581 }
1582 #endif
1583
1584 if ((io) && (io->ioflags & IO_ZMAP))
1585 {
1586 CalculateInterZMapp(eobj, i, paf, pTex, tv);
1587 }
1588
1589 ////////////////////////////////////////////////////////////////////////
1590 // HALO HANDLING START
1591 if ( need_halo && io )
1592 {
1593 long lfr, lfg, lfb;
1594 float ffr, ffg, ffb;
1595 float tot = 0;
1596 float _ffr[3];
1597
1598 IO_HALO curhalo;
1599 memcpy(&curhalo, &io->halo, sizeof(IO_HALO));
1600 int curhaloInitialized = 0;
1601
1602 long max_c;
1603
1604 if (use_io == entities.player())
1605 max_c = 4;
1606 else
1607 max_c = 1;
1608
1609 for (long cnt = 0 ; cnt < max_c ; cnt++)
1610 {
1611 switch (cnt)
1612 {
1613 case 0:
1614
1615 if (use_io == entities.player())
1616 {
1617 if (hio_player)
1618 {
1619 memcpy(&curhalo, &use_io->halo, sizeof(IO_HALO));
1620 ++curhaloInitialized;
1621 }
1622 else continue;
1623 }
1624 else
1625 {
1626 memcpy(&curhalo, &io->halo, sizeof(IO_HALO));
1627 ++curhaloInitialized;
1628 }
1629
1630 break;
1631 case 1:
1632
1633 if ((hio_helmet)
1634 && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_head) >= 0))
1635 {
1636 memcpy(&curhalo, &hio_helmet->halo, sizeof(IO_HALO));
1637 ++curhaloInitialized;
1638 }
1639 else continue;
1640
1641 break;
1642 case 2:
1643
1644 if ((hio_armor)
1645 && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_chest) >= 0))
1646 {
1647 memcpy(&curhalo, &hio_armor->halo, sizeof(IO_HALO));
1648 ++curhaloInitialized;
1649 }
1650 else continue;
1651
1652 break;
1653 case 3:
1654
1655 if ((hio_leggings)
1656 && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_leggings) >= 0))
1657 {
1658 memcpy(&curhalo, &hio_leggings->halo, sizeof(IO_HALO)) ;
1659 ++curhaloInitialized;
1660 }
1661 else continue;
1662
1663 break;
1664 }
1665
1666 arx_assert(curhaloInitialized > 0);
1667
1668 TexturedVertex * workon;
1669 workon = tv;
1670
1671 long o;
1672
1673 for (o = 0 ; o < 3 ; o++)
1674 {
1675 float tttz = EEfabs(eobj->vertexlist3[paf[o]].norm.z) * ( 1.0f / 2 );
1676 float power = 255.f - (float)(255.f * tttz);
1677 power *= (1.f - invisibility);
1678
1679 if (power > 255.f) power = 255.f;
1680 else if (power < 0.f) power = 0.f;
1681
1682 ffr = curhalo.color.r * power;
1683 ffg = curhalo.color.g * power;
1684 ffb = curhalo.color.b * power;
1685 tot += power;
1686 _ffr[o] = power;
1687 lfr = ffr;
1688 lfg = ffg;
1689 lfb = ffb;
1690 tv[o].color = 0xFF000000L | (((lfr) & 255) << 16) | (((lfg) & 255) << 8) | ((lfb) & 255);
1691 }
1692
1693 //GRenderer->SetCulling(Renderer::CullNone);
1694 if (tot > 260) //260.f)
1695 {
1696 long first;
1697 long second;
1698 long third;
1699
1700 if ((_ffr[0] >= _ffr[1]) && (_ffr[1] >= _ffr[2]))
1701 {
1702 first = 0;
1703 second = 1;
1704 third = 2;
1705 }
1706 else if ((_ffr[0] >= _ffr[2]) && (_ffr[2] >= _ffr[1]))
1707 {
1708 first = 0;
1709 second = 2;
1710 third = 1;
1711 }
1712 else if ((_ffr[1] >= _ffr[0]) && (_ffr[0] >= _ffr[2]))
1713 {
1714 first = 1;
1715 second = 0;
1716 third = 2;
1717 }
1718 else if ((_ffr[1] >= _ffr[2]) && (_ffr[2] >= _ffr[0]))
1719 {
1720 first = 1;
1721 second = 2;
1722 third = 0;
1723 }
1724 else if ((_ffr[2] >= _ffr[0]) && (_ffr[0] >= _ffr[1]))
1725 {
1726 first = 2;
1727 second = 0;
1728 third = 1;
1729 }
1730 else
1731 {
1732 first = 2;
1733 second = 1;
1734 third = 0;
1735 }
1736
1737
1738 if ((_ffr[first] > 150.f) && (_ffr[second] > 110.f))
1739 {
1740 Vec3f vect1, vect2;
1741 TexturedVertex * vert = &LATERDRAWHALO[(HALOCUR << 2)];
1742
1743 if(HALOCUR < ((long)HALOMAX) - 1) {
1744 HALOCUR++;
1745 }
1746
1747 memcpy(&vert[0], &workon[first], sizeof(TexturedVertex));
1748 memcpy(&vert[1], &workon[first], sizeof(TexturedVertex));
1749 memcpy(&vert[2], &workon[second], sizeof(TexturedVertex));
1750 memcpy(&vert[3], &workon[second], sizeof(TexturedVertex));
1751
1752 float siz = ddist * (curhalo.radius * (EEsin((float)(arxtime.get_frame_time() + i) * ( 1.0f / 100 )) * ( 1.0f / 10 ) + 1.f)) * 0.6f;
1753
1754 if ((io == entities.player()) && (ddist > 0.8f) && !EXTERNALVIEW)
1755 siz *= 1.5f;
1756
1757 vect1.x = workon[first].p.x - workon[third].p.x;
1758 vect1.y = workon[first].p.y - workon[third].p.y;
1759 float len1 = 2.f / ffsqrt(vect1.x * vect1.x + vect1.y * vect1.y);
1760
1761 if (vect1.x < 0.f) len1 *= 1.2f;
1762
1763 vect1.x *= len1;
1764 vect1.y *= len1;
1765 vect2.x = workon[second].p.x - workon[third].p.x;
1766 vect2.y = workon[second].p.y - workon[third].p.y;
1767
1768 float len2 = 1.f / ffsqrt(vect2.x * vect2.x + vect2.y * vect2.y);
1769
1770 if (vect2.x < 0.f) len2 *= 1.2f;
1771
1772 vect2.x *= len2;
1773 vect2.y *= len2;
1774 vert[1].p.x += (vect1.x + 0.2f - rnd() * 0.1f) * siz;
1775 vert[1].p.y += (vect1.y + 0.2f - rnd() * 0.1f) * siz;
1776 vert[1].color = 0xFF000000;
1777
1778 float valll;
1779 valll = 0.005f + (EEfabs(workon[first].p.z) - EEfabs(workon[third].p.z))
1780 + (EEfabs(workon[second].p.z) - EEfabs(workon[third].p.z));
1781 valll = 0.0001f + valll * ( 1.0f / 10 );
1782
1783 if (valll < 0.f) valll = 0.f;
1784
1785 vert[1].p.z += valll;
1786 vert[2].p.z += valll;
1787 vert[0].p.z += 0.0001f;
1788 vert[3].p.z += 0.0001f;//*( 1.0f / 2 );
1789 vert[1].rhw *= .98f;
1790 vert[2].rhw *= .98f;
1791 vert[0].rhw *= .98f;
1792 vert[3].rhw *= .98f;
1793
1794 vert[2].p.x += (vect2.x + 0.2f - rnd() * 0.1f) * siz;
1795 vert[2].p.y += (vect2.y + 0.2f - rnd() * 0.1f) * siz;
1796
1797 vert[1].p.z = (vert[1].p.z + MAX_ZEDE) * ( 1.0f / 2 );
1798 vert[2].p.z = (vert[2].p.z + MAX_ZEDE) * ( 1.0f / 2 );
1799
1800 if (curhalo.flags & HALO_NEGATIVE)
1801 vert[2].color = 0x00000000;
1802 else
1803 vert[2].color = 0xFF000000;
1804 }
1805 }
1806 }
1807
1808 for (long o = 0 ; o < 3 ; o++)
1809 {
1810 paf[o] = eface->vid[o];
1811 tv[o].color = eobj->vertexlist3[paf[o]].vert.color;
1812 }
1813 }
1814
1815 ////////////////////////////////////////////////////////////////////////
1816 // HALO HANDLING END
1817 ////////////////////////////////////////////////////////////////////////
1818
1819 if (special_color_flag & 2)
1820 {
1821 TexturedVertex * tv2;
1822 {
1823 tv2 = PushVertexInTableCull(&TexSpecialColor);
1824 }
1825 memcpy(tv2, tv, sizeof(TexturedVertex) * 3);
1826
1827 tv2[0].color = tv2[1].color = tv2[2].color = Color::gray(special_color.r).toBGR();
1828 }
1829 }
1830 }
1831 }
1832
Cedric_BlendAnimation(EERIE_3DOBJ * eobj,float timm)1833 void Cedric_BlendAnimation(EERIE_3DOBJ * eobj, float timm) {
1834 for (long i = 0; i < eobj->c_data->nb_bones; i++)
1835 {
1836 EERIE_QUAT tquat;
1837 Quat_Copy(&tquat, &eobj->c_data->bones[i].quatinit);
1838 EERIE_QUAT q2;
1839 Quat_Copy(&q2, &eobj->c_data->bones[i].quatlast);
1840
1841 Quat_Slerp(&eobj->c_data->bones[i].quatinit , &q2, &tquat, timm);
1842
1843 eobj->c_data->bones[i].transinit = eobj->c_data->bones[i].translast
1844 + (eobj->c_data->bones[i].transinit
1845 - eobj->c_data->bones[i].translast) * timm;
1846 }
1847 }
1848
Cedric_SaveBlendData(Entity * io)1849 void Cedric_SaveBlendData(Entity * io) {
1850 if (io->obj->c_data)
1851 {
1852 for (long i = 0; i < io->obj->c_data->nb_bones; i++)
1853 {
1854 Quat_Copy(&io->obj->c_data->bones[i].quatlast, &io->obj->c_data->bones[i].quatinit);
1855 io->obj->c_data->bones[i].scalelast = io->obj->c_data->bones[i].scaleinit;
1856 io->obj->c_data->bones[i].translast = io->obj->c_data->bones[i].transinit;
1857 }
1858 }
1859 }
1860
Cedric_ManageExtraRotationsFirst(Entity * io,EERIE_3DOBJ * obj)1861 void Cedric_ManageExtraRotationsFirst(Entity * io, EERIE_3DOBJ * obj)
1862 {
1863 for (long i = 0; i != obj->c_data->nb_bones; i++)
1864 {
1865 Quat_Init(&obj->c_data->bones[i].quatinit);
1866 obj->c_data->bones[i].transinit = obj->c_data->bones[i].transinit_global;
1867 }
1868
1869 if ((io) && (io->ioflags & IO_NPC) && (io->_npcdata->ex_rotate))
1870 {
1871 for (long k = 0; k < MAX_EXTRA_ROTATE; k++)
1872 {
1873 long i = io->_npcdata->ex_rotate->group_number[k];
1874
1875 if(i >= 0) {
1876 Anglef vt1;
1877 EERIE_QUAT quat1;
1878 vt1.a = radians(io->_npcdata->ex_rotate->group_rotate[k].g);
1879 vt1.b = radians(io->_npcdata->ex_rotate->group_rotate[k].b);
1880 vt1.g = radians(io->_npcdata->ex_rotate->group_rotate[k].a);
1881 QuatFromAngles(&quat1, &vt1);
1882 Quat_Copy(&obj->c_data->bones[i].quatinit, &quat1);
1883 }
1884 }
1885 }
1886 }
1887
Cedric_IO_Visible(Entity * io)1888 static bool Cedric_IO_Visible(Entity * io) {
1889 if (io == entities.player()) return true;
1890
1891 if(ACTIVEBKG && io) {
1892
1893 if (distSqr(io->pos, ACTIVECAM->pos) > square(ACTIVECAM->cdepth) * square(0.6f))
1894 return false;
1895
1896 long xx, yy;
1897 xx = io->pos.x * ACTIVEBKG->Xmul;
1898 yy = io->pos.z * ACTIVEBKG->Zmul;
1899
1900 if ((xx >= 1) && (yy >= 1) && (xx < ACTIVEBKG->Xsize - 1) && (yy < ACTIVEBKG->Zsize - 1))
1901 {
1902 for (long ky = yy - 1; ky <= yy + 1; ky++)
1903 for (long kx = xx - 1; kx <= xx + 1; kx++)
1904 {
1905 FAST_BKG_DATA * feg = (FAST_BKG_DATA *)&ACTIVEBKG->fastdata[kx][ky];
1906
1907 if (feg->treat)
1908 return true;
1909 }
1910
1911 return false;
1912 }
1913 }
1914
1915 return true;
1916 }
1917
1918 extern long MUST_DRAW;
1919 extern long EXTERNALVIEW;
1920
1921 /* Apply animation and draw object */
Cedric_AnimateDrawEntity(EERIE_3DOBJ * eobj,ANIM_USE * animuse,Anglef * angle,Vec3f * pos,Entity * io,bool render,bool update_movement)1922 void Cedric_AnimateDrawEntity(EERIE_3DOBJ * eobj,
1923 ANIM_USE * animuse,
1924 Anglef * angle,
1925 Vec3f * pos,
1926 Entity * io,
1927 bool render,
1928 bool update_movement) {
1929
1930 float invisibility;
1931 float scale;
1932 float timm;
1933 Vec3f ftr;
1934 EERIE_C_DATA * obj;
1935
1936 // Init some data
1937 Cedric_ResetBoundingBox(io);
1938
1939 // Set scale and invisibility factors
1940 Cedric_GetScale(scale, invisibility, io);
1941
1942 // Flag linked objects
1943 //Cedric_FlagLinkedObjects(eobj); ???
1944
1945 // Is There any Between-Animations Interpolation to make ? timm>0.f
1946 Cedric_GetTime(timm, io);
1947
1948 // Buffer size check
1949 if(eobj->nbgroups > max_grps) {
1950 //todo free
1951 grps = (unsigned char *)realloc(grps, eobj->nbgroups);
1952 max_grps = eobj->nbgroups;
1953 }
1954
1955 memset(grps, 0, eobj->nbgroups);
1956
1957 Cedric_AnimCalcTranslation(io, animuse, scale, ftr, update_movement);
1958
1959 if(Cedric_IO_Visible(io)) {
1960
1961 // Manage Extra Rotations in Local Space
1962 Cedric_ManageExtraRotationsFirst(io, eobj);
1963
1964 // Perform animation in Local space
1965 Cedric_AnimateObject(io, eobj, animuse);
1966
1967 // Check for Animation Blending in Local space
1968 if (io)
1969 {
1970 if (timm > 0.f)
1971 {
1972 Cedric_BlendAnimation(eobj, timm);
1973 Cedric_SaveBlendData(io);
1974 }
1975 else
1976 Cedric_SaveBlendData(io);
1977 }
1978
1979 // Build skeleton in Object Space
1980 Cedric_ConcatenateTM(io, eobj->c_data, angle, pos, ftr, scale);
1981
1982 /* Display the object */
1983 obj = eobj->c_data;
1984
1985 if (!obj)
1986 return;
1987
1988
1989 if(Cedric_TransformVerts(io, eobj, obj, pos) && render) {
1990
1991 INTER_DRAW++;
1992
1993 if(!Cedric_ApplyLighting(eobj, obj, io, pos)) {
1994 return;
1995 }
1996
1997 Cedric_RenderObject(eobj, obj, io, pos, ftr, invisibility);
1998
1999 if (io)
2000 {
2001 io->bbox1.x = (short)BBOXMIN.x;
2002 io->bbox2.x = (short)BBOXMAX.x;
2003 io->bbox1.y = (short)BBOXMIN.y;
2004 io->bbox2.y = (short)BBOXMAX.y;
2005 }
2006
2007 // Now we can render Linked Objects
2008
2009 for (long k = 0; k < eobj->nblinked; k++)
2010 {
2011 if ((eobj->linked[k].lgroup != -1) && eobj->linked[k].obj) {
2012
2013 eobj->linked[k].modinfo.rot = Anglef::ZERO;
2014
2015 float old = 0.f;
2016 Entity * ioo = (Entity *)eobj->linked[k].io;
2017 EERIE_3DOBJ * obj = (EERIE_3DOBJ *) eobj->linked[k].obj;
2018
2019 // Store item invisibility flag
2020 if (io && ioo)
2021 {
2022 old = ioo->invisibility;
2023
2024 if (io == entities.player())
2025 {
2026 ioo->invisibility = INVISIBILITY_OVERRIDE;
2027 }
2028 else
2029 {
2030 INVISIBILITY_OVERRIDE = 0.f;
2031 ioo->invisibility = invisibility;
2032 }
2033 }
2034 else
2035 {
2036 if (ioo)
2037 {
2038 INVISIBILITY_OVERRIDE = 0.f;
2039 ioo->invisibility = invisibility;
2040 }
2041 else
2042 INVISIBILITY_OVERRIDE = invisibility;
2043 }
2044
2045 if (ioo)
2046 {
2047 if ((ioo->ignition > 0.f) || (ioo->ioflags & IO_FIERY))
2048 ManageIgnition(ioo);
2049 }
2050
2051 MUST_DRAW = 1;
2052
2053 // specific check to avoid drawing player weapon on its back when in subjective view
2054 if ((io == entities.player()) &&
2055 (eobj->linked[k].lidx == entities.player()->obj->fastaccess.weapon_attach)
2056 && (!EXTERNALVIEW))
2057 continue;
2058
2059 long ll = eobj->linked[k].lidx2;
2060 eobj->linked[k].modinfo.link_position = obj->vertexlist[ll].v - obj->vertexlist[obj->origin].v;
2061
2062 EERIE_QUAT quat;
2063 ll = eobj->linked[k].lidx;
2064 Vec3f * posi = &eobj->vertexlist3[ll].v;
2065 Quat_Copy(&quat, &eobj->c_data->bones[eobj->linked[k].lgroup].quatanim);
2066
2067 EERIEMATRIX matrix;
2068 MatrixFromQuat(&matrix, &quat);
2069 DrawEERIEInterMatrix(obj, &matrix, posi, ioo, &eobj->linked[k].modinfo);
2070 INVISIBILITY_OVERRIDE = 0.f;
2071
2072 // Restore item invisibility flag
2073 if (ioo)
2074 ioo->invisibility = old;
2075
2076 MUST_DRAW = 0;
2077
2078 }
2079 }
2080
2081 }
2082 }
2083 }
2084
MakeCLight(Entity * io,Color3f * infra,Anglef * angle,Vec3f * pos,EERIE_3DOBJ * eobj,EERIEMATRIX * BIGMAT,EERIE_QUAT * BIGQUAT)2085 void MakeCLight(Entity * io, Color3f * infra, Anglef * angle, Vec3f * pos, EERIE_3DOBJ * eobj, EERIEMATRIX * BIGMAT, EERIE_QUAT * BIGQUAT)
2086 {
2087 if ((Project.improve) && (!io))
2088 {
2089 infra->r = 0.6f;
2090 infra->g = 0.f;
2091 infra->b = 1.f;
2092 }
2093
2094 llightsInit();
2095 Vec3f tv = *pos;
2096
2097 if ((io) && (io->ioflags & IO_ITEM))
2098 tv.y -= 60.f;
2099 else
2100 tv.y -= 90.f;
2101
2102 for (long i = 0; i < TOTIOPDL; i++)
2103 {
2104 if (IO_PDL[i]->fallend + 500.f < 0)
2105 continue;
2106
2107 Insertllight(IO_PDL[i], fdist(IO_PDL[i]->pos, tv));
2108 }
2109
2110 for (int i = 0; i < TOTPDL; i++)
2111 {
2112 if (PDL[i]->fallend + 500.f < 0)
2113 continue;
2114
2115 Insertllight(PDL[i], fdist(PDL[i]->pos, tv));
2116 }
2117
2118 Preparellights(&tv);
2119
2120 if ((io) && (io->ioflags & IO_ANGULAR)) return;
2121
2122 Vec3f vLight;
2123 Vec3f vTLights[32];
2124 EERIE_QUAT qInvert;
2125
2126 if (BIGMAT != NULL)
2127 {
2128 QuatFromMatrix(qInvert, *BIGMAT);
2129 }
2130 else
2131 {
2132 if (BIGQUAT != NULL)
2133 {
2134 qInvert = *BIGQUAT;
2135 }
2136 else
2137 {
2138 //FIX LIGHT
2139 Anglef vt1;
2140
2141 if (angle)
2142 {
2143 vt1 = *angle;
2144 }
2145 else
2146 {
2147 if (io)
2148 vt1 = io->angle;
2149 else
2150 vt1 = eobj->angle;
2151 }
2152
2153 vt1.a = radians(MAKEANGLE(-vt1.g));
2154 vt1.b = radians(MAKEANGLE(vt1.b));
2155 vt1.g = radians(MAKEANGLE(vt1.a));
2156 QuatFromAngles(&qInvert, &vt1);
2157 }
2158 }
2159
2160
2161
2162 for (size_t i = 0; i < eobj->vertexlist.size(); i++)
2163 {
2164 float r, g, b;
2165 long ir, ig, ib;
2166
2167 if ((io) && (io->ioflags & (IO_NPC | IO_ITEM)))
2168 {
2169 r = g = b = NPC_ITEMS_AMBIENT_VALUE_255;
2170 }
2171 else
2172 {
2173 r = ACTIVEBKG->ambient255.r;
2174 g = ACTIVEBKG->ambient255.g;
2175 b = ACTIVEBKG->ambient255.b;
2176 }
2177
2178 Vec3f * posVert = &eobj->vertexlist3[i].v;
2179
2180 for (long l = 0 ; l != MAX_LLIGHTS; l++)
2181 {
2182 EERIE_LIGHT * Cur_llights = llights[l];
2183
2184 if (Cur_llights)
2185 {
2186 float cosangle;
2187
2188 vLight = (llights[l]->pos - *posVert).getNormalized();
2189
2190 TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]);
2191 Vec3f * Cur_vLights = &vTLights[l];
2192
2193 // Get cos angle between light and vertex norm
2194 cosangle = (eobj->vertexlist[i].norm.x * Cur_vLights->x +
2195 eobj->vertexlist[i].norm.y * Cur_vLights->y +
2196 eobj->vertexlist[i].norm.z * Cur_vLights->z);
2197
2198 // If light visible
2199 if (cosangle > 0.f)
2200 {
2201 float distance = fdist(*posVert, Cur_llights->pos);
2202
2203 // Evaluate its intensity depending on the distance Light<->Object
2204 if (distance <= Cur_llights->fallstart)
2205 cosangle *= Cur_llights->precalc;
2206 else
2207 {
2208 float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul);
2209
2210 if (p <= 0.f)
2211 cosangle = 0.f;
2212 else
2213 cosangle *= p * Cur_llights->precalc;
2214 }
2215
2216 r += Cur_llights->rgb255.r * cosangle;
2217 g += Cur_llights->rgb255.g * cosangle;
2218 b += Cur_llights->rgb255.b * cosangle;
2219 }
2220 }
2221 else
2222 break;
2223 }
2224
2225 if (eobj->drawflags & DRAWFLAG_HIGHLIGHT)
2226 {
2227 r += iHighLight;
2228 g += iHighLight;
2229 b += iHighLight;
2230 }
2231
2232 if ((Project.improve) && (!io))
2233 {
2234 r *= infra->r;
2235 g *= infra->g;
2236 b *= infra->b;
2237 r += infra->r * 512.f;
2238 g += infra->g;
2239 b += infra->b * 400.f;
2240 }
2241
2242 ir = clipByte255(r);
2243 ig = clipByte255(g);
2244 ib = clipByte255(b);
2245 eobj->vertexlist3[i].vert.color = 0xff000000L | (((ir) & 255) << 16) | (((ig) & 255) << 8) | ((ib) & 255);
2246 }
2247 }
2248
MakeCLight2(Entity * io,Color3f * infra,Anglef * angle,Vec3f * pos,EERIE_3DOBJ * eobj,EERIEMATRIX * BIGMAT,EERIE_QUAT * BIGQUAT,long ii)2249 void MakeCLight2(Entity * io, Color3f * infra, Anglef * angle, Vec3f * pos, EERIE_3DOBJ * eobj, EERIEMATRIX * BIGMAT, EERIE_QUAT * BIGQUAT, long ii) {
2250
2251 Vec3f vLight;
2252 Vec3f vTLights[32];
2253 EERIE_QUAT qInvert;
2254
2255 if (BIGMAT != NULL)
2256 {
2257 QuatFromMatrix(qInvert, *BIGMAT);
2258 }
2259 else
2260 {
2261 if (BIGQUAT != NULL)
2262 {
2263 qInvert = *BIGQUAT;
2264 }
2265 else
2266 {
2267 Anglef vt1;
2268
2269 if (angle)
2270 {
2271 vt1 = *angle;
2272 }
2273 else
2274 {
2275 if (io)
2276 vt1 = io->angle;
2277 else
2278 vt1 = eobj->angle;
2279 }
2280
2281 vt1 = Anglef(radians(vt1.a), radians(vt1.b), radians(vt1.g));
2282 QuatFromAngles(&qInvert, &vt1);
2283 }
2284 }
2285
2286 Vec3f tv = *pos;
2287
2288 if ((io) && (io->ioflags & IO_ITEM))
2289 tv.y -= 60.f;
2290 else
2291 tv.y -= 90.f;
2292
2293 for(long l = 0; l != MAX_LLIGHTS; l++) {
2294 if(llights[l]) {
2295 vLight = (llights[l]->pos - tv) / dists[l];
2296 TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]);
2297 } else {
2298 break;
2299 }
2300 }
2301
2302 long paf[3];
2303 paf[0] = eobj->facelist[ii].vid[0];
2304 paf[1] = eobj->facelist[ii].vid[1];
2305 paf[2] = eobj->facelist[ii].vid[2];
2306
2307 for (long i = 0; i < 3; i++)
2308 {
2309 float r, g, b;
2310 long ir, ig, ib;
2311
2312 if ((io) && (io->ioflags & (IO_NPC | IO_ITEM)))
2313 {
2314 r = g = b = NPC_ITEMS_AMBIENT_VALUE_255;
2315 }
2316 else
2317 {
2318 r = ACTIVEBKG->ambient255.r;
2319 g = ACTIVEBKG->ambient255.g;
2320 b = ACTIVEBKG->ambient255.b;
2321 }
2322
2323 Vec3f * posVert = &eobj->vertexlist3[paf[i]].v;
2324
2325 for (int l = 0 ; l != MAX_LLIGHTS; l++)
2326 {
2327 EERIE_LIGHT * Cur_llights = llights[l];
2328
2329 if (Cur_llights)
2330 {
2331 float cosangle;
2332 float oolength = 1.f / fdist(*posVert, Cur_llights->pos);
2333 vLight = (llights[l]->pos - *posVert) * oolength;
2334
2335 TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]);
2336 Vec3f * Cur_vLights = &vTLights[l];
2337
2338 cosangle = (eobj->facelist[ii].norm.x * Cur_vLights->x +
2339 eobj->facelist[ii].norm.y * Cur_vLights->y +
2340 eobj->facelist[ii].norm.z * Cur_vLights->z) * ( 1.0f / 2 );
2341
2342 // If light visible
2343 if (cosangle > 0.f)
2344 {
2345 float distance = fdist(*posVert, Cur_llights->pos);
2346
2347 // Evaluate its intensity depending on the distance Light<->Object
2348 if (distance <= Cur_llights->fallstart)
2349 cosangle *= Cur_llights->precalc;
2350 else
2351 {
2352 float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul);
2353
2354 if (p <= 0.f)
2355 cosangle = 0.f;
2356 else
2357 cosangle *= p * Cur_llights->precalc;
2358 }
2359
2360 r += Cur_llights->rgb255.r * cosangle;
2361 g += Cur_llights->rgb255.g * cosangle;
2362 b += Cur_llights->rgb255.b * cosangle;
2363 }
2364 }
2365 else
2366 break;
2367 }
2368
2369 if (eobj->drawflags & DRAWFLAG_HIGHLIGHT)
2370 {
2371 r += iHighLight;
2372 g += iHighLight;
2373 b += iHighLight;
2374 }
2375
2376 if (Project.improve)
2377 {
2378 r *= infra->r;
2379 g *= infra->g;
2380 b *= infra->b;
2381 }
2382
2383 ir = clipByte255(r);
2384 ig = clipByte255(g);
2385 ib = clipByte255(b);
2386 eobj->vertexlist3[paf[i]].vert.color = 0xff000000L | (((ir) & 255) << 16) | (((ig) & 255) << 8) | ((ib) & 255);
2387 }
2388 }
2389
2390
ApplyDynLight(EERIEPOLY * ep)2391 void ApplyDynLight(EERIEPOLY * ep)
2392 {
2393 long nbvert, i;
2394
2395 if (ep->type & POLY_QUAD) nbvert = 4;
2396 else nbvert = 3;
2397
2398 if (TOTPDL == 0)
2399 {
2400 for (i = 0; i < nbvert; i++)
2401 ep->tv[i].color = ep->v[i].color;
2402
2403 return;
2404 }
2405
2406 Color3f rgb;
2407 long j;
2408
2409 float epr[4];
2410 float epg[4];
2411 float epb[4];
2412
2413 for (i = 0; i < nbvert; i++)
2414 {
2415 long c = ep->v[i].color;
2416 epr[i] = (float)((c >> 16) & 255);
2417 epg[i] = (float)((c >> 8) & 255);
2418 epb[i] = (float)(c & 255);
2419 }
2420
2421 for (i = 0; i < TOTPDL; i++)
2422 {
2423 EERIE_LIGHT * el = PDL[i];
2424
2425 if (el->fallend + 35.f < 0)
2426 {
2427 TSU_TEST_NB_LIGHT ++;
2428 continue;
2429 }
2430
2431 if (distSqr(el->pos, ep->center) <= square(el->fallend + 35.f))
2432 {
2433 if(Project.improve) {
2434 rgb.r = el->rgb255.r * 4.f;
2435 rgb.g = rgb.b = 0.2f;
2436 } else {
2437 rgb = el->rgb255;
2438 }
2439
2440 for (j = 0; j < nbvert; j++)
2441 {
2442 Vec3f v(ep->v[j].p.x,ep->v[j].p.y, ep->v[j].p.z);
2443 if (el->fallend < 0)
2444 {
2445 TSU_TEST_NB ++;
2446 continue;
2447 }
2448
2449 float d = fdist(el->pos, ep->v[j].p);
2450
2451 if (d <= el->fallend)
2452 {
2453 float divd = 1.f / d;
2454 float nvalue;
2455
2456 Vec3f v1;
2457 v1 = (el->pos - ep->v[j].p) * divd;
2458 nvalue = dot(v1, ep->nrml[j]) * (1.0f / 2);
2459
2460 if (nvalue > 1.f) nvalue = 1.f;
2461 else if (nvalue < 0.f) nvalue = 0.f;
2462
2463 if (nvalue > 0.f)
2464 {
2465 ////
2466 if (d <= el->fallstart)
2467 {
2468 d = nvalue * el->precalc;
2469 }
2470 else
2471 {
2472 d -= el->fallstart;
2473 d = (el->falldiff - d) * el->falldiffmul * nvalue * el->precalc;
2474 }
2475
2476 epr[j] += rgb.r * d;
2477 epg[j] += rgb.g * d;
2478 epb[j] += rgb.b * d;
2479 }
2480 }
2481 else if (d > el->fallend + 100.f) break;
2482 }
2483 }
2484 }
2485
2486 long lepr, lepg, lepb;
2487
2488 for (j = 0; j < nbvert; j++)
2489 {
2490 lepr = clipByte255(epr[j]);
2491 lepg = clipByte255(epg[j]);
2492 lepb = clipByte255(epb[j]);
2493 ep->tv[j].color = (0xFF000000L |
2494 (lepr << 16) |
2495 (lepg << 8) |
2496 (lepb));
2497 }
2498 }
2499
2500 //*************************************************************************************
ApplyDynLight_VertexBuffer(EERIEPOLY * ep,SMY_VERTEX * _pVertex,unsigned short _usInd0,unsigned short _usInd1,unsigned short _usInd2,unsigned short _usInd3)2501 void ApplyDynLight_VertexBuffer(EERIEPOLY * ep, SMY_VERTEX * _pVertex, unsigned short _usInd0, unsigned short _usInd1, unsigned short _usInd2, unsigned short _usInd3)
2502 {
2503 long nbvert, i;
2504
2505 if (ep->type & POLY_QUAD) nbvert = 4;
2506 else nbvert = 3;
2507
2508 if (TOTPDL == 0)
2509 {
2510
2511 ep->tv[0].color = _pVertex[_usInd0].color = ep->v[0].color;
2512 ep->tv[1].color = _pVertex[_usInd1].color = ep->v[1].color;
2513 ep->tv[2].color = _pVertex[_usInd2].color = ep->v[2].color;
2514
2515 if (nbvert & 4)
2516 {
2517 ep->tv[3].color = _pVertex[_usInd3].color = ep->v[3].color;
2518 }
2519
2520 return;
2521 }
2522
2523 long j;
2524 float epr[4];
2525 float epg[4];
2526 float epb[4];
2527
2528 for (i = 0; i < nbvert; i++)
2529 {
2530 long c = ep->v[i].color;
2531 epr[i] = (float)(long)((c >> 16) & 255);
2532 epg[i] = (float)(long)((c >> 8) & 255);
2533 epb[i] = (float)(long)(c & 255);
2534 }
2535
2536 for (i = 0; i < TOTPDL; i++)
2537 {
2538 EERIE_LIGHT * el = PDL[i];
2539
2540 for (j = 0; j < nbvert; j++)
2541 {
2542 float d = fdist(el->pos, ep->v[j].p);
2543
2544 if (d < el->fallend)
2545 {
2546 float nvalue;
2547
2548 nvalue = ((el->pos.x - ep->v[j].p.x) * ep->nrml[j].x
2549 + (el->pos.y - ep->v[j].p.y) * ep->nrml[j].y
2550 + (el->pos.z - ep->v[j].p.z) * ep->nrml[j].z
2551 ) * 0.5f / d;
2552
2553 if (nvalue > 0.f)
2554 {
2555 if (d <= el->fallstart)
2556 {
2557 d = el->precalc * nvalue;
2558 }
2559 else
2560 {
2561 d -= el->fallstart;
2562 d = (el->falldiff - d) * el->falldiffmul * el->precalc * nvalue;
2563 }
2564
2565 epr[j] += el->rgb255.r * d;
2566
2567 epg[j] += el->rgb255.g * d;
2568
2569 epb[j] += el->rgb255.b * d;
2570 }
2571 }
2572 else if (d > el->fallend + 100.f)
2573 break;
2574 }
2575
2576 }
2577
2578 long lepr, lepg, lepb;
2579
2580 lepr = clipByte255(epr[0]);
2581 lepg = clipByte255(epg[0]);
2582 lepb = clipByte255(epb[0]);
2583 ep->tv[0].color = _pVertex[_usInd0].color = (0xFF000000L |
2584 (lepr << 16) |
2585 (lepg << 8) |
2586 (lepb));
2587 lepr = clipByte255(epr[1]);
2588 lepg = clipByte255(epg[1]);
2589 lepb = clipByte255(epb[1]);
2590 ep->tv[1].color = _pVertex[_usInd1].color = (0xFF000000L |
2591 (lepr << 16) |
2592 (lepg << 8) |
2593 (lepb));
2594
2595 lepr = clipByte255(epr[2]);
2596 lepg = clipByte255(epg[2]);
2597 lepb = clipByte255(epb[2]);
2598 ep->tv[2].color = _pVertex[_usInd2].color = (0xFF000000L |
2599 (lepr << 16) |
2600 (lepg << 8) |
2601 (lepb));
2602
2603 if (nbvert & 4)
2604 {
2605 lepr = clipByte255(epr[3]);
2606 lepg = clipByte255(epg[3]);
2607 lepb = clipByte255(epb[3]);
2608 ep->tv[3].color = _pVertex[_usInd3].color = (0xFF000000L |
2609 (lepr << 16) |
2610 (lepg << 8) |
2611 (lepb));
2612 }
2613 }
2614
2615 extern TILE_LIGHTS tilelights[MAX_BKGX][MAX_BKGZ];
2616 //*************************************************************************************
2617
ApplyDynLight_VertexBuffer_2(EERIEPOLY * ep,short _x,short _y,SMY_VERTEX * _pVertex,unsigned short _usInd0,unsigned short _usInd1,unsigned short _usInd2,unsigned short _usInd3)2618 void ApplyDynLight_VertexBuffer_2(EERIEPOLY * ep, short _x, short _y, SMY_VERTEX * _pVertex, unsigned short _usInd0, unsigned short _usInd1, unsigned short _usInd2, unsigned short _usInd3)
2619 {
2620 // Nuky - 25/01/11 - harmless refactor to understand what is slow.
2621 // MASSIVE speed up thanks to "harmless refactor", wtf ?
2622
2623 TILE_LIGHTS * tls = &tilelights[_x][_y];
2624 long nbvert = (ep->type & POLY_QUAD) ? 4 : 3;
2625
2626 if (tls->num == 0)
2627 {
2628 _pVertex[_usInd0].color = ep->v[0].color;
2629 ep->tv[0].color = ep->v[0].color;
2630 _pVertex[_usInd1].color = ep->v[1].color;
2631 ep->tv[1].color = ep->v[1].color;
2632 _pVertex[_usInd2].color = ep->v[2].color;
2633 ep->tv[2].color = ep->v[2].color;
2634
2635 if (nbvert & 4)
2636 {
2637 _pVertex[_usInd3].color = ep->v[3].color;
2638 ep->tv[3].color = ep->v[3].color;
2639 }
2640
2641 return;
2642 }
2643
2644 long i, j;
2645 float epr[4];
2646 float epg[4];
2647 float epb[4];
2648
2649 for (i = 0; i < nbvert; i++)
2650 {
2651 long c = ep->v[i].color;
2652 epr[i] = (float)(long)((c >> 16) & 255);
2653 epg[i] = (float)(long)((c >> 8) & 255);
2654 epb[i] = (float)(long)(c & 255);
2655 }
2656
2657 for (i = 0; i < tls->num; i++)
2658 {
2659 EERIE_LIGHT * el = tls->el[i];
2660
2661 for (j = 0; j < nbvert; j++)
2662 {
2663
2664 float d = fdist(el->pos, ep->v[j].p);
2665
2666 if (d < el->fallend)
2667 {
2668 float nvalue;
2669
2670 nvalue = ((el->pos.x - ep->v[j].p.x) * ep->nrml[j].x
2671 + (el->pos.y - ep->v[j].p.y) * ep->nrml[j].y
2672 + (el->pos.z - ep->v[j].p.z) * ep->nrml[j].z
2673 ) * 0.5f / d;
2674
2675 if (nvalue > 0.f)
2676 {
2677 if (d <= el->fallstart)
2678 {
2679
2680 d = el->precalc * nvalue;
2681 }
2682 else
2683 {
2684 d -= el->fallstart;
2685
2686 d = (el->falldiff - d) * el->falldiffmul * el->precalc * nvalue;
2687 }
2688
2689 epr[j] += el->rgb255.r * d;
2690
2691 epg[j] += el->rgb255.g * d;
2692
2693 epb[j] += el->rgb255.b * d;
2694 }
2695 }
2696 else if (d > el->fallend + 100.f)
2697 break;
2698 }
2699
2700 }
2701
2702 long lepr, lepg, lepb;
2703
2704 lepr = clipByte255(epr[0]);
2705 lepg = clipByte255(epg[0]);
2706 lepb = clipByte255(epb[0]);
2707 ep->tv[0].color = _pVertex[_usInd0].color = (0xFF000000L |
2708 (lepr << 16) |
2709 (lepg << 8) |
2710 (lepb));
2711 lepr = clipByte255(epr[1]);
2712 lepg = clipByte255(epg[1]);
2713 lepb = clipByte255(epb[1]);
2714 ep->tv[1].color = _pVertex[_usInd1].color = (0xFF000000L |
2715 (lepr << 16) |
2716 (lepg << 8) |
2717 (lepb));
2718
2719 lepr = clipByte255(epr[2]);
2720 lepg = clipByte255(epg[2]);
2721 lepb = clipByte255(epb[2]);
2722 ep->tv[2].color = _pVertex[_usInd2].color = (0xFF000000L |
2723 (lepr << 16) |
2724 (lepg << 8) |
2725 (lepb));
2726
2727 if (nbvert & 4)
2728 {
2729 lepr = clipByte255(epr[3]);
2730 lepg = clipByte255(epg[3]);
2731 lepb = clipByte255(epb[3]);
2732 ep->tv[3].color = _pVertex[_usInd3].color = (0xFF000000L |
2733 (lepr << 16) |
2734 (lepg << 8) |
2735 (lepb));
2736 }
2737
2738 }
2739