Initial commit
This commit is contained in:
881
engines/watchmaker/ll/ll_mesh.cpp
Normal file
881
engines/watchmaker/ll/ll_mesh.cpp
Normal file
@@ -0,0 +1,881 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "watchmaker/ll/ll_mesh.h"
|
||||
#include "watchmaker/types.h"
|
||||
#include "watchmaker/t3d.h"
|
||||
#include "watchmaker/3d/math/llmath.h"
|
||||
#include "watchmaker/3d/geometry.h"
|
||||
#include "watchmaker/windows_hacks.h"
|
||||
#include "watchmaker/define.h"
|
||||
#include "watchmaker/globvar.h"
|
||||
#include "watchmaker/ll/ll_util.h"
|
||||
#include "watchmaker/3d/animation.h"
|
||||
#include "watchmaker/utils.h"
|
||||
#include "watchmaker/ll/ll_mouse.h"
|
||||
#include "watchmaker/walk/walkutil.h"
|
||||
#include "watchmaker/walk/walk.h"
|
||||
#include "watchmaker/ll/ll_system.h"
|
||||
|
||||
namespace Watchmaker {
|
||||
|
||||
// locals
|
||||
struct t3dHEADMOVE {
|
||||
t3dV3F OldPos, DestAng, CurAng;
|
||||
};
|
||||
|
||||
t3dHEADMOVE HeadMove[T3D_MAX_CHARACTERS];
|
||||
|
||||
t3dF32 OldArrowLen, OldExplosionScale;
|
||||
uint32 **SavedBodyLight;
|
||||
uint8 LastLightChar, LastLightRoom;
|
||||
/* -----------------14/04/99 18.24-------------------
|
||||
* t3dUpdateArrow
|
||||
* --------------------------------------------------*/
|
||||
void t3dUpdateArrow(t3dMESH *m, t3dF32 len) {
|
||||
uint32 i;
|
||||
|
||||
if (!m) return;
|
||||
|
||||
m->VBptr = m->VertexBuffer;
|
||||
for (i = 0; i < m->NumVerts; i++)
|
||||
if (fabs(m->VBptr[i].z) > 1.0f)
|
||||
m->VBptr[i].z += (-len + OldArrowLen);
|
||||
m->Flags |= T3D_MESH_UPDATEVB;
|
||||
m->VBptr = nullptr;
|
||||
|
||||
OldArrowLen = len;
|
||||
}
|
||||
|
||||
/* -----------------27/04/99 10.52-------------------
|
||||
* t3dLightRoom
|
||||
* --------------------------------------------------*/
|
||||
void t3dLightRoom(Init &init, t3dBODY *b, t3dV3F *p, t3dF32 NearRange, t3dF32 FarRange, t3dF32 IperRange) {
|
||||
uint32 i, j, k, rr, gg, bb, aa, cr, cb, cg, *sbl;
|
||||
uint32 addr = 110;
|
||||
uint32 addg = 95;
|
||||
uint32 addb = 80;
|
||||
t3dMESH *m;
|
||||
t3dF32 dist;
|
||||
t3dV3F tmp;
|
||||
gVertex *gv;
|
||||
|
||||
if (!b || !p) return;
|
||||
|
||||
FarRange *= FarRange;
|
||||
NearRange *= NearRange;
|
||||
IperRange *= IperRange;
|
||||
|
||||
if (!SavedBodyLight) {
|
||||
if (!(SavedBodyLight = (uint32 **)t3dMalloc(sizeof(uint32 *) * b->NumMeshes())))
|
||||
return ;
|
||||
m = &b->MeshTable[0];
|
||||
for (j = 0; j < b->NumMeshes(); j++, m++) {
|
||||
if (!m) continue;
|
||||
if (!(SavedBodyLight[j] = (uint32 *)t3dMalloc(sizeof(uint32) * m->NumVerts * 4)))
|
||||
continue;
|
||||
|
||||
gv = m->VBptr;
|
||||
m->VBptr = m->VertexBuffer;
|
||||
for (i = 0; i < m->NumVerts; i++, gv++) {
|
||||
SavedBodyLight[j][i * 4 + 0] = RGBA_GETRED(gv->diffuse);
|
||||
SavedBodyLight[j][i * 4 + 1] = RGBA_GETGREEN(gv->diffuse);
|
||||
SavedBodyLight[j][i * 4 + 2] = RGBA_GETBLUE(gv->diffuse);
|
||||
SavedBodyLight[j][i * 4 + 3] = RGBA_GETALPHA(gv->diffuse);
|
||||
}
|
||||
m->VBptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LastLightRoom = (LastLightRoom + 1) > 3 ? 0 : LastLightRoom + 1;
|
||||
m = &b->MeshTable[0];
|
||||
for (j = 0; j < b->NumMeshes(); j++, m++) {
|
||||
if (!m) continue;
|
||||
if (m->name.equalsIgnoreCase("p50-cielo") || m->name.equalsIgnoreCase("p50-stelle") || m->name.equalsIgnoreCase("p50-luna")) continue;
|
||||
if (!(m->Flags & T3D_MESH_VISIBLE) && !(m->Flags & T3D_MESH_HIDDEN)) {
|
||||
m->Flags &= ~T3D_MESH_HIDDEN;
|
||||
continue;
|
||||
}
|
||||
m->Flags &= ~T3D_MESH_HIDDEN;
|
||||
// if( (j%4) != LastLightRoom ) continue;
|
||||
|
||||
sbl = (uint32 *)&SavedBodyLight[j][0];
|
||||
for (k = 0; k < MAX_OBJ_MESHLINKS ; k++) {
|
||||
if (((!init.Obj[oNEXTPORTAL].meshLinkIsEmpty(k)) && (m->name.equalsIgnoreCase(init.Obj[oNEXTPORTAL].getMeshLink(k)))) ||
|
||||
m->name.equalsIgnoreCase("p50-sentierini01") || m->name.equalsIgnoreCase("p50-sentierini02") || m->name.equalsIgnoreCase("p50-sentierini03") ||
|
||||
m->name.equalsIgnoreCase("p50-sentierini04") || m->name.equalsIgnoreCase("p50-sentierini05") || m->name.equalsIgnoreCase("p50-sentierini06")) {
|
||||
tmp.x = m->Pos.x - p->x;
|
||||
tmp.z = m->Pos.z - p->z;
|
||||
gv = m->VBptr;
|
||||
m->VBptr = m->VertexBuffer;
|
||||
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) > (FarRange + m->Radius * m->Radius * 1.3f)) {
|
||||
if ((bGolfMode == 0) || (bGolfMode == 1))
|
||||
if (dist > (FarRange + m->Radius * m->Radius) * 2.5f) m->Flags |= T3D_MESH_HIDDEN;
|
||||
for (i = 0; i < m->NumVerts; i++, gv++) {
|
||||
rr = *sbl++;
|
||||
gg = *sbl++;
|
||||
bb = *sbl++;
|
||||
aa = *sbl++;
|
||||
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < m->NumVerts; i++, gv++) {
|
||||
tmp.x = gv->x - p->x;
|
||||
tmp.z = gv->z - p->z;
|
||||
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) < IperRange) {
|
||||
rr = *sbl++ + addr * 2;
|
||||
gg = *sbl++ + addg * 2;
|
||||
bb = *sbl++ + addb * 2;
|
||||
} else if (dist < NearRange) {
|
||||
rr = *sbl++ + addr;
|
||||
gg = *sbl++ + addg;
|
||||
bb = *sbl++ + addb;
|
||||
} else if (dist < FarRange) {
|
||||
dist = 1.0f - (dist - NearRange) / (FarRange - NearRange);
|
||||
rr = *sbl++ + (uint32)((t3dF32)(addr) * dist);
|
||||
gg = *sbl++ + (uint32)((t3dF32)(addg) * dist);
|
||||
bb = *sbl++ + (uint32)((t3dF32)(addb) * dist);
|
||||
} else {
|
||||
rr = *sbl++;
|
||||
gg = *sbl++;
|
||||
bb = *sbl++;
|
||||
}
|
||||
aa = *sbl++;
|
||||
if (rr > 255) rr = 255;
|
||||
if (gg > 255) gg = 255;
|
||||
if (bb > 255) bb = 255;
|
||||
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
|
||||
}
|
||||
}
|
||||
m->Flags |= T3D_MESH_UPDATEVB;
|
||||
m->VBptr = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k < MAX_OBJ_MESHLINKS) continue;
|
||||
|
||||
tmp.x = m->Pos.x - p->x + m->Trasl.x;
|
||||
tmp.z = m->Pos.z - p->z + m->Trasl.z;
|
||||
if ((dist = tmp.x * tmp.x + tmp.z * tmp.z) < IperRange) {
|
||||
cr = addr * 2;
|
||||
cg = addg * 2;
|
||||
cb = addb * 2;
|
||||
} else if (dist < NearRange) {
|
||||
cr = addr;
|
||||
cg = addg;
|
||||
cb = addb;
|
||||
} else if (dist < FarRange) {
|
||||
dist = 1.0f - (dist - NearRange) / (FarRange - NearRange);
|
||||
cr = (uint32)((t3dF32)(addr) * dist);
|
||||
cg = (uint32)((t3dF32)(addg) * dist);
|
||||
cb = (uint32)((t3dF32)(addb) * dist);
|
||||
} else {
|
||||
if ((bGolfMode == 0) || (bGolfMode == 1))
|
||||
if (dist > (FarRange + m->Radius * m->Radius) * 2.5f) m->Flags |= T3D_MESH_HIDDEN;
|
||||
cr = 0;
|
||||
cg = 0;
|
||||
cb = 0;
|
||||
}
|
||||
gv = m->VBptr;
|
||||
m->VBptr = m->VertexBuffer;
|
||||
for (i = 0; i < m->NumVerts; i++, gv++) {
|
||||
rr = cr + *sbl++;
|
||||
gg = cg + *sbl++;
|
||||
bb = cb + *sbl++;
|
||||
aa = *sbl++;
|
||||
if (rr > 255) rr = 255;
|
||||
if (gg > 255) gg = 255;
|
||||
if (bb > 255) bb = 255;
|
||||
gv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
|
||||
}
|
||||
m->Flags |= T3D_MESH_UPDATEVB;
|
||||
m->VBptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -----------------27/04/99 15.35-------------------
|
||||
* t3dLightChar
|
||||
* --------------------------------------------------*/
|
||||
void t3dLightChar(t3dMESH *mesh, t3dV3F *p) {
|
||||
#if 0
|
||||
int16 df;
|
||||
uint32 j, rr, gg, bb, cr, cb, cg;
|
||||
t3dF32 addr = 110 + 60;
|
||||
t3dF32 addg = 95 + 75;
|
||||
t3dF32 addb = 80 + 90;
|
||||
t3dF32 nlight;
|
||||
t3dV3F ppos, l, *normal;
|
||||
gVertex *gv;
|
||||
|
||||
if (!mesh || !p) return;
|
||||
|
||||
t3dVectAdd(&ppos, &mesh->Trasl, &mesh->Pos);
|
||||
gv = mesh->VBptr = mesh->VertexBuffer;
|
||||
|
||||
cr = (t3dU32)t3dCurRoom->AmbientLight.x + 20;
|
||||
cg = (t3dU32)t3dCurRoom->AmbientLight.y + 20;
|
||||
cb = (t3dU32)t3dCurRoom->AmbientLight.z + 20;
|
||||
df = RGBA_MAKE(cr, cg, cb, 255);
|
||||
for (j = 0; j < mesh->NumVerts; j++, gv++)
|
||||
gv->diffuse = df;
|
||||
|
||||
t3dVectSub(&l, p, &ppos);
|
||||
t3dVectTransformInv(&l, &l, &mesh->Matrix);
|
||||
t3dVectNormalize(&l);
|
||||
|
||||
gv = mesh->VBptr;
|
||||
for (j = 0; j < mesh->NumVerts; j++, gv++) {
|
||||
normal = &mesh->NList[j]->n;
|
||||
|
||||
nlight = t3dVectDot(normal, &l);
|
||||
// if( (nlight=t3dVectDot(normal,&l)) >= 0 )
|
||||
{
|
||||
rr = cr + t3dFloatToInt((addr * nlight));
|
||||
gg = cg + t3dFloatToInt((addg * nlight));
|
||||
bb = cb + t3dFloatToInt((addb * nlight));
|
||||
|
||||
if (rr > 255) rr = 255;
|
||||
if (gg > 255) gg = 255;
|
||||
if (bb > 255) bb = 255;
|
||||
|
||||
gv->diffuse = RGBA_MAKE(rr, gg, bb, 255);
|
||||
}
|
||||
}
|
||||
mesh->Flags |= T3D_MESH_UPDATEVB;
|
||||
mesh->VBptr = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -----------------12/04/99 12.11-------------------
|
||||
* t3dVectMeshInters
|
||||
* --------------------------------------------------*/
|
||||
uint8 t3dVectMeshInters(t3dMESH *m, t3dV3F start, t3dV3F end, t3dV3F *inters) {
|
||||
t3dV3F v1, v2, v3;
|
||||
|
||||
if (!m) return 0;
|
||||
if (!t3dVectPlaneIntersection(inters, start, end, m->BBoxNormal[3])) return 0;
|
||||
|
||||
m->VBptr = m->VertexBuffer;
|
||||
for (uint32 j = 0; j < m->NumFaces(); j++) {
|
||||
t3dFACE &f = m->FList[j];
|
||||
if (!f.n) continue;
|
||||
|
||||
v1.x = m->VBptr[f.VertexIndex[0]].x;
|
||||
v1.y = m->VBptr[f.VertexIndex[0]].y;
|
||||
v1.z = m->VBptr[f.VertexIndex[0]].z;
|
||||
v2.x = m->VBptr[f.VertexIndex[1]].x;
|
||||
v2.y = m->VBptr[f.VertexIndex[1]].y;
|
||||
v2.z = m->VBptr[f.VertexIndex[1]].z;
|
||||
v3.x = m->VBptr[f.VertexIndex[2]].x;
|
||||
v3.y = m->VBptr[f.VertexIndex[2]].y;
|
||||
v3.z = m->VBptr[f.VertexIndex[2]].z;
|
||||
|
||||
if (t3dVectTriangleIntersection(inters, start, end, v1, v2, v3, *f.n)) {
|
||||
m->VBptr = nullptr;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
m->VBptr = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------19/05/00 12.43-------------------
|
||||
* t3dMoveAndCheck1stCamera
|
||||
* --------------------------------------------------*/
|
||||
bool t3dMoveAndCheck1stCamera(t3dBODY *rr, t3dCAMERA *cc, t3dV3F *mm) {
|
||||
t3dWALK *w;
|
||||
t3dV3F tmp;
|
||||
int32 i, j;
|
||||
|
||||
if (!Character[ocCURPLAYER]) return FALSE;
|
||||
w = &Character[ocCURPLAYER]->Walk;
|
||||
|
||||
t3dVectAdd(&tmp, &cc->Source, mm);
|
||||
// Controlla che non sia dentro un Bounding Box
|
||||
for (i = 0; i < (int32)rr->NumMeshes(); i++) {
|
||||
t3dMESH &mesh = rr->MeshTable[i];
|
||||
if (!(mesh.Flags & T3D_MESH_HIDDEN)) {
|
||||
// Se il punto di destinazione e' dentro il bound box (allargato dell'altezza del ginocchio)
|
||||
for (j = 0; j < 6; j++)
|
||||
if (t3dVectPlaneDistance(tmp, mesh.BBoxNormal[j]) < -KNEE_HEIGHT)
|
||||
break;
|
||||
|
||||
if (j >= 6) {
|
||||
// Prima controlla che non sia dentro i bounds
|
||||
for (j = 0; j < w->PanelNum; j++) {
|
||||
if (PointInside(ocCURPLAYER, j, (double)tmp.x, (double)tmp.z) != 0) {
|
||||
warning("Inters %s", mesh.name.c_str()); // TODO: Debug
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
warning("Saved by bounds"); // TODO: Debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// evito che si entri nell'altro personaggio giocante
|
||||
i = (CurPlayer ^ 1);
|
||||
if (Character[i + ocDARRELL] && Character[i + ocDARRELL]->Mesh && t3dCurRoom->name.equalsIgnoreCase(PlayerStand[i].roomName)) { // Used to be stricmp
|
||||
t3dF32 d = t3dVectDistance(&tmp, &Character[i + ocDARRELL]->Mesh->Trasl);
|
||||
if (d < 435.f) return FALSE;
|
||||
}
|
||||
|
||||
t3dVectAdd(&cc->Source, &cc->Source, mm);
|
||||
t3dVectAdd(&cc->Target, &cc->Target, mm);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -----------------03/05/99 15.24-------------------
|
||||
* t3dClipToSurface
|
||||
* --------------------------------------------------*/
|
||||
uint8 t3dClipToSurface(Init &init, t3dV3F *pt) {
|
||||
t3dV3F tmp, start, end;
|
||||
int32 i;
|
||||
t3dMESH *m;
|
||||
|
||||
t3dVectCopy(&start, pt);
|
||||
start.y = 260000.0f;
|
||||
t3dVectCopy(&end, pt);
|
||||
end.y = -130000.0f;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if ((m = LinkMeshToStr(init, init.Obj[oNEXTPORTAL].getMeshLink(i))) && (t3dVectMeshInters(m, start, end, &tmp))) {
|
||||
pt->y = tmp.y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -----------------03/05/99 16.44-------------------
|
||||
* t3dUpdateExplosion
|
||||
* --------------------------------------------------*/
|
||||
void t3dUpdateExplosion(t3dMESH *m, t3dF32 scale) {
|
||||
// t3dU32 i;
|
||||
|
||||
if (!m) return;
|
||||
|
||||
m->Matrix.M[0] = scale;
|
||||
m->Matrix.M[4] = scale;
|
||||
m->Matrix.M[8] = scale;
|
||||
|
||||
/* m->VBptr=m->VertexBuffer;
|
||||
for (i=0; i<m->NumVerts; i++ )
|
||||
{
|
||||
m->VBptr[i].x *= (scale/OldExplosionScale);
|
||||
m->VBptr[i].y *= (scale/OldExplosionScale);
|
||||
m->VBptr[i].z *= (scale/OldExplosionScale);
|
||||
}
|
||||
m->Flags |= T3D_MESH_UPDATEVB;
|
||||
m->VBptr = NULL;
|
||||
*/
|
||||
OldExplosionScale = scale;
|
||||
}
|
||||
|
||||
/* -----------------03/09/98 17.42-------------------
|
||||
* UpdateBoundingBox
|
||||
* --------------------------------------------------*/
|
||||
void UpdateBoundingBox(t3dMESH *mesh) {
|
||||
t3dBONEANIM *db;
|
||||
t3dBONE *bone;
|
||||
t3dV3F Appov;
|
||||
int32 i, frame;
|
||||
|
||||
if (!mesh || (mesh->Flags & T3D_MESH_NOBOUNDBOX))return;
|
||||
|
||||
// DebugFile("Update Bounding Box %s",mesh->Name);
|
||||
|
||||
if (mesh->Flags & T3D_MESH_DEFAULTANIM)
|
||||
db = &mesh->DefaultAnim;
|
||||
else
|
||||
db = &mesh->Anim;
|
||||
|
||||
frame = mesh->CurFrame;
|
||||
bone = db->BoneTable;
|
||||
for (i = 0; i < db->NumBones; i++, bone++) {
|
||||
if (!bone || !bone->Trasl || !bone->Matrix || (bone->ModVertices.size() > mesh->NumVerts)) continue;
|
||||
if ((!bone->ModVertices.empty()) && !(mesh->Flags & T3D_MESH_CHARACTER)) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
t3dVectSub(&Appov, &mesh->BBox[i].p, &bone->Trasl[1]);
|
||||
t3dVectTransform(&Appov, &Appov, &bone->Matrix[1]);
|
||||
t3dVectTransformInv(&Appov, &Appov, &bone->Matrix[frame]);
|
||||
t3dVectAdd(&mesh->BBox[i].p, &Appov, &bone->Trasl[frame]);
|
||||
}
|
||||
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[0], &mesh->BBox[0].p, &mesh->BBox[2].p, &mesh->BBox[1].p); //front
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[1], &mesh->BBox[4].p, &mesh->BBox[5].p, &mesh->BBox[6].p); //back
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[2], &mesh->BBox[4].p, &mesh->BBox[0].p, &mesh->BBox[5].p); //Up
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[3], &mesh->BBox[6].p, &mesh->BBox[7].p, &mesh->BBox[2].p); //Down
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[4], &mesh->BBox[4].p, &mesh->BBox[6].p, &mesh->BBox[0].p); //Left
|
||||
t3dPlaneNormal(&mesh->BBoxNormal[5], &mesh->BBox[5].p, &mesh->BBox[1].p, &mesh->BBox[7].p); //Right
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------08/06/00 14.51-------------------
|
||||
* t3dSetSpecialAnimFrame
|
||||
* --------------------------------------------------*/
|
||||
bool t3dSetSpecialAnimFrame(WGame &game, const char *name, t3dMESH *mesh, int32 nf) {
|
||||
if (!name || !mesh)
|
||||
return false;
|
||||
|
||||
if (t3dLoadAnimation(game, name, mesh, T3D_MESH_DEFAULTANIM) <= 0)
|
||||
return false;
|
||||
|
||||
mesh->Flags |= (T3D_MESH_ABS_ANIM | T3D_MESH_DEFAULTANIM);
|
||||
FixupAnim(mesh, 0, "");
|
||||
|
||||
if (nf < 0) nf = mesh->DefaultAnim.NumFrames - 1;
|
||||
|
||||
mesh->CurFrame = nf;
|
||||
mesh->LastFrame = -1;
|
||||
mesh->BlendPercent = 255;
|
||||
mesh->LastBlendPercent = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshModifiers::modifyMesh(WGame &game, t3dMESH *mesh) {
|
||||
struct SMeshModifier *mm;
|
||||
int16 i;
|
||||
|
||||
if (!mesh || (mesh->Flags & T3D_MESH_CHARACTER))
|
||||
return;
|
||||
|
||||
// Check if there is a modifier for this mesh
|
||||
mm = &MMList[0];
|
||||
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
|
||||
if ((!mm->meshName.empty()) && (mm->meshName.equalsIgnoreCase(mesh->name)))
|
||||
break;
|
||||
|
||||
// If there are no modifiers for this mesh or they refer to a body
|
||||
if ((i >= MAX_MODIFIED_MESH) || (mm->getFlags() & (MM_SET_BND_LEVEL | MM_SET_HALOES)))
|
||||
return;
|
||||
|
||||
mm->modifyMesh(game, mesh);
|
||||
}
|
||||
|
||||
void SMeshModifier::modifyMesh(WGame &game, t3dMESH *mesh) {
|
||||
warning("MM %s: addflags %X, removeflags %X, anim |%s|", mesh->name.c_str(), this->AddFlags, this->RemoveFlags, this->animName.c_str());
|
||||
// Update Flags
|
||||
if (this->Flags & MM_REMOVE_FLAGS)
|
||||
mesh->Flags &= ~this->RemoveFlags;
|
||||
if (this->Flags & MM_ADD_FLAGS)
|
||||
mesh->Flags |= this->AddFlags;
|
||||
|
||||
// Update Materials
|
||||
if (this->Flags & MM_REMOVE_MAT_FLAGS)
|
||||
mesh->FList[0].getMaterial()->Flags &= ~this->RemoveMatFlags;
|
||||
if (this->Flags & MM_ADD_MAT_FLAGS)
|
||||
mesh->FList[0].getMaterial()->Flags |= this->AddMatFlags;
|
||||
if (this->Flags & MM_SET_MAT_FRAME)
|
||||
mesh->setMovieFrame(this->MatFrame); // This did NOT check for existing face/material before setting before.
|
||||
|
||||
// Update Anim
|
||||
if ((this->Flags & MM_ANIM_BLOCK) && (!this->animName.empty()) && (!mesh->CurFrame)) {
|
||||
t3dSetSpecialAnimFrame(game, this->animName.c_str(), mesh, -1);
|
||||
t3dCalcMeshBones(mesh, 1);
|
||||
UpdateBoundingBox(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------15/09/98 12.04-------------------
|
||||
* AddMeshModifier
|
||||
* --------------------------------------------------*/
|
||||
void MeshModifiers::addMeshModifier(const Common::String &name, int16 com, void *p) {
|
||||
struct SMeshModifier *mm;
|
||||
int16 i;
|
||||
|
||||
warning("Not sure this is right"); // Used to check for nullptr, not 0 length.
|
||||
if (name.empty() || !p)
|
||||
return;
|
||||
|
||||
// DebugLogFile("AddMM |%s| %d",name,com);
|
||||
|
||||
// Check if a modifier already exists for this mesh
|
||||
mm = &MMList[0];
|
||||
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
|
||||
if ((!mm->meshName.empty()) && mm->meshName.equalsIgnoreCase(name))
|
||||
break;
|
||||
|
||||
// If it's a new modifier look for a free place
|
||||
if (i >= MAX_MODIFIED_MESH) {
|
||||
mm = &MMList[0];
|
||||
for (i = 0; i < MAX_MODIFIED_MESH; i++, mm++)
|
||||
if (mm->meshName.empty())
|
||||
break;
|
||||
if (i >= MAX_MODIFIED_MESH) {
|
||||
warning("Troppi Mesh modifier per %s: MAX %d", name.c_str(), MAX_MODIFIED_MESH);
|
||||
return;
|
||||
}
|
||||
|
||||
*mm = SMeshModifier(name.c_str(), com, p);
|
||||
} else {
|
||||
mm->configure(name.c_str(), com, p);
|
||||
}
|
||||
}
|
||||
|
||||
SMeshModifier::SMeshModifier(Common::SeekableReadStream &stream) {
|
||||
char stringBuffer[T3D_NAMELEN] = {};
|
||||
stream.read(stringBuffer, T3D_NAMELEN);
|
||||
meshName = stringBuffer;
|
||||
Flags = stream.readSint32LE();
|
||||
AddFlags = stream.readUint32LE();
|
||||
RemoveFlags = stream.readUint32LE();
|
||||
AddMatFlags = stream.readUint32LE();
|
||||
RemoveMatFlags = stream.readUint32LE();
|
||||
MatFrame = stream.readSint32LE();
|
||||
BndLevel = stream.readUint16LE();
|
||||
HaloesStatus = stream.readByte(); // TODO: Signed.
|
||||
stream.read(stringBuffer, T3D_NAMELEN);
|
||||
animName = stringBuffer;
|
||||
}
|
||||
|
||||
SMeshModifier::SMeshModifier(const char *name, int16 com, void *p) {
|
||||
configure(name, com, p);
|
||||
}
|
||||
|
||||
void SMeshModifier::configure(const char *name, int16 com, void *p) {
|
||||
this->Flags |= com;
|
||||
switch (com) {
|
||||
case MM_ADD_FLAGS:
|
||||
Flags = *((uint32 *)p);
|
||||
this->RemoveFlags &= ~Flags;
|
||||
this->AddFlags |= Flags;
|
||||
break;
|
||||
|
||||
case MM_REMOVE_FLAGS:
|
||||
Flags = *((uint32 *)p);
|
||||
this->AddFlags &= ~Flags;
|
||||
this->RemoveFlags |= Flags;
|
||||
break;
|
||||
|
||||
case MM_ADD_MAT_FLAGS:
|
||||
Flags = *((uint32 *)p);
|
||||
this->RemoveMatFlags &= ~Flags;
|
||||
this->AddMatFlags |= Flags;
|
||||
break;
|
||||
|
||||
case MM_REMOVE_MAT_FLAGS:
|
||||
Flags = *((uint32 *)p);
|
||||
this->AddMatFlags &= ~Flags;
|
||||
this->RemoveMatFlags |= Flags;
|
||||
break;
|
||||
|
||||
case MM_SET_MAT_FRAME:
|
||||
this->MatFrame = *((int32 *)p);
|
||||
break;
|
||||
|
||||
case MM_ANIM_BLOCK:
|
||||
if (this->animName.empty())
|
||||
this->animName = (char *)p;
|
||||
else
|
||||
this->animName.clear();
|
||||
break;
|
||||
|
||||
case MM_SET_BND_LEVEL:
|
||||
this->BndLevel = *((uint16 *)p);
|
||||
break;
|
||||
|
||||
case MM_SET_HALOES:
|
||||
this->HaloesStatus = *((int8 *)p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshModifiers::applyAllMeshModifiers(WGame &game, t3dBODY *b) {
|
||||
// Check if there is a modifier for this body
|
||||
struct SMeshModifier *mm = &MMList[0];
|
||||
for (int32 j = 0; j < MAX_MODIFIED_MESH; j++, mm++)
|
||||
if ((!mm->meshName.empty()) && b->name.equalsIgnoreCase(mm->meshName)) {
|
||||
if (mm->getFlags() & MM_SET_BND_LEVEL)
|
||||
b->CurLevel = mm->getBndLevel();
|
||||
|
||||
if (mm->getFlags() & MM_SET_HALOES) {
|
||||
for (auto &l : b->LightTable) {
|
||||
if (!(l.Type & T3D_LIGHT_FLARE)) continue;
|
||||
|
||||
if (mm->getHaloesStatus() > 0)
|
||||
l.Type |= T3D_LIGHT_LIGHTON;
|
||||
else
|
||||
l.Type &= ~T3D_LIGHT_LIGHTON;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < (int32)b->NumMeshes(); i++) {
|
||||
modifyMesh(game, &b->MeshTable[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------29/03/99 14.33-------------------
|
||||
* HideRoomMeshes
|
||||
* --------------------------------------------------*/
|
||||
void HideRoomMeshes(Init &init, t3dBODY *body) {
|
||||
int32 cr, c, a, b, i, j, k, h, skip;
|
||||
t3dMESH *m;
|
||||
|
||||
if (!(cr = getRoomFromStr(init, body->name))) return;
|
||||
// DebugFile("Hiding Room %s (%d)",body->Name,cr);
|
||||
for (a = 0; a < MAX_OBJS_IN_ROOM; a++) {
|
||||
if (!(c = init.Room[cr].objects[a])) continue;
|
||||
if (init.Obj[c].flags & NOUPDATE) continue;
|
||||
if (!(init.Obj[c].flags & ON) || (init.Obj[c].flags & HIDE)) {
|
||||
for (b = 0; b < MAX_OBJ_MESHLINKS; b++) {
|
||||
if (init.Obj[c].meshLinkIsEmpty(b)) continue;
|
||||
m = nullptr;
|
||||
const Common::String &str = init.Obj[c].getMeshLink(b);
|
||||
for (h = 0; h < (uint16)body->NumMeshes(); h++) {
|
||||
if (body->MeshTable[h].name.equalsIgnoreCase(str)) {
|
||||
m = &body->MeshTable[h];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m == nullptr) continue;
|
||||
// DebugFile("CandidateObj '%s'",Obj[c].meshlink[b]);
|
||||
|
||||
skip = 0;
|
||||
for (i = 0; i < MAX_OBJS_IN_ROOM; i++) {
|
||||
if (!(k = init.Room[cr].objects[i]) || (k == c)) continue;
|
||||
if (!(init.Obj[k].flags & ON) || (init.Obj[k].flags & HIDE)) continue;
|
||||
|
||||
for (j = 0; j < MAX_OBJ_MESHLINKS; j++) {
|
||||
if (init.Obj[k].meshLinkIsEmpty(j)) continue;
|
||||
if (!init.Obj[c].getMeshLink(b).equalsIgnoreCase(init.Obj[k].getMeshLink(j))) continue;
|
||||
|
||||
// DebugFile("Skipped for %d,%d",k,j);
|
||||
skip ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip && m) {
|
||||
// DebugFile("Hiding Mesh %s",Obj[c].meshlink[b]);
|
||||
m->Flags |= T3D_MESH_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------28/12/98 17.43-------------------
|
||||
* UpdateCharHead
|
||||
* --------------------------------------------------*/
|
||||
void UpdateCharHead(int32 oc, t3dV3F *dir) {
|
||||
t3dCHARACTER *Ch = Character[oc];
|
||||
t3dMESH *mesh;
|
||||
t3dHEADMOVE *t;
|
||||
t3dBONE *bone;
|
||||
t3dV3F tmp;
|
||||
int32 i, cf;
|
||||
t3dF32 s;
|
||||
|
||||
if (!Ch || !(mesh = Ch->Mesh) || mHide || !dir) return;
|
||||
if ((bDialogActive) || (bT2DActive) || (InvStatus)) return;
|
||||
|
||||
if (oc == ocCURPLAYER) oc = ocDARRELL + CurPlayer;
|
||||
t = &HeadMove[oc];
|
||||
|
||||
if ((Player->Mesh->CurFrame > ActionStart[aSTAND]) || !(Player->Mesh->Flags & T3D_MESH_DEFAULTANIM))
|
||||
t3dVectFill(&t->DestAng, 0.0f);
|
||||
else if (t->OldPos != *dir) {
|
||||
t3dVectCopy(&tmp, &mesh->Trasl);
|
||||
tmp.y = CurFloorY + EYES_HEIGHT;
|
||||
t3dVectSub(&tmp, dir, &tmp);
|
||||
t->DestAng.x = t3dVectAngle(&tmp, &Ch->Dir);
|
||||
if (t->DestAng.x < -MAX_HEAD_ANGLE_X * 2) t->DestAng.x = -MAX_HEAD_ANGLE_X * 2;
|
||||
if (t->DestAng.x > MAX_HEAD_ANGLE_X * 2) t->DestAng.x = MAX_HEAD_ANGLE_X * 2;
|
||||
t->DestAng.y = -(t3dF32)asin((mPos.y - (CurFloorY + EYES_HEIGHT)) / t3dVectMod(&tmp)) * 180.0f / T3D_PI;
|
||||
if (t->DestAng.y < -MAX_HEAD_ANGLE_Y / 2) t->DestAng.y = -MAX_HEAD_ANGLE_Y / 2;
|
||||
if (t->DestAng.y > MAX_HEAD_ANGLE_Y / 2) t->DestAng.y = MAX_HEAD_ANGLE_Y / 2;
|
||||
t->DestAng.z = 0.0f;
|
||||
t3dVectCopy(&t->OldPos, dir);
|
||||
}
|
||||
|
||||
if (t->DestAng != t->CurAng) {
|
||||
Player->Mesh->LastFrame = 0;
|
||||
if (Player->Mesh->Flags & T3D_MESH_DEFAULTANIM) {
|
||||
if (Player->Mesh->CurFrame < ActionStart[aSTAND])
|
||||
Player->Mesh->CurFrame = ActionStart[aSTAND];
|
||||
cf = 1;
|
||||
for (i = 1; i < Player->Mesh->DefaultAnim.NumBones; i++) {
|
||||
if (!(bone = &Player->Mesh->DefaultAnim.BoneTable[i]) || !(bone->Trasl) || !(bone->Matrix))
|
||||
continue;
|
||||
|
||||
t3dVectCopy(&bone->Trasl[cf], &bone->Trasl[Player->Mesh->CurFrame]);
|
||||
t3dMatCopy(&bone->Matrix[cf], &bone->Matrix[Player->Mesh->CurFrame]);
|
||||
}
|
||||
bone = &Player->Mesh->DefaultAnim.BoneTable[12];
|
||||
} else {
|
||||
cf = Player->Mesh->CurFrame;
|
||||
bone = &Player->Mesh->Anim.BoneTable[12];
|
||||
}
|
||||
|
||||
if ((bone) && (bone->Trasl) && (bone->Matrix)) {
|
||||
t3dVectSub(&tmp, &t->DestAng, &t->CurAng);
|
||||
s = t3dVectMod(&tmp);
|
||||
if (s > MAX_HEAD_SPEED) {
|
||||
tmp.x *= (MAX_HEAD_SPEED / s);
|
||||
tmp.y *= (MAX_HEAD_SPEED / s);
|
||||
}
|
||||
t->CurAng.x += tmp.x;
|
||||
t->CurAng.y += tmp.y;
|
||||
t->CurAng.z = 0.0f;
|
||||
|
||||
t3dMatRot(&bone->Matrix[cf], (t->CurAng.y * T3D_PI) / 180.0f, (t->CurAng.x * T3D_PI) / 180.0f, 0.0f);
|
||||
bone->Matrix[cf].Flags &= ~T3D_MATRIX_IDENTITY;
|
||||
|
||||
// Player->Mesh->BlendPercent = 0;
|
||||
Player->Mesh->CurFrame = cf;
|
||||
}
|
||||
}
|
||||
|
||||
// se siamo in un dialogo o RTV non gli faccio muovere la testolina
|
||||
if (bDialogActive) {
|
||||
t3dVectFill(&t->CurAng, 0.0f);
|
||||
t3dVectFill(&t->DestAng, 0.0f);
|
||||
t3dVectFill(&t->OldPos, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------22/06/00 12.15-------------------
|
||||
* ChangeMeshFlags
|
||||
* --------------------------------------------------*/
|
||||
void ChangeMeshFlags(t3dMESH *m, int8 add, uint32 newflags) {
|
||||
if (!m) return;
|
||||
|
||||
if (add > 0) {
|
||||
m->Flags |= newflags;
|
||||
_vm->addMeshModifier(m->name, MM_ADD_FLAGS, &newflags);
|
||||
} else {
|
||||
m->Flags &= ~newflags;
|
||||
_vm->addMeshModifier(m->name, MM_REMOVE_FLAGS, &newflags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* -----------------29/06/00 11.22-------------------
|
||||
* ChangeHaloesStatus
|
||||
* --------------------------------------------------*/
|
||||
void ChangeHaloesStatus(t3dBODY *b, int8 op) {
|
||||
if (b == nullptr) b = t3dCurRoom;
|
||||
if (b == nullptr) return;
|
||||
|
||||
for (auto &l : b->LightTable) {
|
||||
if (!(l.Type & T3D_LIGHT_FLARE)) continue;
|
||||
|
||||
if (op > 0)
|
||||
l.Type |= T3D_LIGHT_LIGHTON;
|
||||
else
|
||||
l.Type &= ~T3D_LIGHT_LIGHTON;
|
||||
}
|
||||
_vm->addMeshModifier(b->name.c_str(), MM_SET_HALOES, &op);
|
||||
}
|
||||
|
||||
/* -----------------01/06/00 11.12-------------------
|
||||
* UpdateObjMesh
|
||||
* --------------------------------------------------*/
|
||||
void UpdateObjMesh(Init &init, int32 in) {
|
||||
t3dMESH *m;
|
||||
int32 a;
|
||||
|
||||
if (init.Obj[in].flags & NOUPDATE) return;
|
||||
|
||||
for (a = 0; a < MAX_OBJ_MESHLINKS; a++) {
|
||||
m = LinkMeshToStr(init, init.Obj[in].getMeshLink(a));
|
||||
if (m) {
|
||||
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
|
||||
// m->Flags &= ~T3D_MESH_HIDDEN;
|
||||
ChangeMeshFlags(m, -1, T3D_MESH_HIDDEN);
|
||||
else
|
||||
// m->Flags |= T3D_MESH_HIDDEN;
|
||||
ChangeMeshFlags(m, +1, T3D_MESH_HIDDEN);
|
||||
} else {
|
||||
//se non la trova in memoria aggiunge solo il modifier alla lista
|
||||
uint32 newflags;
|
||||
|
||||
newflags = T3D_MESH_HIDDEN;
|
||||
if (!init.Obj[in].meshLinkIsEmpty(a)) {
|
||||
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
|
||||
_vm->addMeshModifier(init.Obj[in].getMeshLink(a), MM_REMOVE_FLAGS, &newflags);
|
||||
else
|
||||
_vm->addMeshModifier(init.Obj[in].getMeshLink(a), MM_ADD_FLAGS, &newflags);
|
||||
}
|
||||
}
|
||||
}//for
|
||||
}
|
||||
|
||||
|
||||
/* -----------------22/06/00 12.15-------------------
|
||||
* SetMeshMaterialMovieFrame
|
||||
* --------------------------------------------------*/
|
||||
void SetMeshMaterialMovieFrame(t3dMESH *m, int8 op, int32 newframe) {
|
||||
if (!m || m->FList.empty() || !m->FList[0].getMaterial()) return;
|
||||
|
||||
if (op == 0)
|
||||
m->setMovieFrame(newframe);
|
||||
else if (op > 0)
|
||||
m->setMovieFrame(m->getMovieFrame() + newframe);
|
||||
else if (op < 0)
|
||||
m->setMovieFrame(m->getMovieFrame() - newframe);
|
||||
|
||||
newframe = m->getMovieFrame();
|
||||
|
||||
_vm->addMeshModifier(m->name, MM_SET_MAT_FRAME, &newframe);
|
||||
}
|
||||
|
||||
/* -----------------22/06/00 12.15-------------------
|
||||
* ChangeMeshMaterialFlags
|
||||
* --------------------------------------------------*/
|
||||
void ChangeMeshMaterialFlag(t3dMESH *m, int8 add, uint32 newflag) {
|
||||
if (!m || m->hasFaceMaterial()) return;
|
||||
|
||||
if (add > 0) {
|
||||
m->FList[0].getMaterial()->addProperty(newflag);
|
||||
_vm->addMeshModifier(m->name, MM_ADD_MAT_FLAGS, &newflag);
|
||||
} else {
|
||||
m->FList[0].getMaterial()->clearFlag(newflag);
|
||||
_vm->addMeshModifier(m->name, MM_REMOVE_MAT_FLAGS, &newflag);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------20/04/99 15.29-------------------
|
||||
* t3dProcessGolfSky
|
||||
* --------------------------------------------------*/
|
||||
void t3dProcessGolfSky(t3dMESH *gs) {
|
||||
uint32 i;
|
||||
t3dF32 GolfSkySpeed = 0.00009f;
|
||||
gVertex *gv;
|
||||
|
||||
if (!gs) return ;
|
||||
|
||||
gv = gs->VertexBuffer;
|
||||
for (i = 0; i < gs->NumVerts; i++, gv++) {
|
||||
gv->u1 += GolfSkySpeed;
|
||||
gv->v1 += GolfSkySpeed;
|
||||
}
|
||||
gs->Flags |= T3D_MESH_UPDATEVB;
|
||||
gs->VBptr = NULL;
|
||||
}
|
||||
|
||||
} // End of namespace Watchmaker
|
||||
Reference in New Issue
Block a user