/* =========================================================================== ARX FATALIS GPL Source Code Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company. This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code'). Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see . In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #include "EERIEAnim.h" #include "HermesMain.h" #include "Arx_Collisions.h" #include "EERIEClothes.h" #include "EERIEObject.h" #include "EERIEMath.h" #include "EERIELight.h" #include "EERIEPoly.h" #include "EERIEDraw.h" #include #include #include #include #include #include #include "ARX_Time.h" #include "danae.h" #include #include "arx_menu2.h" #define _CRTDBG_MAP_ALLOC #include #include "arx_cedric.h" #if CEDRIC extern BOOL MIPM; extern float vdist; extern float FORCED_REDUCTION_VALUE; extern unsigned char * grps; extern long max_grps; extern long FORCE_NO_HIDE; extern long USEINTERNORM; extern long INTER_DRAW; extern float dists[]; extern bool bZBUFFER; extern bool bGATI8500; extern bool bSoftRender; extern bool bALLOW_BUMP; extern long BH_MODE; extern int iHighLight; extern float IN_FRONT_DIVIDER; extern float IN_FRONT_DIVIDER_FEET; extern bool bRenderInterList; extern TextureContainer TexSpecialColor; extern long FLAG_ALLOW_CLOTHES; long TSU_TEST = 0; extern long TSU_TEST_NB; extern long TSU_TEST_NB_LIGHT; extern D3DMATRIX ProjectionMatrix; extern float fZFogStart; extern CDirectInput * pGetInfoDirectInput; float SOFTNEARCLIPPZ=1.f; #define SOFTNEARCLIPPTANDLZ (60.f) void CalculateInterZMappTANDL(EERIE_3DOBJ * _pobj3dObj, long lIdList, long * _piInd, TextureContainer * _pTex); void PushInterBumpTANDL(TextureContainer * _pTex, D3DTLVERTEX * _pVertex, EERIE_3D * _pee3d0, EERIE_3D * _pee3d1, EERIE_3D * _pee3d2); void EE_P2(D3DTLVERTEX * in, D3DTLVERTEX * out); __inline void ResetBBox3D(INTERACTIVE_OBJ * io) { if (io) { io->bbox3D.min.x = 99999999.f; io->bbox3D.min.y = 99999999.f; io->bbox3D.min.z = 99999999.f; io->bbox3D.max.x = -99999999.f; io->bbox3D.max.y = -99999999.f; io->bbox3D.max.z = -99999999.f; } } __inline void AddToBBox3D(INTERACTIVE_OBJ * io, EERIE_3D * pos) { if (io) { io->bbox3D.min.x = __min(io->bbox3D.min.x, pos->x); io->bbox3D.min.y = __min(io->bbox3D.min.y, pos->y); io->bbox3D.min.z = __min(io->bbox3D.min.z, pos->z); io->bbox3D.max.x = __max(io->bbox3D.max.x, pos->x); io->bbox3D.max.y = __max(io->bbox3D.max.y, pos->y); io->bbox3D.max.z = __max(io->bbox3D.max.z, pos->z); } } /* Init bounding box */ inline static void Cedric_ResetBoundingBox(INTERACTIVE_OBJ * io) { // resets 2D Bounding Box BBOXMIN.y = BBOXMIN.x = 32000; BBOXMAX.y = BBOXMAX.x = -32000; // Resets 3D Bounding Box ResetBBox3D(io); } //----------------------------------------------------------------------------- __forceinline float GetMaxManhattanDistance(const EERIE_3D * _e1, const EERIE_3D * _e2) { return 0; if (!TSU_TEST) return 0; register float fMaxX(0); register float fMaxY(0); register float fMaxZ(0); fMaxX = _e1->x - _e2->x; fMaxX = (fMaxX < 0) ? -fMaxX : fMaxX; fMaxY = _e1->y - _e2->y; fMaxY = (fMaxY < 0) ? -fMaxY : fMaxY; fMaxZ = _e1->z - _e2->z; fMaxZ = (fMaxZ < 0) ? -fMaxZ : fMaxZ; fMaxX = (fMaxX < fMaxY) ? fMaxY : fMaxX; fMaxX = (fMaxX < fMaxZ) ? fMaxZ : fMaxX; return fMaxX; } extern float INVISIBILITY_OVERRIDE; extern long EXTERNALVIEW; static void Cedric_GetScale(float & scale, float & invisibility, INTERACTIVE_OBJ * io) { if (io) { invisibility = io->invisibility; if (invisibility > 1.f) invisibility -= 1.f; if ((io != inter.iobj[0]) && (invisibility > 0.f) && (!EXTERNALVIEW)) { long num = ARX_SPELLS_GetSpellOn(io, SPELL_INVISIBILITY); if (num >= 0) { if (player.Full_Skill_Intuition > spells[num].caster_level * 10) { invisibility -= (float)player.Full_Skill_Intuition * DIV100 + (float)spells[num].caster_level * DIV10; if (invisibility < 0.1f) invisibility = 0.1f; else if (invisibility > 1.f) invisibility = 1.f; } } } // Scaling Value for this object (Movements will also be scaled) scale = io->scale; } else { if (INVISIBILITY_OVERRIDE != 0.f) { invisibility = INVISIBILITY_OVERRIDE; if (invisibility > 1.f) invisibility -= 1.f; } else { invisibility = 0.f; } scale = 1.f; } } static void Cedric_GetTime(float & timm, INTERACTIVE_OBJ * io, long typ) { if ((io) && (!(typ & ANIMQUATTYPE_FIRST_PERSON))) { if (io->nb_lastanimvertex) { timm = (FrameTime - io->lastanimtime) + 0.0001f; if (timm >= 300.f) { timm = 0.f; io->nb_lastanimvertex = 0; } else { timm *= DIV300; if (timm >= 1.f) timm = 0.f; else if (timm < 0.f) timm = 0.f; } } else timm = 0.f; } else timm = 0.f; } #define ANIMQUATTYPE_NO_COMPUTATIONS 8 /* Evaluate main entity translation */ static void Cedric_AnimCalcTranslation(INTERACTIVE_OBJ * io, ANIM_USE * animuse, float scale, long typ, EERIE_3D & ftr, EERIE_3D & ftr2) { // Resets Frame Translate Vector_Init(&ftr); Vector_Init(&ftr2); // Fill frame translate values with multi-layer translate informations... for (int count = MAX_ANIM_LAYERS - 1; count >= 0; count--) { EERIE_ANIM * eanim; if (!io) { count = -1; } else { animuse = &io->animlayer[count]; } if (!animuse) continue; if (!animuse->cur_anim) continue; eanim = animuse->cur_anim->anims[animuse->altidx_cur]; if (!eanim) continue; //Avoiding impossible cases if (animuse->fr < 0) { animuse->fr = 0; animuse->pour = 0.f; } else if (animuse->fr >= eanim->nb_key_frames - 1) { animuse->fr = eanim->nb_key_frames - 2; animuse->pour = 1.f; } else if (animuse->pour > 1.f) animuse->pour = 1.f; else if (animuse->pour < 0.f) animuse->pour = 0.f; // FRAME TRANSLATE : Gives the Virtual pos of Main Object if (((eanim->frames[animuse->fr].f_translate) && (!(animuse->flags & EA_STATICANIM)))) { EERIE_FRAME * sFrame = &eanim->frames[animuse->fr]; EERIE_FRAME * eFrame = &eanim->frames[animuse->fr+1]; // Linear interpolation of object translation (MOVE) ftr.x = sFrame->translate.x + (eFrame->translate.x - sFrame->translate.x) * animuse->pour; ftr.y = sFrame->translate.y + (eFrame->translate.y - sFrame->translate.y) * animuse->pour; ftr.z = sFrame->translate.z + (eFrame->translate.z - sFrame->translate.z) * animuse->pour; if ((io) && !(typ & ANIMQUATTYPE_NO_RENDER)) { ftr.x *= scale; ftr.y *= scale; ftr.z *= scale; float temp = DEG2RAD(MAKEANGLE(180.f - io->angle.b)); if (io == inter.iobj[0]) temp = DEG2RAD(MAKEANGLE(180.f - player.angle.b)); _YRotatePoint(&ftr, &ftr2, (float)EEcos(temp), (float)EEsin(temp)); // stores Translations for a later use io->move.x = ftr2.x; io->move.y = ftr2.y; io->move.z = ftr2.z; } } } if ((io) && (io->animlayer[0].cur_anim) && !(typ & ANIMQUATTYPE_NO_RENDER)) { // Use calculated value to notify the Movement engine of the translation to do if (io->ioflags & IO_NPC) { Vector_Init(&ftr); io->move.x -= io->lastmove.x; io->move.y -= io->lastmove.y; io->move.z -= io->lastmove.z; } // Must recover translations for NON-NPC IO else { if (io->GameFlags & GFLAG_ELEVATOR) { PushIO_ON_Top(io, io->move.y - io->lastmove.y); } } io->lastmove.x = ftr2.x; io->lastmove.y = ftr2.y; io->lastmove.z = ftr2.z; } } long Looking_At = -1; // Animate skeleton static void Cedric_AnimateObject(INTERACTIVE_OBJ * io, EERIE_3DOBJ * eobj, ANIM_USE * animuse) { int j, l; EERIE_ANIM * eanim = animuse->cur_anim->anims[animuse->altidx_cur]; EERIE_C_DATA * obj = eobj->c_data; for (long count = MAX_ANIM_LAYERS - 1; count >= 0; count--) { EERIE_QUAT t, temp; EERIE_3D vect; EERIE_3D scale; if (!io) { count = -1; if (animuse->cur_anim == NULL) continue; eanim = animuse->cur_anim->anims[animuse->altidx_cur]; } else { animuse = &io->animlayer[count]; if (animuse->cur_anim == NULL) continue; eanim = animuse->cur_anim->anims[animuse->altidx_cur]; } if (!animuse) continue; if (!eanim) continue; if (animuse->fr < 0) { animuse->fr = 0; animuse->pour = 0.f; } else if (animuse->fr >= eanim->nb_key_frames - 1) { animuse->fr = eanim->nb_key_frames - 2; animuse->pour = 1.f; } else if (animuse->pour > 1.f) animuse->pour = 1.f; else if (animuse->pour < 0.f) animuse->pour = 0.f; // Now go for groups rotation/translation/scaling, And transform Linked objects by the way l = __min(eobj->nbgroups - 1, eanim->nb_groups - 1); for (j = l; j >= 0; j--) { if (grps[j]) continue; EERIE_GROUP * sGroup = &eanim->groups[j+(animuse->fr*eanim->nb_groups)]; EERIE_GROUP * eGroup = &eanim->groups[j+(animuse->fr*eanim->nb_groups)+eanim->nb_groups]; if (!eanim->voidgroups[j]) grps[j] = 1; if (eanim->nb_key_frames != 1) { Quat_Slerp(&t, &sGroup->quat, &eGroup->quat, animuse->pour); Quat_Copy(&temp, &obj->bones[j].quatinit); Quat_Multiply(&obj->bones[j].quatinit, &temp, &t); vect.x = sGroup->translate.x + (eGroup->translate.x - sGroup->translate.x) * animuse->pour; vect.y = sGroup->translate.y + (eGroup->translate.y - sGroup->translate.y) * animuse->pour; vect.z = sGroup->translate.z + (eGroup->translate.z - sGroup->translate.z) * animuse->pour; Vector_Add(&obj->bones[j].transinit, &vect, &obj->bones[j].transinit_global); scale.x = sGroup->zoom.x + (eGroup->zoom.x - sGroup->zoom.x) * animuse->pour; scale.y = sGroup->zoom.y + (eGroup->zoom.y - sGroup->zoom.y) * animuse->pour; scale.z = sGroup->zoom.z + (eGroup->zoom.z - sGroup->zoom.z) * animuse->pour; if (BH_MODE) { if (j == eobj->fastaccess.head_group) { scale.x += 1.f; scale.y += 1.f; scale.z += 1.f; } } Vector_Copy(&obj->bones[j].scaleinit, &scale); } } } } /* Apply transformations on all bones */ void Cedric_ConcatenateTM(INTERACTIVE_OBJ * io, EERIE_C_DATA * obj, EERIE_3D * angle, EERIE_3D * pos, EERIE_3D & ftr, float g_scale) { int i; if (!obj) return; for (i = 0; i != obj->nb_bones; i++) { EERIE_QUAT qt2; EERIE_3D vt1; if (obj->bones[i].father >= 0) // Child Bones { // Rotation Quat_Multiply(&obj->bones[i].quatanim, &obj->bones[obj->bones[i].father].quatanim, &obj->bones[i].quatinit); // Translation obj->bones[i].transanim.x = obj->bones[i].transinit.x * obj->bones[obj->bones[i].father].scaleanim.x; obj->bones[i].transanim.y = obj->bones[i].transinit.y * obj->bones[obj->bones[i].father].scaleanim.y; obj->bones[i].transanim.z = obj->bones[i].transinit.z * obj->bones[obj->bones[i].father].scaleanim.z; TransformVertexQuat(&obj->bones[obj->bones[i].father].quatanim, &obj->bones[i].transanim, &obj->bones[i].transanim); Vector_Add(&obj->bones[i].transanim, &obj->bones[obj->bones[i].father].transanim, &obj->bones[i].transanim); /* Scale */ obj->bones[i].scaleanim.x = (obj->bones[i].scaleinit.x + 1.f) * obj->bones[obj->bones[i].father].scaleanim.x; obj->bones[i].scaleanim.y = (obj->bones[i].scaleinit.y + 1.f) * obj->bones[obj->bones[i].father].scaleanim.y; obj->bones[i].scaleanim.z = (obj->bones[i].scaleinit.z + 1.f) * obj->bones[obj->bones[i].father].scaleanim.z; } else // Root Bone { // Rotation if ((io) && !(io->ioflags & IO_NPC)) { // To correct invalid angle in Animated FIX/ITEMS EERIE_3D ang; Vector_Copy(&ang, angle); ang.a = (360 - ang.a); ang.b = (ang.b); ang.g = (ang.g); EERIEMATRIX mat; EERIE_3D vect, up; Vector_Init(&vect, 0, 0, 1); Vector_Init(&up, 0, 1, 0); VRotateY(&vect, ang.b); VRotateX(&vect, ang.a); VRotateZ(&vect, ang.g); VRotateY(&up, ang.b); VRotateX(&up, ang.a); VRotateZ(&up, ang.g); MatrixSetByVectors(&mat, &vect, &up); QuatFromMatrix(qt2, mat); Quat_Multiply(&obj->bones[i].quatanim, &qt2, &obj->bones[i].quatinit); } else { Vector_Copy(&vt1, angle); vt1.x *= EEdef_DEGTORAD; vt1.y *= EEdef_DEGTORAD; vt1.z *= EEdef_DEGTORAD; QuatFromAngles(&qt2, &vt1); Quat_Multiply(&obj->bones[i].quatanim, &qt2, &obj->bones[i].quatinit); } // Translation Vector_Add(&vt1, &obj->bones[i].transinit, &ftr); TransformVertexQuat(&qt2, &vt1, &obj->bones[i].transanim); obj->bones[i].transanim.x *= g_scale; obj->bones[i].transanim.y *= g_scale; obj->bones[i].transanim.z *= g_scale; Vector_Add(&obj->bones[i].transanim, pos, &obj->bones[i].transanim); // Compute Global Object Scale AND Global Animation Scale obj->bones[i].scaleanim.x = (obj->bones[i].scaleinit.x + 1.f) * g_scale; obj->bones[i].scaleanim.y = (obj->bones[i].scaleinit.y + 1.f) * g_scale; obj->bones[i].scaleanim.z = (obj->bones[i].scaleinit.z + 1.f) * g_scale; } } } void EE_RT(D3DTLVERTEX * in, EERIE_3D * out); void EE_P(EERIE_3D * in, D3DTLVERTEX * out); extern long INTERPOLATE_BETWEEN_BONES; /* Transform object vertices */ int Cedric_TransformVerts(INTERACTIVE_OBJ * io, EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, EERIE_3D * pos, EERIE_3D * angle) { int i, v; EERIE_3DPAD * inVert; EERIE_VERTEX * outVert; /* Transform & project all vertices */ for (i = 0; i != obj->nb_bones; i++) { EERIEMATRIX matrix; EERIE_3D vector; MatrixFromQuat(&matrix, &obj->bones[i].quatanim); Vector_Copy(&vector, &obj->bones[i].transanim); // Apply Scale matrix._11 *= obj->bones[i].scaleanim.x; matrix._12 *= obj->bones[i].scaleanim.x; matrix._13 *= obj->bones[i].scaleanim.x; matrix._21 *= obj->bones[i].scaleanim.y; matrix._22 *= obj->bones[i].scaleanim.y; matrix._23 *= obj->bones[i].scaleanim.y; matrix._31 *= obj->bones[i].scaleanim.z; matrix._32 *= obj->bones[i].scaleanim.z; matrix._33 *= obj->bones[i].scaleanim.z; for (v = 0; v != obj->bones[i].nb_idxvertices; v++) { inVert = &eobj->vertexlocal[obj->bones[i].idxvertices[v]]; outVert = &eobj->vertexlist3[obj->bones[i].idxvertices[v]]; TransformVertexMatrix(&matrix, (EERIE_3D *)inVert, &outVert->v); Vector_Add(&outVert->v, &vector, &outVert->v); outVert->vert.sx = outVert->v.x; outVert->vert.sy = outVert->v.y; outVert->vert.sz = outVert->v.z; } } if (FLAG_ALLOW_CLOTHES && eobj->cdata && eobj->sdata) { for (i = 0; i < eobj->nbvertex; i++) { eobj->vertexlist[i].vert.sx = eobj->vertexlist3[i].v.x - pos->x; eobj->vertexlist[i].vert.sy = eobj->vertexlist3[i].v.y - pos->y; eobj->vertexlist[i].vert.sz = eobj->vertexlist3[i].v.z - pos->z; } } for (i = 0; i < eobj->nbvertex; i++) { outVert = &eobj->vertexlist3[i]; AddToBBox3D(io, &outVert->v); EE_RT(&outVert->vert, &outVert->vworld); EE_P(&outVert->vworld, &outVert->vert); // Updates 2D Bounding Box if (outVert->vert.rhw > 0.f) { BBOXMIN.x = __min(BBOXMIN.x, outVert->vert.sx); BBOXMAX.x = __max(BBOXMAX.x, outVert->vert.sx); BBOXMIN.y = __min(BBOXMIN.y, outVert->vert.sy); BBOXMAX.y = __max(BBOXMAX.y, outVert->vert.sy); } } if ((io) && (io->ioflags & IO_NPC) && (io->_npcdata->behavior & BEHAVIOUR_FIGHT) && (EEDistance3D(&io->pos, &player.pos) < 240.f)) return true; if ((io != inter.iobj[0]) && (!EXTERNALVIEW) && (!eobj->cdata) && ((BBOXMIN.x >= DANAESIZX - 1) || (BBOXMAX.x <= 1) || (BBOXMIN.y >= DANAESIZY - 1) || (BBOXMAX.y <= 1)) ) { return false; } if (ARX_SCENE_PORTAL_ClipIO(io, eobj, pos, &BBOXMIN, &BBOXMAX)) return false; return true; } extern INTERACTIVE_OBJ * DESTROYED_DURING_RENDERING; long special_color_flag = 0; EERIE_RGB special_color; extern long DEBUG_PATHFAIL; extern long FINAL_RELEASE; extern long TRAP_DETECT; extern long TRAP_SECRET; extern long FRAME_COUNT; extern long ALTERNATE_LIGHTING; extern float GLOBAL_LIGHT_FACTOR; /* Object dynamic lighting */ bool Cedric_ApplyLighting(EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, INTERACTIVE_OBJ * io, EERIE_3D * pos, long typ) { EERIE_RGB infra; int i, v, l; EERIE_3D tv; EERIE_3D vTLights[32];//MAX_LLIGHTS]; /* Same as above but in bone space (for faster calculation) */ ZeroMemory(&infra, sizeof(EERIE_RGB)); special_color_flag = 0; if (io) { float poisonpercent = 0.f; float trappercent = 0.f; float secretpercent = 0.f; if (io->ioflags & IO_NPC) { if ((DEBUG_PATHFAIL) && (!FINAL_RELEASE)) { if (io->_npcdata->pathfind.listnb == -2) trappercent = 1; if (io->_npcdata->pathfind.pathwait) poisonpercent = 1; } if (io->_npcdata->poisonned > 0.f) { poisonpercent = io->_npcdata->poisonned * DIV20; if (poisonpercent > 1.f) poisonpercent = 1.f; } } if ((io->ioflags & IO_ITEM) && (io->poisonous > 0.f) && (io->poisonous_count != 0)) { poisonpercent = (float)io->poisonous * DIV20; if (poisonpercent > 1.f) poisonpercent = 1.f; } if ((io->ioflags & IO_FIX) && (io->_fixdata->trapvalue > -1)) { trappercent = (float)TRAP_DETECT - (float)io->_fixdata->trapvalue; if (trappercent > 0.f) { trappercent = 0.6f + trappercent * DIV100; if (trappercent < 0.6f) trappercent = 0.6f; if (trappercent > 1.f) trappercent = 1.f; } } if ((io->ioflags & IO_FIX) && (io->secretvalue > -1)) { secretpercent = (float)TRAP_SECRET - (float)io->secretvalue; if (secretpercent > 0.f) { secretpercent = 0.6f + secretpercent * DIV100; if (secretpercent < 0.6f) secretpercent = 0.6f; else if (secretpercent > 1.f) secretpercent = 1.f; } } if (poisonpercent > 0.f) { special_color_flag = 1; special_color.r = 0.f; special_color.g = 1.f; special_color.b = 0.f; } if (trappercent > 0.f) { special_color_flag = 1; special_color.r = trappercent; special_color.g = 1.f - trappercent; special_color.b = 1.f - trappercent; } if (secretpercent > 0.f) { special_color_flag = 1; special_color.r = 1.f - secretpercent; special_color.g = 1.f - secretpercent; special_color.b = secretpercent; } if (io->ioflags & IO_FREEZESCRIPT) { special_color_flag = 1; special_color.r = 0.f; special_color.g = 0.f; special_color.b = 1.f; } if (io->sfx_flag & SFX_TYPE_YLSIDE_DEATH) { if (io->show == SHOW_FLAG_TELEPORTING) { float fTime = io->sfx_time + FrameDiff; ARX_CHECK_ULONG(fTime); io->sfx_time = ARX_CLEAN_WARN_CAST_LONG(fTime); if (io->sfx_time >= ARXTimeUL()) io->sfx_time = ARXTimeUL(); } else { special_color_flag = 1; float elapsed = ARXTime - io->sfx_time; if (elapsed > 0.f) { if (elapsed < 3000.f) // 5 seconds to red { float ratio = elapsed * DIV3000; special_color.r = 1.f; special_color.g = 1.f - ratio; special_color.b = 1.f - ratio; AddRandomSmoke(io, 1); } else if (elapsed < 6000.f) // 5 seconds to White { float ratio = (elapsed - 3000.f) * DIV3000; special_color.r = ratio; special_color_flag = 2; AddRandomSmoke(io, 2); } else // SFX finish { special_color_flag = 0; io->sfx_time = 0; if (io->ioflags & IO_NPC) { MakePlayerAppearsFX(io); AddRandomSmoke(io, 50); EERIE_RGB rgb; unsigned long color = io->_npcdata->blood_color; rgb.r = (float)((long)((color >> 16) & 255)) * DIV255; rgb.g = (float)((long)((color >> 8) & 255)) * DIV255; rgb.b = (float)((long)((color) & 255)) * DIV255; EERIE_SPHERE sp; sp.origin.x = io->pos.x; sp.origin.y = io->pos.y; sp.origin.z = io->pos.z; sp.radius = 200.f; long count = 6; while (count--) { SpawnGroundSplat(&sp, &rgb, rnd() * 30.f + 30.f, 1); sp.origin.y -= rnd() * 150.f; if (count == 0) ARX_PARTICLES_Spawn_Splat(&sp.origin, 200, io->_npcdata->blood_color, 0, io, 1); else ARX_PARTICLES_Spawn_Splat(&sp.origin, 200, io->_npcdata->blood_color, 0, io, 0); sp.origin.x = io->pos.x + rnd() * 200.f - 100.f; sp.origin.y = io->pos.y + rnd() * 20.f - 10.f; sp.origin.z = io->pos.z + rnd() * 200.f - 100.f; sp.radius = rnd() * 100.f + 100.f; } long nn = GetFreeDynLight(); if (nn >= 0) { DynLight[nn].exist = 1; DynLight[nn].intensity = 0.7f + 2.f * rnd(); DynLight[nn].fallend = 600.f; DynLight[nn].fallstart = 400.f; DynLight[nn].rgb.r = 1.0f; DynLight[nn].rgb.g = 0.8f; DynLight[nn].rgb.b = .0f; DynLight[nn].pos.x = io->pos.x; DynLight[nn].pos.y = io->pos.y - 80.f; DynLight[nn].pos.z = io->pos.z; DynLight[nn].duration = 600; } if (io->sfx_flag & SFX_TYPE_INCINERATE) { io->sfx_flag &= ~SFX_TYPE_INCINERATE; io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; long num = ARX_SPELLS_GetSpellOn(io, SPELL_INCINERATE); if (num < 0) num = ARX_SPELLS_GetSpellOn(io, SPELL_MASS_INCINERATE); if (num >= 0) { spells[num].tolive = 0; float damages = 20 * spells[num].caster_level; damages = ARX_SPELLS_ApplyFireProtection(io, damages); if (ValidIONum(spells[num].caster)) ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &inter.iobj[spells[num].caster]->pos); else ARX_DAMAGES_DamageNPC(io, damages, spells[num].caster, 1, &io->pos); ARX_SOUND_PlaySFX(SND_SPELL_FIRE_HIT, &io->pos); } } else { io->sfx_flag &= ~SFX_TYPE_YLSIDE_DEATH; ARX_INTERACTIVE_DestroyIO(io); DESTROYED_DURING_RENDERING = io; return false; } } } } } } } if (eobj->drawflags & DRAWFLAG_HIGHLIGHT) { special_color_flag = 4; special_color.r = ARX_CLEAN_WARN_CAST_FLOAT(iHighLight); //100.f; special_color.g = ARX_CLEAN_WARN_CAST_FLOAT(iHighLight); //100.f; special_color.b = ARX_CLEAN_WARN_CAST_FLOAT(iHighLight); //100.f; } if (FRAME_COUNT > 0) return true; if (Project.improve) { if (io != NULL) { infra.r = io->infracolor.r; infra.g = io->infracolor.g; infra.b = io->infracolor.b; } else { infra.r = 0.6f; infra.g = 0.f; infra.b = 1.f; } } /* Get nearest lights */ tv = *pos; if (typ & ANIMQUATTYPE_FIRST_PERSON) { tv.x = subj.pos.x; tv.y = subj.pos.y; tv.z = subj.pos.z; } if ((io) && (io->obj->fastaccess.view_attach >= 0) && (io->obj->fastaccess.head_group_origin != -1)) { tv.y = io->obj->vertexlist3[io->obj->fastaccess.head_group_origin].v.y + 10; } else tv.y -= 90.f; llightsInit(); for (i = 0; i < TOTIOPDL; i++) { if (!(GetMaxManhattanDistance(&IO_PDL[i]->pos, &tv) <= IO_PDL[i]->fallend + 500.f)) continue; Insertllight(IO_PDL[i], TRUEEEDistance3D(&IO_PDL[i]->pos, &tv)); } for (i = 0; i < TOTPDL; i++) { if (!(GetMaxManhattanDistance(&PDL[i]->pos, &tv) <= PDL[i]->fallend + 500.f)) continue; Insertllight(PDL[i], TRUEEEDistance3D(&PDL[i]->pos, &tv));//-PDL[i]->fallstart); } if (!USEINTERNORM) { /* Apply light on all vertices */ for (i = 0; i != obj->nb_bones; i++) { /* Get light value for each vertex */ for (v = 0; v != obj->bones[i].nb_idxvertices; v++) { EERIE_3DPAD * inVert; EERIE_3D * posVert; float r, g, b; long ir, ig, ib; if (io) { inVert = (EERIE_3DPAD *)&io->obj->vertexlist[obj->bones[i].idxvertices[v]].norm; posVert = (EERIE_3D *)&io->obj->vertexlist3[obj->bones[i].idxvertices[v]].v; } else { inVert = (EERIE_3DPAD *)&eobj->vertexlist[obj->bones[i].idxvertices[v]].norm; posVert = (EERIE_3D *)&eobj->vertexlist3[obj->bones[i].idxvertices[v]].v; } /* Ambient light */ if ((io) && (io->ioflags & (IO_NPC | IO_ITEM))) { r = g = b = NPC_ITEMS__AMBIENT_VALUE_255; } else { r = ACTIVEBKG->ambient255.r; g = ACTIVEBKG->ambient255.g; b = ACTIVEBKG->ambient255.b; } /* Dynamic lights */ for (l = 0 ; l != MAX_LLIGHTS; l++) { EERIE_LIGHT * Cur_llights = llights[l]; if (Cur_llights) { // tsu if (!(GetMaxManhattanDistance(&Cur_llights->pos, (EERIE_3D *)&posVert) <= Cur_llights->fallend)) { TSU_TEST_NB_LIGHT ++; continue; } float cosangle; float distance = EEDistance3D((EERIE_3D *)posVert, &Cur_llights->pos); /* Evaluate its intensity depending on the distance Light<->Object */ if (distance <= Cur_llights->fallstart) cosangle = Cur_llights->intensity * GLOBAL_LIGHT_FACTOR; else { float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul); if (p <= 0.f) cosangle = 0.f; else cosangle = p * Cur_llights->precalc; //>intensity*GLOBAL_LIGHT_FACTOR; } r += Cur_llights->rgb255.r * cosangle; g += Cur_llights->rgb255.g * cosangle; b += Cur_llights->rgb255.b * cosangle; } else break; } if (special_color_flag) { if (special_color_flag & 1) { r *= special_color.r; g *= special_color.g; b *= special_color.b; } else if (special_color_flag & 2) { r = 1.f; g = 0.f; b = 0.f; } else if (special_color_flag & 4) // HIGHLIGHT { r += special_color.r; g += special_color.g; b += special_color.b; } } /* PACK color */ F2L(r, &ir); F2L(g, &ig); F2L(b, &ib); ir = clipByte255(ir); ig = clipByte255(ig); ib = clipByte255(ib); eobj->vertexlist3[obj->bones[i].idxvertices[v]].vert.color = (0xFF000000L | ((ir) << 16) | ((ig) << 8) | (ib)); } } } else { /* Apply light on all vertices */ for (i = 0; i != obj->nb_bones; i++) { EERIE_QUAT qt1; EERIEMATRIX matrix;//,omatrix; Quat_Copy(&qt1, &obj->bones[i].quatanim); Quat_Reverse(&qt1); MatrixFromQuat(&matrix, &qt1); // FMatrixInvert(matrix,omatrix); /* Get light value for each vertex */ for (v = 0; v != obj->bones[i].nb_idxvertices; v++) { EERIE_3DPAD * inVert; float r, g, b; long ir, ig, ib; inVert = (EERIE_3DPAD *)&eobj->vertexlist[obj->bones[i].idxvertices[v]].norm; /* Ambient light */ if ((io) && (io->ioflags & (IO_NPC | IO_ITEM))) { r = g = b = NPC_ITEMS__AMBIENT_VALUE_255; } else { r = ACTIVEBKG->ambient255.r; g = ACTIVEBKG->ambient255.g; b = ACTIVEBKG->ambient255.b; } /* Dynamic lights */ for (l = 0 ; l != MAX_LLIGHTS; l++) { EERIE_LIGHT * Cur_llights = llights[l]; if (Cur_llights) { float cosangle; EERIE_3D * Cur_vTLights = &vTLights[l]; EERIE_3D tl; tl.x = (Cur_llights->pos.x - eobj->vertexlist3[obj->bones[i].idxvertices[v]].v.x); tl.y = (Cur_llights->pos.y - eobj->vertexlist3[obj->bones[i].idxvertices[v]].v.y); tl.z = (Cur_llights->pos.z - eobj->vertexlist3[obj->bones[i].idxvertices[v]].v.z); float dista = Vector_Magnitude(&tl); if (dista < Cur_llights->fallend) { float divv = 1.f / dista; tl.x *= divv; tl.y *= divv; tl.z *= divv; VectorMatrixMultiply(Cur_vTLights, &tl, &matrix); cosangle = (inVert->x * Cur_vTLights->x + inVert->y * Cur_vTLights->y + inVert->z * Cur_vTLights->z); /* If light visible */ if (cosangle > 0.0f) { /* Evaluate its intensity depending on the distance Light<->Object */ if (dista <= Cur_llights->fallstart) cosangle *= Cur_llights->precalc; else { float p = ((Cur_llights->fallend - dista) * Cur_llights->falldiffmul); if (p <= 0.f) cosangle = 0.f; else cosangle *= p * Cur_llights->precalc; } r += Cur_llights->rgb255.r * cosangle; g += Cur_llights->rgb255.g * cosangle; b += Cur_llights->rgb255.b * cosangle; } } } else break; } /* Fake adjust */ if (Project.improve) { r *= infra.r; g *= infra.g; b *= infra.b; } if (special_color_flag) { if (special_color_flag & 1) { r *= special_color.r; g *= special_color.g; b *= special_color.b; } else if (special_color_flag & 2) { r = 1.f; g = 0.f; b = 0.f; } else if (special_color_flag & 4) // HIGHLIGHT { r += special_color.r; g += special_color.g; b += special_color.b; } } /* PACK color */ F2L(r, &ir); F2L(g, &ig); F2L(b, &ib); ir = clipByte255(ir); ig = clipByte255(ig); ib = clipByte255(ib); eobj->vertexlist3[obj->bones[i].idxvertices[v]].vert.color = (0xFF000000L | ((ir) << 16) | ((ig) << 8) | (ib)); } } } return true; } void Cedric_PrepareHalo(LPDIRECT3DDEVICE7 pd3dDevice, EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, INTERACTIVE_OBJ * io, EERIE_3D * pos, EERIE_3D & ftr) { EERIE_3D cam_vector, t_vector; cam_vector.x = -EEsin(DEG2RAD(ACTIVECAM->angle.b)) * EEcos(DEG2RAD(ACTIVECAM->angle.a)); cam_vector.y = EEsin(DEG2RAD(ACTIVECAM->angle.a)); cam_vector.z = EEcos(DEG2RAD(ACTIVECAM->angle.b)) * EEcos(DEG2RAD(ACTIVECAM->angle.a)); /* Apply light on all vertices */ for (long i = 0; i != obj->nb_bones; i++) { EERIE_QUAT qt1; Quat_Copy(&qt1, &obj->bones[i].quatanim); TransformInverseVertexQuat(&qt1, &cam_vector, &t_vector); /* Get light value for each vertex */ for (long v = 0; v != obj->bones[i].nb_idxvertices; v++) { EERIE_3DPAD * inVert; //inVert = &eobj->normallocal[obj->bones[i].idxvertices[v]]; inVert = (EERIE_3DPAD *)&eobj->vertexlist[obj->bones[i].idxvertices[v]].norm; /* Get cos angle between light and vertex norm */ eobj->vertexlist3[obj->bones[i].idxvertices[v]].norm.z = (inVert->x * t_vector.x + inVert->y * t_vector.y + inVert->z * t_vector.z); } } } //----------------------------------------------------------------------------- __forceinline void ARX_ClippZ(D3DTLVERTEX * _pD3DA, D3DTLVERTEX * _pD3DB, EERIE_VERTEX * _pVertexA, EERIE_VERTEX * _pVertexB, D3DTLVERTEX * _pOut) { EERIE_3D e3dTemp; float fDenom = (SOFTNEARCLIPPZ - _pVertexB->vworld.z) / (_pVertexA->vworld.z - _pVertexB->vworld.z); e3dTemp.x = (_pVertexA->vworld.x - _pVertexB->vworld.x) * fDenom + _pVertexB->vworld.x; e3dTemp.y = (_pVertexA->vworld.y - _pVertexB->vworld.y) * fDenom + _pVertexB->vworld.y; e3dTemp.z = SOFTNEARCLIPPZ ; float fRA, fGA, fBA; float fRB, fGB, fBB; fRA = ARX_CLEAN_WARN_CAST_FLOAT((_pD3DA->color >> 16) & 255); fGA = ARX_CLEAN_WARN_CAST_FLOAT((_pD3DA->color >> 8) & 255); fBA = ARX_CLEAN_WARN_CAST_FLOAT(_pD3DA->color & 255); fRB = ARX_CLEAN_WARN_CAST_FLOAT((_pD3DB->color >> 16) & 255); fGB = ARX_CLEAN_WARN_CAST_FLOAT((_pD3DB->color >> 8) & 255); fBB = ARX_CLEAN_WARN_CAST_FLOAT(_pD3DB->color & 255); float fRC, fGC, fBC; fRC = (fRA - fRB) * fDenom + fRB; fGC = (fGA - fGB) * fDenom + fGB; fBC = (fBA - fBB) * fDenom + fBB; _pOut->color = (((int)fRC) << 16) | (((int)fGC) << 8) | ((int)fBC); _pOut->tu = (_pD3DA->tu - _pD3DB->tu) * fDenom + _pD3DB->tu; _pOut->tv = (_pD3DA->tv - _pD3DB->tv) * fDenom + _pD3DB->tv; EE_P(&e3dTemp, _pOut); } //----------------------------------------------------------------------------- void ARX_DrawPrimitive_ClippZ(D3DTLVERTEX * _pVertexA, D3DTLVERTEX * _pVertexB, D3DTLVERTEX * _pOut, float _fAdd = 0.f); void ARX_DrawPrimitive_ClippZ(D3DTLVERTEX * _pVertexA, D3DTLVERTEX * _pVertexB, D3DTLVERTEX * _pOut, float _fAdd) { EERIE_3D e3dTemp; float fDenom = ((SOFTNEARCLIPPZ + _fAdd) - _pVertexB->sz) / (_pVertexA->sz - _pVertexB->sz); e3dTemp.x = (_pVertexA->sx - _pVertexB->sx) * fDenom + _pVertexB->sx; e3dTemp.y = (_pVertexA->sy - _pVertexB->sy) * fDenom + _pVertexB->sy; e3dTemp.z = SOFTNEARCLIPPZ + _fAdd; float fRA, fGA, fBA; float fRB, fGB, fBB; fRA = ARX_CLEAN_WARN_CAST_FLOAT((_pVertexA->color >> 16) & 255); fGA = ARX_CLEAN_WARN_CAST_FLOAT((_pVertexA->color >> 8) & 255); fBA = ARX_CLEAN_WARN_CAST_FLOAT(_pVertexA->color & 255); fRB = ARX_CLEAN_WARN_CAST_FLOAT((_pVertexB->color >> 16) & 255); fGB = ARX_CLEAN_WARN_CAST_FLOAT((_pVertexB->color >> 8) & 255); fBB = ARX_CLEAN_WARN_CAST_FLOAT(_pVertexB->color & 255); float fRC, fGC, fBC; fRC = (fRA - fRB) * fDenom + fRB; fGC = (fGA - fGB) * fDenom + fGB; fBC = (fBA - fBB) * fDenom + fBB; _pOut->color = (((int) fRC) << 16) | (((int)fGC) << 8) | ((int) fBC); _pOut->tu = (_pVertexA->tu - _pVertexB->tu) * fDenom + _pVertexB->tu; _pOut->tv = (_pVertexA->tv - _pVertexB->tv) * fDenom + _pVertexB->tv; EE_P(&e3dTemp, _pOut); } //----------------------------------------------------------------------------- D3DTLVERTEX * GetNewVertexList(EERIE_FACE * _pFace, float _fInvisibility, TextureContainer * _pTex) { if ((_pFace->facetype & POLY_TRANS) || (_fInvisibility > 0.f)) { float fTransp; if (_fInvisibility > 0.f) fTransp = 2.f - _fInvisibility; else fTransp = _pFace->transval; if (fTransp >= 2.f) //MULTIPLICATIVE { fTransp *= DIV2; fTransp += 0.5f; return PushVertexInTableCull_TMultiplicative(_pTex); } else { if (fTransp >= 1.f) //ADDITIVE { fTransp -= 1.f; return PushVertexInTableCull_TAdditive(_pTex); } else { if (fTransp > 0.f) //NORMAL TRANS { fTransp = 1.f - fTransp; return PushVertexInTableCull_TNormalTrans(_pTex); } else //SUBTRACTIVE { fTransp = 1.f - fTransp; return PushVertexInTableCull_TSubstractive(_pTex); } } } } else { return PushVertexInTableCull(_pTex); } } //----------------------------------------------------------------------------- int ARX_SoftClippZ(EERIE_VERTEX * _pVertex1, EERIE_VERTEX * _pVertex2, EERIE_VERTEX * _pVertex3, D3DTLVERTEX ** _ptV, EERIE_FACE * _pFace, float _fInvibility, TextureContainer * _pTex, bool _bBump, bool _bZMapp, EERIE_3DOBJ * _pObj, int _iNumFace, long * _pInd, INTERACTIVE_OBJ * _pioInteractive, bool _bNPC, long _lSpecialColorFlag, EERIE_RGB * _pRGB, bool _bPassTANDL) { int iPointAdd = 3; int iClipp = 0; if ((_pVertex1->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 1; if ((_pVertex2->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 2; if ((_pVertex3->vworld.z) < SOFTNEARCLIPPZ) iClipp |= 4; D3DTLVERTEX D3DClippZ1, D3DClippZ2; D3DTLVERTEX * pD3DPointAdd = NULL; D3DTLVERTEX * ptV = *_ptV; switch (iClipp) { case 1: //pt1 outside ARX_ClippZ(&ptV[0], &ptV[1], _pVertex1, _pVertex2, &D3DClippZ1); ARX_ClippZ(&ptV[0], &ptV[2], _pVertex1, _pVertex3, &D3DClippZ2); pD3DPointAdd = GetNewVertexList(_pFace, _fInvibility, _pTex); ptV = pD3DPointAdd - 3; if (pD3DPointAdd) { pD3DPointAdd[0] = D3DClippZ1; pD3DPointAdd[1] = ptV[1]; pD3DPointAdd[2] = D3DClippZ2; } ptV[0] = D3DClippZ2; iPointAdd = 6; break; case 2: //pt2 outside ARX_ClippZ(&ptV[1], &ptV[2], _pVertex2, _pVertex3, &D3DClippZ1); ARX_ClippZ(&ptV[1], &ptV[0], _pVertex2, _pVertex1, &D3DClippZ2); pD3DPointAdd = GetNewVertexList(_pFace, _fInvibility, _pTex); ptV = pD3DPointAdd - 3; if (pD3DPointAdd) { pD3DPointAdd[0] = ptV[2]; pD3DPointAdd[1] = D3DClippZ1; pD3DPointAdd[2] = D3DClippZ2; } ptV[1] = D3DClippZ2; iPointAdd = 6; break; case 4: //pt3 outside ARX_ClippZ(&ptV[2], &ptV[0], _pVertex3, _pVertex1, &D3DClippZ1); ARX_ClippZ(&ptV[2], &ptV[1], _pVertex3, _pVertex2, &D3DClippZ2); pD3DPointAdd = GetNewVertexList(_pFace, _fInvibility, _pTex); ptV = pD3DPointAdd - 3; if (pD3DPointAdd) { pD3DPointAdd[0] = ptV[0]; pD3DPointAdd[1] = D3DClippZ2; pD3DPointAdd[2] = D3DClippZ1; } ptV[2] = D3DClippZ2; iPointAdd = 6; break; case 3: //pt1_2 outside ARX_ClippZ(&ptV[0], &ptV[2], _pVertex1, _pVertex3, &D3DClippZ1); ARX_ClippZ(&ptV[1], &ptV[2], _pVertex2, _pVertex3, &D3DClippZ2); ptV[0] = D3DClippZ1; ptV[1] = D3DClippZ2; break; case 5: //pt1_3 outside ARX_ClippZ(&ptV[0], &ptV[1], _pVertex1, _pVertex2, &D3DClippZ1); ARX_ClippZ(&ptV[2], &ptV[1], _pVertex3, _pVertex2, &D3DClippZ2); ptV[0] = D3DClippZ1; ptV[2] = D3DClippZ2; break; case 6: //pt2_3 outside ARX_ClippZ(&ptV[2], &ptV[0], _pVertex3, _pVertex1, &D3DClippZ1); ARX_ClippZ(&ptV[1], &ptV[0], _pVertex2, _pVertex1, &D3DClippZ2); ptV[1] = D3DClippZ1; ptV[2] = D3DClippZ2; break; case 7: return 0; } if (pD3DPointAdd) { *_ptV = ptV; if (_bBump) { PushInterBump(_pTex, pD3DPointAdd); } if (_bZMapp) { CalculateInterZMapp(_pObj, _iNumFace, _pInd, _pTex, pD3DPointAdd); } if ((_pFace->facetype & POLY_METAL) || ((_pTex) && (_pTex->userflags & POLY_METAL))) { if (_bNPC) { D3DTLVERTEX * tv2; if (_lSpecialColorFlag & 2) { tv2 = PushVertexInTableCull(&TexSpecialColor); memcpy((void *)tv2, (void *)pD3DPointAdd, sizeof(D3DTLVERTEX) * 3); tv2[0].color = tv2[1].color = tv2[2].color = _EERIERGB(_pRGB->r); } tv2 = PushVertexInTableCull_TMetal(_pTex); unsigned long * pulNbVertexList_TMetal = &_pTex->ulNbVertexListCull_TMetal; memcpy((void *)tv2, (void *)pD3DPointAdd, sizeof(D3DTLVERTEX) * 3); long r, g, b; long todo = 0; for (long j = 0; j < 3; j++) { r = (tv2[j].color >> 16) & 255; g = (tv2[j].color >> 8) & 255; b = tv2[j].color & 255; if (r > 192 || g > 192 || b > 192) { todo++; } r -= 192; if (r < 0.f) r = 0; g -= 192; if (g < 0.f) g = 0; b -= 192; if (b < 0.f) b = 0; tv2[j].color = 0xFF000000 | (r << 18) | (g << 10) | (b << 2); } if (!todo) { *pulNbVertexList_TMetal -= 3; } } else { ARX_D3DVERTEX * vert_list_metal = PushVertexInTableCull_TMetal(_pTex); unsigned long * pulNbVertexList_TMetal = &_pTex->ulNbVertexListCull_TMetal; memcpy((void *)vert_list_metal, (void *)pD3DPointAdd, sizeof(D3DTLVERTEX) * 3); D3DTLVERTEX * tl = vert_list_metal; long r, g, b; long todo = 0; r = g = b = 0 ; for (long j = 0 ; j < 3 ; j++) { r = (tl->color >> 16) & 255; g = (tl->color >> 8) & 255; b = tl->color & 255; if (r > 192 || g > 192 || b > 192) { todo++; } r -= 192; if (r < 0.f) r = 0; g -= 192; if (g < 0.f) g = 0; b -= 192; if (b < 0.f) b = 0; tl->color = 0xFF000000 | (r << 18) | (g << 10) | (b << 2); tl++; } if (todo) { if ((todo > 2) && (rnd() > 0.997f)) { if (_pioInteractive) SpawnMetalShine((EERIE_3D *)&_pObj->vertexlist3[_pObj->facelist[_iNumFace].vid[0]].vert, r, g, b, GetInterNum(_pioInteractive)); } } else { *pulNbVertexList_TMetal -= 3; } } } } return iPointAdd; } extern long IsInGroup(EERIE_3DOBJ * obj, long vert, long tw); //----------------------------------------------------------------------------- bool ARX_DrawPrimitive_SoftClippZ(D3DTLVERTEX * _pVertex1, D3DTLVERTEX * _pVertex2, D3DTLVERTEX * _pVertex3, float _fAddZ) { int iClipp = 0; if (_pVertex1->sz < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 1; if (_pVertex2->sz < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 2; if (_pVertex3->sz < (SOFTNEARCLIPPZ + _fAddZ)) iClipp |= 4; D3DTLVERTEX D3DClippZ1, D3DClippZ2; D3DTLVERTEX pD3DPointAdd[6]; int iNbTotVertex = 3; switch (iClipp) { case 0: EERIE_3D e3dTemp; e3dTemp.x = _pVertex1->sx; e3dTemp.y = _pVertex1->sy; e3dTemp.z = _pVertex1->sz; EE_P(&e3dTemp, &pD3DPointAdd[0]); e3dTemp.x = _pVertex2->sx; e3dTemp.y = _pVertex2->sy; e3dTemp.z = _pVertex2->sz; EE_P(&e3dTemp, &pD3DPointAdd[1]); e3dTemp.x = _pVertex3->sx; e3dTemp.y = _pVertex3->sy; e3dTemp.z = _pVertex3->sz; EE_P(&e3dTemp, &pD3DPointAdd[2]); pD3DPointAdd[0].color = _pVertex1->color; pD3DPointAdd[0].specular = _pVertex1->specular; pD3DPointAdd[0].tu = _pVertex1->tu; pD3DPointAdd[0].tv = _pVertex1->tv; pD3DPointAdd[1].color = _pVertex2->color; pD3DPointAdd[1].specular = _pVertex2->specular; pD3DPointAdd[1].tu = _pVertex2->tu; pD3DPointAdd[1].tv = _pVertex2->tv; pD3DPointAdd[2].color = _pVertex3->color; pD3DPointAdd[2].specular = _pVertex3->specular; pD3DPointAdd[2].tu = _pVertex3->tu; pD3DPointAdd[2].tv = _pVertex3->tv; break; case 1: //pt1 outside ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex2, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex3, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = D3DClippZ2; pD3DPointAdd[1] = *_pVertex2; EE_P2(&pD3DPointAdd[1], &pD3DPointAdd[1]); pD3DPointAdd[2] = *_pVertex3; EE_P2(&pD3DPointAdd[2], &pD3DPointAdd[2]); pD3DPointAdd[3] = D3DClippZ1; pD3DPointAdd[4] = pD3DPointAdd[1]; pD3DPointAdd[5] = D3DClippZ2; iNbTotVertex = 6; break; case 2: //pt2 outside ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex3, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex1, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = *_pVertex1; EE_P2(&pD3DPointAdd[0], &pD3DPointAdd[0]); pD3DPointAdd[1] = D3DClippZ2; pD3DPointAdd[2] = *_pVertex3; EE_P2(&pD3DPointAdd[2], &pD3DPointAdd[2]); pD3DPointAdd[3] = pD3DPointAdd[2]; pD3DPointAdd[4] = D3DClippZ1; pD3DPointAdd[5] = D3DClippZ2; iNbTotVertex = 6; break; case 4: //pt3 outside ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex1, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex2, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = *_pVertex1; EE_P2(&pD3DPointAdd[0], &pD3DPointAdd[0]); pD3DPointAdd[1] = *_pVertex2; EE_P2(&pD3DPointAdd[1], &pD3DPointAdd[1]); pD3DPointAdd[2] = D3DClippZ2; pD3DPointAdd[3] = pD3DPointAdd[0]; pD3DPointAdd[4] = D3DClippZ2; pD3DPointAdd[5] = D3DClippZ1; iNbTotVertex = 6; break; case 3: //pt1_2 outside ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex3, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex3, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = D3DClippZ1; pD3DPointAdd[1] = D3DClippZ2; pD3DPointAdd[2] = *_pVertex3; EE_P2(&pD3DPointAdd[2], &pD3DPointAdd[2]); break; case 5: //pt1_3 outside ARX_DrawPrimitive_ClippZ(_pVertex1, _pVertex2, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex2, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = D3DClippZ1; pD3DPointAdd[1] = *_pVertex2; EE_P2(&pD3DPointAdd[1], &pD3DPointAdd[1]); pD3DPointAdd[2] = D3DClippZ2; break; case 6: //pt2_3 outside ARX_DrawPrimitive_ClippZ(_pVertex3, _pVertex1, &D3DClippZ1, _fAddZ); ARX_DrawPrimitive_ClippZ(_pVertex2, _pVertex1, &D3DClippZ2, _fAddZ); pD3DPointAdd[0] = *_pVertex1; EE_P2(&pD3DPointAdd[0], &pD3DPointAdd[0]); pD3DPointAdd[1] = D3DClippZ1; pD3DPointAdd[2] = D3DClippZ2; break; case 7: return false; } EERIEDRAWPRIM(GDevice, D3DPT_TRIANGLELIST, D3DFVF_TLVERTEX, pD3DPointAdd, iNbTotVertex, 0, (bSoftRender?EERIE_USEVB:0) ); return true; } long FORCE_FRONT_DRAW = 0; //----------------------------------------------------------------------------- extern long IN_BOOK_DRAW; /* Render object */ void Cedric_RenderObject2(LPDIRECT3DDEVICE7 pd3dDevice, EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, INTERACTIVE_OBJ * io, EERIE_3D * pos, EERIE_3D & ftr, float invisibility) { int i; float MAX_ZEDE = 0.f; // Sets IO BBox to calculated BBox :) if (io) { io->bbox1.x = (short) BBOXMIN.x; io->bbox2.x = (short) BBOXMAX.x; io->bbox1.y = (short) BBOXMIN.y; io->bbox2.y = (short) BBOXMAX.y; } if (invisibility == 1.f) return; float ddist = 0.f; long need_halo; need_halo = 0; INTERACTIVE_OBJ * hio_helmet = NULL; INTERACTIVE_OBJ * hio_armor = NULL; INTERACTIVE_OBJ * hio_leggings = NULL; INTERACTIVE_OBJ * hio_player = NULL; INTERACTIVE_OBJ * use_io = io; if ((!io) && (IN_BOOK_DRAW) && (eobj == inter.iobj[0]->obj)) use_io = inter.iobj[0]; if (use_io) { if (use_io == inter.iobj[0]) { if ((player.equiped[EQUIP_SLOT_HELMET] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_HELMET])) { INTERACTIVE_OBJ * tio = inter.iobj[player.equiped[EQUIP_SLOT_HELMET]]; if (tio->halo.flags & HALO_ACTIVE) hio_helmet = tio; } if ((player.equiped[EQUIP_SLOT_ARMOR] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_ARMOR])) { INTERACTIVE_OBJ * tio = inter.iobj[player.equiped[EQUIP_SLOT_ARMOR]]; if (tio->halo.flags & HALO_ACTIVE) hio_armor = tio; } if ((player.equiped[EQUIP_SLOT_LEGGINGS] != 0) && ValidIONum(player.equiped[EQUIP_SLOT_LEGGINGS])) { INTERACTIVE_OBJ * tio = inter.iobj[player.equiped[EQUIP_SLOT_LEGGINGS]]; if (tio->halo.flags & HALO_ACTIVE) hio_leggings = tio; } if (use_io->halo.flags & HALO_ACTIVE) hio_player = use_io; } if (hio_player || hio_armor || hio_leggings || hio_helmet || (use_io->halo.flags & HALO_ACTIVE)) { float mdist = ACTIVECAM->cdepth * DIV2; ddist = mdist - Distance3D(pos->x + ftr.x, pos->y + ftr.y, pos->z + ftr.z, ACTIVECAM->pos.x, ACTIVECAM->pos.y, ACTIVECAM->pos.z); ddist = (ddist / mdist); //*0.1f; ddist *= ddist * ddist * ddist * ddist * ddist; if (ddist <= 0.25f) ddist = 0.25f; else if (ddist > 0.9f) ddist = 0.9f; if ((use_io) && (use_io->halo.flags & HALO_DYNLIGHT)) HALO_IO_DynLight_Update(io); Cedric_PrepareHalo(pd3dDevice, eobj, obj, use_io, pos, ftr); need_halo = 1; MAX_ZEDE = 0.f; for (long i = 0 ; i < eobj->nbvertex ; i++) { if (eobj->vertexlist3[i].vert.rhw > 0.f) MAX_ZEDE = __max(eobj->vertexlist3[i].vert.sz, MAX_ZEDE); } } } { bool bPassInTANDL; bool bBumpOnIO; float fDist = EEDistance3D(pos, &ACTIVECAM->pos); bPassInTANDL = false; bBumpOnIO = ( bALLOW_BUMP ) && ( io ) && ( io->ioflags & IO_BUMP ) && ( fDist < __min( __max( 0.f, ( ACTIVECAM->cdepth * fZFogStart ) - 200.f ), 600.f ) ) ? true : false ; for (i = 0 ; i < eobj->nbfaces ; i++) { D3DTLVERTEX tv_static[3]; ARX_D3DVERTEX * tv = NULL; EERIE_FACE * eface; long paf[3]; eface = &eobj->facelist[i]; if ((eface->facetype & POLY_HIDE) && (!FORCE_NO_HIDE)) continue; if (bGATI8500) { long OUTSIDE = 0; if (eobj->vertexlist3[eface->vid[0]].vworld.z < SOFTNEARCLIPPTANDLZ) OUTSIDE++; if (eobj->vertexlist3[eface->vid[1]].vworld.z < SOFTNEARCLIPPTANDLZ) OUTSIDE++; if (eobj->vertexlist3[eface->vid[2]].vworld.z < SOFTNEARCLIPPTANDLZ) OUTSIDE++; if (OUTSIDE) { bPassInTANDL = true; } else { bPassInTANDL = false; } } //CULL3D EERIE_3D nrm; nrm.x = eobj->vertexlist3[eface->vid[0]].v.x - ACTIVECAM->pos.x; nrm.y = eobj->vertexlist3[eface->vid[0]].v.y - ACTIVECAM->pos.y; nrm.z = eobj->vertexlist3[eface->vid[0]].v.z - ACTIVECAM->pos.z; if (!(eface->facetype & POLY_DOUBLESIDED)) { EERIE_3D normV10; EERIE_3D normV20; normV10.x = eobj->vertexlist3[eface->vid[1]].v.x - eobj->vertexlist3[eface->vid[0]].v.x; normV10.y = eobj->vertexlist3[eface->vid[1]].v.y - eobj->vertexlist3[eface->vid[0]].v.y; normV10.z = eobj->vertexlist3[eface->vid[1]].v.z - eobj->vertexlist3[eface->vid[0]].v.z; normV20.x = eobj->vertexlist3[eface->vid[2]].v.x - eobj->vertexlist3[eface->vid[0]].v.x; normV20.y = eobj->vertexlist3[eface->vid[2]].v.y - eobj->vertexlist3[eface->vid[0]].v.y; normV20.z = eobj->vertexlist3[eface->vid[2]].v.z - eobj->vertexlist3[eface->vid[0]].v.z; EERIE_3D normFace; normFace.x = (normV10.y * normV20.z) - (normV10.z * normV20.y); normFace.y = (normV10.z * normV20.x) - (normV10.x * normV20.z); normFace.z = (normV10.x * normV20.y) - (normV10.y * normV20.x); if ((DOTPRODUCT(normFace , nrm) > 0.f)) continue; } TextureContainer * pTex; if ((eobj->facelist[i].texid < 0) || (!(pTex = eobj->texturecontainer[eobj->facelist[i].texid]))) continue; float fTransp = 0; unsigned long * pNb; if ((eobj->facelist[i].facetype & POLY_TRANS) || (invisibility > 0.f)) { if (invisibility > 0.f) fTransp = 2.f - invisibility; else fTransp = eobj->facelist[i].transval; if (fTransp >= 2.f) //MULTIPLICATIVE { fTransp *= DIV2; fTransp += 0.5f; tv = PushVertexInTableCull_TMultiplicative(pTex); pNb = &pTex->ulNbVertexListCull_TMultiplicative; } else { if (fTransp >= 1.f) //ADDITIVE { fTransp -= 1.f; tv = PushVertexInTableCull_TAdditive(pTex); pNb = &pTex->ulNbVertexListCull_TAdditive; } else { if (fTransp > 0.f) //NORMAL TRANS { fTransp = 1.f - fTransp; tv = PushVertexInTableCull_TNormalTrans(pTex); pNb = &pTex->ulNbVertexListCull_TNormalTrans; } else //SUBTRACTIVE { fTransp = 1.f - fTransp; tv = PushVertexInTableCull_TSubstractive(pTex); pNb = &pTex->ulNbVertexListCull_TSubstractive; } } } } else { tv = PushVertexInTableCull(pTex); pNb = &pTex->ulNbVertexListCull; } for (long n = 0 ; n < 3 ; n++) { paf[n] = eface->vid[n]; tv[n].sx = eobj->vertexlist3[paf[n]].vert.sx; tv[n].sy = eobj->vertexlist3[paf[n]].vert.sy; tv[n].sz = eobj->vertexlist3[paf[n]].vert.sz; if (FORCE_FRONT_DRAW) { if (IsInGroup(eobj, paf[n], 1) != -1) tv[n].sz *= IN_FRONT_DIVIDER; else tv[n].sz *= IN_FRONT_DIVIDER_FEET; } tv[n].rhw = eobj->vertexlist3[paf[n]].vert.rhw; tv[n].tu = eface->u[n]; tv[n].tv = eface->v[n]; tv[n].color = eobj->vertexlist3[paf[n]].vert.color; } if (special_color_flag) { if (special_color_flag & 1) { for (long j = 0 ; j < 3 ; j++) { tv[j].color = (0xFF000000L | (((long)((float)((long)((tv[j].color >> 16) & 255)) * (special_color.r)) & 255) << 16) | (((long)((float)((long)((tv[j].color >> 8) & 255)) * special_color.g) & 255) << 8) | (long)((float)((long)(tv[j].color & 255)) * (special_color.b)) & 255); } } else if (special_color_flag & 2) { for (long j = 0 ; j < 3 ; j++) { tv[j].color = 0xFFFF0000; } } } if ((eobj->facelist[i].facetype & POLY_TRANS) || (invisibility > 0.f)) { tv[0].color = D3DRGB(fTransp, fTransp, fTransp); tv[1].color = D3DRGB(fTransp, fTransp, fTransp); tv[2].color = D3DRGB(fTransp, fTransp, fTransp); } if (!bPassInTANDL) ComputeFog(tv, 3); else { memcpy(tv_static, tv, sizeof(D3DTLVERTEX) * 3); } int iNbPointAdd; if (!(iNbPointAdd = ARX_SoftClippZ(&eobj->vertexlist3[paf[0]], &eobj->vertexlist3[paf[1]], &eobj->vertexlist3[paf[2]], &tv, eface, invisibility, pTex, bBumpOnIO, (io) && (io->ioflags & IO_ZMAP), eobj, i, paf, NULL, true, special_color_flag, &special_color, bPassInTANDL))) { *pNb -= 3; continue; } if (!bPassInTANDL) { if (bBumpOnIO) { if (bPassInTANDL) { PushInterBumpTANDL(pTex, tv_static, &eobj->vertexlist3[paf[0]].v, &eobj->vertexlist3[paf[1]].v, &eobj->vertexlist3[paf[2]].v); } else { PushInterBump(pTex, tv); } } if ((io) && (io->ioflags & IO_ZMAP)) { if (bPassInTANDL) { CalculateInterZMappTANDL(eobj, i, paf, pTex); } else { CalculateInterZMapp(eobj, i, paf, pTex, tv); } } } //////////////////////////////////////////////////////////////////////// // HALO HANDLING START if ( need_halo && io ) { long lfr, lfg, lfb; float ffr, ffg, ffb; float tot = 0; float _ffr[3]; IO_HALO curhalo; memcpy(&curhalo, &io->halo, sizeof(IO_HALO)); int curhaloInitialized = 0; long max_c; if (use_io == inter.iobj[0]) max_c = 4; else max_c = 1; for (long cnt = 0 ; cnt < max_c ; cnt++) { switch (cnt) { case 0: if (use_io == inter.iobj[0]) { if (hio_player) { memcpy(&curhalo, &use_io->halo, sizeof(IO_HALO)); ++curhaloInitialized; } else continue; } else { memcpy(&curhalo, &io->halo, sizeof(IO_HALO)); ++curhaloInitialized; } break; case 1: if ((hio_helmet) && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_head) >= 0)) { memcpy(&curhalo, &hio_helmet->halo, sizeof(IO_HALO)); ++curhaloInitialized; } else continue; break; case 2: if ((hio_armor) && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_chest) >= 0)) { memcpy(&curhalo, &hio_armor->halo, sizeof(IO_HALO)); ++curhaloInitialized; } else continue; break; case 3: if ((hio_leggings) && (IsInSelection(use_io->obj, paf[0], use_io->obj->fastaccess.sel_leggings) >= 0)) { memcpy(&curhalo, &hio_leggings->halo, sizeof(IO_HALO)) ; ++curhaloInitialized; } else continue; break; } ARX_CHECK(curhaloInitialized > 0); D3DTLVERTEX * workon; workon = tv; long o; for (o = 0 ; o < 3 ; o++) { float tttz = EEfabs(eobj->vertexlist3[paf[o]].norm.z) * DIV2; float power = 255.f - (float)(255.f * tttz); power *= (1.f - invisibility); if (power > 255.f) power = 255.f; else if (power < 0.f) power = 0.f; ffr = curhalo.color.r * power; ffg = curhalo.color.g * power; ffb = curhalo.color.b * power; tot += power; _ffr[o] = power; F2L(ffr, &lfr); F2L(ffg, &lfg); F2L(ffb, &lfb); tv[o].color = (0xFF000000L | (((lfr) & 255) << 16) | (((lfg) & 255) << 8) | (lfb) & 255); } //SETCULL(pd3dDevice,D3DCULL_NONE); if (tot > 260) //260.f) { long first; long second; long third; if ((_ffr[0] >= _ffr[1]) && (_ffr[1] >= _ffr[2])) { first = 0; second = 1; third = 2; } else if ((_ffr[0] >= _ffr[2]) && (_ffr[2] >= _ffr[1])) { first = 0; second = 2; third = 1; } else if ((_ffr[1] >= _ffr[0]) && (_ffr[0] >= _ffr[2])) { first = 1; second = 0; third = 2; } else if ((_ffr[1] >= _ffr[2]) && (_ffr[2] >= _ffr[0])) { first = 1; second = 2; third = 0; } else if ((_ffr[2] >= _ffr[0]) && (_ffr[0] >= _ffr[1])) { first = 2; second = 0; third = 1; } else { first = 2; second = 1; third = 0; } if ((_ffr[first] > 150.f) && (_ffr[second] > 110.f)) { EERIE_3D vect1, vect2; D3DTLVERTEX * vert = &LATERDRAWHALO[(HALOCUR << 2)]; HALOCUR++; if (HALOCUR >= HALOMAX) HALOCUR--; memcpy(&vert[0], &workon[first], sizeof(D3DTLVERTEX)); memcpy(&vert[1], &workon[first], sizeof(D3DTLVERTEX)); memcpy(&vert[2], &workon[second], sizeof(D3DTLVERTEX)); memcpy(&vert[3], &workon[second], sizeof(D3DTLVERTEX)); float siz = ddist * (curhalo.radius * (EEsin((float)(FrameTime + i) * DIV100) * DIV10 + 1.f)) * 0.6f; if ((io == inter.iobj[0]) && (ddist > 0.8f) && !EXTERNALVIEW) siz *= 1.5f; vect1.x = workon[first].sx - workon[third].sx; vect1.y = workon[first].sy - workon[third].sy; float len1 = 2.f / EEsqrt(vect1.x * vect1.x + vect1.y * vect1.y); if (vect1.x < 0.f) len1 *= 1.2f; vect1.x *= len1; vect1.y *= len1; vect2.x = workon[second].sx - workon[third].sx; vect2.y = workon[second].sy - workon[third].sy; float len2 = 1.f / EEsqrt(vect2.x * vect2.x + vect2.y * vect2.y); if (vect2.x < 0.f) len2 *= 1.2f; vect2.x *= len2; vect2.y *= len2; vert[1].sx += (vect1.x + 0.2f - rnd() * 0.1f) * siz; vert[1].sy += (vect1.y + 0.2f - rnd() * 0.1f) * siz; vert[1].color = 0xFF000000; float valll; if (bZBUFFER) { valll = 0.005f + (EEfabs(workon[first].sz) - EEfabs(workon[third].sz) + EEfabs(workon[second].sz) - EEfabs(workon[third].sz)); valll = 0.0001f + valll * DIV10; if (valll < 0.f) valll = 0.f; vert[1].sz += valll; vert[2].sz += valll; vert[0].sz += 0.0001f; vert[3].sz += 0.0001f;//*DIV2; vert[1].rhw *= .98f; vert[2].rhw *= .98f; vert[0].rhw *= .98f; vert[3].rhw *= .98f; } else { vert[1].rhw *= .98f; vert[2].rhw *= .98f; vert[0].rhw *= .98f; vert[3].rhw *= .98f; } vert[2].sx += (vect2.x + 0.2f - rnd() * 0.1f) * siz; vert[2].sy += (vect2.y + 0.2f - rnd() * 0.1f) * siz; vert[1].sz = (vert[1].sz + MAX_ZEDE) * DIV2; vert[2].sz = (vert[2].sz + MAX_ZEDE) * DIV2; if (curhalo.flags & HALO_NEGATIVE) vert[2].color = 0x00000000; else vert[2].color = 0xFF000000; } } } for (long o = 0 ; o < 3 ; o++) { paf[o] = eface->vid[o]; tv[o].color = eobj->vertexlist3[paf[o]].vert.color; } } //////////////////////////////////////////////////////////////////////// // HALO HANDLING END //////////////////////////////////////////////////////////////////////// if ((eobj->facelist[i].facetype & POLY_TRANS) || (invisibility > 0.f)) { if (bPassInTANDL) { D3DTLVERTEX * ptvTL; if (invisibility > 0.f) fTransp = 2.f - invisibility; else fTransp = eobj->facelist[i].transval; if (fTransp >= 2.f) //MULTIPLICATIVE { fTransp *= DIV2; fTransp += 0.5f; ptvTL = PushVertexInTableCull_TMultiplicativeH(pTex); } else { if (fTransp >= 1.f) //ADDITIVE { fTransp -= 1.f; ptvTL = PushVertexInTableCull_TAdditiveH(pTex); } else { if (fTransp > 0.f) //NORMAL TRANS { fTransp = 1.f - fTransp; ptvTL = PushVertexInTableCull_TNormalTrans(pTex); } else //SUBTRACTIVE { fTransp = 1.f - fTransp; ptvTL = PushVertexInTableCull_TSubstractive(pTex); } } } ptvTL[0].sx = eobj->vertexlist3[paf[0]].v.x; ptvTL[0].sy = eobj->vertexlist3[paf[0]].v.y; ptvTL[0].sz = eobj->vertexlist3[paf[0]].v.z; ptvTL[0].color = tv_static[0].color; ptvTL[0].tu = tv_static[0].tu; ptvTL[0].tv = tv_static[0].tv; ptvTL[1].sx = eobj->vertexlist3[paf[1]].v.x; ptvTL[1].sy = eobj->vertexlist3[paf[1]].v.y; ptvTL[1].sz = eobj->vertexlist3[paf[1]].v.z; ptvTL[1].color = tv_static[1].color; ptvTL[1].tu = tv_static[1].tu; ptvTL[1].tv = tv_static[1].tv; ptvTL[2].sx = eobj->vertexlist3[paf[2]].v.x; ptvTL[2].sy = eobj->vertexlist3[paf[2]].v.y; ptvTL[2].sz = eobj->vertexlist3[paf[2]].v.z; ptvTL[2].color = tv_static[2].color; ptvTL[2].tu = tv_static[2].tu; ptvTL[2].tv = tv_static[2].tv; *pNb -= iNbPointAdd; } continue; } if (special_color_flag & 2) { D3DTLVERTEX * tv2; { tv2 = PushVertexInTableCull(&TexSpecialColor); } memcpy((void *) tv2, (void *)tv, sizeof(D3DTLVERTEX) * 3); unsigned long v = _EERIERGB(special_color.r); tv2[0].color = v; tv2[1].color = v; tv2[2].color = v; } // Add a little bit of Fake Metal Specular if needed :p if ((eface->facetype & POLY_METAL) || ((pTex) && (pTex->userflags & POLY_METAL))) { D3DTLVERTEX * tv2; unsigned long * pulNbVertexList_TMetal; if (bPassInTANDL) { tv2 = PushVertexInTableCull_TMetalH(pTex); pulNbVertexList_TMetal = &pTex->ulNbVertexListCull_TMetalH; tv2[0].sx = eobj->vertexlist3[paf[0]].v.x; tv2[0].sy = eobj->vertexlist3[paf[0]].v.y; tv2[0].sz = eobj->vertexlist3[paf[0]].v.z; tv2[0].color = tv_static[0].color; tv2[0].tu = tv_static[0].tu; tv2[0].tv = tv_static[0].tv; tv2[1].sx = eobj->vertexlist3[paf[1]].v.x; tv2[1].sy = eobj->vertexlist3[paf[1]].v.y; tv2[1].sz = eobj->vertexlist3[paf[1]].v.z; tv2[1].color = tv_static[1].color; tv2[1].tu = tv_static[1].tu; tv2[1].tv = tv_static[1].tv; tv2[2].sx = eobj->vertexlist3[paf[2]].v.x; tv2[2].sy = eobj->vertexlist3[paf[2]].v.y; tv2[2].sz = eobj->vertexlist3[paf[2]].v.z; tv2[2].color = tv_static[2].color; tv2[2].tu = tv_static[2].tu; tv2[2].tv = tv_static[2].tv; } else { tv2 = PushVertexInTableCull_TMetal(pTex); pulNbVertexList_TMetal = &pTex->ulNbVertexListCull_TMetal; memcpy((void *)tv2, (void *)tv, sizeof(D3DTLVERTEX) * 3); } long r, g, b; long todo = 0; for (long j = 0 ; j < 3 ; j++) { r = (tv2[j].color >> 16) & 255; g = (tv2[j].color >> 8) & 255; b = tv2[j].color & 255; if (r > 192 || g > 192 || b > 192) { todo++; } r -= 192; if (r < 0.f) r = 0; g -= 192; if (g < 0.f) g = 0; b -= 192; if (b < 0.f) b = 0; tv2[j].color = 0xFF000000 | (r << 18) | (g << 10) | (b << 2); } if (!todo) { *pulNbVertexList_TMetal -= 3; } } if (bPassInTANDL) { D3DTLVERTEX * ptvTL; ptvTL = PushVertexInTableCullH(pTex); ptvTL[0].sx = eobj->vertexlist3[paf[0]].v.x; ptvTL[0].sy = eobj->vertexlist3[paf[0]].v.y; ptvTL[0].sz = eobj->vertexlist3[paf[0]].v.z; ptvTL[0].color = tv_static[0].color; ptvTL[0].tu = tv_static[0].tu; ptvTL[0].tv = tv_static[0].tv; ptvTL[1].sx = eobj->vertexlist3[paf[1]].v.x; ptvTL[1].sy = eobj->vertexlist3[paf[1]].v.y; ptvTL[1].sz = eobj->vertexlist3[paf[1]].v.z; ptvTL[1].color = tv_static[1].color; ptvTL[1].tu = tv_static[1].tu; ptvTL[1].tv = tv_static[1].tv; ptvTL[2].sx = eobj->vertexlist3[paf[2]].v.x; ptvTL[2].sy = eobj->vertexlist3[paf[2]].v.y; ptvTL[2].sz = eobj->vertexlist3[paf[2]].v.z; ptvTL[2].color = tv_static[2].color; ptvTL[2].tu = tv_static[2].tu; ptvTL[2].tv = tv_static[2].tv; *pNb -= iNbPointAdd; } } } } /* Render object */ void Cedric_RenderObject(LPDIRECT3DDEVICE7 pd3dDevice, EERIE_3DOBJ * eobj, EERIE_C_DATA * obj, INTERACTIVE_OBJ * io, EERIE_3D * pos, EERIE_3D & ftr, float invisibility) { if (bRenderInterList) { Cedric_RenderObject2(pd3dDevice, eobj, obj, io, pos, ftr, invisibility); return; } int i; // Finally we can draw polys !!! SETCULL(pd3dDevice, D3DCULL_NONE); // Sets IO BBox to calculated BBox :) if (io) { io->bbox1.x = (short)BBOXMIN.x; io->bbox2.x = (short)BBOXMAX.x; io->bbox1.y = (short)BBOXMIN.y; io->bbox2.y = (short)BBOXMAX.y; } if (invisibility == 1.f) return; float ddist = 0; long need_halo; need_halo = 0; if ((io) && (io->halo.flags & HALO_ACTIVE)) { ddist = 500.f - Distance3D(pos->x + ftr.x, pos->y + ftr.y, pos->z + ftr.z, ACTIVECAM->pos.x, ACTIVECAM->pos.y, ACTIVECAM->pos.z); if (ddist > 0.f) { ddist = (ddist * DIV500); } else if (ddist < 0.f) { ddist = 0.f; } else if (ddist > 1.f) { ddist = 1.f; } if ((io) && (io->halo.flags & HALO_DYNLIGHT))//(io->halo.flags & HALO_ACTIVE) HALO_IO_DynLight_Update(io); if ((io) && (io->halo.flags & HALO_ACTIVE) && (ddist > 0.01f)) { Cedric_PrepareHalo(pd3dDevice, eobj, obj, io, pos, ftr); need_halo = 1; } } { for (i = 0; i < eobj->nbfaces; i++) { D3DTLVERTEX tv[3]; EERIE_FACE * eface; long paf[3]; eface = &eobj->facelist[i]; if ((eface->facetype & POLY_HIDE) && (!FORCE_NO_HIDE)) continue; if ((eobj->vertexlist3[eface->vid[0]].vert.rhw < 0) && (eobj->vertexlist3[eface->vid[1]].vert.rhw < 0) && (eobj->vertexlist3[eface->vid[2]].vert.rhw < 0)) continue; // To avoid reverse-flip draw. long OUTSIDE = 0; for (long n = 0; n < 3; n++) { paf[n] = eface->vid[n]; tv[n].sx = eobj->vertexlist3[paf[n]].vert.sx; tv[n].sy = eobj->vertexlist3[paf[n]].vert.sy; tv[n].sz = eobj->vertexlist3[paf[n]].vert.sz; if (tv[n].sz <= 0.f) OUTSIDE++; tv[n].rhw = eobj->vertexlist3[paf[n]].vert.rhw; tv[n].tu = eface->u[n]; tv[n].tv = eface->v[n]; tv[n].color = eobj->vertexlist3[paf[n]].vert.color; } if (OUTSIDE == 3) continue; //////////////////////////////////////////////////////////////////////// // HALO HANDLING START if (need_halo) { long lfr, lfg, lfb; float ffr, ffg, ffb; float tot = 0; float _ffr[3]; D3DTLVERTEX * workon = tv; for (long o = 0; o < 3; o++) { float tttz = eobj->vertexlist3[paf[o]].norm.z; if (tttz < 0.f) tttz *= -0.5f; else tttz *= 0.5f; float power = 255.f - (float)(255.f * tttz); power *= (1.f - invisibility); if (power > 255.f) power = 255.f; else if (power < 0.f) power = 0.f; ffr = io->halo.color.r * power; ffg = io->halo.color.g * power; ffb = io->halo.color.b * power; tot += power; _ffr[o] = power; F2L(ffr, &lfr); F2L(ffg, &lfg); F2L(ffb, &lfb); tv[o].color = (0xFF000000L | (((lfr) & 255) << 16) | (((lfg) & 255) << 8) | (lfb) & 255); } if (tot > 260.f) { long first; long second; long third; if ((_ffr[0] >= _ffr[1]) && (_ffr[1] >= _ffr[2])) { first = 0; second = 1; third = 2; } else if ((_ffr[0] >= _ffr[2]) && (_ffr[2] >= _ffr[1])) { first = 0; second = 2; third = 1; } else if ((_ffr[1] >= _ffr[0]) && (_ffr[0] >= _ffr[2])) { first = 1; second = 0; third = 2; } else if ((_ffr[1] >= _ffr[2]) && (_ffr[2] >= _ffr[0])) { first = 1; second = 2; third = 0; } else if ((_ffr[2] >= _ffr[0]) && (_ffr[0] >= _ffr[1])) { first = 2; second = 0; third = 1; } else { first = 2; second = 1; third = 0; } if ((_ffr[first] > 150.f) && (_ffr[second] > 110.f)) // && (workon[0].sz>0.f) && (workon[3].sz>0.f)) { EERIE_3D vect1, vect2; D3DTLVERTEX * vert = &LATERDRAWHALO[(HALOCUR << 2)]; HALOCUR++; if (HALOCUR >= HALOMAX) HALOCUR--; memcpy(&vert[0], &workon[first], sizeof(D3DTLVERTEX)); memcpy(&vert[1], &workon[first], sizeof(D3DTLVERTEX)); memcpy(&vert[2], &workon[second], sizeof(D3DTLVERTEX)); memcpy(&vert[3], &workon[second], sizeof(D3DTLVERTEX)); float siz = ddist * (io->halo.radius * (EEsin((float)(FrameTime + i) * DIV100) * DIV50 + 1.f)); vect1.x = workon[first].sx - workon[third].sx; vect1.y = workon[first].sy - workon[third].sy; float len1 = 1.f / EEsqrt(vect1.x * vect1.x + vect1.y * vect1.y); vect1.x *= len1; vect1.y *= len1; vect2.x = workon[second].sx - workon[third].sx; vect2.y = workon[second].sy - workon[third].sy; float len2 = 1.f / EEsqrt(vect2.x * vect2.x + vect2.y * vect2.y); vect2.x *= len2; vect2.y *= len2; vert[1].sx += (vect1.x + 0.2f - rnd() * 0.1f) * siz; //+len1; vert[1].sy += (vect1.y + 0.2f - rnd() * 0.1f) * siz; //+len2; vert[1].color = 0xFF000000; float valll; if (bZBUFFER) { valll = (EEfabs(workon[first].sz - workon[third].sz) + EEfabs(workon[second].sz - workon[third].sz)) * 1.8f; valll = 0.01f + valll; if (valll < 0.f) valll = 0.f; vert[1].sz += valll; vert[2].sz += valll; vert[0].sz += 0.0001f; vert[3].sz += 0.0001f; //*DIV2; } else { vert[1].rhw *= .98f; vert[2].rhw *= .98f; vert[0].rhw *= .98f; vert[3].rhw *= .98f; //*DIV2; } vert[2].sx += (vect2.x + 0.2f - rnd() * 0.1f) * siz; //+len2; vert[2].sy += (vect2.y + 0.2f - rnd() * 0.1f) * siz; //+len1; if (io->halo.flags & HALO_NEGATIVE) vert[2].color = 0x00000000; else vert[2].color = 0xFF000000; } } for (long n = 0; n < 3; n++) { paf[n] = eface->vid[n]; tv[n].color = eobj->vertexlist3[paf[n]].vert.color; } } if (special_color_flag) { if (special_color_flag & 1) { for (long j = 0; j < 3; j++) { tv[j].color = (0xFF000000L | (((long)((float)((long)((tv[j].color >> 16) & 255)) * (special_color.r)) & 255) << 16) | (((long)((float)((long)((tv[j].color >> 8) & 255)) * special_color.g) & 255) << 8) | (long)((float)((long)(tv[j].color & 255)) * (special_color.b)) & 255); } } else if (special_color_flag & 2) { for (long j = 0; j < 3; j++) { tv[j].color = 0xFFFF0000; } } } // HALO HANDLING END //////////////////////////////////////////////////////////////////////// const int EERIE_FLAG = bSoftRender?EERIE_USEVB:0; //Should we use Vertex Buffer // Backface culling if required if (eface->facetype & POLY_DOUBLESIDED) SETCULL(pd3dDevice, D3DCULL_NONE); else SETCULL(pd3dDevice, D3DCULL_CW); // Is Transparent? if (eface->facetype & POLY_TRANS) { memcpy(&InterTransPol[INTERTRANSPOLYSPOS], &tv, sizeof(D3DTLVERTEX) * 3); InterTransFace[INTERTRANSPOLYSPOS] = eface; InterTransTC[INTERTRANSPOLYSPOS] = eobj->texturecontainer[eface->texid]; INTERTRANSPOLYSPOS++; if (INTERTRANSPOLYSPOS >= MAX_INTERTRANSPOL) INTERTRANSPOLYSPOS = MAX_INTERTRANSPOL - 1; continue; } // Set texture if ((eface->texid == -1) || (eobj->texturecontainer[eface->texid] == NULL)) SETTC(pd3dDevice, NULL); else SETTC(pd3dDevice, eobj->texturecontainer[eface->texid]); if (invisibility > 0.f) { memcpy(&InterTransPol[INTERTRANSPOLYSPOS], &tv, sizeof(D3DTLVERTEX) * 3); InterTransFace[INTERTRANSPOLYSPOS] = eface; InterTransFace[INTERTRANSPOLYSPOS]->transval = 2.f - invisibility; InterTransTC[INTERTRANSPOLYSPOS] = eobj->texturecontainer[eface->texid]; INTERTRANSPOLYSPOS++; if (INTERTRANSPOLYSPOS >= MAX_INTERTRANSPOL) INTERTRANSPOLYSPOS = MAX_INTERTRANSPOL - 1; continue; } EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX | D3DFVF_DIFFUSE , &tv, 3, 0, EERIE_FLAG ); if (special_color_flag & 2) { pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTCOLOR); pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); SETALPHABLEND(pd3dDevice, TRUE); SETZWRITE(pd3dDevice, FALSE); SETTC(pd3dDevice, NULL); unsigned long v = _EERIERGB(special_color.r); for (long j = 0; j < 3; j++) { tv[j].color = v; } EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX| D3DFVF_DIFFUSE , &tv, 3, 0, EERIE_FLAG ); EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX| D3DFVF_DIFFUSE , &tv, 3, 0, EERIE_FLAG );//duplicate ???? @TBR ? SETALPHABLEND(pd3dDevice, FALSE); SETZWRITE(pd3dDevice, TRUE); } // Add a little bit of Fake Metal Specular if needed if ((eface->facetype & POLY_METAL) || ((eobj->texturecontainer[eface->texid]) && (eobj->texturecontainer[eface->texid]->userflags & POLY_METAL))) { long r, g, b; long todo = 0; for (long j = 0; j < 3; j++) { r = (tv[j].color >> 16) & 255; g = (tv[j].color >> 8) & 255; b = tv[j].color & 255; if (r > 192 || g > 192 || b > 192) { todo++; } r -= 192; if (r < 0.f) r = 0; g -= 192; if (g < 0.f) g = 0; b -= 192; if (b < 0.f) b = 0; tv[j].color = 0xFF000000 | (r << 18) | (g << 10) | (b << 2); } if (todo) { pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTCOLOR); pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); SETALPHABLEND(pd3dDevice, TRUE); SETZWRITE(pd3dDevice, FALSE); EERIEDRAWPRIM(pd3dDevice,D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX| D3DFVF_DIFFUSE, &tv, 3, 0, EERIE_FLAG ); SETALPHABLEND(pd3dDevice, FALSE); SETZWRITE(pd3dDevice, TRUE); } } } } } void Cedric_BlendAnimation(INTERACTIVE_OBJ * io, EERIE_3DOBJ * eobj, float timm, EERIE_3D * angle) { for (long i = 0; i < eobj->c_data->nb_bones; i++) { EERIE_QUAT tquat; Quat_Copy(&tquat, &eobj->c_data->bones[i].quatinit); EERIE_QUAT q2; Quat_Copy(&q2, &eobj->c_data->bones[i].quatlast); Quat_Slerp(&eobj->c_data->bones[i].quatinit , &q2, &tquat, timm); eobj->c_data->bones[i].transinit.x = eobj->c_data->bones[i].translast.x + (eobj->c_data->bones[i].transinit.x - eobj->c_data->bones[i].translast.x) * timm; eobj->c_data->bones[i].transinit.y = eobj->c_data->bones[i].translast.y + (eobj->c_data->bones[i].transinit.y - eobj->c_data->bones[i].translast.y) * timm; eobj->c_data->bones[i].transinit.z = eobj->c_data->bones[i].translast.z + (eobj->c_data->bones[i].transinit.z - eobj->c_data->bones[i].translast.z) * timm; } } void Cedric_SaveBlendData(INTERACTIVE_OBJ * io, EERIE_3DOBJ * eobj, EERIE_3D * angle) { if (io->obj->c_data) { for (long i = 0; i < io->obj->c_data->nb_bones; i++) { Quat_Copy(&io->obj->c_data->bones[i].quatlast, &io->obj->c_data->bones[i].quatinit); Vector_Copy(&io->obj->c_data->bones[i].scalelast, &io->obj->c_data->bones[i].scaleinit); Vector_Copy(&io->obj->c_data->bones[i].translast, &io->obj->c_data->bones[i].transinit); } } } void Cedric_ManageExtraRotationsFirst(INTERACTIVE_OBJ * io, EERIE_3DOBJ * obj) { for (long i = 0; i != obj->c_data->nb_bones; i++) { Quat_Init(&obj->c_data->bones[i].quatinit); Vector_Copy(&obj->c_data->bones[i].transinit, &obj->c_data->bones[i].transinit_global); } if ((io) && (io->ioflags & IO_NPC) && (io->_npcdata->ex_rotate)) { for (long k = 0; k < MAX_EXTRA_ROTATE; k++) { long i = io->_npcdata->ex_rotate->group_number[k]; if (i >= 0) { EERIE_3D vt1; EERIE_QUAT quat1; vt1.x = DEG2RAD(io->_npcdata->ex_rotate->group_rotate[k].g); vt1.y = DEG2RAD(io->_npcdata->ex_rotate->group_rotate[k].b); vt1.z = DEG2RAD(io->_npcdata->ex_rotate->group_rotate[k].a); QuatFromAngles(&quat1, &vt1); Quat_Copy(&obj->c_data->bones[i].quatinit, &quat1); } } } } extern long LOOK_AT_TARGET; extern long ForceIODraw; bool Cedric_IO_Visible(INTERACTIVE_OBJ * io, long typ) { if (io == inter.iobj[0]) return true; if ((!ForceIODraw) && (ACTIVEBKG != NULL) && (io) && (!(typ & 1))) { if (EEDistance3D(&io->pos, &ACTIVECAM->pos) > ACTIVECAM->cdepth * 0.6f) return false; long xx, yy; F2L(((io->pos.x)*ACTIVEBKG->Xmul), &xx); F2L(((io->pos.z)*ACTIVEBKG->Zmul), &yy); if ((xx >= 1) && (yy >= 1) && (xx < ACTIVEBKG->Xsize - 1) && (yy < ACTIVEBKG->Zsize - 1)) { for (long ky = yy - 1; ky <= yy + 1; ky++) for (long kx = xx - 1; kx <= xx + 1; kx++) { FAST_BKG_DATA * feg = (FAST_BKG_DATA *)&ACTIVEBKG->fastdata[kx][ky]; if (feg->treat) return true; } return false; } } return true; } extern long __MUST_DRAW; extern long EXTERNALVIEW; /* Apply animation and draw object */ void Cedric_AnimateDrawEntity(LPDIRECT3DDEVICE7 pd3dDevice, EERIE_3DOBJ * eobj, ANIM_USE * animuse, EERIE_3D * angle, EERIE_3D * pos, INTERACTIVE_OBJ * io, D3DCOLOR col, long typ) { float invisibility; float scale; float timm; EERIE_3D ftr, ftr2; EERIE_C_DATA * obj; // Init some data Cedric_ResetBoundingBox(io); // Set scale and invisibility factors Cedric_GetScale(scale, invisibility, io); // Flag linked objects //Cedric_FlagLinkedObjects(eobj); ??? // Is There any Between-Animations Interpolation to make ? timm>0.f Cedric_GetTime(timm, io, typ); // Buffer size check if (eobj->nbgroups > max_grps) { //todo free grps = (unsigned char *)realloc(grps, eobj->nbgroups); max_grps = eobj->nbgroups; } memset(grps, 0, eobj->nbgroups); Cedric_AnimCalcTranslation(io, animuse, scale, typ, ftr, ftr2); if (Cedric_IO_Visible(io, typ)) { // Manage Extra Rotations in Local Space Cedric_ManageExtraRotationsFirst(io, eobj); Looking_At = -1; // Perform animation in Local space Cedric_AnimateObject(io, eobj, animuse); // Check for Animation Blending in Local space if (io) { if (timm > 0.f) { Cedric_BlendAnimation(io, eobj, timm, angle); Cedric_SaveBlendData(io, eobj, angle); } else Cedric_SaveBlendData(io, eobj, angle); } // Build skeleton in Object Space Cedric_ConcatenateTM(io, eobj->c_data, angle, pos, ftr, scale); /* Display the object */ obj = eobj->c_data; if (!obj) return; if ((Cedric_TransformVerts(io, eobj, obj, pos, angle)) && (!(typ & ANIMQUATTYPE_NO_RENDER))) { INTER_DRAW++; if (!Cedric_ApplyLighting(eobj, obj, io, pos, typ)) return; Cedric_RenderObject(pd3dDevice, eobj, obj, io, pos, ftr, invisibility); if (io) { io->bbox1.x = (short)BBOXMIN.x; io->bbox2.x = (short)BBOXMAX.x; io->bbox1.y = (short)BBOXMIN.y; io->bbox2.y = (short)BBOXMAX.y; } // Now we can render Linked Objects for (long k = 0; k < eobj->nblinked; k++) { if (k == 1) k = k; if ((eobj->linked[k].lgroup != -1) && eobj->linked[k].obj) { eobj->linked[k].modinfo.rot.a = 0; eobj->linked[k].modinfo.rot.b = 0; eobj->linked[k].modinfo.rot.g = 0; float old = 0.f; INTERACTIVE_OBJ * ioo = (INTERACTIVE_OBJ *)eobj->linked[k].io; EERIE_3DOBJ * obj = (EERIE_3DOBJ *) eobj->linked[k].obj; // Store item invisibility flag if (io && ioo) { old = ioo->invisibility; if (io == inter.iobj[0]) { ioo->invisibility = INVISIBILITY_OVERRIDE; } else { INVISIBILITY_OVERRIDE = 0.f; ioo->invisibility = invisibility; } } else { if (ioo) { INVISIBILITY_OVERRIDE = 0.f; ioo->invisibility = invisibility; } else INVISIBILITY_OVERRIDE = invisibility; } if (ioo) { if ((ioo->ignition > 0.f) || (ioo->ioflags & IO_FIERY)) ManageIgnition(ioo); } __MUST_DRAW = 1; // specific check to avoid drawing player weapon on its back when in subjective view if ((io == inter.iobj[0]) && (eobj->linked[k].lidx == inter.iobj[0]->obj->fastaccess.weapon_attach) && (!EXTERNALVIEW)) continue; long ll = eobj->linked[k].lidx2; eobj->linked[k].modinfo.link_position.x = obj->vertexlist[ll].v.x - obj->vertexlist[obj->origin].v.x; eobj->linked[k].modinfo.link_position.y = obj->vertexlist[ll].v.y - obj->vertexlist[obj->origin].v.y; eobj->linked[k].modinfo.link_position.z = obj->vertexlist[ll].v.z - obj->vertexlist[obj->origin].v.z; EERIE_QUAT quat; ll = eobj->linked[k].lidx; EERIE_3D * posi = &eobj->vertexlist3[ll].v; Quat_Copy(&quat, &eobj->c_data->bones[eobj->linked[k].lgroup].quatanim); EERIEMATRIX matrix; MatrixFromQuat(&matrix, &quat); DrawEERIEInterMatrix(pd3dDevice, obj, &matrix, posi, ioo, NULL, &eobj->linked[k].modinfo); INVISIBILITY_OVERRIDE = 0.f; // Restore item invisibility flag if (ioo) ioo->invisibility = old; __MUST_DRAW = 0; } } } } } void MakeCLight(INTERACTIVE_OBJ * io, EERIE_RGB * infra, EERIE_3D * angle, EERIE_3D * pos, EERIE_3DOBJ * eobj, EERIEMATRIX * BIGMAT, EERIE_QUAT * BIGQUAT) { if ((Project.improve) && (!io)) { infra->r = 0.6f; infra->g = 0.f; infra->b = 1.f; } llightsInit(); EERIE_3D tv; if ((io) && (io->ioflags & IO_ITEM)) Vector_Init(&tv, pos->x, pos->y - 60.f, pos->z); else Vector_Init(&tv, pos->x, pos->y - 90.f, pos->z); for (long i = 0; i < TOTIOPDL; i++) { if (!(GetMaxManhattanDistance(&IO_PDL[i]->pos, &tv) <= IO_PDL[i]->fallend + 500.f)) continue; Insertllight(IO_PDL[i], EEDistance3D(&IO_PDL[i]->pos, &tv)); } for (int i = 0; i < TOTPDL; i++) { if (!(GetMaxManhattanDistance(&PDL[i]->pos, &tv) <= PDL[i]->fallend + 500.f)) continue; Insertllight(PDL[i], EEDistance3D(&PDL[i]->pos, &tv)); } Preparellights(&tv); if ((io) && (io->ioflags & IO_ANGULAR)) return; EERIE_3D vLight; EERIE_3D vTLights[32]; EERIE_QUAT qInvert; if (BIGMAT != NULL) { QuatFromMatrix(qInvert, *BIGMAT); } else { if (BIGQUAT != NULL) { qInvert = *BIGQUAT; } else { //FIX LIGHT EERIE_3D vt1; if (angle) { Vector_Copy(&vt1, angle); } else { if (io) Vector_Copy(&vt1, &io->angle); else Vector_Copy(&vt1, &eobj->angle); } vt1.x = MAKEANGLE(-vt1.z) * EEdef_DEGTORAD; vt1.y = MAKEANGLE(vt1.y) * EEdef_DEGTORAD; vt1.z = MAKEANGLE(vt1.x) * EEdef_DEGTORAD; QuatFromAngles(&qInvert, &vt1); } } for (int i = 0; i < eobj->nbvertex; i++) { float r, g, b; long ir, ig, ib; if ((io) && (io->ioflags & (IO_NPC | IO_ITEM))) { r = g = b = NPC_ITEMS__AMBIENT_VALUE_255; } else { r = ACTIVEBKG->ambient255.r; g = ACTIVEBKG->ambient255.g; b = ACTIVEBKG->ambient255.b; } EERIE_3D * posVert = &eobj->vertexlist3[i].v; for (long l = 0 ; l != MAX_LLIGHTS; l++) { EERIE_LIGHT * Cur_llights = llights[l]; if (Cur_llights) { float cosangle; vLight.x = (llights[l]->pos.x - posVert->x); vLight.y = (llights[l]->pos.y - posVert->y); vLight.z = (llights[l]->pos.z - posVert->z); TRUEVector_Normalize(&vLight); TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]); EERIE_3D * Cur_vLights = &vTLights[l]; // Get cos angle between light and vertex norm cosangle = (eobj->vertexlist[i].norm.x * Cur_vLights->x + eobj->vertexlist[i].norm.y * Cur_vLights->y + eobj->vertexlist[i].norm.z * Cur_vLights->z); // If light visible if (cosangle > 0.f) { float distance = EEDistance3D((EERIE_3D *)posVert, &Cur_llights->pos); // Evaluate its intensity depending on the distance Light<->Object if (distance <= Cur_llights->fallstart) cosangle *= Cur_llights->precalc; else { float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul); if (p <= 0.f) cosangle = 0.f; else cosangle *= p * Cur_llights->precalc; } r += Cur_llights->rgb255.r * cosangle; g += Cur_llights->rgb255.g * cosangle; b += Cur_llights->rgb255.b * cosangle; } } else break; } if (eobj->drawflags & DRAWFLAG_HIGHLIGHT) { r += iHighLight; g += iHighLight; b += iHighLight; } if ((Project.improve) && (!io)) { r *= infra->r; g *= infra->g; b *= infra->b; r += infra->r * 512.f; g += infra->g; b += infra->b * 400.f; } F2L(r, &ir); ir = clipByte255(ir); F2L(g, &ig); ig = clipByte255(ig); F2L(b, &ib); ib = clipByte255(ib); eobj->vertexlist3[i].vert.color = (0xff000000L | (((ir) & 255) << 16) | (((ig) & 255) << 8) | (ib) & 255); } } void MakeCLight2(INTERACTIVE_OBJ * io, EERIE_RGB * infra, EERIE_3D * angle, EERIE_3D * pos, EERIE_3DOBJ * eobj, EERIEMATRIX * BIGMAT, EERIE_QUAT * BIGQUAT, long ii) { EERIE_3D vLight; EERIE_3D vTLights[32]; EERIE_QUAT qInvert; if (BIGMAT != NULL) { QuatFromMatrix(qInvert, *BIGMAT); } else { if (BIGQUAT != NULL) { qInvert = *BIGQUAT; } else { EERIE_3D vt1; if (angle) { Vector_Copy(&vt1, angle); } else { if (io) Vector_Copy(&vt1, &io->angle); else Vector_Copy(&vt1, &eobj->angle); } vt1.x *= EEdef_DEGTORAD; vt1.y *= EEdef_DEGTORAD; vt1.z *= EEdef_DEGTORAD; QuatFromAngles(&qInvert, &vt1); } } EERIE_3D tv; if ((io) && (io->ioflags & IO_ITEM)) Vector_Init(&tv, pos->x, pos->y - 60.f, pos->z); else Vector_Init(&tv, pos->x, pos->y - 90.f, pos->z); for (long l = 0; l != MAX_LLIGHTS; l++) { if (llights[l]) { float oolength = 1.f / dists[l]; vLight.x = (llights[l]->pos.x - tv.x) * oolength; vLight.y = (llights[l]->pos.y - tv.y) * oolength; vLight.z = (llights[l]->pos.z - tv.z) * oolength; TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]); } else break; } long paf[3]; paf[0] = eobj->facelist[ii].vid[0]; paf[1] = eobj->facelist[ii].vid[1]; paf[2] = eobj->facelist[ii].vid[2]; for (long i = 0; i < 3; i++) { float r, g, b; long ir, ig, ib; if ((io) && (io->ioflags & (IO_NPC | IO_ITEM))) { r = g = b = NPC_ITEMS__AMBIENT_VALUE_255; } else { r = ACTIVEBKG->ambient255.r; g = ACTIVEBKG->ambient255.g; b = ACTIVEBKG->ambient255.b; } EERIE_3D * posVert = &eobj->vertexlist3[paf[i]].v; for (int l = 0 ; l != MAX_LLIGHTS; l++) { EERIE_LIGHT * Cur_llights = llights[l]; if (Cur_llights) { float cosangle; float oolength = 1.f / EEDistance3D((EERIE_3D *)posVert, &Cur_llights->pos); //dists[l]; vLight.x = (llights[l]->pos.x - posVert->x) * oolength; vLight.y = (llights[l]->pos.y - posVert->y) * oolength; vLight.z = (llights[l]->pos.z - posVert->z) * oolength; TransformInverseVertexQuat(&qInvert, &vLight, &vTLights[l]); EERIE_3D * Cur_vLights = &vTLights[l]; cosangle = (eobj->facelist[ii].norm.x * Cur_vLights->x + eobj->facelist[ii].norm.y * Cur_vLights->y + eobj->facelist[ii].norm.z * Cur_vLights->z) * DIV2; // If light visible if (cosangle > 0.f) { float distance = EEDistance3D((EERIE_3D *)posVert, &Cur_llights->pos); // Evaluate its intensity depending on the distance Light<->Object if (distance <= Cur_llights->fallstart) cosangle *= Cur_llights->precalc; else { float p = ((Cur_llights->fallend - distance) * Cur_llights->falldiffmul); if (p <= 0.f) cosangle = 0.f; else cosangle *= p * Cur_llights->precalc; } r += Cur_llights->rgb255.r * cosangle; g += Cur_llights->rgb255.g * cosangle; b += Cur_llights->rgb255.b * cosangle; } } else break; } if (eobj->drawflags & DRAWFLAG_HIGHLIGHT) { r += iHighLight; g += iHighLight; b += iHighLight; } if (Project.improve) { r *= infra->r; g *= infra->g; b *= infra->b; } F2L(r, &ir); ir = clipByte255(ir); F2L(g, &ig); ig = clipByte255(ig); F2L(b, &ib); ib = clipByte255(ib); eobj->vertexlist3[paf[i]].vert.color = (0xff000000L | (((ir) & 255) << 16) | (((ig) & 255) << 8) | (ib) & 255); } } extern long DYNAMIC_NORMALS; void ApplyDynLight(EERIEPOLY * ep) { long nbvert, i; if (ep->type & POLY_QUAD) nbvert = 4; else nbvert = 3; if (TOTPDL == 0) { for (i = 0; i < nbvert; i++) ep->tv[i].color = ep->v[i].color; return; } EERIE_RGB rgb; long j; register float epr[4]; register float epg[4]; register float epb[4]; for (i = 0; i < nbvert; i++) { long c = ep->v[i].color; epr[i] = (float)((c >> 16) & 255); epg[i] = (float)((c >> 8) & 255); epb[i] = (float)(c & 255); } for (i = 0; i < TOTPDL; i++) { EERIE_LIGHT * el = PDL[i]; if (!(GetMaxManhattanDistance(&el->pos, (EERIE_3D *)&ep->center) <= el->fallend + 35.f)) { TSU_TEST_NB_LIGHT ++; continue; } float d = EEDistance3D(&el->pos, (EERIE_3D *)&ep->center); if (d <= el->fallend + 35.f) { if (Project.improve) { rgb.r = el->rgb255.r * 4.f; rgb.g = rgb.b = 0.2f; } else { rgb.r = el->rgb255.r; rgb.g = el->rgb255.g; rgb.b = el->rgb255.b; } for (j = 0; j < nbvert; j++) { if (!(GetMaxManhattanDistance(&el->pos, (EERIE_3D *)&ep->v[j]) <= el->fallend)) { TSU_TEST_NB ++; continue; } d = EEDistance3D(&el->pos, (EERIE_3D *)&ep->v[j]); if (d <= el->fallend) { float divd = 1.f / d; float nvalue; if (DYNAMIC_NORMALS) { EERIE_3D v1; v1.x = (el->pos.x - ep->v[j].sx) * divd; v1.y = (el->pos.y - ep->v[j].sy) * divd; v1.z = (el->pos.z - ep->v[j].sz) * divd; nvalue = Vector_DotProduct(&v1, &ep->nrml[j]) * DIV2; if (nvalue > 1.f) nvalue = 1.f; else if (nvalue < 0.f) nvalue = 0.f; } else nvalue = 1.f; if (nvalue > 0.f) { //// if (d <= el->fallstart) { d = nvalue * el->precalc; } else { d -= el->fallstart; d = (el->falldiff - d) * el->falldiffmul * nvalue * el->precalc; } epr[j] += rgb.r * d; epg[j] += rgb.g * d; epb[j] += rgb.b * d; } } else if (d > el->fallend + 100.f) break; } } } long lepr, lepg, lepb; for (j = 0; j < nbvert; j++) { F2L(epr[j], &lepr); lepr = clipByte255(lepr); F2L(epg[j], &lepg); lepg = clipByte255(lepg); F2L(epb[j], &lepb); lepb = clipByte255(lepb); ep->tv[j].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); } } float TOTAL_CHRONO = 0.f; //************************************************************************************* void ApplyDynLight_VertexBuffer(EERIEPOLY * ep, SMY_D3DVERTEX * _pVertex, unsigned short _usInd0, unsigned short _usInd1, unsigned short _usInd2, unsigned short _usInd3) { long nbvert, i; if (ep->type & POLY_QUAD) nbvert = 4; else nbvert = 3; if (TOTPDL == 0) { ep->tv[0].color = _pVertex[_usInd0].color = ep->v[0].color; ep->tv[1].color = _pVertex[_usInd1].color = ep->v[1].color; ep->tv[2].color = _pVertex[_usInd2].color = ep->v[2].color; if (nbvert & 4) { ep->tv[3].color = _pVertex[_usInd3].color = ep->v[3].color; } return; } long j; register float d; register float epr[4]; register float epg[4]; register float epb[4]; // To keep... // register float DVAL; // if (LIGHTPOWERUP) DVAL=LPpower*100.f; // else // DVAL=300.f; //register float nvalue; for (i = 0; i < nbvert; i++) { long c = ep->v[i].color; epr[i] = (float)(long)((c >> 16) & 255); epg[i] = (float)(long)((c >> 8) & 255); epb[i] = (float)(long)(c & 255); } for (i = 0; i < TOTPDL; i++) { EERIE_LIGHT * el = PDL[i]; for (j = 0; j < nbvert; j++) { d = EEDistance3D(&el->pos, (EERIE_3D *)&ep->v[j]); if (d < el->fallend) { float nvalue; nvalue = ((el->pos.x - ep->v[j].sx) * ep->nrml[j].x + (el->pos.y - ep->v[j].sy) * ep->nrml[j].y + (el->pos.z - ep->v[j].sz) * ep->nrml[j].z ) * 0.5f / d; if (nvalue > 0.f) { if (d <= el->fallstart) { d = el->precalc * nvalue; } else { d -= el->fallstart; d = (el->falldiff - d) * el->falldiffmul * el->precalc * nvalue; } epr[j] += el->rgb255.r * d; epg[j] += el->rgb255.g * d; epb[j] += el->rgb255.b * d; } } else if (d > el->fallend + 100.f) break; } } long lepr, lepg, lepb; F2L(epr[0], &lepr); lepr = clipByte255(lepr); F2L(epg[0], &lepg); lepg = clipByte255(lepg); F2L(epb[0], &lepb); lepb = clipByte255(lepb); ep->tv[0].color = _pVertex[_usInd0].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); F2L(epr[1], &lepr); lepr = clipByte255(lepr); F2L(epg[1], &lepg); lepg = clipByte255(lepg); F2L(epb[1], &lepb); lepb = clipByte255(lepb); ep->tv[1].color = _pVertex[_usInd1].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); F2L(epr[2], &lepr); lepr = clipByte255(lepr); F2L(epg[2], &lepg); lepg = clipByte255(lepg); F2L(epb[2], &lepb); lepb = clipByte255(lepb); ep->tv[2].color = _pVertex[_usInd2].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); if (nbvert & 4) { F2L(epr[3], &lepr); lepr = clipByte255(lepr); F2L(epg[3], &lepg); lepg = clipByte255(lepg); F2L(epb[3], &lepb); lepb = clipByte255(lepb); ep->tv[3].color = _pVertex[_usInd3].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); } } extern TILE_LIGHTS tilelights[MAX_BKGX][MAX_BKGZ]; //************************************************************************************* void ApplyDynLight_VertexBuffer_2(EERIEPOLY * ep, short _x, short _y, SMY_D3DVERTEX * _pVertex, unsigned short _usInd0, unsigned short _usInd1, unsigned short _usInd2, unsigned short _usInd3) { long nbvert, i; if (ep->type & POLY_QUAD) nbvert = 4; else nbvert = 3; TILE_LIGHTS * tls = &tilelights[_x][_y]; if (tls->num == 0) { ep->tv[0].color = _pVertex[_usInd0].color = ep->v[0].color; ep->tv[1].color = _pVertex[_usInd1].color = ep->v[1].color; ep->tv[2].color = _pVertex[_usInd2].color = ep->v[2].color; if (nbvert & 4) { ep->tv[3].color = _pVertex[_usInd3].color = ep->v[3].color; } return; } long j; register float d; register float epr[4]; register float epg[4]; register float epb[4]; // To keep... // register float DVAL; // if (LIGHTPOWERUP) DVAL=LPpower*100.f; // else // DVAL=300.f; //register float nvalue; for (i = 0; i < nbvert; i++) { long c = ep->v[i].color; epr[i] = (float)(long)((c >> 16) & 255); epg[i] = (float)(long)((c >> 8) & 255); epb[i] = (float)(long)(c & 255); } for (i = 0; i < tls->num; i++) { EERIE_LIGHT * el = tls->el[i]; for (j = 0; j < nbvert; j++) { d = EEDistance3D(&el->pos, (EERIE_3D *)&ep->v[j]); if (d < el->fallend) { float nvalue; nvalue = ((el->pos.x - ep->v[j].sx) * ep->nrml[j].x + (el->pos.y - ep->v[j].sy) * ep->nrml[j].y + (el->pos.z - ep->v[j].sz) * ep->nrml[j].z ) * 0.5f / d; if (nvalue > 0.f) { if (d <= el->fallstart) { d = el->precalc * nvalue; } else { d -= el->fallstart; d = (el->falldiff - d) * el->falldiffmul * el->precalc * nvalue; } epr[j] += el->rgb255.r * d; epg[j] += el->rgb255.g * d; epb[j] += el->rgb255.b * d; } } else if (d > el->fallend + 100.f) break; } } long lepr, lepg, lepb; F2L(epr[0], &lepr); lepr = clipByte255(lepr); F2L(epg[0], &lepg); lepg = clipByte255(lepg); F2L(epb[0], &lepb); lepb = clipByte255(lepb); ep->tv[0].color = _pVertex[_usInd0].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); F2L(epr[1], &lepr); lepr = clipByte255(lepr); F2L(epg[1], &lepg); lepg = clipByte255(lepg); F2L(epb[1], &lepb); lepb = clipByte255(lepb); ep->tv[1].color = _pVertex[_usInd1].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); F2L(epr[2], &lepr); lepr = clipByte255(lepr); F2L(epg[2], &lepg); lepg = clipByte255(lepg); F2L(epb[2], &lepb); lepb = clipByte255(lepb); ep->tv[2].color = _pVertex[_usInd2].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); if (nbvert & 4) { F2L(epr[3], &lepr); lepr = clipByte255(lepr); F2L(epg[3], &lepg); lepg = clipByte255(lepg); F2L(epb[3], &lepb); lepb = clipByte255(lepb); ep->tv[3].color = _pVertex[_usInd3].color = (0xFF000000L | (lepr << 16) | (lepg << 8) | (lepb)); } } #endif