mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-25 12:05:53 +00:00
3414 lines
105 KiB
C++
3414 lines
105 KiB
C++
/* 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/3d/mem_management.h"
|
|
#include "watchmaker/3d/geometry.h"
|
|
#include "watchmaker/3d/light.h"
|
|
#include "watchmaker/3d/loader.h"
|
|
#include "watchmaker/3d/math/llmath.h"
|
|
#include "watchmaker/3d/t3d_face.h"
|
|
#include "watchmaker/3d/t3d_body.h"
|
|
#include "watchmaker/3d/t3d_mesh.h"
|
|
#include "watchmaker/globvar.h"
|
|
#include "watchmaker/ll/ll_system.h"
|
|
#include "watchmaker/render.h"
|
|
#include "watchmaker/renderer.h"
|
|
#include "watchmaker/t3d.h"
|
|
#include "watchmaker/utils.h"
|
|
#include "watchmaker/windows_hacks.h"
|
|
|
|
#define SKY_SPEED 0.00005f
|
|
#define EXPRESSION_SET_LEN 14
|
|
|
|
namespace Watchmaker {
|
|
|
|
t3dCAMERA Camera;
|
|
t3dCAMERA *t3dCurCamera = &Camera;
|
|
t3dBODY *t3dCurRoom, *t3dOrigRoom;
|
|
t3dBODY *PortalCrossed = nullptr;
|
|
t3dCHARACTER *t3dCurCharacter;
|
|
|
|
t3dM3X3F t3dCurViewMatrix;
|
|
t3dV3F t3dCurTranslation;
|
|
int16 t3dCurUserViewMatrix, t3dOldUserViewMatrix, t3dOrigUserViewMatrix;
|
|
|
|
uint32 t3dStartIndex, t3dNumVertices;
|
|
|
|
uint8 FloorHit;
|
|
t3dV3F FloorHitCoords;
|
|
|
|
t3dV3F t3d3dMousePos;
|
|
|
|
t3dBODY *t3dRxt = nullptr;
|
|
t3dBODY *t3dSky = nullptr;
|
|
//s t3dBODY *t3dSun= nullptr;
|
|
|
|
uint32 t3d_NumMeshesVisible;
|
|
t3dMESH *t3d_VisibleMeshes[255];
|
|
|
|
t3dNORMAL ClipPlanes[NUMCLIPPLANES];
|
|
|
|
t3dMESH *t3dPortalList[MAX_RECURSION_LEVEL];
|
|
uint32 t3dNumPortals;
|
|
uint8 bOrigRoom;
|
|
uint8 bPortalRoom;
|
|
uint8 bViewOnlyPortal;
|
|
uint8 bDisableMirrors;
|
|
uint8 bNoLightmapsCalc;
|
|
uint8 LastFlaresVisible;
|
|
t3dMESH *t3dGlobalMirrorList[MAX_MIRRORS];
|
|
uint32 t3dNumGlobalMirrors;
|
|
|
|
uint32 StatNumTris, StatNumVerts;
|
|
|
|
int32 MaxSetDimX, MaxSetDimY;
|
|
|
|
uint32 skyval1, skyval2;
|
|
gTexture *SkySurface;
|
|
gTexture *SmokeSurface, *NoiseSmokeSurface;
|
|
|
|
#define T3D_PARTICLE_ACTIVE (1<<0)
|
|
#define T3D_PARTICLE_REGEN (1<<1)
|
|
|
|
struct Particle {
|
|
t3dV3F Pos;
|
|
t3dF32 Size;
|
|
uint32 Flags;
|
|
t3dV3F Color;
|
|
};
|
|
|
|
struct _PARTICLESTRUCT {
|
|
Particle *ParticlePos;
|
|
uint32 NumParticles;
|
|
uint32 FirstParticleRendered;
|
|
gMaterial Material;
|
|
int8 RandTable[16];
|
|
uint8 ParticleWait;
|
|
} Particles[MAX_PARTICLES];
|
|
uint32 t3dNumParticles = 0;
|
|
|
|
#define MAX_MATERIAL_LISTS 50
|
|
|
|
struct _MaterialList {
|
|
MaterialTable *mat_list; // This is brittle, as there is no ownership flagging.
|
|
unsigned int num_mat;
|
|
signed short int matrix;
|
|
} t3dMaterialList[MAX_MATERIAL_LISTS];
|
|
|
|
uint32 t3dNumMaterialLists = 0;
|
|
|
|
/* -----------------10/06/99 15.45-------------------
|
|
* t3dCheckBoundSphere
|
|
* --------------------------------------------------*/
|
|
uint8 t3dCheckBoundSphere(t3dMESH &mesh) {
|
|
t3dV3F pos;
|
|
t3dF32 d1;
|
|
|
|
if (mesh.Flags & T3D_MESH_ALWAYSVISIBLE)
|
|
return 1;
|
|
|
|
t3dVectAdd(&pos, &mesh.Pos, &mesh.Trasl);
|
|
t3dVectSub(&pos, &pos, &t3dCurCamera->Source);
|
|
t3dVectTransform(&pos, &pos, &t3dCurViewMatrix); // rotate by the mesh matrix
|
|
|
|
if ((pos.z < 0) && (pos.z < -mesh.Radius))
|
|
return 0;
|
|
|
|
d1 = t3dVectDot(&pos, &ClipPlanes[RIGHTCLIP].n) + ClipPlanes[RIGHTCLIP].dist;
|
|
if ((d1 > 0) || (mesh.Radius > (-d1))) {
|
|
d1 = ClipPlanes[LEFTCLIP].dist + t3dVectDot(&pos, &ClipPlanes[LEFTCLIP].n);
|
|
if ((d1 > 0) || (mesh.Radius > (-d1))) {
|
|
d1 = ClipPlanes[TOPCLIP].dist + t3dVectDot(&pos, &ClipPlanes[TOPCLIP].n);
|
|
if ((d1 > 0) || (mesh.Radius > (-d1))) {
|
|
d1 = ClipPlanes[BOTTOMCLIP].dist + t3dVectDot(&pos, &ClipPlanes[BOTTOMCLIP].n);
|
|
if ((d1 > 0) || (mesh.Radius > (-d1))) {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.45-------------------
|
|
* t3dCheckBoundBox
|
|
* --------------------------------------------------*/
|
|
uint8 t3dCheckBoundBox(t3dMESH &mesh) {
|
|
t3dV3F TBBox[8], inter;
|
|
t3dF32 d1;
|
|
uint32 in = 0, i;
|
|
|
|
if (mesh.Flags & T3D_MESH_ALWAYSVISIBLE)
|
|
return 1;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
t3dVectAdd(&TBBox[i], &mesh.BBox[i].p, &mesh.Trasl);
|
|
t3dVectSub(&TBBox[i], &TBBox[i], &t3dCurCamera->Source);
|
|
t3dVectTransform(&TBBox[i], &TBBox[i], &t3dCurViewMatrix); // rotate by the mesh matrix
|
|
}
|
|
|
|
for (i = 0; i < 8; i++)
|
|
if ((d1 = t3dVectDot(&TBBox[i], &ClipPlanes[RIGHTCLIP].n) + ClipPlanes[RIGHTCLIP].dist) > 0)
|
|
if ((d1 = ClipPlanes[LEFTCLIP].dist + t3dVectDot(&TBBox[i], &ClipPlanes[LEFTCLIP].n)) > 0)
|
|
if ((d1 = ClipPlanes[TOPCLIP].dist + t3dVectDot(&TBBox[i], &ClipPlanes[TOPCLIP].n)) > 0)
|
|
if ((d1 = ClipPlanes[BOTTOMCLIP].dist + t3dVectDot(&TBBox[i], &ClipPlanes[BOTTOMCLIP].n)) > 0)
|
|
in++;
|
|
|
|
if (in) return 1;
|
|
|
|
for (i = 0; i < NUMCLIPPLANES; i++) {
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[0], TBBox[1], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[1], TBBox[5], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[5], TBBox[4], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[4], TBBox[0], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[2], TBBox[3], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[3], TBBox[7], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[7], TBBox[6], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[6], TBBox[2], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[0], TBBox[2], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[1], TBBox[3], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[5], TBBox[7], ClipPlanes[i])) return 1;
|
|
if (t3dVectPlaneIntersection(&inter, TBBox[4], TBBox[6], ClipPlanes[i])) return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------11/06/99 12.23-------------------
|
|
* t3dCheckBlockMesh
|
|
* --------------------------------------------------*/
|
|
void t3dCheckBlockMesh(Common::Array<t3dMESH> &mt, uint32 NumMeshes, t3dMESH *blockmesh) {
|
|
t3dF32 xa, za, xb, zb, xc, zc, xd, zd;
|
|
t3dF32 r, s, divisor;
|
|
|
|
uint8 ref[4] = {2, 3, 6, 7};
|
|
|
|
if (!blockmesh || mt.empty() || !blockmesh->VertexBuffer) return;
|
|
|
|
xc = t3dCurCamera->Source.x;
|
|
zc = t3dCurCamera->Source.z;
|
|
|
|
xa = za = 9999999.9f;
|
|
xb = zb = -9999999.9f;
|
|
blockmesh->VBptr = blockmesh->VertexBuffer;
|
|
for (uint32 j = 0; j < blockmesh->NumFaces(); j++) {
|
|
t3dFACE &f = blockmesh->FList[j];
|
|
if (!f.n) continue;
|
|
|
|
for (uint32 i = 0; i < 3; i++) {
|
|
if (blockmesh->VBptr[f.VertexIndex[i]].x < xa) {
|
|
xa = blockmesh->VBptr[f.VertexIndex[i]].x;
|
|
za = blockmesh->VBptr[f.VertexIndex[i]].z;
|
|
}
|
|
if (blockmesh->VBptr[f.VertexIndex[i]].x > xb) {
|
|
xb = blockmesh->VBptr[f.VertexIndex[i]].x;
|
|
zb = blockmesh->VBptr[f.VertexIndex[i]].z;
|
|
}
|
|
}
|
|
}
|
|
blockmesh->VBptr = nullptr;
|
|
|
|
for (uint32 i = 0; i < NumMeshes; i++) {
|
|
t3dMESH &mesh = mt[i];
|
|
if ((mesh.Flags & T3D_MESH_HIDDEN) || (mesh.Flags & T3D_MESH_INVISIBLEFROMSECT))
|
|
continue;
|
|
|
|
uint32 j;
|
|
for (j = 0; j < 4; j++) {
|
|
xd = mesh.Trasl.x + mesh.BBox[ref[j]].p.x;
|
|
zd = mesh.Trasl.z + mesh.BBox[ref[j]].p.z;
|
|
|
|
divisor = (t3dF32)((xb - xa) * (zd - zc) - (zb - za) * (xd - xc));
|
|
if (!divisor) divisor = 0.000001f;
|
|
r = (t3dF32)((za - zc) * (xd - xc) - (xa - xc) * (zd - zc)) / divisor;
|
|
s = (t3dF32)((za - zc) * (xb - xa) - (xa - xc) * (zb - za)) / divisor;
|
|
|
|
if ((r < 0.0f) || (r > (1.0f)) || (s < 0.0f) || (s > (1.0f)))
|
|
break;
|
|
}
|
|
if (j >= 4) mesh.Flags |= T3D_MESH_INVISIBLEFROMSECT;
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.53-------------------
|
|
* t3dCalcRejectedMeshFromPortal
|
|
* --------------------------------------------------*/
|
|
void t3dCalcRejectedMeshFromPortal(t3dBODY *body) {
|
|
t3dV3F appo, c0;
|
|
t3dV3F ppv1, ppv2, ppv3, ppv4, Source, Target;
|
|
uint32 p;
|
|
t3dNORMAL OldClipPlanes[NUMCLIPPLANES];
|
|
t3dF32 minx, miny, minz, maxx, maxy, maxz;
|
|
|
|
for (uint32 i = 0; i < body->NumMeshes(); i++) {
|
|
t3dMESH &mesh = body->MeshTable[i];
|
|
if ((mesh.Flags & T3D_MESH_PREPROCESSPORTAL) && (!(mesh.Flags & T3D_MESH_NOPORTALCHECK)) &&
|
|
(mesh.PortalList) && (mesh.RejectedMeshes.empty())) {
|
|
mesh.VBptr = mesh.VertexBuffer;
|
|
ppv1.x = mesh.VBptr[mesh.FList[0].VertexIndex[0]].x;
|
|
ppv1.y = mesh.VBptr[mesh.FList[0].VertexIndex[0]].y;
|
|
ppv1.z = mesh.VBptr[mesh.FList[0].VertexIndex[0]].z;
|
|
ppv2.x = mesh.VBptr[mesh.FList[0].VertexIndex[1]].x;
|
|
ppv2.y = mesh.VBptr[mesh.FList[0].VertexIndex[1]].y;
|
|
ppv2.z = mesh.VBptr[mesh.FList[0].VertexIndex[1]].z;
|
|
ppv3.x = mesh.VBptr[mesh.FList[0].VertexIndex[2]].x;
|
|
ppv3.y = mesh.VBptr[mesh.FList[0].VertexIndex[2]].y;
|
|
ppv3.z = mesh.VBptr[mesh.FList[0].VertexIndex[2]].z;
|
|
|
|
for (p = 0; p < 3; p++) {
|
|
appo.x = mesh.VBptr[mesh.FList[1].VertexIndex[p]].x;
|
|
appo.y = mesh.VBptr[mesh.FList[1].VertexIndex[p]].y;
|
|
appo.z = mesh.VBptr[mesh.FList[1].VertexIndex[p]].z;
|
|
|
|
if ((ppv1 != appo) && (ppv2 != appo) && (ppv3 != appo))
|
|
memcpy(&ppv4, &appo, sizeof(t3dV3F));
|
|
}
|
|
|
|
memcpy(OldClipPlanes, ClipPlanes, sizeof(t3dNORMAL)*NUMCLIPPLANES);
|
|
|
|
minx = miny = minz = 9999999.9f;
|
|
maxx = maxy = maxz = -9999999.9f;
|
|
if (ppv1.x < minx) minx = ppv1.x;
|
|
if (ppv1.y < miny) miny = ppv1.y;
|
|
if (ppv1.z < minz) minz = ppv1.z;
|
|
if (ppv1.x > maxx) maxx = ppv1.x;
|
|
if (ppv1.y > maxy) maxy = ppv1.y;
|
|
if (ppv1.z > maxz) maxz = ppv1.z;
|
|
|
|
if (ppv2.x < minx) minx = ppv2.x;
|
|
if (ppv2.y < miny) miny = ppv2.y;
|
|
if (ppv2.z < minz) minz = ppv2.z;
|
|
if (ppv2.x > maxx) maxx = ppv2.x;
|
|
if (ppv2.y > maxy) maxy = ppv2.y;
|
|
if (ppv2.z > maxz) maxz = ppv2.z;
|
|
|
|
if (ppv3.x < minx) minx = ppv3.x;
|
|
if (ppv3.y < miny) miny = ppv3.y;
|
|
if (ppv3.z < minz) minz = ppv3.z;
|
|
if (ppv3.x > maxx) maxx = ppv3.x;
|
|
if (ppv3.y > maxy) maxy = ppv3.y;
|
|
if (ppv3.z > maxz) maxz = ppv3.z;
|
|
|
|
if (ppv4.x < minx) minx = ppv4.x;
|
|
if (ppv4.y < miny) miny = ppv4.y;
|
|
if (ppv4.z < minz) minz = ppv4.z;
|
|
if (ppv4.x > maxx) maxx = ppv4.x;
|
|
if (ppv4.y > maxy) maxy = ppv4.y;
|
|
if (ppv4.z > maxz) maxz = ppv4.z;
|
|
|
|
Source.x = minx + ((maxx - minx) / 2.0f) + mesh.NList[0]->n.x * 100;
|
|
Source.y = miny + ((maxy - miny) / 2.0f) + mesh.NList[0]->n.y * 100;
|
|
Source.z = minz + ((maxz - minz) / 2.0f) + mesh.NList[0]->n.z * 100;
|
|
Target.x = minx + ((maxx - minx) / 2.0f);
|
|
Target.y = miny + ((maxy - miny) / 2.0f);
|
|
Target.z = minz + ((maxz - minz) / 2.0f);
|
|
|
|
t3dMatView(&t3dCurViewMatrix, &Source, &Target);
|
|
|
|
|
|
t3dVectSub(&ppv4, &ppv4, &Source);
|
|
t3dVectSub(&ppv3, &ppv3, &Source);
|
|
t3dVectSub(&ppv2, &ppv2, &Source);
|
|
t3dVectSub(&ppv1, &ppv1, &Source);
|
|
t3dVectTransform(&ppv1, &ppv1, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv2, &ppv2, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv3, &ppv3, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv4, &ppv4, &t3dCurViewMatrix);
|
|
t3dVectFill(&c0, 0.0f);
|
|
|
|
// t3dVectCopy(&c0,&cam->Source);
|
|
|
|
t3dPlaneNormal(&ClipPlanes[RIGHTCLIP], &c0, &ppv3, &ppv4);
|
|
t3dPlaneNormal(&ClipPlanes[LEFTCLIP], &c0, &ppv1, &ppv2);
|
|
t3dPlaneNormal(&ClipPlanes[TOPCLIP], &c0, &ppv4, &ppv1);
|
|
t3dPlaneNormal(&ClipPlanes[BOTTOMCLIP], &c0, &ppv2, &ppv3);
|
|
|
|
mesh.VBptr = nullptr;
|
|
|
|
t3dVectCopy(&t3dCurCamera->Source, &Source);
|
|
t3dVectCopy(&t3dCurCamera->Target, &Target);
|
|
|
|
for (uint32 j = 0; j < mesh.PortalList->NumMeshes(); j++) {
|
|
t3dMESH *m = &mesh.PortalList->MeshTable[j];
|
|
if (!t3dCheckBoundSphere(*m)) {
|
|
mesh.RejectedMeshes.push_back(m);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.39-------------------
|
|
* t3dReleaseBody
|
|
* --------------------------------------------------*/
|
|
void t3dReleaseBody(t3dBODY *b) {
|
|
if (!b) return;
|
|
|
|
for (auto &mesh : b->MeshTable) {
|
|
mesh.release();
|
|
}
|
|
b->MeshTable.clear();
|
|
|
|
if (!b->MatTable.empty())
|
|
rRemoveMaterials(b->MatTable);
|
|
b->MatTable.clear();
|
|
|
|
if (b->LightmapTable.size() > 0)
|
|
rRemoveMaterials(b->LightmapTable);
|
|
b->LightmapTable.clear();
|
|
|
|
if (b->MirrorMatTable.size() > 0) {
|
|
rRemoveMaterials(b->MirrorMatTable);
|
|
}
|
|
b->MirrorMatTable.clear();
|
|
|
|
|
|
b->clearVBTable();
|
|
|
|
for (int i = 0; i < T3D_MAX_LEVELS; i++) {
|
|
delete[] b->Panel[i];
|
|
b->Panel[i] = nullptr;
|
|
}
|
|
|
|
// Not at all necessary
|
|
b->CameraGrid.Grid.clear();
|
|
b->CameraPath.clear();
|
|
b->CameraTable.clear();
|
|
b->LightTable.clear();
|
|
b->PosLightTable.clear();
|
|
b->NList.clear();
|
|
b->VolumetricLights.reset();
|
|
for (int i = 0; i < T3D_MAX_BLOCK_MESHES; i++)
|
|
b->BlockMeshes[i] = nullptr;
|
|
t3dFree(b);
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.40-------------------
|
|
* t3dReleaseCharacter
|
|
* --------------------------------------------------*/
|
|
void t3dReleaseCharacter(t3dCHARACTER *b) {
|
|
warning("STUBBED: t3dReleaseCharacter");
|
|
#if 0
|
|
t3dU32 i, j;
|
|
|
|
if (!b)
|
|
return;
|
|
|
|
// if ( b->Body )
|
|
// t3dReleaseBody(b->Body);
|
|
b->Body = nullptr;
|
|
|
|
if (b->Shadow) {
|
|
for (i = 0; i < b->Shadow->NumMeshes; i++)
|
|
b->Shadow->MeshTable[i].VertexBuffer = nullptr;
|
|
//m t3dReleaseBody(b->Shadow);
|
|
}
|
|
b->Shadow = nullptr;
|
|
|
|
for (i = 0; i < T3D_MAX_SHADOWBOX_PER_CHAR; i++) {
|
|
if (b->ShadowBox[i]) {
|
|
for (j = 0; j < MAX_SHADOWS_PER_LIGHT; j++) {
|
|
rDeleteVertexBuffer(b->ShadowBox[i]->ShadowsList[j].VB);
|
|
b->ShadowBox[i]->ShadowsList[j].VB = nullptr;
|
|
rDeleteVertexBuffer(b->ShadowBox[i]->ShadowsList[j].ProjVertsVB);
|
|
b->ShadowBox[i]->ShadowsList[j].ProjVertsVB = nullptr;
|
|
|
|
if (b->ShadowBox[i]->ShadowsList[j].pwShadVolIndices != b->ShadowBox[i]->ShadowsList[j].pwShadVolSideIndices)
|
|
t3dFree(b->ShadowBox[i]->ShadowsList[j].pwShadVolIndices);
|
|
b->ShadowBox[i]->ShadowsList[j].pwShadVolIndices = nullptr;
|
|
t3dFree(b->ShadowBox[i]->ShadowsList[j].pwShadVolSideIndices);
|
|
b->ShadowBox[i]->ShadowsList[j].pwShadVolSideIndices = nullptr;
|
|
|
|
t3dFree(b->ShadowBox[i]->ShadowsList[j].pwShadVolCapIndices);
|
|
b->ShadowBox[i]->ShadowsList[j].pwShadVolCapIndices = nullptr;
|
|
}
|
|
rDeleteVertexBuffer(b->ShadowBox[i]->VB);
|
|
b->ShadowBox[i]->VB = nullptr;
|
|
t3dFree(b->ShadowBox[i]->pwIndices);
|
|
b->ShadowBox[i]->pwIndices = nullptr;
|
|
t3dFree(b->ShadowBox[i]);
|
|
b->ShadowBox[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
t3dFree(b);
|
|
b = nullptr;
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.40-------------------
|
|
* t3dBackfaceCulling
|
|
* --------------------------------------------------*/
|
|
uint16 t3dBackfaceCulling(NormalList &normals, uint32 NumNormals, t3dV3F *eye) {
|
|
uint32 NumVisiNorm = 0;
|
|
// Attiva solo le normali che si vedono
|
|
for (uint32 i = 0; i < NumNormals; i++) {
|
|
auto n = normals[i];
|
|
n->tras_n = n->dist - t3dVectDot(&n->n, eye);
|
|
if (n->tras_n > 0)
|
|
n->flag = T3D_NORMAL_INVISIBLE;
|
|
else
|
|
n->flag = T3D_NORMAL_VISIBLE;
|
|
}
|
|
|
|
return NumVisiNorm;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.55-------------------
|
|
* ssqrt
|
|
* --------------------------------------------------*/
|
|
inline long ssqrt(long i) {
|
|
error("TODO: ssqrt");
|
|
#if 0
|
|
long r = rand(), rnew = 1, rold = r;
|
|
|
|
do {
|
|
rold = r;
|
|
r = rnew;
|
|
rnew = (r + (i / r));
|
|
rnew >>= 1;
|
|
} while (rold != rnew);
|
|
return rnew;
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.55-------------------
|
|
* isprime
|
|
* --------------------------------------------------*/
|
|
inline int isprime(long i) {
|
|
long si, j;
|
|
|
|
if (i == 0)
|
|
return 0;
|
|
|
|
si = ssqrt(i);
|
|
|
|
for (j = 2; (j <= si); j++) {
|
|
if (i % j == 0)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* -----------------10/06/99 15.55-------------------
|
|
* Cosine_Interpolate
|
|
* --------------------------------------------------*/
|
|
t3dF32 Cosine_Interpolate(t3dF32 a, t3dF32 b, t3dF32 x) {
|
|
t3dF32 ft = x * T3D_PI;
|
|
t3dF32 f = (1.0f - (t3dF32)cos(ft)) * 0.5f;
|
|
return a * (1.0f - f) + b * f;
|
|
|
|
//return a*(1.0f-x) + b*x;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.55-------------------
|
|
* SelectRandomNumbers
|
|
* --------------------------------------------------*/
|
|
void SelectRandomNumbers() {
|
|
error("TODO: SelectRandomNumbers");
|
|
#if 0
|
|
while (!isprime(skyval1 = (uint32)rand() % 100));
|
|
while (!isprime(skyval2 = (uint32)(skyval1 - rand() % 100) % 15));
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.56-------------------
|
|
* Noise1
|
|
* --------------------------------------------------*/
|
|
t3dF32 Noise1(int32 x, int32 y) {
|
|
int32 n;
|
|
t3dF32 f;
|
|
|
|
/* n = x + y * 57;
|
|
n = (n<<13)^n;
|
|
f=(t3dF32)((n * (n * n * 15731 + 789221) + 1 376 312 589) & 0x7fffffff);
|
|
return ( 1.0f - f / 1 073 741 824.0f);
|
|
*/
|
|
skyval1 = 13;
|
|
skyval2 = 131;
|
|
n = x + y * skyval1;
|
|
n = (n << skyval2)^n;
|
|
f = (t3dF32)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff);
|
|
return (1.0f - f / 1073741824.0f);
|
|
// f=(t3dF32)((n * (n * n * skyval3 + skyval4) + skyval5) & 0x7fffffff);
|
|
//return ( 1.0f - f / (t3dF32)skyval6);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.56-------------------
|
|
* SmoothNoise_1
|
|
* --------------------------------------------------*/
|
|
t3dF32 SmoothNoise_1(int32 x, int32 y) {
|
|
t3dF32 corners = (Noise1(x - 1, y - 1) + Noise1(x + 1, y - 1) + Noise1(x - 1, y + 1) + Noise1(x + 1, y + 1)) / 16;
|
|
t3dF32 sides = (Noise1(x - 1, y) + Noise1(x + 1, y) + Noise1(x, y - 1) + Noise1(x, y + 1)) / 8;
|
|
t3dF32 center = Noise1(x, y) / 4;
|
|
return corners + sides + center;
|
|
|
|
// return ((Noise1(x-1, y-1)+Noise1(x+1, y-1)+Noise1(x-1, y+1)+Noise1(x+1, y+1))+( Noise1(x-1, y) +Noise1(x+1, y) +Noise1(x, y-1) +Noise1(x, y+1) )+Noise1(x, y))/9.0f;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.56-------------------
|
|
* InterpolatedNoise_1
|
|
* --------------------------------------------------*/
|
|
t3dF32 InterpolatedNoise_1(t3dF32 x, t3dF32 y) {
|
|
int32 integer_X = (int32)(x);
|
|
t3dF32 fractional_X = x - (t3dF32)integer_X;
|
|
|
|
int32 integer_Y = (int32)(y);
|
|
t3dF32 fractional_Y = y - (t3dF32)integer_Y;
|
|
|
|
t3dF32 v1 = SmoothNoise_1(integer_X, integer_Y);
|
|
t3dF32 v2 = SmoothNoise_1(integer_X + 1, integer_Y);
|
|
t3dF32 v3 = SmoothNoise_1(integer_X, integer_Y + 1);
|
|
t3dF32 v4 = SmoothNoise_1(integer_X + 1, integer_Y + 1);
|
|
|
|
t3dF32 i1 = Cosine_Interpolate(v1, v2, fractional_X);
|
|
t3dF32 i2 = Cosine_Interpolate(v3, v4, fractional_X);
|
|
|
|
return Cosine_Interpolate(i1, i2, fractional_Y);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.56-------------------
|
|
* CloudExpCurve
|
|
* --------------------------------------------------*/
|
|
t3dF32 CloudExpCurve(t3dF32 v, t3dF32 CloudCover, t3dF32 CloudSharpness) {
|
|
t3dF32 c = v - CloudCover;
|
|
if (c < 0.0f)
|
|
c = 0;
|
|
|
|
return (255 - ((t3dF32)pow(CloudSharpness, c) * 255));
|
|
}
|
|
|
|
/* -----------------10/06/99 15.57-------------------
|
|
* PerlinNoise_2D
|
|
* --------------------------------------------------*/
|
|
t3dF32 PerlinNoise_2D(t3dF32 x, t3dF32 y, t3dF32 persistence, uint32 NumberOfOctaves) {
|
|
uint32 i;
|
|
t3dF32 total = 0.0f;
|
|
t3dF32 frequency;
|
|
t3dF32 amplitude = 1;
|
|
|
|
for (i = 0; i < NumberOfOctaves; i++) {
|
|
frequency = /*1.0f*/(t3dF32)pow(2, i);
|
|
amplitude = /*1.0f*/((t3dF32)pow(persistence, i));
|
|
|
|
total += InterpolatedNoise_1((x * frequency), (y * frequency)) * amplitude;
|
|
}
|
|
// DebugFile("perl: %f",(total));
|
|
return total;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.57-------------------
|
|
* t3dCreateProceduralSky
|
|
* --------------------------------------------------*/
|
|
void t3dCreateProceduralSky() {
|
|
unsigned short *p;
|
|
int32 i, j, pitch;
|
|
t3dF32 f, x, y, xstep, ystep;
|
|
uint32 cr, cb, cg;
|
|
t3dF32 CloudCover[4] = { 2.0f, 5.0f, 2.0f, 1.0f };
|
|
t3dF32 CloudSharpness[4] = { 0.98f, 0.95f, 0.98f, 0.98f };
|
|
t3dF32 CloudR[4] = { 143.0f, 131.0f, 145.0f, 45.0f };
|
|
t3dF32 CloudG[4] = { 155.0f, 129.0f, 130.0f, 49.0f };
|
|
t3dF32 CloudB[4] = { 174.0f, 100.0f, 148.0f, 50.0f };
|
|
uint32 Refr[4] = {88, 110, 110, 36 };
|
|
uint32 Refg[4] = {106, 150, 106, 35 };
|
|
uint32 Refb[4] = {164, 240, 134, 42 };
|
|
uint8 *tab;
|
|
uint32 MARGIN;
|
|
|
|
if (t3dSky == nullptr) return;
|
|
if ((t3dCurOliSet < 0) || (t3dCurOliSet > 3)) t3dCurOliSet = 0;
|
|
|
|
//set a random seed
|
|
error("TODO:t3dCreateProceduralSky");
|
|
#if 0
|
|
srand((unsigned)t3dReadTime());
|
|
SelectRandomNumbers();
|
|
#endif
|
|
MaxSetDimX = MaxSetDimY = 256;
|
|
MARGIN = MaxSetDimX / 2;
|
|
tab = new uint8[MaxSetDimX * MaxSetDimY * 3]{};
|
|
|
|
if (!SkySurface) // rReleaseBitmapDirect( SkySurface );
|
|
SkySurface = (gTexture *)rCreateSurfaceP(256, 256, rTEXTURESURFACE);
|
|
|
|
p = (unsigned short *)rLockSurfaceDirect(SkySurface, (unsigned int *)&pitch);
|
|
pitch /= 2;
|
|
|
|
x = y = 0;
|
|
ystep = xstep = (1.0f / (256.0f));
|
|
for (j = 0; j < MaxSetDimY; j++, y += ystep) {
|
|
x = 0.0f;
|
|
for (i = 0; i < MaxSetDimX; i++, x += xstep) {
|
|
f = (PerlinNoise_2D(x * 2.0f, y * 4.0f, 0.65f, 8));
|
|
if (f < 0.0f)
|
|
f = -f;
|
|
|
|
cr = (uint32)CloudExpCurve(f * CloudR[t3dCurOliSet], CloudCover[t3dCurOliSet], CloudSharpness[t3dCurOliSet]);
|
|
cg = (uint32)CloudExpCurve(f * CloudG[t3dCurOliSet], CloudCover[t3dCurOliSet], CloudSharpness[t3dCurOliSet]);
|
|
cb = (uint32)CloudExpCurve(f * CloudB[t3dCurOliSet], CloudCover[t3dCurOliSet], CloudSharpness[t3dCurOliSet]);
|
|
|
|
if (cr < Refr[t3dCurOliSet]) {
|
|
cr += Refr[t3dCurOliSet];
|
|
cr /= 2;
|
|
}
|
|
if (cg < Refg[t3dCurOliSet]) {
|
|
cg += Refg[t3dCurOliSet];
|
|
cg /= 2;
|
|
}
|
|
if (cb < Refb[t3dCurOliSet]) {
|
|
cb += Refb[t3dCurOliSet];
|
|
cb /= 2;
|
|
}
|
|
if (cr > 255)
|
|
cr = 255 - (cr - 255);
|
|
if (cg > 255)
|
|
cg = 255 - (cg - 255);
|
|
if (cb > 255)
|
|
cb = 255 - (cb - 255);
|
|
|
|
if (cr > 255)
|
|
cr = 255;
|
|
if (cg > 255)
|
|
cg = 255;
|
|
if (cb > 255)
|
|
cb = 255;
|
|
|
|
tab[i * 3 + 0 + j * 3 * MaxSetDimX] = cr;
|
|
tab[i * 3 + 1 + j * 3 * MaxSetDimX] = cg;
|
|
tab[i * 3 + 2 + j * 3 * MaxSetDimX] = cb;
|
|
}
|
|
}
|
|
|
|
ystep = 1.0f / MARGIN;
|
|
y = 1.0f;
|
|
for (j = 0; j < (int32)MARGIN; j++, y -= ystep) {
|
|
for (i = 0; i < MaxSetDimX; i++) {
|
|
cr = (uint32)Cosine_Interpolate(tab[i * 3 + 0 + j * 3 * MaxSetDimX], tab[i * 3 + 0 + (255 - j) * 3 * MaxSetDimX], y);
|
|
cg = (uint32)Cosine_Interpolate(tab[i * 3 + 1 + j * 3 * MaxSetDimX], tab[i * 3 + 1 + (255 - j) * 3 * MaxSetDimX], y);
|
|
cb = (uint32)Cosine_Interpolate(tab[i * 3 + 2 + j * 3 * MaxSetDimX], tab[i * 3 + 2 + (255 - j) * 3 * MaxSetDimX], y);
|
|
if (cr > 255)
|
|
cr = 255;
|
|
if (cg > 255)
|
|
cg = 255;
|
|
if (cb > 255)
|
|
cb = 255;
|
|
tab[i * 3 + 0 + j * 3 * MaxSetDimX] = cr;
|
|
tab[i * 3 + 1 + j * 3 * MaxSetDimX] = cg;
|
|
tab[i * 3 + 2 + j * 3 * MaxSetDimX] = cb;
|
|
}
|
|
}
|
|
xstep = 1.0f / MARGIN;
|
|
x = 1.0f;
|
|
for (j = 0; j < MaxSetDimY; j++) {
|
|
x = 1.0f;
|
|
for (i = 0; i < (int32)MARGIN; i++, x -= xstep) {
|
|
cr = (uint32)Cosine_Interpolate(tab[i * 3 + 0 + j * 3 * MaxSetDimX], tab[(255 - i) * 3 + 0 + (j) * 3 * MaxSetDimX], x);
|
|
cg = (uint32)Cosine_Interpolate(tab[i * 3 + 1 + j * 3 * MaxSetDimX], tab[(255 - i) * 3 + 1 + (j) * 3 * MaxSetDimX], x);
|
|
cb = (uint32)Cosine_Interpolate(tab[i * 3 + 2 + j * 3 * MaxSetDimX], tab[(255 - i) * 3 + 2 + (j) * 3 * MaxSetDimX], x);
|
|
if (cr > 255)
|
|
cr = 255;
|
|
if (cg > 255)
|
|
cg = 255;
|
|
if (cb > 255)
|
|
cb = 255;
|
|
tab[i * 3 + 0 + j * 3 * MaxSetDimX] = cr;
|
|
tab[i * 3 + 1 + j * 3 * MaxSetDimX] = cg;
|
|
tab[i * 3 + 2 + j * 3 * MaxSetDimX] = cb;
|
|
}
|
|
}
|
|
|
|
|
|
for (j = 0; j < MaxSetDimY; j++) {
|
|
for (i = 0; i < MaxSetDimX; i++) {
|
|
cr = tab[i * 3 + 0 + j * 3 * MaxSetDimX];
|
|
cg = tab[i * 3 + 1 + j * 3 * MaxSetDimX];
|
|
cb = tab[i * 3 + 2 + j * 3 * MaxSetDimX];
|
|
p[i + j * pitch] = (short)rRGBAToTextureFormat(cr, cg, cb, 255);
|
|
}
|
|
}
|
|
|
|
rUnlockSurfaceDirect(SkySurface);
|
|
delete[] tab;
|
|
|
|
if (t3dSky && t3dSky->MatTable.size() >= 2)
|
|
t3dSky->MatTable[1]->Texture = (SkySurface);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.57-------------------
|
|
* t3dCreateSmokeParticle
|
|
* --------------------------------------------------*/
|
|
uint8 t3dCreateSmokeParticle(uint32 Num, uint8 Type, uint32 Opacity) {
|
|
error("TODO: t3dCreateSmokeParticle");
|
|
#if 0
|
|
t3dF32 v1, v2;
|
|
int32 i, j, pitch, color;
|
|
unsigned short *p;
|
|
|
|
Particles[t3dNumParticles].Material = gMaterial();
|
|
|
|
if ((SmokeSurface == nullptr) && (Type == 1)) {
|
|
SmokeSurface = (gTexture *)rCreateSurface(16, 16, rTEXTURESURFACE);
|
|
|
|
p = (unsigned short *)rLockSurfaceDirect(SmokeSurface, (unsigned int *)&pitch);
|
|
pitch /= 2;
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
for (i = 0; i < 16; i++) {
|
|
v1 = (t3dF32)fabs(sin(DEGREE_TO_RADIANS(360 * i / 32)));
|
|
v2 = (t3dF32)fabs(sin(DEGREE_TO_RADIANS(360 * j / 32)));
|
|
color = (uint32)(v1 * v2 * Opacity);
|
|
// color-=(rand()%(color+1)/2);
|
|
if (color <= 3)
|
|
p[i + j * pitch] = (short)rRGBAToTextureFormat(color, color, color, 0);
|
|
else
|
|
p[i + j * pitch] = (short)rRGBAToTextureFormat(color, color, color, 255);
|
|
}
|
|
}
|
|
|
|
rUnlockSurfaceDirect(SmokeSurface);
|
|
} else if ((NoiseSmokeSurface == nullptr) && (Type == 2)) {
|
|
NoiseSmokeSurface = (gTexture *)rCreateSurface(16, 16, rTEXTURESURFACE);
|
|
|
|
p = (unsigned short *)rLockSurfaceDirect(NoiseSmokeSurface, (unsigned int *)&pitch);
|
|
pitch /= 2;
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
for (i = 0; i < 16; i++) {
|
|
v1 = (t3dF32)fabs(sin(DEGREE_TO_RADIANS(360 * i / 32)));
|
|
v2 = (t3dF32)fabs(sin(DEGREE_TO_RADIANS(360 * j / 32)));
|
|
color = (uint32)(v1 * v2 * Opacity);
|
|
color -= (rand() % (color + 1) / 2);
|
|
if (color <= 3)
|
|
p[i + j * pitch] = (short)rRGBAToTextureFormat(color, color, color, 0);
|
|
else
|
|
p[i + j * pitch] = (short)rRGBAToTextureFormat(color, color, color, 255);
|
|
}
|
|
}
|
|
|
|
rUnlockSurfaceDirect(NoiseSmokeSurface);
|
|
}
|
|
|
|
warning("Partially stubbed t3dCreateSmokeParticle");
|
|
#if 0
|
|
if (Type == 1)
|
|
Particles[t3dNumParticles].Material.Texture = (SmokeSurface);
|
|
else
|
|
Particles[t3dNumParticles].Material.Texture = (NoiseSmokeSurface);
|
|
Particles[t3dNumParticles].Material.VB = rGetUserVertexBuffer();
|
|
#endif
|
|
for (i = 0; i < 16; i++)
|
|
Particles[t3dNumParticles].RandTable[i] = rand() % 3 - 1;
|
|
|
|
Particles[t3dNumParticles].Material.addNumFaces(Num);
|
|
Particles[t3dNumParticles].Material.addProperty(T3D_MATERIAL_SMOKE | T3D_MATERIAL_NOLIGHTMAP);
|
|
Particles[t3dNumParticles].ParticlePos = (Particle *)t3dMalloc(sizeof(Particle) * Num);
|
|
memset(Particles[t3dNumParticles].ParticlePos, 0, sizeof(Particle)*Num);
|
|
Particles[t3dNumParticles].NumParticles = Num / 3;
|
|
t3dNumParticles++;
|
|
|
|
#endif
|
|
return t3dNumParticles - 1;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.44-------------------
|
|
* t3dCalcVertsInterpolants
|
|
* --------------------------------------------------*/
|
|
void t3dCalcVertsInterpolants(gVertex *oldptr, gVertex *newptr, t3dV3F *VI, uint32 num) {
|
|
#define NUMINTERPOLANTS (1.0f/255.0f)
|
|
uint32 i;
|
|
|
|
if (!oldptr || !newptr || !VI)
|
|
return ;
|
|
|
|
for (i = 0; i < num; i++, oldptr++, newptr++, VI++) {
|
|
VI->x = (newptr->x - oldptr->x) * NUMINTERPOLANTS;
|
|
VI->y = (newptr->y - oldptr->y) * NUMINTERPOLANTS;
|
|
VI->z = (newptr->z - oldptr->z) * NUMINTERPOLANTS;
|
|
// newptr->diffuse=oldptr->diffuse;
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.45-------------------
|
|
* t3dAddExpression
|
|
* --------------------------------------------------*/
|
|
void t3dAddExpression(t3dMESH *mesh, uint32 Frame, gVertex *v) {
|
|
if (Frame >= mesh->MorphFrames.size()) {
|
|
if (!mesh->MorphFrames.empty())
|
|
warning("t3dAddExpression() mesh %s frame %d mesh->NumMorphFrames %d", mesh->name.c_str(), Frame, mesh->MorphFrames.size());
|
|
|
|
Frame = 0;
|
|
return;
|
|
}
|
|
|
|
mesh->LastExpressionFrame = mesh->ExpressionFrame;
|
|
|
|
for (auto &mv : mesh->MorphFrames[Frame]._morphModVertices) {
|
|
gVertex *ap = &v[mv._index];
|
|
ap->x = mv._v.x;
|
|
ap->y = mv._v.y;
|
|
ap->z = mv._v.z;
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.45-------------------
|
|
* CalcBones
|
|
* --------------------------------------------------*/
|
|
void CalcBones(t3dMESH *mesh, t3dBONEANIM *Anim, int32 Frame) {
|
|
t3dBONE *bone;
|
|
t3dM3X3F *Matrix;
|
|
t3dV3F *Trasl, Appov;
|
|
int32 i, cv;
|
|
gVertex *Newptr;
|
|
uint8 *Average/*,first=0*/;
|
|
uint32 memalloc = 0;
|
|
t3dF32 InvAvg;
|
|
gVertex *gv;
|
|
gVertex *v;
|
|
// t3dF32 x,y,z;
|
|
|
|
if (Frame > Anim->NumFrames - 1)
|
|
return;
|
|
|
|
memalloc = (sizeof(uint8) * mesh->NumVerts);
|
|
Average = (uint8 *)t3dAlloc(memalloc);
|
|
memset(Average, 0, memalloc);
|
|
|
|
if (!(Newptr = mesh->SavedVertexBuffer))
|
|
return ;
|
|
|
|
t3dAddExpression(mesh, mesh->ExpressionFrame, Newptr);
|
|
|
|
//Search first valid vertex
|
|
cv = 99999999;
|
|
bone = Anim->BoneTable;
|
|
for (i = 0; i < Anim->NumBones; i++, bone++) {
|
|
if (!bone->Trasl || !bone->Matrix || (bone->ModVertices.size() > mesh->NumVerts)) continue;
|
|
|
|
for (auto &modVertex : bone ->ModVertices) {
|
|
if (modVertex < cv) {
|
|
cv = modVertex;
|
|
}
|
|
}
|
|
}
|
|
if (cv == 99999999) {
|
|
warning("Questa animazione non modifica vertici in %s", mesh->name.c_str());
|
|
t3dDealloc(memalloc);
|
|
return ;
|
|
}
|
|
|
|
/* for ( i=0; i<mesh->NumVerts; i++ )
|
|
{
|
|
memcpy(&Newptr[i],&mesh->VBptr[cv+i].p,sizeof(t3dV3F));
|
|
}*/
|
|
|
|
bone = Anim->BoneTable;
|
|
// DebugFile("\nFrame %d",Frame);
|
|
for (i = 0; i < Anim->NumBones; i++, bone++) {
|
|
if (!bone->Trasl || !bone->Matrix || (bone->ModVertices.size() > mesh->NumVerts)) continue;
|
|
|
|
// DebugFile("Bone %d",i);
|
|
Matrix = &bone->Matrix[Frame];
|
|
Trasl = &bone->Trasl[Frame];
|
|
|
|
|
|
for (auto &modVertex : bone->ModVertices) {
|
|
// DebugFile("%d",bone->ModVertices[k].Vertex);
|
|
gv = &mesh->VBptr[modVertex];
|
|
|
|
// t3dVectCopy(&Appov,&Newptr[bone->ModVertices[k].Vertex-cv]);
|
|
// t3dVectSub(&Appov, &Appov, &bone->Trasl[0]);
|
|
|
|
Appov.x = Newptr[modVertex - cv].x - bone->Trasl[0].x;
|
|
Appov.y = Newptr[modVertex - cv].y - bone->Trasl[0].y;
|
|
Appov.z = Newptr[modVertex - cv].z - bone->Trasl[0].z;
|
|
t3dVectTransformInv(&Appov, &Appov, Matrix);
|
|
|
|
if (Average[modVertex - cv] == 0) {
|
|
gv->x = Appov.x + Trasl->x;
|
|
gv->y = Appov.y + Trasl->y;
|
|
gv->z = Appov.z + Trasl->z;
|
|
} else {
|
|
gv->x += Appov.x + Trasl->x;
|
|
gv->y += Appov.y + Trasl->y;
|
|
gv->z += Appov.z + Trasl->z;
|
|
}
|
|
Average[modVertex - cv] ++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
v = &mesh->VBptr[0];
|
|
for (i = 0; i < mesh->NumVerts; i++, v++, Average++, Newptr++) {
|
|
if (!(mesh->Flags & T3D_MESH_CHARACTER))
|
|
v->diffuse = Newptr->diffuse;
|
|
// v->diffuse=RGBA_MAKE(255,255,255,255);
|
|
if ((*Average) <= 1)
|
|
continue;
|
|
|
|
InvAvg = 1.0f / (*Average);
|
|
|
|
v->x *= InvAvg;
|
|
v->y *= InvAvg;
|
|
v->z *= InvAvg;
|
|
}
|
|
|
|
/* v=&mesh->VBptr[0];
|
|
for (i=0; i<mesh->NumVerts; i++, v++, Average++)
|
|
{
|
|
x = (v->x * mesh->Matrix.M[0]) + (v->y * mesh->Matrix.M[1]) + (v->z * mesh->Matrix.M[2]);
|
|
y = (v->x * mesh->Matrix.M[3]) + (v->y * mesh->Matrix.M[4]) + (v->z * mesh->Matrix.M[5]);
|
|
z = (v->x * mesh->Matrix.M[6]) + (v->y * mesh->Matrix.M[7]) + (v->z * mesh->Matrix.M[8]);
|
|
v->x=x;
|
|
v->y=y;
|
|
v->z=z;
|
|
}*/
|
|
|
|
t3dDealloc(memalloc);
|
|
|
|
t3dCalcVertsInterpolants(mesh->OldVertexBuffer, mesh->VBptr, mesh->VertsInterpolants, mesh->NumVerts);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.46-------------------
|
|
* t3dAddBlend
|
|
* --------------------------------------------------*/
|
|
void t3dAddBlend(t3dF32 AddPercent, t3dMESH *mesh) {
|
|
gVertex *gv;
|
|
t3dV3F *VI;
|
|
uint32 i;
|
|
|
|
if (!mesh->VBptr)
|
|
return;
|
|
|
|
gv = mesh->VBptr;
|
|
VI = mesh->VertsInterpolants;
|
|
for (i = 0; i < mesh->NumVerts; i++, gv++, VI++) {
|
|
gv->x += VI->x * AddPercent;
|
|
gv->y += VI->y * AddPercent;
|
|
gv->z += VI->z * AddPercent;
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.46-------------------
|
|
* t3dCalcMeshBones
|
|
* --------------------------------------------------*/
|
|
void t3dCalcMeshBones(t3dMESH *mesh, int32 last) {
|
|
int16 TempFrame = 0;
|
|
if (!mesh) return;
|
|
|
|
if (last) {
|
|
TempFrame = mesh->CurFrame;
|
|
if (mesh->Flags & T3D_MESH_DEFAULTANIM)
|
|
mesh->CurFrame = mesh->DefaultAnim.NumFrames - 1;
|
|
else
|
|
mesh->CurFrame = mesh->Anim.NumFrames - 1;
|
|
}
|
|
|
|
if ((mesh->CurFrame > 0) || (mesh->ExpressionFrame != mesh->LastExpressionFrame)) {
|
|
if ((mesh->LastFrame != mesh->CurFrame) || (mesh->ExpressionFrame != mesh->LastExpressionFrame) ||
|
|
((mesh->Flags & T3D_MESH_LAST_DEFAULTANIM) && !(mesh->Flags & T3D_MESH_DEFAULTANIM)) ||
|
|
(!(mesh->Flags & T3D_MESH_LAST_DEFAULTANIM) && (mesh->Flags & T3D_MESH_DEFAULTANIM))) {
|
|
if (mesh->LastFrame != mesh->CurFrame)
|
|
mesh->LastFrame = mesh->CurFrame;
|
|
|
|
if (!(mesh->VBptr = mesh->VertexBuffer) || !mesh->OldVertexBuffer)
|
|
return;
|
|
|
|
memcpy(mesh->OldVertexBuffer, mesh->VertexBuffer, mesh->NumVerts * sizeof(gVertex));
|
|
|
|
mesh->Flags |= T3D_MESH_UPDATEVB;
|
|
if (mesh->Flags & T3D_MESH_DEFAULTANIM) {
|
|
mesh->Flags |= T3D_MESH_LAST_DEFAULTANIM;
|
|
CalcBones(mesh, &mesh->DefaultAnim, mesh->CurFrame);
|
|
if (mesh->CurFrame > mesh->DefaultAnim.NumFrames - 1)
|
|
mesh->CurFrame = 0;
|
|
} else {
|
|
mesh->Flags &= ~T3D_MESH_LAST_DEFAULTANIM;
|
|
CalcBones(mesh, &mesh->Anim, mesh->CurFrame);
|
|
if (mesh->CurFrame > mesh->Anim.NumFrames - 1)
|
|
mesh->CurFrame = 0;
|
|
}
|
|
|
|
mesh->LastBlendPercent = 255;
|
|
mesh->VBptr = nullptr;
|
|
}
|
|
|
|
if (mesh->LastBlendPercent != mesh->BlendPercent) {
|
|
if (!(mesh->VBptr = mesh->VertexBuffer))
|
|
return;
|
|
|
|
mesh->Flags |= T3D_MESH_UPDATEVB;
|
|
if (!mesh->BlendPercent) {
|
|
gVertex *OldVBptr;
|
|
if (!(OldVBptr = mesh->OldVertexBuffer))
|
|
return ;
|
|
memcpy(mesh->VBptr, OldVBptr, sizeof(gVertex)*mesh->NumVerts);
|
|
} else
|
|
t3dAddBlend((t3dF32)(mesh->BlendPercent - mesh->LastBlendPercent), mesh);
|
|
|
|
mesh->LastBlendPercent = mesh->BlendPercent;
|
|
mesh->VBptr = nullptr;
|
|
}
|
|
}
|
|
|
|
if (last) mesh->CurFrame = TempFrame;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.49-------------------
|
|
* t3dRotateMoveCamera
|
|
* --------------------------------------------------*/
|
|
void t3dRotateMoveCamera(t3dCAMERA *cam, t3dF32 AngleX, t3dF32 AngleY, t3dF32 AngleSpeed) {
|
|
t3dV3F dir, sdir, tmp;
|
|
// t3dF32 /*angley,angle*/;
|
|
t3dM3X3F mx;
|
|
|
|
if ((AngleX == 0.0f) && (AngleY == 0.0f) && (!AngleSpeed)) return;
|
|
/*
|
|
t3dVectSub(&dir,&cam->Target,&cam->Source);
|
|
angle=(t3dF32)sqrt(dir.x*dir.x+dir.z*dir.z);
|
|
|
|
cam->Target.y = cam->Source.y + dir.y*(t3dF32)cos(-AngleX) + angle*(t3dF32)sin(-AngleX);
|
|
// cam->Target.x = cam->Source.x - dir.y*(t3dF32)sin(-AngleX) + angle*(t3dF32)cos(-AngleX);
|
|
// cam->Target.z = cam->Source.z - dir.y*(t3dF32)sin(-AngleX) + angle*(t3dF32)cos(-AngleX);
|
|
|
|
cam->Target.x = cam->Source.x + dir.x*(t3dF32)cos(AngleY) + dir.z*(t3dF32)sin(AngleY);
|
|
cam->Target.z = cam->Source.z - dir.x*(t3dF32)sin(AngleY) + dir.z*(t3dF32)cos(AngleY);
|
|
*/
|
|
|
|
t3dMatView(&cam->Matrix, &cam->Source, &cam->Target);
|
|
t3dMatRot(&mx, AngleX, AngleY, 0);
|
|
t3dVectSub(&dir, &cam->Target, &cam->Source);
|
|
t3dVectTransform(&sdir, &dir, &cam->Matrix);
|
|
t3dVectTransform(&sdir, &sdir, &mx);
|
|
t3dVectTransformInv(&sdir, &sdir, &cam->Matrix);
|
|
t3dVectNormalize(&sdir);
|
|
t3dVectCopy(&tmp, &sdir);
|
|
sdir *= AngleSpeed;
|
|
t3dVectAdd(&cam->Source, &cam->Source, &sdir);
|
|
t3dVectAdd(&cam->Target, &cam->Source, &tmp);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.49-------------------
|
|
* t3dResetPipeline
|
|
* --------------------------------------------------*/
|
|
void t3dResetPipeline() {
|
|
t3dMESH *m;
|
|
uint32 i, j;
|
|
|
|
rResetPipeline();
|
|
t3dStartIndex = t3dNumVertices = 0;
|
|
t3d_NumMeshesVisible = 0;
|
|
t3dNumGlobalMirrors = 0;
|
|
t3dNumMaterialLists = 0;
|
|
StatNumTris = 0;
|
|
StatNumVerts = 0;
|
|
|
|
for (i = 0; i < t3dNumPortals; i++) {
|
|
if ((!t3dPortalList[i]) || (!t3dPortalList[i]->PortalList)) continue;
|
|
|
|
for (j = 0, m = &t3dPortalList[i]->PortalList->MeshTable[0]; j < t3dPortalList[i]->PortalList->NumMeshes(); j++, m++)
|
|
m->Flags &= ~T3D_MESH_PORTALPROCESSED;
|
|
}
|
|
|
|
t3dNumPortals = 0;
|
|
if (PortalCrossed) {
|
|
t3dCurRoom = PortalCrossed;
|
|
PortalCrossed = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.58-------------------
|
|
* t3dReleaseParticles
|
|
* --------------------------------------------------*/
|
|
void t3dReleaseParticles() {
|
|
for (int i = 0; i < MAX_PARTICLES; i++) {
|
|
t3dFree(Particles[i].ParticlePos);
|
|
Particles[i].Material.clear();
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.46-------------------
|
|
* t3dResetMesh
|
|
* --------------------------------------------------*/
|
|
void t3dResetMesh(t3dMESH *mesh) {
|
|
if (!mesh->VertexBuffer || !mesh->OldVertexBuffer || !mesh->SavedVertexBuffer)
|
|
return ;
|
|
|
|
memcpy(mesh->VertexBuffer, mesh->SavedVertexBuffer, sizeof(gVertex)*mesh->NumVerts);
|
|
memcpy(mesh->OldVertexBuffer, mesh->SavedVertexBuffer, sizeof(gVertex)*mesh->NumVerts);
|
|
mesh->Flags |= T3D_MESH_UPDATEVB;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.49-------------------
|
|
* CheckAndClip
|
|
* --------------------------------------------------*/
|
|
uint8 CheckAndClip(t3dV3F *start, t3dV3F *end, t3dNORMAL *n) {
|
|
t3dF32 divi;
|
|
t3dF32 d1 = t3dVectDot(start, &n->n) - n->dist;
|
|
t3dF32 d2 = t3dVectDot(end, &n->n) - n->dist;
|
|
|
|
if ((d1 < 0) && (d2 < 0))
|
|
return 0;
|
|
else if ((d1 >= 0) && (d2 >= 0))
|
|
return 1;
|
|
|
|
|
|
if ((d1 < 0) && (d2 >= 0)) {
|
|
d2 = d2 - d1;
|
|
divi = -d1 / d2;
|
|
start->x = start->x + divi * (end->x - start->x);
|
|
start->y = start->y + divi * (end->y - start->y);
|
|
start->z = start->z + divi * (end->z - start->z);
|
|
return 1;
|
|
} else {
|
|
d1 = d1 - d2;
|
|
divi = -d2 / d1;
|
|
end->x = end->x + divi * (start->x - end->x);
|
|
end->y = end->y + divi * (start->y - end->y);
|
|
end->z = end->z + divi * (start->z - end->z);
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.50-------------------
|
|
* t3dCheckWithFloor
|
|
* --------------------------------------------------*/
|
|
t3dF32 t3dCheckWithFloor() {
|
|
extern t3dF32 CurFloorY;
|
|
t3dVERTEX a, b, c;
|
|
t3dNORMAL bbn;
|
|
t3dV3F StartDir, EndDir, Sight, pos, en, st;
|
|
t3dF32 MaxX, AverageZ = -99999999999.9f;
|
|
|
|
a.p.x = -10;
|
|
a.p.y = CurFloorY + 15;
|
|
a.p.z = 10;
|
|
b.p.x = 10;
|
|
b.p.y = CurFloorY + 15;
|
|
b.p.z = 10;
|
|
c.p.x = 10;
|
|
c.p.y = CurFloorY + 15;
|
|
c.p.z = -10;
|
|
t3dPlaneNormal(&bbn, &a.p, &b.p, &c.p); //floor
|
|
|
|
t3dVectCopy(&StartDir, &t3dCurCamera->Source);
|
|
t3dVectTransformInv(&EndDir, &t3d3dMousePos, &t3dCurViewMatrix);
|
|
t3dVectAdd(&EndDir, &EndDir, &t3dCurCamera->Source);
|
|
// t3dVectSub(&EndDir,&EndDir,&mesh->Pos);
|
|
|
|
t3dVectSub(&Sight, &EndDir, &StartDir);
|
|
t3dVectNormalize(&Sight);
|
|
Sight *= 2000000.0f;
|
|
t3dVectAdd(&EndDir, &StartDir, &Sight);
|
|
|
|
|
|
if (CheckAndClip(&StartDir, &EndDir, &bbn)) {
|
|
pos.x = - t3dCurCamera->Source.x; // posizione centro mesh dalla camera
|
|
pos.y = - t3dCurCamera->Source.y;
|
|
pos.z = - t3dCurCamera->Source.z;
|
|
t3dVectTransform(&pos, &pos, &t3dCurViewMatrix); // rotate by the mesh matrix
|
|
|
|
// t3dVectTransform(&StartDir,&StartDir,&t3dCurCamera->Matrix);
|
|
// t3dVectTransform(&EndDir,&EndDir,&t3dCurCamera->Matrix);
|
|
|
|
t3dVectCopy(&st, &StartDir);
|
|
t3dVectCopy(&en, &EndDir);
|
|
t3dVectTransform(&StartDir, &StartDir, &t3dCurViewMatrix);
|
|
t3dVectTransform(&EndDir, &EndDir, &t3dCurViewMatrix);
|
|
t3dVectAdd(&StartDir, &StartDir, &pos);
|
|
t3dVectAdd(&EndDir, &EndDir, &pos);
|
|
|
|
if ((MaxX = t3dPointSquaredDistance(&StartDir)) > AverageZ) {
|
|
t3dVectCopy(&FloorHitCoords, &st);
|
|
AverageZ = MaxX;
|
|
}
|
|
if ((MaxX = t3dPointSquaredDistance(&EndDir)) > AverageZ) {
|
|
t3dVectCopy(&FloorHitCoords, &en);
|
|
AverageZ = MaxX;
|
|
}
|
|
|
|
return AverageZ;
|
|
}
|
|
|
|
return 999999999999.9f;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.43-------------------
|
|
* t3dProcessMirror
|
|
* --------------------------------------------------*/
|
|
void t3dProcessMirror(t3dMESH *mesh, t3dCAMERA *cam) {
|
|
warning("STUBBED: t3dProcessMirror");
|
|
#if 0
|
|
// t3dBODY *NewBody=NULL;
|
|
t3dV3F appo, c0;
|
|
t3dV3F ppv1, ppv2, ppv3, ppv4/*,eye,pos,oldtrasl,oldpos*/;
|
|
t3dU32 p/*,k*/;
|
|
t3dNORMAL OldClipPlanes[NUMCLIPPLANES];
|
|
t3dM3X3F ReflMatrix;
|
|
t3dV3F mirrorpos;
|
|
// t3dMESH *m;
|
|
t3dM3X3F OldViewMatrix;
|
|
t3dCAMERA OldCurCamera;
|
|
gMaterial *OldMaterialTable;
|
|
|
|
if (!mesh->VertexBuffer)
|
|
return ;
|
|
|
|
mesh->VBptr = mesh->VertexBuffer;
|
|
ppv1.x = mesh->VBptr[mesh->FList[0].VertexIndex[0]].x;
|
|
ppv1.y = mesh->VBptr[mesh->FList[0].VertexIndex[0]].y;
|
|
ppv1.z = mesh->VBptr[mesh->FList[0].VertexIndex[0]].z;
|
|
ppv2.x = mesh->VBptr[mesh->FList[0].VertexIndex[1]].x;
|
|
ppv2.y = mesh->VBptr[mesh->FList[0].VertexIndex[1]].y;
|
|
ppv2.z = mesh->VBptr[mesh->FList[0].VertexIndex[1]].z;
|
|
ppv3.x = mesh->VBptr[mesh->FList[0].VertexIndex[2]].x;
|
|
ppv3.y = mesh->VBptr[mesh->FList[0].VertexIndex[2]].y;
|
|
ppv3.z = mesh->VBptr[mesh->FList[0].VertexIndex[2]].z;
|
|
|
|
for (p = 0; p < 3; p++) {
|
|
appo.x = mesh->VBptr[mesh->FList[1].VertexIndex[p]].x;
|
|
appo.y = mesh->VBptr[mesh->FList[1].VertexIndex[p]].y;
|
|
appo.z = mesh->VBptr[mesh->FList[1].VertexIndex[p]].z;
|
|
|
|
if ((!t3dVectCmp(&ppv1, &appo)) &&
|
|
(!t3dVectCmp(&ppv2, &appo)) &&
|
|
(!t3dVectCmp(&ppv3, &appo)))
|
|
memcpy(&ppv4, &appo, sizeof(t3dV3F));
|
|
}
|
|
|
|
memcpy(OldClipPlanes, ClipPlanes, sizeof(t3dNORMAL)*NUMCLIPPLANES);
|
|
|
|
t3dVectSub(&ppv4, &ppv4, &cam->Source);
|
|
t3dVectSub(&ppv3, &ppv3, &cam->Source);
|
|
t3dVectSub(&ppv2, &ppv2, &cam->Source);
|
|
t3dVectSub(&ppv1, &ppv1, &cam->Source);
|
|
t3dVectTransform(&ppv1, &ppv1, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv2, &ppv2, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv3, &ppv3, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv4, &ppv4, &t3dCurViewMatrix);
|
|
t3dVectFill(&c0, 0.0f);
|
|
|
|
// t3dVectCopy(&c0,&cam->Source);
|
|
|
|
t3dPlaneNormal(&ClipPlanes[RIGHTCLIP], &c0, &ppv3, &ppv4);
|
|
t3dPlaneNormal(&ClipPlanes[LEFTCLIP], &c0, &ppv1, &ppv2);
|
|
t3dPlaneNormal(&ClipPlanes[TOPCLIP], &c0, &ppv4, &ppv1);
|
|
t3dPlaneNormal(&ClipPlanes[BOTTOMCLIP], &c0, &ppv2, &ppv3);
|
|
|
|
mesh->VBptr = NULL;
|
|
|
|
t3dMatReflect(&ReflMatrix, &mirrorpos, mesh->FList[0].n);
|
|
// t3dVectAdd(&mirrorpos,&mirrorpos,&mesh->Pos);
|
|
|
|
bDisableMirrors = 1;
|
|
t3dMatCopy(&OldViewMatrix, &t3dCurViewMatrix);
|
|
memcpy(&OldCurCamera, t3dCurCamera, sizeof(t3dCAMERA));
|
|
{
|
|
t3dU32 i, j;
|
|
t3dMESH *m;
|
|
t3dFACE *f;
|
|
for (i = 0, m = t3dCurRoom->MeshTable; i < t3dCurRoom->NumMeshes; i++, m++)
|
|
for (j = 0, f = m->FList; j < m->NumFaces; j++, f++)
|
|
if (f->mat)
|
|
f->mat = (gMaterial *)((t3dU8 *)f->mat - (t3dU8 *)t3dCurRoom->MatTable + (t3dU8 *)t3dCurRoom->MirrorMatTable);
|
|
OldMaterialTable = t3dCurRoom->MatTable;
|
|
t3dCurRoom->MatTable = t3dCurRoom->MirrorMatTable;
|
|
}
|
|
|
|
t3dVectAdd(&t3dCurCamera->Source, &t3dCurCamera->Source, &mirrorpos);
|
|
t3dVectTransform(&t3dCurCamera->Source, &t3dCurCamera->Source, &ReflMatrix);
|
|
t3dVectAdd(&t3dCurCamera->Target, &t3dCurCamera->Target, &mirrorpos);
|
|
t3dVectTransform(&t3dCurCamera->Target, &t3dCurCamera->Target, &ReflMatrix);
|
|
|
|
t3dMatMul(&t3dCurViewMatrix, &t3dCurViewMatrix, &ReflMatrix);
|
|
|
|
|
|
if (!t3dTransformBody(t3dCurRoom)) {
|
|
DebugLogWindow("Can't transform %s", mesh->PortalList->Name);
|
|
}
|
|
|
|
bDisableMirrors = 0;
|
|
t3dMatCopy(&t3dCurViewMatrix, &OldViewMatrix);
|
|
memcpy(ClipPlanes, OldClipPlanes, sizeof(t3dNORMAL)*NUMCLIPPLANES);
|
|
{
|
|
t3dU32 i, j;
|
|
t3dMESH *m;
|
|
t3dFACE *f;
|
|
t3dCurRoom->MatTable = OldMaterialTable;
|
|
for (i = 0, m = t3dCurRoom->MeshTable; i < t3dCurRoom->NumMeshes; i++, m++)
|
|
for (j = 0, f = m->FList; j < m->NumFaces; j++, f++)
|
|
if (f->mat)
|
|
f->mat = (gMaterial *)((t3dU8 *)f->mat - (t3dU8 *)t3dCurRoom->MirrorMatTable + (t3dU8 *)t3dCurRoom->MatTable);
|
|
}
|
|
memcpy(t3dCurCamera, &OldCurCamera, sizeof(t3dCAMERA));
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.51-------------------
|
|
* t3dProcessMirrors
|
|
* --------------------------------------------------*/
|
|
void t3dProcessMirrors(t3dMESH **MirrorList, uint32 NumMirrors) {
|
|
uint32 i;
|
|
|
|
for (i = 0; i < NumMirrors; i++)
|
|
t3dProcessMirror(MirrorList[i], t3dCurCamera);
|
|
}
|
|
|
|
#define _ADDLINES(x) *ptr=num+x; ptr++; rAddLinesArray()
|
|
/* -----------------02/06/99 16.53-------------------
|
|
* t3dShowBoundingBox
|
|
* --------------------------------------------------*/
|
|
void t3dShowBoundingBox(t3dBODY *b) {
|
|
t3dV3F tmp;
|
|
uint16 *ptr;
|
|
uint16 num;
|
|
|
|
gVertex *VertPointer = (gVertex *)rLockPointArray();
|
|
|
|
ptr = rGetLinesArrayPtr();
|
|
num = rGetNumPointArray();
|
|
|
|
tmp.x = -t3dCurCamera->Source.x;
|
|
tmp.y = -t3dCurCamera->Source.y;
|
|
tmp.z = -t3dCurCamera->Source.z;
|
|
t3dVectTransform(&tmp, &tmp, &t3dCurViewMatrix);
|
|
rBuildLinesViewMatrix(t3dCurViewMatrix, tmp);
|
|
|
|
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
|
t3dMESH &mesh = b->MeshTable[i];
|
|
if (mesh.Flags & (T3D_MESH_PORTAL | T3D_MESH_HIDDEN)) {
|
|
continue;
|
|
}
|
|
|
|
for (uint32 j = 0; j < 8; j++) {
|
|
VertPointer->x = mesh.BBox[j].p.x + mesh.Trasl.x;
|
|
VertPointer->y = mesh.BBox[j].p.y + mesh.Trasl.y;
|
|
VertPointer->z = mesh.BBox[j].p.z + mesh.Trasl.z;
|
|
VertPointer->diffuse = RGBA_MAKE(0, 0, 255, 255);
|
|
rAddPointArray();
|
|
VertPointer++;
|
|
// t3dNumVertices++;
|
|
}
|
|
|
|
_ADDLINES(0);
|
|
_ADDLINES(1);
|
|
|
|
_ADDLINES(1);
|
|
_ADDLINES(3);
|
|
|
|
_ADDLINES(3);
|
|
_ADDLINES(2);
|
|
|
|
_ADDLINES(2);
|
|
_ADDLINES(0);
|
|
|
|
_ADDLINES(4);
|
|
_ADDLINES(5);
|
|
|
|
_ADDLINES(5);
|
|
_ADDLINES(7);
|
|
|
|
_ADDLINES(7);
|
|
_ADDLINES(6);
|
|
|
|
_ADDLINES(6);
|
|
_ADDLINES(4);
|
|
|
|
_ADDLINES(4);
|
|
_ADDLINES(0);
|
|
|
|
_ADDLINES(6);
|
|
_ADDLINES(2);
|
|
|
|
_ADDLINES(7);
|
|
_ADDLINES(3);
|
|
|
|
_ADDLINES(5);
|
|
_ADDLINES(1);
|
|
|
|
num += 8;
|
|
}
|
|
|
|
rUnlockPointArray();
|
|
}
|
|
|
|
/* -----------------02/06/99 16.54-------------------
|
|
* t3dShowBounds
|
|
* --------------------------------------------------*/
|
|
void t3dShowBounds(t3dPAN *p, uint32 numpan) {
|
|
t3dV3F tmp;
|
|
uint32 j;
|
|
uint16 *ptr;
|
|
uint16 num;
|
|
gVertex *VertPointer = (gVertex *)rLockPointArray();
|
|
ptr = rGetLinesArrayPtr();
|
|
num = rGetNumPointArray();
|
|
|
|
tmp.x = -t3dCurCamera->Source.x;
|
|
tmp.y = -t3dCurCamera->Source.y;
|
|
tmp.z = -t3dCurCamera->Source.z;
|
|
t3dVectTransform(&tmp, &tmp, &t3dCurViewMatrix);
|
|
rBuildLinesViewMatrix(t3dCurViewMatrix, tmp);
|
|
|
|
for (j = 0; j < numpan; j++) {
|
|
VertPointer->x = p[j].x1;
|
|
VertPointer->y = CurFloorY + 1.0f;
|
|
VertPointer->z = p[j].z1;
|
|
VertPointer->diffuse = RGBA_MAKE(250, 0, 0, 255);
|
|
rAddPointArray();
|
|
VertPointer++;
|
|
// t3dNumVertices++;
|
|
|
|
VertPointer->x = p[j].x2;
|
|
VertPointer->y = CurFloorY + 1.0f;
|
|
VertPointer->z = p[j].z2;
|
|
VertPointer->diffuse = RGBA_MAKE(250, 0, 0, 255);
|
|
rAddPointArray();
|
|
VertPointer++;
|
|
// t3dNumVertices++;
|
|
|
|
VertPointer->x = p[j].bx1;
|
|
VertPointer->y = CurFloorY + 1.0f;
|
|
VertPointer->z = p[j].bz1;
|
|
VertPointer->diffuse = RGBA_MAKE(250, 0, 0, 255);
|
|
rAddPointArray();
|
|
VertPointer++;
|
|
// t3dNumVertices++;
|
|
|
|
VertPointer->x = p[j].bx2;
|
|
VertPointer->y = CurFloorY + 1.0f;
|
|
VertPointer->z = p[j].bz2;
|
|
VertPointer->diffuse = RGBA_MAKE(250, 0, 0, 255);
|
|
rAddPointArray();
|
|
VertPointer++;
|
|
// t3dNumVertices++;
|
|
|
|
_ADDLINES(0);
|
|
_ADDLINES(1);
|
|
|
|
_ADDLINES(0);
|
|
_ADDLINES(2);
|
|
|
|
_ADDLINES(1);
|
|
_ADDLINES(3);
|
|
|
|
num += 4;
|
|
|
|
}
|
|
|
|
rUnlockPointArray();
|
|
}
|
|
|
|
/* -----------------10/06/99 15.51-------------------
|
|
* t3dCalcVolumetricLights
|
|
* --------------------------------------------------*/
|
|
void t3dCalcVolumetricLights(t3dMESH *m, t3dBODY *body) {
|
|
uint32 i;
|
|
t3dF32 invcellssize;
|
|
int32 x, y, z;
|
|
uint8 val;
|
|
// t3dS32 val1,val2,val3,tval;
|
|
int32 xcells;
|
|
int32 ycells;
|
|
int32 zcells;
|
|
t3dF32 xcells_rest, ycells_rest, zcells_rest;
|
|
gVertex *gv;
|
|
uint8 r, g, b;
|
|
t3dV3F vect, sco;
|
|
|
|
if (!body->VolumetricLights) return;
|
|
if (!(gv = m->VBptr)) return;
|
|
|
|
invcellssize = 1.0f / body->VolumetricLights->CellsSize;
|
|
xcells = body->VolumetricLights->xcells;
|
|
ycells = body->VolumetricLights->ycells;
|
|
zcells = body->VolumetricLights->zcells;
|
|
t3dVectSub(&sco, &m->Trasl, &body->MinPos);
|
|
|
|
for (i = 0; i < m->NumVerts; i++, gv++) {
|
|
t3dVectInit(&vect, gv->x, gv->y, gv->z);
|
|
t3dVectTransform(&vect, &vect, &m->Matrix);
|
|
t3dVectAdd(&vect, &vect, &sco);
|
|
|
|
x = (int32)(xcells_rest = (vect.x * invcellssize));
|
|
y = (int32)(ycells_rest = (vect.y * invcellssize));
|
|
z = (int32)(zcells_rest = (vect.z * invcellssize));
|
|
|
|
if ((x < 0) || (y < 0) || (z < 0) || (x > xcells) || (y > ycells) || (z > zcells)) {
|
|
gv->diffuse = RGBA_MAKE(128, 128, 128, 255);
|
|
continue;
|
|
}
|
|
|
|
val = body->VolumetricLights->VolMap[x + (z * xcells) + (y * xcells * zcells)];
|
|
|
|
r = (uint8)(((RGBA_GETRED(gv->diffuse) * val) >> 8) & 0xFF);
|
|
g = (uint8)(((RGBA_GETGREEN(gv->diffuse) * val) >> 8) & 0xFF);
|
|
b = (uint8)(((RGBA_GETBLUE(gv->diffuse) * val) >> 8) & 0xFF);
|
|
|
|
gv->diffuse = RGBA_MAKE(r, g, b, RGBA_GETALPHA(gv->diffuse));
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.53-------------------
|
|
* t3dLightCharacter
|
|
* --------------------------------------------------*/
|
|
void t3dLightCharacter(t3dCHARACTER *Ch) {
|
|
t3dMESH *mesh;
|
|
uint32 j;
|
|
t3dV3F l;
|
|
t3dF32 dist, far_range, near_range, AttenIntensity;
|
|
t3dF32 ang, half_hotspot, half_falloff, SpotIntensity;
|
|
t3dF32 nlight, Intensity;
|
|
t3dV3F ppos;
|
|
t3dV3F *normal, dir;
|
|
int32 rr, gg, bb, arr, agg, abb;
|
|
gVertex *gv;
|
|
DWORD amb;
|
|
|
|
mesh = Ch->Mesh;
|
|
|
|
if (!mesh || !mesh->VertexBuffer)
|
|
return ;
|
|
|
|
gv = mesh->VBptr = mesh->VertexBuffer;
|
|
mesh->Flags |= T3D_MESH_UPDATEVB;
|
|
|
|
arr = (uint32)(Ch->Body->AmbientLight.x + t3dCurRoom->AmbientLight.x);
|
|
agg = (uint32)(Ch->Body->AmbientLight.y + t3dCurRoom->AmbientLight.y);
|
|
abb = (uint32)(Ch->Body->AmbientLight.z + t3dCurRoom->AmbientLight.z);
|
|
if (arr > 255) arr = 255;
|
|
if (agg > 255) agg = 255;
|
|
if (abb > 255) abb = 255;
|
|
amb = RGBA_MAKE(arr, agg, abb, 255);
|
|
for (j = 0; j < mesh->NumVerts; j++, gv++)
|
|
gv->diffuse = amb;
|
|
|
|
auto light = Ch->CurRoom->LightTable[0];
|
|
if (light.Type & T3D_LIGHT_ALLLIGHTSOFF) {
|
|
mesh->VBptr = nullptr;
|
|
return;
|
|
}
|
|
t3dVectAdd(&ppos, &mesh->Trasl, &mesh->Pos);
|
|
|
|
//for (uint32 i = 0; i < Ch->CurRoom->NumLights(); i++, lt++) {
|
|
for (auto < : Ch->CurRoom->LightTable) {
|
|
if (!(lt.Type & T3D_LIGHT_LIGHTON)) continue;
|
|
if (!(lt.Type & T3D_LIGHT_REALTIME)) continue;
|
|
if ((lt.Type & T3D_LIGHT_FLARE)) continue;
|
|
|
|
AttenIntensity = 1.0f;
|
|
if (lt.Type & T3D_LIGHT_ATTENUATION) {
|
|
near_range = lt.NearRange;
|
|
far_range = lt.FarRange;
|
|
|
|
dist = t3dVectDistance(<.Source, &ppos);
|
|
if (dist > far_range)
|
|
continue;
|
|
else if (dist > near_range)
|
|
AttenIntensity = (1.0f - ((dist - near_range) / (far_range - near_range)));
|
|
}
|
|
SpotIntensity = 1.0f;
|
|
if (lt.Type & T3D_LIGHT_SPOTLIGHT) {
|
|
half_hotspot = DEGREE_TO_RADIANS(lt.HotSpot) * 0.5f;
|
|
half_falloff = DEGREE_TO_RADIANS(lt.FallOff) * 0.5f;
|
|
|
|
t3dVectSub(&l, &ppos, <.Source);
|
|
t3dVectNormalize(&l);
|
|
t3dVectSub(&dir, <.Target, <.Source);
|
|
t3dVectNormalize(&dir);
|
|
|
|
ang = (t3dF32)acos(t3dVectDot(&dir, &l));
|
|
if (ang > half_falloff)
|
|
continue;
|
|
else if (ang > half_hotspot)
|
|
SpotIntensity = (1.0f - ((ang - half_hotspot) / (half_falloff - half_hotspot)));
|
|
}
|
|
|
|
t3dVectSub(&l, <.Source, &ppos);
|
|
t3dVectTransformInv(&l, &l, &mesh->Matrix);
|
|
t3dVectNormalize(&l);
|
|
|
|
Intensity = AttenIntensity * SpotIntensity;
|
|
gv = mesh->VBptr;
|
|
for (j = 0; j < mesh->NumVerts; j++, gv++) {
|
|
normal = &mesh->NList[j]->n;
|
|
if ((nlight = t3dVectDot(normal, &l)) >= 0) {
|
|
nlight *= Intensity;
|
|
rr = t3dFloatToInt(lt.Color.x * nlight) + RGBA_GETRED(gv->diffuse);
|
|
gg = t3dFloatToInt(lt.Color.y * nlight) + RGBA_GETGREEN(gv->diffuse);
|
|
bb = t3dFloatToInt(lt.Color.z * nlight) + RGBA_GETBLUE(gv->diffuse);
|
|
if (rr > 255) rr = 255;
|
|
if (gg > 255) gg = 255;
|
|
if (bb > 255) bb = 255;
|
|
gv->diffuse = RGBA_MAKE(rr, gg, bb, 255);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Ch->Flags & T3D_CHARACTER_VOLUMETRICLIGHTING)
|
|
t3dCalcVolumetricLights(mesh, Ch->CurRoom);
|
|
|
|
mesh->VBptr = nullptr;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.50-------------------
|
|
* CheckInBoundBox
|
|
* --------------------------------------------------*/
|
|
uint8 CheckInBoundBox(t3dV3F *start, t3dV3F *end, t3dVERTEX *bbv, t3dNORMAL *bbn) {
|
|
if (!CheckAndClip(start, end, &bbn[0])) return 0;
|
|
if (!CheckAndClip(start, end, &bbn[1])) return 0;
|
|
if (!CheckAndClip(start, end, &bbn[2])) return 0;
|
|
if (!CheckAndClip(start, end, &bbn[3])) return 0;
|
|
if (!CheckAndClip(start, end, &bbn[4])) return 0;
|
|
if (!CheckAndClip(start, end, &bbn[5])) return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.50-------------------
|
|
* t3dDetectObj
|
|
* --------------------------------------------------*/
|
|
uint8 t3dDetectObj(t3dCAMERA *cam, t3dMESH *mesh, t3dM3X3F *matrix) {
|
|
t3dV3F StartDir, EndDir, Sight, pos;
|
|
t3dF32 MaxX;
|
|
|
|
if (mesh->Flags & T3D_MESH_NOBOUNDBOX)
|
|
return 0;
|
|
|
|
t3dVectTransformInv(&EndDir, &t3d3dMousePos, &t3dCurViewMatrix);
|
|
t3dVectAdd(&EndDir, &EndDir, &cam->Source);
|
|
|
|
t3dVectCopy(&StartDir, &cam->Source);
|
|
t3dVectSub(&Sight, &EndDir, &StartDir);
|
|
t3dVectNormalize(&Sight);
|
|
Sight *= 2000000.0f;
|
|
t3dVectAdd(&EndDir, &StartDir, &Sight);
|
|
mesh->BBoxAverageZ = 9999999999.9f;
|
|
|
|
t3dVectInit(&pos, 0.0f, 0.0f, 0.0f);
|
|
if (mesh->Flags & T3D_MESH_CHARACTER) {
|
|
t3dVectInit(&pos, mesh->Trasl.x, CurFloorY, mesh->Trasl.z);
|
|
t3dVectSub(&StartDir, &StartDir, &pos);
|
|
t3dVectSub(&EndDir, &EndDir, &pos);
|
|
}
|
|
|
|
if (CheckInBoundBox(&StartDir, &EndDir, &mesh->BBox[0], &mesh->BBoxNormal[0]) && (t3d_NumMeshesVisible < 255)) {
|
|
t3dV3F st, en;
|
|
|
|
pos.x -= cam->Source.x; // posizione centro mesh dalla camera
|
|
pos.y -= cam->Source.y;
|
|
pos.z -= cam->Source.z;
|
|
t3dVectTransform(&pos, &pos, &t3dCurViewMatrix); // rotate by the mesh matrix
|
|
|
|
t3dVectCopy(&st, &StartDir);
|
|
t3dVectCopy(&en, &EndDir);
|
|
t3dVectTransform(&StartDir, &StartDir, &t3dCurViewMatrix);
|
|
t3dVectTransform(&EndDir, &EndDir, &t3dCurViewMatrix);
|
|
t3dVectAdd(&StartDir, &StartDir, &pos);
|
|
t3dVectAdd(&EndDir, &EndDir, &pos);
|
|
MaxX = t3dPointSquaredDistance(&StartDir);
|
|
if ((MaxX) < mesh->BBoxAverageZ) {
|
|
mesh->BBoxAverageZ = MaxX;
|
|
t3dVectCopy(&mesh->Intersection, &st);
|
|
}
|
|
MaxX = t3dPointSquaredDistance(&EndDir);
|
|
if ((MaxX) < mesh->BBoxAverageZ) {
|
|
mesh->BBoxAverageZ = MaxX;
|
|
t3dVectCopy(&mesh->Intersection, &en);
|
|
}
|
|
|
|
t3d_NumMeshesVisible++;
|
|
t3d_VisibleMeshes[t3d_NumMeshesVisible - 1] = mesh;
|
|
|
|
return 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.42-------------------
|
|
* t3dSetVisibileVertex
|
|
* --------------------------------------------------*/
|
|
void t3dSetVisibileVertex(t3dMESH &mesh) {
|
|
// if (mesh->Flags&T3D_MESH_PORTAL)
|
|
// return ;
|
|
|
|
for (uint32 i = 0; i < mesh.NumFaces() ; i++) {
|
|
t3dFACE &f = mesh.FList[i];
|
|
if ((/*(!(f->flags&T3D_MATERIAL_OPACITY)) &&*/ (!(f.flags & T3D_MATERIAL_CLIPMAP)) &&
|
|
(!(f.flags & T3D_MATERIAL_ADDITIVE))) &&
|
|
(!(f.flags & T3D_MATERIAL_GLASS))) {
|
|
if (f.isVisible())
|
|
f.flags |= T3D_FACE_VISIBLE;
|
|
else
|
|
f.flags &= ~(T3D_FACE_VISIBLE); // continue
|
|
/* if ((f->flags&T3D_MATERIAL_PORTAL))
|
|
if (f->flags&T3D_FACE_VISIBLE)
|
|
f->flags&=~T3D_FACE_VISIBLE;
|
|
else
|
|
f->flags|=T3D_FACE_VISIBLE;*/
|
|
} else
|
|
f.flags |= T3D_FACE_VISIBLE;
|
|
}
|
|
}
|
|
|
|
/* -----------------18/06/99 10.46-------------------
|
|
* t3dAddTextureBufferShadow
|
|
* --------------------------------------------------*/
|
|
void t3dAddTextureBufferShadow(t3dCHARACTER *c, uint32 CurShadowBox, t3dLIGHT *light) {
|
|
warning("TODO: t3dAddTextureBufferShadow");
|
|
return;
|
|
#if 0
|
|
SHADOWBOX *sb = c->ShadowBox[CurShadowBox];
|
|
SHADOW *shad = &sb->ShadowsList[0];
|
|
uint32 i, k, ff, kkk, StartVert;
|
|
uint8 *ProjectedPolys, *pp;
|
|
t3dMESH *cm = c->Mesh;
|
|
t3dBODY *cr = t3dCurRoom; //c->CurRoom;
|
|
pVert tempv, *pv;
|
|
WORD *ptr = nullptr;
|
|
gVertex *gv, *pc;
|
|
t3dV3F v, tmp, MinSco, MaxSco, Aspect, BBox[8], dir;
|
|
|
|
if (!cm || !cm->VertexBuffer)
|
|
return ;
|
|
//tb
|
|
t3dMatView(&t3dCurViewMatrix, &light->Source, &cm->Trasl, 0.0f); // punta la luce ai piedi
|
|
t3dVectSub(&t3dCurTranslation, &cr->MeshTable[0].Trasl, &light->Source);
|
|
t3dVectTransform(&t3dCurTranslation, &t3dCurTranslation, &t3dCurViewMatrix); // rotate by the camera matrix
|
|
|
|
t3dBackfaceCulling(cr->NList, cr->NumNormals, &light->Source); // setta le normali che sono backface la luce
|
|
|
|
if (shad->totalverts < cr->NumTotVerts) {
|
|
rDeleteVertexBuffer(shad->ProjVertsVB);
|
|
if (shad->pwShadVolCapIndices) t3dFree(shad->pwShadVolCapIndices);
|
|
shad->ProjVertsVB = rCreateVertexBuffer(cr->NumTotVerts);
|
|
shad->pwShadVolCapIndices = t3dCalloc<WORD>(cr->NumTotVerts * 3);
|
|
shad->totalverts = cr->NumTotVerts;
|
|
} else {
|
|
if (!shad->ProjVertsVB) shad->ProjVertsVB = rCreateVertexBuffer(cr->NumTotVerts);
|
|
if (!shad->pwShadVolCapIndices) shad->pwShadVolCapIndices = t3dCalloc<WORD>(cr->NumTotVerts * 3);
|
|
shad->totalverts = cr->NumTotVerts;
|
|
}
|
|
ProjectedPolys = (t3dU8 *)t3dAlloc(sizeof(t3dU8) * cr->NumTotVerts);
|
|
rMakeProjectiveShadow(sb, nullptr, cm->NumVerts);
|
|
StartVert = 0;
|
|
|
|
for (i = 0; i < 8; i++) t3dVectCopy(&BBox[i], &cm->Trasl);
|
|
for (i = 0; i < 4; i++) BBox[i + 4].y += c->Height;
|
|
t3dVectSub(&tmp, &cm->Trasl, &light->Source);
|
|
tmp.y = 0.0f;
|
|
t3dVectNormalize(&tmp);
|
|
t3dVectScale(&tmp, &tmp, c->Radius * 2.0f);
|
|
|
|
t3dVectAdd(&BBox[0], &BBox[0], &tmp);
|
|
t3dVectAdd(&BBox[4], &BBox[4], &tmp);
|
|
t3dVectSub(&BBox[1], &BBox[1], &tmp);
|
|
t3dVectSub(&BBox[5], &BBox[5], &tmp);
|
|
tmp.y = tmp.x;
|
|
tmp.x = -tmp.z;
|
|
tmp.z = tmp.y;
|
|
tmp.y = 0.0f;
|
|
t3dVectAdd(&BBox[2], &BBox[2], &tmp);
|
|
t3dVectAdd(&BBox[6], &BBox[6], &tmp);
|
|
t3dVectSub(&BBox[3], &BBox[3], &tmp);
|
|
t3dVectSub(&BBox[7], &BBox[7], &tmp);
|
|
|
|
t3dVectFill(&MinSco, 9999999.9f);
|
|
t3dVectFill(&MaxSco, -9999999.9f);
|
|
for (i = 0; i < 8; i++) {
|
|
t3dVectTransform(&v, &BBox[i], &t3dCurViewMatrix);
|
|
t3dVectAdd(&v, &v, &t3dCurTranslation);
|
|
v.x /= v.z;
|
|
v.y = -v.y / v.z;
|
|
if (v.x < MinSco.x) MinSco.x = v.x;
|
|
if (v.y < MinSco.y) MinSco.y = v.y;
|
|
if (v.z < MinSco.z) MinSco.z = v.z;
|
|
if (v.x > MaxSco.x) MaxSco.x = v.x;
|
|
if (v.y > MaxSco.y) MaxSco.y = v.y;
|
|
if (v.z > MaxSco.z) MaxSco.z = v.z;
|
|
}
|
|
Aspect.x = 1.0f / (MaxSco.x - MinSco.x);
|
|
Aspect.y = 1.0f / (MaxSco.y - MinSco.y);
|
|
t3dVectSub(&dir, &cm->Trasl, &light->Source);
|
|
t3dVectNormalize(&dir);
|
|
// Aspect.x *= (1.0-0.1f*fabs(dir.x));
|
|
// Aspect.y *= (1.0-0.1f*fabs(dir.y));
|
|
tempv.rhw = 1.0f / t3dVectDistance(&light->Source, &cm->Trasl);
|
|
|
|
pc = rLockVertexPtr(shad->ProjVertsVB, rVBLOCK_NOSYSLOCK);
|
|
|
|
for (k = 0; k < cr->NumMeshes(); k++) { // scorre tutte le mesh della stanza
|
|
t3dMESH &mm = cr->MeshTable[k];
|
|
if (!(mm.Flags & T3D_MESH_VISIBLE) || (mm.Flags & T3D_MESH_HIDDEN)) continue; // salta se e' nascosta o se non e' visibile
|
|
if ((mm.Flags & T3D_MESH_MIRROR) || (mm.Flags & T3D_MESH_PORTAL)) continue; // salta se e' un portale o uno specchio
|
|
|
|
t3dSetVisibileVertex(mm); // segna le facce che sono backface la luce
|
|
|
|
gv = mm.VertexBuffer;
|
|
pp = &ProjectedPolys[StartVert];
|
|
|
|
for (i = 0; i < mm.NumVerts; i++, pp++, gv++, pc++) {
|
|
memcpy(pc, gv, sizeof(gVertex));
|
|
pc->diffuse = 0xFFFFFFFF;
|
|
|
|
t3dVectInit(&v, gv->x, gv->y, gv->z);
|
|
t3dVectTransform(&v, &v, &t3dCurViewMatrix);
|
|
t3dVectAdd(&v, &v, &t3dCurTranslation);
|
|
|
|
// tempv.rhw = 1.0f/MinSco.z;
|
|
tempv.x = v.x * tempv.rhw;
|
|
tempv.y = -v.y * tempv.rhw;
|
|
tempv.z = v.z;
|
|
pc->u1 = (tempv.x - MinSco.x) * Aspect.x;
|
|
pc->v1 = (tempv.y - MinSco.y) * Aspect.y;
|
|
|
|
*pp = 0;
|
|
if (tempv.x < MinSco.x * 4.0f) *pp |= (1 << 1);
|
|
if (tempv.x > MaxSco.x * 4.0f) *pp |= (1 << 2);
|
|
if (tempv.y < MinSco.y * 4.0f) *pp |= (1 << 3);
|
|
if (tempv.y > MaxSco.y * 4.0f) *pp |= (1 << 4);
|
|
if (tempv.z < MinSco.z) *pp |= (1 << 5);
|
|
}
|
|
|
|
pp = &ProjectedPolys[StartVert];
|
|
ptr = &shad->pwShadVolCapIndices[shad->num_cap_indices];
|
|
for (t3dU32 ff = 0; ff < mm.NumFaces(); ff++) {
|
|
t3dFACE &face = mm.FList[ff];
|
|
if (!(face.flags & T3D_FACE_VISIBLE))
|
|
continue;
|
|
|
|
if ((pp[face.VertexIndex[0]]) && (pp[face.VertexIndex[1]]) && (pp[face.VertexIndex[2]]))
|
|
continue;
|
|
|
|
*(ptr++) = face.VertexIndex[0] + StartVert;
|
|
*(ptr++) = face.VertexIndex[1] + StartVert;
|
|
*(ptr++) = face.VertexIndex[2] + StartVert;
|
|
shad->num_cap_indices += 3;
|
|
}
|
|
|
|
StartVert += mm.NumVerts;
|
|
}
|
|
t3dDealloc(sizeof(t3dU8)*cr->NumTotVerts);
|
|
rUnlockVertexPtr(shad->ProjVertsVB);
|
|
pc = nullptr;
|
|
|
|
t3dVectSub(&t3dCurTranslation, &cm->Trasl, &light->Source); // punta la luce sull'omino
|
|
t3dVectTransform(&t3dCurTranslation, &t3dCurTranslation, &t3dCurViewMatrix);
|
|
t3dMatMul(&t3dCurViewMatrix, &t3dCurViewMatrix, &cm->Matrix);
|
|
|
|
if (shad->pwShadVolSideIndices) {
|
|
kkk = 0;
|
|
for (i = 0; i < c->Shadow->NumMeshes(); i++) {
|
|
t3dMESH &mm = c->Shadow->MeshTable[i];
|
|
for (k = 0; k < mm.NumFaces(); k++) {
|
|
shad->pwShadVolSideIndices[kkk++] = mm.FList[k].VertexIndex[0];
|
|
shad->pwShadVolSideIndices[kkk++] = mm.FList[k].VertexIndex[1];
|
|
shad->pwShadVolSideIndices[kkk++] = mm.FList[k].VertexIndex[2];
|
|
}
|
|
}
|
|
/*f for( k=0; k<cm->NumFaces; k++ )
|
|
{
|
|
shad->pwShadVolSideIndices[kkk++] = cm->FList[k].VertexIndex[0];
|
|
shad->pwShadVolSideIndices[kkk++] = cm->FList[k].VertexIndex[1];
|
|
shad->pwShadVolSideIndices[kkk++] = cm->FList[k].VertexIndex[2];
|
|
}f*/
|
|
shad->num_side_indices = kkk;
|
|
}
|
|
|
|
if (shad->VB) {
|
|
gv = cm->VertexBuffer;
|
|
pv = (pVert *)rLockVertexPtr(shad->VB, rVBLOCK_NOSYSLOCK);
|
|
|
|
for (i = 0; i < cm->NumVerts; i++, pv++, gv++) {
|
|
t3dVectInit(&v, gv->x, gv->y, gv->z);
|
|
//f if ( v.y < 60.0f ) v.y -= 60.0f;
|
|
t3dVectTransform(&v, &v, &t3dCurViewMatrix);
|
|
t3dVectAdd(&v, &v, &t3dCurTranslation);
|
|
|
|
pv->rhw = 1.0f / v.z;
|
|
pv->x = (v.x * pv->rhw - MinSco.x) * Aspect.x * 256.0f;
|
|
pv->y = (-v.y * pv->rhw - MinSco.y) * Aspect.y * 256.0f;
|
|
pv->z = v.z * (1.0f / 30000.0f);
|
|
// pv->diffuse = RGBA_MAKE(1,1,1,sb->Intensity);
|
|
assert(false);
|
|
#if 0
|
|
pv->diffuse = RGB_MAKE(255 - sb->Intensity, 255 - sb->Intensity, 255 - sb->Intensity);
|
|
#endif
|
|
// pv->diffuse = RGB_MAKE(128,128,128);
|
|
}
|
|
rUnlockVertexPtr(shad->VB);
|
|
}
|
|
//tb
|
|
#endif
|
|
}
|
|
|
|
/* -----------------18/06/99 10.47-------------------
|
|
* t3dAddStencilBufferShadow
|
|
* --------------------------------------------------*/
|
|
void t3dAddStencilBufferShadow(t3dCHARACTER *c, uint32 CurShadowBox, t3dLIGHT *light) {
|
|
SHADOWBOX *sb = c->ShadowBox[CurShadowBox];
|
|
uint32 i, j, k, f, NumVerts;
|
|
t3dMESH *cm = c->Mesh;
|
|
t3dV3F tmp, NormLight;
|
|
t3dM3X3F lm;
|
|
|
|
if (!cm || !cm->VertexBuffer)
|
|
return ;
|
|
//sb
|
|
t3dVectSub(&NormLight, &cm->Trasl, &light->Source);
|
|
t3dVectNormalize(&NormLight);
|
|
t3dVectTransformInv(&NormLight, &NormLight, &cm->Matrix);
|
|
NormLight.y = - NormLight.y;
|
|
NormLight.z = - NormLight.z;
|
|
NormLight.x = - NormLight.x;
|
|
|
|
t3dVectSub(&tmp, &cm->Trasl, &t3dCurCamera->Source);
|
|
tmp.y = 0.0f;
|
|
t3dVectNormalize(&tmp);
|
|
|
|
tmp = tmp * 2.0f;
|
|
tmp *= c->Radius * 2.0f;
|
|
t3dVectTransformInv(&tmp, &tmp, &cm->Matrix);
|
|
|
|
if (rMakeShadowBox(sb, tmp.x, c->Height, tmp.z, sb->Intensity))
|
|
return ;
|
|
|
|
gVertex *VBptr = cm->VertexBuffer;
|
|
for (i = 0; i < c->Shadow->NumMeshes(); i++) {
|
|
t3dMESH &mm = c->Shadow->MeshTable[i];
|
|
uint32 *FaceList = (uint32 *)t3dAlloc(sizeof(uint32) * mm.NumFaces() * 3);
|
|
gVertex *VertList = (gVertex *)t3dAlloc(sizeof(gVertex) * mm.NumFaces() * 3);
|
|
NumVerts = 0;
|
|
for (k = 0; k < mm.NumFaces(); k++) {
|
|
for (f = 0; f < 3; f++) {
|
|
FaceList[NumVerts] = mm.FList[k].VertexIndex[f];
|
|
for (j = 0; j < NumVerts; j++)
|
|
if (FaceList[j] == FaceList[NumVerts]) break;
|
|
if (j >= NumVerts) NumVerts++;
|
|
}
|
|
}
|
|
for (j = 0; j < NumVerts; j++)
|
|
VertList[j] = VBptr[FaceList[j]];
|
|
|
|
t3dVectFill(&tmp, 0.0f);
|
|
t3dMatView(&lm, &tmp, &NormLight);
|
|
rMakeShadowVolume(sb, VertList, NumVerts, lm.M);
|
|
|
|
t3dDealloc(sizeof(gVertex)*mm.NumFaces() * 3);
|
|
t3dDealloc(sizeof(uint32) * mm.NumFaces() * 3);
|
|
}
|
|
//sb
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.49-------------------
|
|
* t3dTransformCharacter
|
|
* --------------------------------------------------*/
|
|
bool t3dTransformCharacter(t3dCHARACTER *c) {
|
|
uint32 OldMeshFlags, l, CurShadowBox;
|
|
t3dV3F tmp, SavedTrasl;
|
|
t3dBODY *OldCurRoom;
|
|
t3dM3X3F SavedMat;
|
|
t3dVERTEX vv;
|
|
int16 intens;
|
|
|
|
if (!c || !c->Body || !c->Mesh) return FALSE;
|
|
if (c->Flags & T3D_CHARACTER_HIDE)
|
|
goto enabledinmirror;
|
|
|
|
c->CurRoom = t3dCurRoom;
|
|
if (c->Flags & T3D_CHARACTER_REALTIMELIGHTING)
|
|
t3dLightCharacter(c);
|
|
|
|
bDisableMirrors = 1;
|
|
if (c->Mesh->ExpressionFrame >= EXPRESSION_SET_LEN) {
|
|
DebugLogWindow("Errore Espressione");
|
|
c->Mesh->ExpressionFrame = 0;
|
|
}
|
|
c->Mesh->ExpressionFrame += c->CurExpressionSet * EXPRESSION_SET_LEN;
|
|
if (!t3dTransformBody(c->Body))
|
|
DebugLogWindow("Can't transform %s", c->Body->name.c_str());
|
|
c->Mesh->ExpressionFrame -= c->CurExpressionSet * EXPRESSION_SET_LEN;
|
|
if (c->Mesh) t3dDetectObj(t3dCurCamera, c->Mesh, &t3dCurViewMatrix);
|
|
bDisableMirrors = 0;
|
|
|
|
if ((c->Flags & T3D_CHARACTER_CASTREALTIMESHADOWS) && !bDisableMirrors && (!(LoaderFlags & T3D_NOSHADOWS))) {
|
|
CurShadowBox = 0;
|
|
t3dOldUserViewMatrix = t3dCurUserViewMatrix;
|
|
rSaveViewMatrix();
|
|
|
|
t3dVectCopy(&SavedTrasl, &t3dCurTranslation);
|
|
t3dMatCopy(&SavedMat, &t3dCurViewMatrix);
|
|
for (l = 0; l < t3dCurRoom->NumLights(); l++) {
|
|
if (CurShadowBox > 1) continue;
|
|
if (!(t3dCurRoom->LightTable[l].Type & T3D_LIGHT_REALTIME)) continue;
|
|
if (!(t3dCurRoom->LightTable[l].Type & T3D_LIGHT_CASTSHADOWS)) continue;
|
|
if (!(t3dCurRoom->LightTable[l].Type & T3D_LIGHT_LIGHTON)) continue;
|
|
if ((t3dCurRoom->LightTable[l].Type & T3D_LIGHT_FLARE)) continue;
|
|
|
|
t3dVectAdd(&tmp, &c->Body->MeshTable[0].Trasl, &c->Body->MeshTable[0].Pos);
|
|
if (t3dCurRoom->LightTable[l].Source.y < tmp.y) continue;
|
|
if (!LightVertex(&vv, &tmp, &t3dCurRoom->LightTable[l])) continue;
|
|
if ((vv.r + vv.g + vv.b) < 30) continue;
|
|
|
|
if (c->ShadowBox[CurShadowBox] == nullptr)
|
|
c->ShadowBox[CurShadowBox] = t3dCalloc<SHADOWBOX>(1);
|
|
c->ShadowBox[CurShadowBox]->NumShadowsList = 0;
|
|
intens = (int16)(vv.r + vv.g + vv.b /*- t3dCurRoom->AmbientLight.x - t3dCurRoom->AmbientLight.y - t3dCurRoom->AmbientLight.z*/) / 4;
|
|
if (intens < 0) intens = 0;
|
|
if (intens > 255) intens = 255;
|
|
c->ShadowBox[CurShadowBox]->Intensity = intens;
|
|
|
|
if (!rGetStencilBitDepth()) {
|
|
c->ShadowBox[CurShadowBox]->ViewMatrixNum = t3dOrigUserViewMatrix;
|
|
t3dAddTextureBufferShadow(c, CurShadowBox++, &t3dCurRoom->LightTable[l]);
|
|
} else {
|
|
c->ShadowBox[CurShadowBox]->ViewMatrixNum = t3dCurUserViewMatrix;
|
|
t3dAddStencilBufferShadow(c, CurShadowBox++, &t3dCurRoom->LightTable[l]);
|
|
}
|
|
}
|
|
t3dMatCopy(&t3dCurViewMatrix, &SavedMat);
|
|
t3dVectCopy(&t3dCurTranslation, &SavedTrasl);
|
|
rRestoreViewMatrix();
|
|
t3dCurUserViewMatrix = t3dOldUserViewMatrix;
|
|
}
|
|
|
|
enabledinmirror:
|
|
if ((c->Flags & T3D_CHARACTER_ENABLEDINMIRROR) || !(c->Flags & T3D_CHARACTER_HIDE)) {
|
|
OldMeshFlags = c->Flags;
|
|
c->Flags &= ~T3D_CHARACTER_HIDE;
|
|
|
|
OldCurRoom = t3dCurRoom;
|
|
t3dCurRoom = c->Body;
|
|
t3dProcessMirrors(t3dGlobalMirrorList, t3dNumGlobalMirrors);
|
|
t3dCurRoom = OldCurRoom;
|
|
|
|
c->Flags = OldMeshFlags;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.58-------------------
|
|
* ProcessWater
|
|
* --------------------------------------------------*/
|
|
void ProcessWater(t3dMESH &mesh, int32 CurPass, int32 MaxPass) {
|
|
MaterialPtr mat = mesh.FList[0].getMaterial();
|
|
uint32 dimx = mat->Texture->DimX;
|
|
uint32 dimy = mat->Texture->DimY;
|
|
int32 *dest = mesh.WaterBuffer2 + dimx * 2, *source = mesh.WaterBuffer1 + dimx * 2;
|
|
uint32 i;
|
|
|
|
for (i = dimx; i < (dimx * dimy) - dimx; i++, dest++, source++) {
|
|
if (((int32)i % MaxPass) != CurPass) continue; // divide il renderig in piu' passi
|
|
|
|
*dest = (((*(source - 1) +
|
|
* (source + 1) +
|
|
* (source - dimx) +
|
|
* (source + dimx)) >> 1)) - (*dest);
|
|
*dest -= ((*dest) >> 10);
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.58-------------------
|
|
* t3dRenderWater
|
|
* --------------------------------------------------*/
|
|
void t3dRenderWater(t3dMESH &mesh, uint32 Type) {
|
|
MaterialPtr mat = mesh.FList[0].getMaterial();
|
|
int32 pitch, Xoffset, Yoffset;
|
|
int32 dimx = (int32)mat->Texture->DimX;
|
|
int32 dimy = (int32)mat->Texture->DimY;
|
|
uint16 *texturesource, *texturedest, *textsource;
|
|
int32 *WaterBuffer = mesh.WaterBuffer2 + dimx, *AppoWaterBuffer;
|
|
static int32 WaterPass = 0;
|
|
int32 R, G, B, A;
|
|
|
|
//w
|
|
return ;
|
|
//w
|
|
if (mat->AddictionalMaterial.empty() || !mat->AddictionalMaterial[0]->Texture)
|
|
return;
|
|
|
|
if (--WaterPass < 0)
|
|
WaterPass = 4;
|
|
else {
|
|
ProcessWater(mesh, WaterPass, 4);
|
|
return ;
|
|
}
|
|
|
|
textsource = texturesource = (uint16 *)rLockSurfaceDirect(mat->AddictionalMaterial[0]->Texture, (unsigned int *)&pitch);
|
|
texturedest = (uint16 *)rLockSurfaceDirect(mat->Texture, (unsigned int *)&pitch);
|
|
|
|
pitch /= 2;
|
|
/* for (i=0; i<(dimx*dimy); i++, texturedest+=2,texturesource+=2, WaterBuffer++)
|
|
{
|
|
Xoffset=(*(WaterBuffer-1))-(*(WaterBuffer+1));
|
|
Yoffset=(*(WaterBuffer-dimx))-(*(WaterBuffer+dimx));
|
|
*texturedest=*(texturesource+((Xoffset*2+Yoffset*pitch)&(dimy*dimy*2-1)));
|
|
}*/
|
|
|
|
for (int32 j = 0; j < dimy; j++)
|
|
for (int32 i = 0; i < dimx; i++, texturedest++, WaterBuffer++, textsource++) {
|
|
if (Type & T3D_MESH_POOLWATER) {
|
|
Xoffset = ((*(WaterBuffer - 1)) - (*(WaterBuffer + 1))) >> 16;
|
|
Yoffset = ((*(WaterBuffer - dimx)) - (*(WaterBuffer + dimx))) >> 16;
|
|
*texturedest = (texturesource[((i + Xoffset) & (dimx - 1)) + (((j + Yoffset) & (dimy - 1)) * pitch)]);
|
|
} else if (Type & T3D_MESH_RECEIVERIPPLES) {
|
|
R = ((*textsource) & 0x1f);
|
|
G = ((*textsource) >> 5) & 0x1f;
|
|
B = ((*textsource) >> 10) & 0x1f;
|
|
A = ((*textsource) >> 15) & 1;
|
|
// if(*WaterBuffer>0)
|
|
{
|
|
R += ((*WaterBuffer) >> 16);
|
|
G += ((*WaterBuffer) >> 16);
|
|
B += ((*WaterBuffer) >> 16);
|
|
if (R > 30) R = 30;
|
|
if (G > 30) G = 30;
|
|
if (B > 30) B = 30;
|
|
}
|
|
|
|
*texturedest = (R & 0x1f) | ((G & 0x1f) << 5) | ((B & 0x1f) << 10) | (A << 15);
|
|
}
|
|
}
|
|
|
|
|
|
rUnlockSurfaceDirect(mat->AddictionalMaterial[0]->Texture);
|
|
rUnlockSurfaceDirect(mat->Texture);
|
|
|
|
AppoWaterBuffer = mesh.WaterBuffer1;
|
|
mesh.WaterBuffer1 = mesh.WaterBuffer2;
|
|
mesh.WaterBuffer2 = AppoWaterBuffer;
|
|
|
|
// DebugLogWindow("--------");
|
|
|
|
/* for every pixel (x,y) in the buffer
|
|
Xoffset = buffer(x-1, y) - buffer(x+1, y)
|
|
Yoffset = buffer(x, y-1) - buffer(x, y+1)
|
|
Shading = Xoffset
|
|
t = texture(x+Xoffset, y+Yoffset)
|
|
p = t + Shading
|
|
plot pixel at (x,y) from texture(x+Xoffset, y+Yoffset)
|
|
end loop*/
|
|
}
|
|
|
|
/* -----------------10/06/99 15.58-------------------
|
|
* t3dRenderWaves
|
|
* --------------------------------------------------*/
|
|
void t3dRenderWaves(gVertex *gv, uint32 NumVerts, t3dF32 mul, t3dF32 Y) {
|
|
static uint16 Posit = 0;
|
|
uint32 i;
|
|
t3dF32 v1, v2, y;
|
|
// gVertex *ogv=gv;
|
|
|
|
/* mul=0.00009f;
|
|
for (i=0; i<NumVerts; i++, ogv++)
|
|
{
|
|
if (ogv->u1>2.0f || ogv->v1>2.0f)
|
|
mul=0.005f;
|
|
}
|
|
*/
|
|
for (i = 0; i < NumVerts; i++, gv++) {
|
|
if (i & 0x1) {
|
|
v1 = (t3dF32)sin(DEGREE_TO_RADIANS(Posit)) * mul;
|
|
v2 = (t3dF32)cos(DEGREE_TO_RADIANS(Posit)) * mul;
|
|
y = (t3dF32)sin(DEGREE_TO_RADIANS(Posit)) * Y;
|
|
} else {
|
|
v1 = (t3dF32)cos(DEGREE_TO_RADIANS(Posit)) * mul;
|
|
v2 = (t3dF32)sin(DEGREE_TO_RADIANS(Posit)) * mul;
|
|
y = (t3dF32)cos(DEGREE_TO_RADIANS(Posit)) * Y;
|
|
}
|
|
|
|
|
|
gv->v1 += v1;
|
|
gv->v2 += v2;
|
|
gv->u1 += v1;
|
|
gv->u2 += v2;
|
|
gv->y += y;
|
|
}
|
|
|
|
Posit++;
|
|
if (Posit > 360)
|
|
Posit -= 360;
|
|
|
|
// Posit=Posit>360 ? 0 : Posit++;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.58-------------------
|
|
* t3dMoveTexture
|
|
* --------------------------------------------------*/
|
|
void t3dMoveTexture(gVertex *gv, uint32 NumVerts, t3dF32 XInc, t3dF32 YInc) {
|
|
uint32 i;
|
|
|
|
for (i = 0; i < NumVerts; i++, gv++) {
|
|
gv->u1 += XInc;
|
|
gv->v1 += YInc;
|
|
}
|
|
}
|
|
|
|
void t3dSetFaceVisibilityPortal(t3dMESH *mesh) {
|
|
if (bOrigRoom && !bDisableMirrors && (!(mesh->Flags & T3D_MESH_NOPORTALCHECK)) && (mesh->PortalList)) {
|
|
for (uint32 pl = 0; pl < t3dNumPortals; pl++)
|
|
if (t3dPortalList[pl] == mesh)
|
|
return;
|
|
t3dPortalList[t3dNumPortals++] = mesh; // aggiunge a lista portali
|
|
}
|
|
}
|
|
|
|
void t3dSetFaceVisibilityMirror(t3dMESH *mesh) {
|
|
if (bOrigRoom && !bDisableMirrors)
|
|
if ((t3dNumGlobalMirrors + 1) < MAX_MIRRORS)
|
|
t3dGlobalMirrorList[t3dNumGlobalMirrors++] = mesh; // aggiunge alla lista
|
|
}
|
|
|
|
/* -----------------10/06/99 15.44-------------------
|
|
* t3dSetFaceVisibility
|
|
* --------------------------------------------------*/
|
|
void t3dSetFaceVisibility(t3dMESH *mesh, t3dCAMERA *cam) {
|
|
if (mesh->Flags & T3D_MESH_PORTAL) { // se e' un portale
|
|
t3dSetFaceVisibilityPortal(mesh);
|
|
return; // ed esce
|
|
} else if (mesh->Flags & T3D_MESH_MIRROR) { // se e' uno specchio
|
|
t3dSetFaceVisibilityMirror(mesh);
|
|
return; // ed esce
|
|
}
|
|
|
|
int16 LastT1, LastT2, T1, T2;
|
|
LastT1 = LastT2 = -2;
|
|
T1 = T2 = -1;
|
|
|
|
MaterialPtr target = nullptr;
|
|
for (uint32 i = 0; i < mesh->NumFaces(); i++) {
|
|
t3dFACE &f = mesh->FList[i];
|
|
|
|
if (!f.getMaterial() || !(f.flags & T3D_FACE_VISIBLE))
|
|
continue;
|
|
|
|
f.checkVertices();
|
|
MaterialPtr Material = f.getMaterial();
|
|
T1 = Material->Texture->ID;
|
|
|
|
if (!bNoLightmapsCalc && f.lightmap) {
|
|
T2 = f.lightmap->Texture->ID;
|
|
} else
|
|
T2 = -1;
|
|
|
|
if (Material->hasFlag(T3D_MATERIAL_ENVIROMENT)) { // se ha l'enviroment
|
|
t3dM3X3F m;
|
|
t3dMatMul(&m, &mesh->Matrix, &t3dCurViewMatrix);
|
|
|
|
if (!(mesh->VBptr = mesh->VertexBuffer))
|
|
continue;
|
|
|
|
for (int j = 0; j < 3; j++) {
|
|
t3dV3F v;
|
|
gVertex *gv = &mesh->VBptr[f.VertexIndex[j]];
|
|
t3dV3F *n = &mesh->NList[f.VertexIndex[j]]->n;
|
|
t3dVectTransform(&v, n, &m);
|
|
gv->u1 = (v.x);
|
|
gv->v1 = (v.y);
|
|
}
|
|
|
|
mesh->VBptr = nullptr;
|
|
mesh->Flags |= T3D_MESH_UPDATEVB;
|
|
}
|
|
|
|
if ((T1 != LastT1) || (T2 != LastT2) || !target) {
|
|
if (T2 > 0) {
|
|
if (!Material->NumAddictionalMaterial)
|
|
DebugLogWindow("Error no Sub Material found in %s!", mesh->name.c_str());
|
|
int32 j = -1;
|
|
for (j = 0; j < Material->NumAddictionalMaterial; j++)
|
|
if (Material->AddictionalMaterial[j]->Texture->ID == T2)
|
|
break;
|
|
|
|
if (j == Material->NumAddictionalMaterial) {
|
|
DebugLogWindow("Sub Material not found in %s!", mesh->name.c_str());
|
|
DebugLogWindow("%d %d | %d", Material->NumAddictionalMaterial, T2, f.lightmap->Texture->ID);
|
|
for (j = 0; j < Material->NumAddictionalMaterial; j++)
|
|
DebugLogWindow("%d", Material->AddictionalMaterial[j]->Texture->ID);
|
|
continue;
|
|
|
|
}
|
|
target = Material->AddictionalMaterial[j];
|
|
} else {
|
|
target = Material;
|
|
}
|
|
LastT1 = T1;
|
|
LastT2 = T2;
|
|
}
|
|
|
|
// Something is wrong here, as the original game seems to be just writing to NumFaces + 0,1,2, as if there
|
|
// was space allocated there.
|
|
for (int v = 0; v < 3; v++) {
|
|
target->addFace(f.getMatVertexIndex(v));
|
|
}
|
|
|
|
StatNumTris++;
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.46-------------------
|
|
* t3dTransformMesh
|
|
* --------------------------------------------------*/
|
|
void t3dTransformMesh(t3dMESH &mesh) {
|
|
if ((mesh.Flags & (T3D_MESH_HIDDEN)) &&
|
|
((mesh.Flags & T3D_MESH_CHARACTER)))
|
|
return;
|
|
|
|
if ((bDisableMirrors == 0) && (bViewOnlyPortal == 0)) {
|
|
t3dDetectObj(t3dCurCamera, &mesh, &t3dCurViewMatrix);
|
|
|
|
//s if (t3dSun)
|
|
//s t3dCheckIfFlaresRayVisible(t3dCurCamera->Source,t3dSun->LightTable[0].Source, mesh);
|
|
}
|
|
|
|
t3dSetVisibileVertex(mesh); // setta tutti i vertici visibili della mesh
|
|
t3dCalcMeshBones(&mesh, 0); // calcola eventuali bones
|
|
|
|
//setup indices array, texture mapping and materials states
|
|
if ((!(mesh.Flags & T3D_MESH_HIDDEN)))
|
|
t3dSetFaceVisibility(&mesh, t3dCurCamera);
|
|
|
|
if (bOrigRoom && !bDisableMirrors) { // Solo se e' nella stanza principale
|
|
if (mesh.Flags & T3D_MESH_RECEIVERIPPLES)
|
|
t3dRenderWater(mesh, T3D_MESH_RECEIVERIPPLES);
|
|
else if (mesh.Flags & T3D_MESH_POOLWATER)
|
|
t3dRenderWater(mesh, T3D_MESH_POOLWATER);
|
|
|
|
if (mesh.Flags & T3D_MESH_WAVESTEXTURE || (mesh.XInc) || (mesh.YInc)) {
|
|
if (!(mesh.VBptr = mesh.VertexBuffer))
|
|
return;
|
|
|
|
if (mesh.Flags & T3D_MESH_WAVESTEXTURE)
|
|
t3dRenderWaves(mesh.VBptr, mesh.NumVerts, mesh.WavesSpeed, mesh.YSpeed);
|
|
|
|
if ((mesh.XInc) || (mesh.YInc))
|
|
t3dMoveTexture(mesh.VBptr, mesh.NumVerts, mesh.XInc, mesh.YInc);
|
|
|
|
mesh.Flags |= T3D_MESH_UPDATEVB;
|
|
mesh.VBptr = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
void t3dCAMERA::normalizedSight() {
|
|
t3dV3F normalizedSightOfView = this->Target - this->Source;
|
|
t3dVectNormalize(&normalizedSightOfView);
|
|
this->NormalizedDir = normalizedSightOfView;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.48-------------------
|
|
* t3dCalcHalos
|
|
* --------------------------------------------------*/
|
|
void t3dCalcHalos(t3dBODY *b) {
|
|
// The userVertexBuffer stuff is not ready yet, giving us nullptr writes.
|
|
warning("TODO: t3dCalcHalos");
|
|
return;
|
|
|
|
gMaterial *Material;
|
|
uint32 uvbc;
|
|
uint32 i;
|
|
gVertex *gv;
|
|
t3dF32 size;
|
|
//uint16 *fp;
|
|
t3dV3F v0, v1, v2, v3, tmp;
|
|
|
|
for (i = 0; i < b->NumLights(); i++) {
|
|
t3dLIGHT &l = b->LightTable[i];
|
|
if (!(l.Type & T3D_LIGHT_LIGHTON)) continue;
|
|
|
|
if (l.Type & T3D_LIGHT_FLARE)
|
|
break;
|
|
}
|
|
if (i >= b->NumLights()) return ;
|
|
|
|
t3dOldUserViewMatrix = t3dCurUserViewMatrix;
|
|
rSaveViewMatrix();
|
|
tmp.x = -t3dCurCamera->Source.x;
|
|
tmp.y = -t3dCurCamera->Source.y;
|
|
tmp.z = -t3dCurCamera->Source.z;
|
|
t3dVectTransform(&tmp, &tmp, &t3dCurViewMatrix);
|
|
rSetViewMatrix(t3dCurViewMatrix, tmp);
|
|
t3dCurUserViewMatrix = rAddUserViewMatrix(t3dCurViewMatrix, tmp);
|
|
|
|
uvbc = rGetUserVertexBufferCounter();
|
|
gv = rLockVertexPtr(rGetUserVertexBuffer(), rVBLOCK_NOSYSLOCK);
|
|
gv += uvbc;
|
|
|
|
for (i = 0; i < b->NumLights(); i++) {
|
|
t3dLIGHT &l = b->LightTable[i];
|
|
if (!(l.Type & T3D_LIGHT_LIGHTON)) continue;
|
|
|
|
if (l.Type & T3D_LIGHT_FLARE) {
|
|
Material = &l.Material[0];
|
|
|
|
size = l.FlareSize;
|
|
|
|
v0.x = -size;
|
|
v0.y = size;
|
|
v0.z = 0.0f;
|
|
t3dVectTransformInv(&v0, &v0, &t3dCurViewMatrix);
|
|
|
|
v1.x = size;
|
|
v1.y = size;
|
|
v1.z = 0.0f;
|
|
t3dVectTransformInv(&v1, &v1, &t3dCurViewMatrix);
|
|
|
|
v2.x = -size;
|
|
v2.y = -size;
|
|
v2.z = 0.0f;
|
|
t3dVectTransformInv(&v2, &v2, &t3dCurViewMatrix);
|
|
|
|
v3.x = size;
|
|
v3.y = -size;
|
|
v3.z = 0.0f;
|
|
t3dVectTransformInv(&v3, &v3, &t3dCurViewMatrix);
|
|
|
|
for (int f = 0; f < 3; f++) {
|
|
Material->addFace(f + uvbc);
|
|
}
|
|
StatNumTris++;
|
|
|
|
Material->addFace(2 + uvbc);
|
|
Material->addFace(3 + uvbc);
|
|
Material->addFace(1 + uvbc);
|
|
StatNumTris++;
|
|
|
|
gv[0].x = v0.x + l.Source.x;
|
|
gv[0].y = v0.y + l.Source.y;
|
|
gv[0].z = v0.z + l.Source.z;
|
|
gv[0].u2 = gv[0].u1 = 0.0f;
|
|
gv[0].v2 = gv[0].v1 = 0.0f;
|
|
gv[1].x = v1.x + l.Source.x;
|
|
gv[1].y = v1.y + l.Source.y;
|
|
gv[1].z = v1.z + l.Source.z;
|
|
gv[1].u2 = gv[1].u1 = 1.0f;
|
|
gv[1].v2 = gv[1].v1 = 0.0f;
|
|
gv[2].x = v2.x + l.Source.x;
|
|
gv[2].y = v2.y + l.Source.y;
|
|
gv[2].z = v2.z + l.Source.z;
|
|
gv[2].u2 = gv[2].u1 = 0.0f;
|
|
gv[2].v2 = gv[2].v1 = 1.0f;
|
|
gv[3].x = v3.x + l.Source.x;
|
|
gv[3].y = v3.y + l.Source.y;
|
|
gv[3].z = v3.z + l.Source.z;
|
|
gv[3].u2 = gv[3].u1 = 1.0f;
|
|
gv[3].v2 = gv[3].v1 = 1.0f;
|
|
|
|
gv[0].diffuse = gv[1].diffuse = gv[2].diffuse = gv[3].diffuse = RGBA_MAKE((uint32)l.Color.x, (uint32)l.Color.y, (uint32)l.Color.z, 255);
|
|
|
|
// rProcessVertices(rGetUserVertexBuffer(), t3dStartIndex,4);
|
|
t3dStartIndex += 4;
|
|
StatNumVerts += 4;
|
|
uvbc += 4;
|
|
gv += 4;
|
|
|
|
rAddToMaterialList(l.Material[0], t3dCurUserViewMatrix);
|
|
}
|
|
}
|
|
rUnlockVertexPtr(rGetUserVertexBuffer());
|
|
rSetUserVertexBufferCounter(uvbc);
|
|
|
|
rRestoreViewMatrix();
|
|
t3dCurUserViewMatrix = t3dOldUserViewMatrix;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.53-------------------
|
|
* t3dAddParticle
|
|
* --------------------------------------------------*/
|
|
void t3dAddParticle(gMaterial *Material, t3dV3F *Source, t3dF32 size, t3dV3F Color, uint32 num) {
|
|
warning("TODO: t3dAddParticle");
|
|
return;
|
|
#if 0
|
|
int16 T1;
|
|
uint32 uvbc;
|
|
gVertex *gv;
|
|
t3dV3F v0, v1, v2, v3;
|
|
uint32 rr, gg, bl, i;
|
|
|
|
uvbc = rGetUserVertexBufferCounter();
|
|
gv = rLockVertexPtr(rGetUserVertexBuffer(), rVBLOCK_NOSYSLOCK);
|
|
gv += uvbc;
|
|
|
|
T1 = Material->Texture->ID;
|
|
|
|
uint32 faceOffset = Material->NumFaces;
|
|
|
|
for (i = 0; i < num; i++, gv += 4) {
|
|
v0.x = -size;
|
|
v0.y = size;
|
|
v0.z = 0.0f;
|
|
t3dVectTransformInv(&v0, &v0, &t3dCurViewMatrix);
|
|
|
|
v1.x = size;
|
|
v1.y = size;
|
|
v1.z = 0.0f;
|
|
t3dVectTransformInv(&v1, &v1, &t3dCurViewMatrix);
|
|
|
|
v2.x = -size;
|
|
v2.y = -size;
|
|
v2.z = 0.0f;
|
|
t3dVectTransformInv(&v2, &v2, &t3dCurViewMatrix);
|
|
|
|
v3.x = size;
|
|
v3.y = -size;
|
|
v3.z = 0.0f;
|
|
t3dVectTransformInv(&v3, &v3, &t3dCurViewMatrix);
|
|
|
|
Material->FacesList[faceOffset++] = 0 + uvbc;
|
|
Material->FacesList[faceOffset++] = 1 + uvbc;
|
|
Material->FacesList[faceOffset++] = 2 + uvbc;
|
|
StatNumTris++;
|
|
Material->NumFaces += 3;
|
|
|
|
Material->FacesList[faceOffset++] = 2 + uvbc;
|
|
Material->FacesList[faceOffset++] = 3 + uvbc;
|
|
Material->FacesList[faceOffset++] = 1 + uvbc;
|
|
StatNumTris++;
|
|
Material->NumFaces += 3;
|
|
|
|
gv[0].x = v0.x + Source->x;
|
|
gv[0].y = v0.y + Source->y;
|
|
gv[0].z = v0.z + Source->z;
|
|
gv[0].u2 = gv[0].u1 = 0.0f;
|
|
gv[0].v2 = gv[0].v1 = 0.0f;
|
|
gv[1].x = v1.x + Source->x;
|
|
gv[1].y = v1.y + Source->y;
|
|
gv[1].z = v1.z + Source->z;
|
|
gv[1].u2 = gv[1].u1 = 1.0f;
|
|
gv[1].v2 = gv[1].v1 = 0.0f;
|
|
gv[2].x = v2.x + Source->x;
|
|
gv[2].y = v2.y + Source->y;
|
|
gv[2].z = v2.z + Source->z;
|
|
gv[2].u2 = gv[2].u1 = 0.0f;
|
|
gv[2].v2 = gv[2].v1 = 1.0f;
|
|
gv[3].x = v3.x + Source->x;
|
|
gv[3].y = v3.y + Source->y;
|
|
gv[3].z = v3.z + Source->z;
|
|
gv[3].u2 = gv[3].u1 = 1.0f;
|
|
gv[3].v2 = gv[3].v1 = 1.0f;
|
|
|
|
rr = (uint32)(Color.x);
|
|
gg = (uint32)(Color.y);
|
|
bl = (uint32)(Color.z);
|
|
|
|
gv[0].diffuse = gv[1].diffuse = gv[2].diffuse = gv[3].diffuse = RGBA_MAKE((uint32)rr, gg, bl, rand() % 255);
|
|
|
|
StatNumVerts += 4;
|
|
uvbc += 4;
|
|
}
|
|
|
|
// rProcessVertices(rGetUserVertexBuffer(), t3dStartIndex,num*4);
|
|
t3dStartIndex += num * 4;
|
|
|
|
rUnlockVertexPtr(rGetUserVertexBuffer());
|
|
rSetUserVertexBufferCounter(uvbc);
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.57-------------------
|
|
* t3dRaiseSmoke
|
|
* --------------------------------------------------*/
|
|
void t3dRaiseSmoke(t3dV3F *pos, t3dParticle *p) {
|
|
uint32 i, j = p->ParticleIndex;
|
|
Particle *pPos;
|
|
// t3dV3F Color;
|
|
|
|
// if (Particles[j].NumParticles<NumParticles)
|
|
// Particles[j].NumParticles++;
|
|
|
|
// if (j==0)
|
|
// return ;//Particles[j].NumParticles=0;
|
|
pPos = &Particles[j].ParticlePos[Particles[j].FirstParticleRendered];
|
|
for (i = Particles[j].FirstParticleRendered; i < Particles[j].NumParticles; i++, pPos++) {
|
|
if (pPos->Flags & T3D_PARTICLE_ACTIVE)
|
|
t3dAddParticle(&Particles[j].Material, &pPos->Pos, pPos->Size, pPos->Color, 1);
|
|
}
|
|
pPos = Particles[j].ParticlePos;
|
|
for (i = 0; i < Particles[j].FirstParticleRendered; i++, pPos++) {
|
|
if (pPos->Flags & T3D_PARTICLE_ACTIVE)
|
|
t3dAddParticle(&Particles[j].Material, &pPos->Pos, pPos->Size, pPos->Color, 1);
|
|
}
|
|
|
|
pPos = Particles[j].ParticlePos;
|
|
for (i = 0; i < Particles[j].NumParticles; i++, pPos++) {
|
|
if (pPos->Flags & T3D_PARTICLE_ACTIVE) {
|
|
// t3dAddParticle(&Particles[j].Material, &pPos->Pos, pPos->Size, pPos->Color, 1);
|
|
pPos->Pos.y += p->Speed;
|
|
if (pPos->Pos.y < pos->y + p->Seg1) {
|
|
pPos->Size += p->Dim1;
|
|
pPos->Pos.x += p->Caos1 * Particles[j].RandTable[(uint32)pPos->Pos.y & 0xf];
|
|
if ((pPos->Color.x += p->R2) > 255.0f) pPos->Color.x = 255.0f;
|
|
if ((pPos->Color.y += p->G2) > 255.0f) pPos->Color.y = 255.0f;
|
|
if ((pPos->Color.z += p->B2) > 255.0f) pPos->Color.z = 255.0f;
|
|
} else {
|
|
if ((pPos->Color.x += p->R3) > 255.0f) pPos->Color.x = 255.0f;
|
|
if ((pPos->Color.y += p->G3) > 255.0f) pPos->Color.y = 255.0f;
|
|
if ((pPos->Color.z += p->B3) > 255.0f) pPos->Color.z = 255.0f;
|
|
pPos->Pos.x += p->Caos2 * Particles[j].RandTable[(uint32)pPos->Pos.y & 0xf];
|
|
if (pPos->Pos.y > pos->y + p->Seg2)
|
|
pPos->Size -= p->Dim2;
|
|
else
|
|
pPos->Size += p->Dim2;
|
|
}
|
|
if (pPos->Pos.y > pos->y + p->Lung) {
|
|
pPos->Flags &= ~T3D_PARTICLE_ACTIVE;
|
|
pPos->Flags |= T3D_PARTICLE_REGEN;
|
|
|
|
if (Particles[j].FirstParticleRendered <= Particles[j].NumParticles - 1)
|
|
Particles[j].FirstParticleRendered++;
|
|
else
|
|
Particles[j].FirstParticleRendered = 0;
|
|
}
|
|
} else {
|
|
if ((!(Particles[j].ParticleWait) || (pPos->Flags & T3D_PARTICLE_REGEN))) {
|
|
error("TODO: Complete particle support");
|
|
#if 0
|
|
pPos->Flags &= ~T3D_PARTICLE_REGEN;
|
|
pPos->Flags |= T3D_PARTICLE_ACTIVE;
|
|
pPos->Pos.x = pos->x;
|
|
pPos->Pos.y = pos->y;
|
|
pPos->Pos.z = pos->z;
|
|
pPos->Size = p->Size;
|
|
pPos->Color.x = p->R1;
|
|
pPos->Color.y = p->G1;
|
|
pPos->Color.z = p->B1;
|
|
Particles[j].RandTable[i & 0xf] = rand() % 3 - 1;
|
|
Particles[j].ParticleWait = p->Delay;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
Particles[j].ParticleWait--;
|
|
|
|
rAddToMaterialList(Particles[j].Material, t3dCurUserViewMatrix);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.48-------------------
|
|
* t3dAnimLights
|
|
* --------------------------------------------------*/
|
|
void t3dAnimLights(t3dBODY *b) {
|
|
// t3dU8 exist=0;
|
|
gVertex *vv;
|
|
int32 rr, gg, bb, aa;
|
|
uint8 bProcessLights;
|
|
|
|
if (b->LightTable.empty())
|
|
return;
|
|
|
|
if (b->LightTable[0].Type & T3D_LIGHT_ALLLIGHTSOFF)
|
|
return;
|
|
|
|
t3dCalcHalos(b); // Calculate flare/halos for lights
|
|
|
|
bProcessLights = 0;
|
|
uint32 light = 0;
|
|
while ((light < b->NumLights())) {
|
|
t3dLIGHT &l = b->LightTable[light];
|
|
if (l.Type & T3D_LIGHT_CANDLESMOKE)
|
|
t3dRaiseSmoke(&l.Source, l.Particle.get());
|
|
else if (l.Type & T3D_LIGHT_PULSE) {
|
|
error("TODO: Pulsing lights");
|
|
#if 0
|
|
bProcessLights = 1;
|
|
l.LightRandomizer = -rand() % ((int32)(l.Color.x + l.Color.y + l.Color.z) / 12);
|
|
#endif
|
|
}
|
|
light++;
|
|
}
|
|
|
|
if (bProcessLights) {
|
|
//lock all vertexbuffers
|
|
for (uint i = 0; i < b->NumMeshes(); i++) {
|
|
t3dMESH &m = b->MeshTable[i];
|
|
m.VBptr = m.VertexBuffer;
|
|
m.Flags |= T3D_MESH_UPDATEVB;
|
|
}
|
|
|
|
for (auto &l : b->LightTable) {
|
|
if (!(l.Type & T3D_LIGHT_PULSE) || !(l.Type & T3D_LIGHT_LIGHTON)) continue;
|
|
|
|
if (l.FlickerDelay > (l.Flicker)) {
|
|
l.FlickerDelay = 0;
|
|
for (int j = 0; j < l.AnimLight.NumVisVerts(); j++) {
|
|
vv = l.AnimLight.VisVerts[j];
|
|
rr = RGBA_GETRED(vv->diffuse);
|
|
gg = RGBA_GETGREEN(vv->diffuse);
|
|
bb = RGBA_GETBLUE(vv->diffuse);
|
|
aa = RGBA_GETALPHA(vv->diffuse);
|
|
rr += l.AnimLight.LastRandomizer + l.LightRandomizer;
|
|
gg += l.AnimLight.LastRandomizer + l.LightRandomizer;
|
|
bb += l.AnimLight.LastRandomizer + l.LightRandomizer;
|
|
if (rr < 0) rr = 0;
|
|
if (gg < 0) gg = 0;
|
|
if (bb < 0) bb = 0;
|
|
if (rr > 255) rr = 255;
|
|
if (gg > 255) gg = 255;
|
|
if (bb > 255) bb = 255;
|
|
|
|
vv->diffuse = RGBA_MAKE(rr, gg, bb, aa);
|
|
}
|
|
l.AnimLight.LastRandomizer = -l.LightRandomizer;
|
|
}
|
|
l.FlickerDelay++;
|
|
}
|
|
//lock all vertexbuffers
|
|
for (uint i = 0; i < b->NumMeshes(); i++) {
|
|
b->MeshTable[i].VBptr = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -----------------29/07/99 16.13-------------------
|
|
* t3dCheckMaterialVB
|
|
* --------------------------------------------------*/
|
|
void t3dCheckMaterialVB(MaterialPtr mat) {
|
|
if (!mat || (mat->NumAllocatedVerts() < 3))
|
|
return ;
|
|
|
|
{
|
|
int i = 0;
|
|
for (; i < mat->NumAllocatedMesh; i++)
|
|
if (*(mat->FlagsList[i]) & T3D_MESH_UPDATEVB)
|
|
break;
|
|
|
|
if (i >= mat->NumAllocatedMesh)
|
|
return;
|
|
}
|
|
//warning("TODO: Implement t3dCheckMaterialVB");
|
|
// gv = rLockVertexPtr(mat->VB, DDLOCK_WRITEONLY | DDLOCK_NOSYSLOCK);
|
|
mat->VBO->_buffer.clear();
|
|
for (int i = 0; i < mat->NumAllocatedVerts(); i++) {
|
|
auto vert = *mat->VertsList[i];
|
|
mat->VBO->_buffer.push_back(vert);
|
|
//memcpy(gv, mat->VertsList[i], sizeof(gVertex));
|
|
}
|
|
|
|
// rUnlockVertexPtr(mat->VB);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.49-------------------
|
|
* t3dTransformBody
|
|
* --------------------------------------------------*/
|
|
bool t3dTransformBody(t3dBODY *b) {
|
|
if (b == nullptr) return false;
|
|
|
|
if ((t3dOrigRoom == b) && !(bDisableMirrors)) // If I'm in the main room
|
|
bOrigRoom = 1;
|
|
else
|
|
bOrigRoom = 0;
|
|
|
|
//Normalize view (normalized too many times; can be optimized)
|
|
t3dCurCamera->normalizedSight();
|
|
|
|
//Check if all light are turned off
|
|
bNoLightmapsCalc = 0;
|
|
if (!b->LightTable.empty() && b->LightTable[0].Type & T3D_LIGHT_ALLLIGHTSOFF)
|
|
bNoLightmapsCalc = 1;
|
|
|
|
//Do primary backface culling
|
|
//f
|
|
t3dV3F Sight;
|
|
t3dVectTransformInv(&Sight, &t3dCurCamera->Source, &b->MeshTable[0].Matrix);
|
|
#if 0
|
|
t3dBackfaceCulling(b->NList, b->NumNormals/*+b->NumVerticesNormals*/, &Sight);
|
|
#endif
|
|
// t3dBackfaceCulling(b->NList, b->NumNormals/*+b->NumVerticesNormals*/, &t3dCurCamera->Source);
|
|
//f
|
|
//Setting up transformation matrices. Mesh-Translation for moved/moveable objects
|
|
t3dCurTranslation = -t3dCurCamera->Source + b->MeshTable[0].Trasl;
|
|
t3dVectTransform(&t3dCurTranslation, &t3dCurTranslation, &t3dCurViewMatrix); // rotate by the camera matrix
|
|
//f
|
|
t3dM3X3F LastViewMatrix;
|
|
t3dMatCopy(&LastViewMatrix, &t3dCurViewMatrix); // Save original view-matrix
|
|
t3dMatMul(&t3dCurViewMatrix, &t3dCurViewMatrix, &b->MeshTable[0].Matrix);
|
|
//f
|
|
rSetViewMatrix(t3dCurViewMatrix, t3dCurTranslation);
|
|
t3dCurUserViewMatrix = rAddUserViewMatrix(t3dCurViewMatrix, t3dCurTranslation);
|
|
if (bOrigRoom)
|
|
t3dOrigUserViewMatrix = t3dCurUserViewMatrix;
|
|
|
|
//Lights Animations (flicker, pulse etc etc)
|
|
t3dAnimLights(b);
|
|
//f
|
|
t3dMatCopy(&t3dCurViewMatrix, &LastViewMatrix); // Restore original matrix
|
|
//f
|
|
|
|
// Remove the meshes that remain behind BlockMesh
|
|
if (bOrigRoom)
|
|
for (uint32 j = 0; j < T3D_MAX_BLOCK_MESHES; j++)
|
|
t3dCheckBlockMesh(b->MeshTable, b->NumMeshes(), b->BlockMeshes[j]);
|
|
|
|
//Main loop through the meshes
|
|
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
|
t3dMESH &m = b->MeshTable[i];
|
|
if ((!(m.Flags & (T3D_MESH_HIDDEN | T3D_MESH_INVISIBLEFROMSECT | T3D_MESH_PORTALPROCESSED))) && // hidden or invisible
|
|
(bDisableMirrors || !(m.Flags & T3D_MESH_ONLYINMIRRORS)) && // only in mirrors
|
|
(t3dCheckBoundSphere(m)) && // check bound-sphere
|
|
!((m.NumFaces() > 16) && !t3dCheckBoundBox(m))) { // check bound-box
|
|
// Set visible
|
|
m.Flags |= T3D_MESH_VISIBLE;
|
|
// If viewed from a portal, mark it as processed to avoid double rendering
|
|
if (bPortalRoom) m.Flags |= T3D_MESH_PORTALPROCESSED;
|
|
// Transform mesh. This function also apply bones deformation and other mesh modifications
|
|
t3dTransformMesh(m);
|
|
|
|
// Now send vertices to render.dll for transformations
|
|
if ((!(m.Flags & T3D_MESH_HIDDEN) && (!(m.Flags & T3D_MESH_MIRROR)) && (!(m.Flags & T3D_MESH_PORTAL)))) {
|
|
t3dStartIndex += m.NumVerts;
|
|
StatNumVerts += m.NumVerts;
|
|
}
|
|
} else
|
|
m.Flags &= ~(T3D_MESH_VISIBLE | T3D_MESH_INVISIBLEFROMSECT); //Mesh is invisible
|
|
}
|
|
|
|
//Now build up the material lists. Check also if lightmaps are active;if active process lightmaps
|
|
for (auto &mat : b->MatTable) {
|
|
if (!mat) continue;
|
|
|
|
t3dCheckMaterialVB(mat);
|
|
|
|
for (auto &cm : mat->AddictionalMaterial) {
|
|
t3dCheckMaterialVB(cm);
|
|
}
|
|
//f rAddToMaterialList( mat, t3dCurUserViewMatrix );
|
|
}
|
|
QueueMaterialList(b->MatTable, b->NumMaterials(), t3dCurUserViewMatrix);
|
|
|
|
for (uint32 i = 0; i < b->NumMeshes(); i++) {
|
|
b->MeshTable[i].Flags &= ~T3D_MESH_UPDATEVB;
|
|
}
|
|
|
|
//if there are mirrors in the body is now time to process them...
|
|
if (!bDisableMirrors && bOrigRoom)
|
|
t3dProcessMirrors(t3dGlobalMirrorList, t3dNumGlobalMirrors);
|
|
|
|
bOrigRoom = 0;
|
|
return true;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.53-------------------
|
|
* t3dAddLensFlare
|
|
* --------------------------------------------------*/
|
|
void t3dAddLensFlare(gMaterial *Material, t3dV3F *Source, t3dF32 size, t3dF32 perc2, t3dV3F Color) {
|
|
warning("TODO: t3dAddLensFlare");
|
|
return;
|
|
#if 0
|
|
uint32 uvbc;
|
|
gVertex *gv;
|
|
t3dV3F v0, v1, v2, v3;
|
|
int32 rr, gg, bb;
|
|
|
|
uvbc = rGetUserVertexBufferCounter();
|
|
gv = rLockVertexPtr(rGetUserVertexBuffer(), rVBLOCK_NOSYSLOCK);
|
|
gv += uvbc;
|
|
|
|
// for (i=0; i<num; i++)
|
|
{
|
|
|
|
|
|
v0.x = -size;
|
|
v0.y = size;
|
|
v0.z = 0.0f;
|
|
t3dVectTransformInv(&v0, &v0, &t3dCurViewMatrix);
|
|
|
|
v1.x = size;
|
|
v1.y = size;
|
|
v1.z = 0.0f;
|
|
t3dVectTransformInv(&v1, &v1, &t3dCurViewMatrix);
|
|
|
|
v2.x = -size;
|
|
v2.y = -size;
|
|
v2.z = 0.0f;
|
|
t3dVectTransformInv(&v2, &v2, &t3dCurViewMatrix);
|
|
|
|
v3.x = size;
|
|
v3.y = -size;
|
|
v3.z = 0.0f;
|
|
t3dVectTransformInv(&v3, &v3, &t3dCurViewMatrix);
|
|
|
|
int faceIndex = Material->NumFaces;
|
|
Material->FacesList[faceIndex++] = 0 + uvbc;
|
|
Material->FacesList[faceIndex++] = 1 + uvbc;
|
|
Material->FacesList[faceIndex++] = 2 + uvbc;
|
|
StatNumTris++;
|
|
Material->NumFaces += 3;
|
|
|
|
Material->FacesList[faceIndex++] = 2 + uvbc;
|
|
Material->FacesList[faceIndex++] = 3 + uvbc;
|
|
Material->FacesList[faceIndex++] = 1 + uvbc;
|
|
StatNumTris++;
|
|
Material->NumFaces += 3;
|
|
|
|
gv[0].x = v0.x + Source->x;
|
|
gv[0].y = v0.y + Source->y;
|
|
gv[0].z = v0.z + Source->z;
|
|
gv[0].u2 = gv[0].u1 = 0.0f;
|
|
gv[0].v2 = gv[0].v1 = 0.0f;
|
|
gv[1].x = v1.x + Source->x;
|
|
gv[1].y = v1.y + Source->y;
|
|
gv[1].z = v1.z + Source->z;
|
|
gv[1].u2 = gv[1].u1 = 1.0f;
|
|
gv[1].v2 = gv[1].v1 = 0.0f;
|
|
gv[2].x = v2.x + Source->x;
|
|
gv[2].y = v2.y + Source->y;
|
|
gv[2].z = v2.z + Source->z;
|
|
gv[2].u2 = gv[2].u1 = 0.0f;
|
|
gv[2].v2 = gv[2].v1 = 1.0f;
|
|
gv[3].x = v3.x + Source->x;
|
|
gv[3].y = v3.y + Source->y;
|
|
gv[3].z = v3.z + Source->z;
|
|
gv[3].u2 = gv[3].u1 = 1.0f;
|
|
gv[3].v2 = gv[3].v1 = 1.0f;
|
|
|
|
rr = (uint32)(Color.x - perc2);
|
|
gg = (uint32)(Color.y - perc2);
|
|
bb = (uint32)(Color.z - perc2);
|
|
if (rr < 0) rr = 0;
|
|
if (gg < 0) gg = 0;
|
|
if (bb < 0) bb = 0;
|
|
if (rr > 255) rr = 255;
|
|
if (gg > 255) gg = 255;
|
|
if (bb > 255) bb = 255;
|
|
|
|
gv[0].diffuse = gv[1].diffuse = gv[2].diffuse = gv[3].diffuse = RGBA_MAKE((uint32)rr, gg, bb, rand() % 255);
|
|
|
|
// rProcessVertices(rGetUserVertexBuffer(), t3dStartIndex,4);
|
|
t3dStartIndex += 4;
|
|
StatNumVerts += 4;
|
|
uvbc += 4;
|
|
}
|
|
|
|
rUnlockVertexPtr(rGetUserVertexBuffer());
|
|
rSetUserVertexBufferCounter(uvbc);
|
|
#endif
|
|
}
|
|
|
|
/* -----------------10/06/99 15.54-------------------
|
|
*
|
|
* --------------------------------------------------*/
|
|
uint8 t3dPointInFrustum(t3dV3F pos) {
|
|
t3dF32 d1;
|
|
|
|
t3dVectSub(&pos, &pos, &t3dCurCamera->Source);
|
|
t3dVectTransform(&pos, &pos, &t3dCurViewMatrix); // rotate by the mesh matrix
|
|
|
|
d1 = t3dVectDot(&pos, &ClipPlanes[RIGHTCLIP].n) + ClipPlanes[RIGHTCLIP].dist;
|
|
if ((d1 > 0)) {
|
|
d1 = ClipPlanes[LEFTCLIP].dist + t3dVectDot(&pos, &ClipPlanes[LEFTCLIP].n);
|
|
if ((d1 > 0)) {
|
|
d1 = ClipPlanes[TOPCLIP].dist + t3dVectDot(&pos, &ClipPlanes[TOPCLIP].n);
|
|
if ((d1 > 0)) {
|
|
d1 = ClipPlanes[BOTTOMCLIP].dist + t3dVectDot(&pos, &ClipPlanes[BOTTOMCLIP].n);
|
|
if ((d1 > 0)) {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* -----------------10/06/99 15.54-------------------
|
|
* t3dTransformSky
|
|
* --------------------------------------------------*/
|
|
void t3dTransformSky() {
|
|
gVertex *gv;
|
|
t3dBODY *sky = t3dSky;
|
|
t3dBODY *sun = nullptr; //s t3dSun;
|
|
t3dV3F SunDir, color, inc, pos, tmp;
|
|
t3dF32 perc;
|
|
static t3dV3F OldSunPosition;
|
|
// static t3dU32 value;
|
|
|
|
if (sky) {
|
|
for (uint32 i = 0; i < sky->NumMeshes(); i++) {
|
|
t3dVectCopy(&sky->MeshTable[i].Trasl, &t3dCurCamera->Source);
|
|
}
|
|
if (!t3dTransformBody(sky)) {
|
|
DebugLogWindow("Can't transform %s", t3dSky->name.c_str());
|
|
}
|
|
|
|
gv = t3dSky->MeshTable[0].VertexBuffer;
|
|
for (uint32 i = 0; i < t3dSky->MeshTable[0].NumVerts; i++, gv++) {
|
|
gv->u1 += SKY_SPEED;
|
|
gv->v1 += SKY_SPEED;
|
|
}
|
|
t3dSky->MeshTable[0].Flags |= T3D_MESH_UPDATEVB;
|
|
}
|
|
|
|
if (sun) {
|
|
t3dF32 size;
|
|
// t3dV3F v1;
|
|
// unsigned short *p;
|
|
// t3dS32 pitch;
|
|
t3dF32 perc2;
|
|
uint32 rr = 50, gg = 50, bb = 50/*,aa*/;
|
|
|
|
/* p=(unsigned short*)rLockSurface(SkySurface, &pitch);
|
|
pitch/=2;
|
|
|
|
v1.x=SunPositionInTexture.x;
|
|
v1.y=SunPositionInTexture.y;
|
|
if ((v1.x<0.0f) || (v1.y<0.0f) || (v1.x>1.0f) || (v1.x>1.0f))
|
|
return;
|
|
rSurfaceFormatToRGBA((WORD)p[(t3dU32)(v1.x*256.0f)+(t3dU32)(v1.y*256.0f)*pitch],
|
|
&rr,&gg,&bb,&aa);
|
|
// p[(t3dU32)(v1.x*256.0f)+(t3dU32)(v1.y*256.0f)*pitch]=(short)rRGBAToSurfaceFormat(rand(),rand(),rand(),255);
|
|
// p[(t3dU32)(0.5f*256.0f)+(t3dU32)(0.5f*256.0f)*pitch]=(short)rRGBAToSurfaceFormat(rand(),rand(),rand(),aa);
|
|
rUnlockSurface(SkySurface);
|
|
*/
|
|
|
|
t3dSky->MatTable[1]->Texture = (SkySurface);
|
|
|
|
|
|
perc2 = ((((rr + gg + bb) * (1.0f / 3.0f))));
|
|
|
|
t3dOldUserViewMatrix = t3dCurUserViewMatrix;
|
|
rSaveViewMatrix();
|
|
tmp = -t3dCurCamera->Source;
|
|
t3dVectTransform(&tmp, &tmp, &t3dCurViewMatrix);
|
|
|
|
rSetViewMatrix(t3dCurViewMatrix, tmp);
|
|
t3dCurUserViewMatrix = rAddUserViewMatrix(t3dCurViewMatrix, tmp);
|
|
|
|
auto &l = sun->LightTable[0];
|
|
|
|
t3dVectSub(&SunDir, &l.Source, &t3dCurCamera->Source);
|
|
t3dVectNormalize(&SunDir);
|
|
perc = t3dVectDot(&SunDir, &t3dCurCamera->NormalizedDir);
|
|
|
|
if ((l.Type & T3D_LIGHT_FLARE) && (perc > 0)) {
|
|
t3dV3F appo, appo2;
|
|
|
|
size = (perc * perc2) * 180; //f era: 500
|
|
|
|
t3dVectSub(&appo, &t3dCurCamera->Source, &OldSunPosition);
|
|
t3dVectCopy(&OldSunPosition, &t3dCurCamera->Source);
|
|
appo2.x = l.Source.x + appo.x;
|
|
appo2.y = 8000; //f era: 7000
|
|
appo2.z = l.Source.z + appo.z;
|
|
|
|
if (t3dPointInFrustum(appo2) && (LastFlaresVisible)) {
|
|
//Draw Lensflares
|
|
l.Source.y = 8000; //f era: 7000
|
|
|
|
t3dVectCopy(&pos, &t3dCurCamera->Source);
|
|
t3dVectCopy(&inc, &t3dCurCamera->NormalizedDir);
|
|
inc *= 2200.0f;
|
|
t3dVectAdd(&pos, &pos, &inc);
|
|
t3dVectSub(&SunDir, &l.Source, &pos);
|
|
inc.x = (SunDir.x / 3);
|
|
inc.y = (SunDir.y / 3);
|
|
inc.z = (SunDir.z / 3);
|
|
|
|
perc = 1.0f - ((1.0f - perc) / 0.15f);
|
|
|
|
t3dVectCopy(&pos, &l.Source);
|
|
|
|
color.x = 0 * perc;
|
|
color.y = 155 * perc;
|
|
color.z = 155 * perc;
|
|
t3dVectSub(&pos, &pos, &inc);
|
|
t3dAddLensFlare(&l.Material[1], &pos, 500, 0, color);
|
|
|
|
color.x = 0 * perc;
|
|
color.y = 155 * perc;
|
|
color.z = 200 * perc;
|
|
t3dVectSub(&pos, &pos, &inc);
|
|
t3dAddLensFlare(&l.Material[1], &pos, 400, 0, color);
|
|
|
|
color.x = 0 * perc;
|
|
color.y = 55 * perc;
|
|
color.z = 155 * perc;
|
|
inc *= 0.8f;
|
|
t3dVectSub(&pos, &pos, &inc);
|
|
t3dAddLensFlare(&l.Material[1], &pos, 100, 0, color);
|
|
|
|
color.x = 255 * (perc);
|
|
color.y = 222 * (perc);
|
|
color.z = 2 * (perc);
|
|
inc *= 0.5f;
|
|
t3dVectSub(&pos, &pos, &inc);
|
|
t3dAddLensFlare(&l.Material[1], &pos, 200, 0, color);
|
|
|
|
rAddToMaterialList(l.Material[1], t3dCurUserViewMatrix);
|
|
}
|
|
|
|
LastFlaresVisible = 1;
|
|
|
|
//Draw Sun
|
|
t3dAddLensFlare(&l.Material[0], &l.Source, size, perc2, l.Color);
|
|
rAddToMaterialList(l.Material[0], t3dCurUserViewMatrix);
|
|
}
|
|
rRestoreViewMatrix();
|
|
t3dCurUserViewMatrix = t3dOldUserViewMatrix;
|
|
}
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.43-------------------
|
|
* t3dCheckPortalCrossed
|
|
* --------------------------------------------------*/
|
|
t3dBODY *t3dCheckPortalCrossed(t3dV3F *a) {
|
|
NormalPtr n;
|
|
uint32 i;
|
|
t3dMESH *mesh;
|
|
t3dV3F line, inter, scale, v0, v1, v2;
|
|
t3dF32 d;
|
|
|
|
for (i = 0; i < t3dNumPortals; i++) {
|
|
mesh = t3dPortalList[i];
|
|
|
|
if (mesh->Flags & T3D_MESH_VIEWONLYPORTAL) continue;
|
|
|
|
n = mesh->FList[0].n;
|
|
d = n->dist - (t3dVectDot(a, &n->n));
|
|
if (d > -1.0f) {
|
|
if (!(mesh->VBptr = mesh->VertexBuffer))
|
|
return nullptr;
|
|
|
|
t3dVectCopy(&line, a);
|
|
line.y += 10;
|
|
t3dVectCopy(&scale, &n->n);
|
|
scale *= 20000.0f;
|
|
t3dVectAdd(&line, &line, &scale);
|
|
|
|
v0.x = mesh->VBptr[mesh->FList[0].VertexIndex[0]].x;
|
|
v0.y = mesh->VBptr[mesh->FList[0].VertexIndex[0]].y;
|
|
v0.z = mesh->VBptr[mesh->FList[0].VertexIndex[0]].z;
|
|
v1.x = mesh->VBptr[mesh->FList[0].VertexIndex[1]].x;
|
|
v1.y = mesh->VBptr[mesh->FList[0].VertexIndex[1]].y;
|
|
v1.z = mesh->VBptr[mesh->FList[0].VertexIndex[1]].z;
|
|
v2.x = mesh->VBptr[mesh->FList[0].VertexIndex[2]].x;
|
|
v2.y = mesh->VBptr[mesh->FList[0].VertexIndex[2]].y;
|
|
v2.z = mesh->VBptr[mesh->FList[0].VertexIndex[2]].z;
|
|
|
|
if (t3dVectTriangleIntersection(&inter, line, *a, v0, v1, v2, *n)) { //return 1 if the vector from start to end pass trought the triangle v1,v2,v3
|
|
mesh->VBptr = nullptr;
|
|
return mesh->PortalList;
|
|
}
|
|
v0.x = mesh->VBptr[mesh->FList[1].VertexIndex[0]].x;
|
|
v0.y = mesh->VBptr[mesh->FList[1].VertexIndex[0]].y;
|
|
v0.z = mesh->VBptr[mesh->FList[1].VertexIndex[0]].z;
|
|
v1.x = mesh->VBptr[mesh->FList[1].VertexIndex[1]].x;
|
|
v1.y = mesh->VBptr[mesh->FList[1].VertexIndex[1]].y;
|
|
v1.z = mesh->VBptr[mesh->FList[1].VertexIndex[1]].z;
|
|
v2.x = mesh->VBptr[mesh->FList[1].VertexIndex[2]].x;
|
|
v2.y = mesh->VBptr[mesh->FList[1].VertexIndex[2]].y;
|
|
v2.z = mesh->VBptr[mesh->FList[1].VertexIndex[2]].z;
|
|
|
|
if (t3dVectTriangleIntersection(&inter, line, *a, v0, v1, v2, *n)) { //return 1 if the vector from start to end pass trought the triangle v1,v2,v3
|
|
mesh->VBptr = nullptr;
|
|
return mesh->PortalList;
|
|
}
|
|
mesh->VBptr = nullptr;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/* -----------------08/03/2000 15.08-----------------
|
|
* QueueMaterialList
|
|
* --------------------------------------------------*/
|
|
void QueueMaterialList(MaterialTable &MatList, unsigned int NumMat, signed short int ViewMatrixNum) {
|
|
uint32 i;
|
|
|
|
if (!NumMat) return;
|
|
|
|
for (i = 0; i < t3dNumMaterialLists; i++)
|
|
if (t3dMaterialList[i].mat_list == &MatList)
|
|
break;
|
|
|
|
if ((i >= t3dNumMaterialLists) || (t3dMaterialList[i].num_mat != NumMat) || (t3dMaterialList[i].matrix != ViewMatrixNum)) {
|
|
if ((t3dNumMaterialLists + 1) >= MAX_MATERIAL_LISTS) {
|
|
DebugLogWindow("Too mach material lists! %d MAX is %d", t3dNumMaterialLists + 1, MAX_MATERIAL_LISTS);
|
|
return ;
|
|
}
|
|
|
|
t3dMaterialList[t3dNumMaterialLists].mat_list = &MatList;
|
|
t3dMaterialList[t3dNumMaterialLists].num_mat = NumMat;
|
|
t3dMaterialList[t3dNumMaterialLists].matrix = ViewMatrixNum;
|
|
t3dNumMaterialLists ++;
|
|
}
|
|
}
|
|
|
|
/* -----------------08/03/2000 15.13-----------------
|
|
* ProcessMaterialList
|
|
* --------------------------------------------------*/
|
|
void ProcessMaterialList() {
|
|
for (uint32 i = 0; i < t3dNumMaterialLists; i++) {
|
|
rBuildMaterialList(*t3dMaterialList[i].mat_list, t3dMaterialList[i].num_mat, t3dMaterialList[i].matrix);
|
|
}
|
|
}
|
|
|
|
/* -----------------10/06/99 15.50-------------------
|
|
* SortMesh
|
|
* --------------------------------------------------*/
|
|
static int SortMesh(const void *element1, const void *element2) {
|
|
const t3dMESH * const *mm1 = (const t3dMESH * const *)(element1);
|
|
const t3dMESH * const *mm2 = (const t3dMESH * const *)(element2);
|
|
|
|
const t3dMESH *m1 = *mm1;
|
|
const t3dMESH *m2 = *mm2;
|
|
|
|
/* DebugLogWindow("%s",m1->Name);
|
|
DebugLogWindow("%s",m2->Name);
|
|
DebugLogWindow("----------------");*/
|
|
if (m1->BBoxAverageZ > m2->BBoxAverageZ)
|
|
return 1;
|
|
else if (m1->BBoxAverageZ < m2->BBoxAverageZ)
|
|
return -1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.51-------------------
|
|
* t3dSortMeshes
|
|
* --------------------------------------------------*/
|
|
void t3dSortMeshes() {
|
|
qsort((void *)&t3d_VisibleMeshes[0], (size_t)t3d_NumMeshesVisible, sizeof(t3dMESH *),
|
|
SortMesh);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.43-------------------
|
|
* t3dProcessPortal
|
|
* --------------------------------------------------*/
|
|
void t3dProcessPortal(t3dMESH *mesh, t3dCAMERA *cam) {
|
|
t3dV3F appo, c0;
|
|
t3dV3F ppv1, ppv2, ppv3, ppv4;
|
|
uint32 p;
|
|
t3dNORMAL OldClipPlanes[NUMCLIPPLANES];
|
|
|
|
if (!mesh->VertexBuffer)
|
|
return ;
|
|
|
|
mesh->VBptr = mesh->VertexBuffer;
|
|
ppv1.x = mesh->VBptr[mesh->FList[0].VertexIndex[0]].x;
|
|
ppv1.y = mesh->VBptr[mesh->FList[0].VertexIndex[0]].y;
|
|
ppv1.z = mesh->VBptr[mesh->FList[0].VertexIndex[0]].z;
|
|
ppv2.x = mesh->VBptr[mesh->FList[0].VertexIndex[1]].x;
|
|
ppv2.y = mesh->VBptr[mesh->FList[0].VertexIndex[1]].y;
|
|
ppv2.z = mesh->VBptr[mesh->FList[0].VertexIndex[1]].z;
|
|
ppv3.x = mesh->VBptr[mesh->FList[0].VertexIndex[2]].x;
|
|
ppv3.y = mesh->VBptr[mesh->FList[0].VertexIndex[2]].y;
|
|
ppv3.z = mesh->VBptr[mesh->FList[0].VertexIndex[2]].z;
|
|
|
|
for (p = 0; p < 3; p++) {
|
|
appo.x = mesh->VBptr[mesh->FList[1].VertexIndex[p]].x;
|
|
appo.y = mesh->VBptr[mesh->FList[1].VertexIndex[p]].y;
|
|
appo.z = mesh->VBptr[mesh->FList[1].VertexIndex[p]].z;
|
|
|
|
if ((ppv1 != appo) && (ppv2 != appo) && (ppv3 != appo))
|
|
memcpy(&ppv4, &appo, sizeof(t3dV3F));
|
|
}
|
|
|
|
memcpy(OldClipPlanes, ClipPlanes, sizeof(t3dNORMAL)*NUMCLIPPLANES);
|
|
|
|
t3dVectSub(&ppv4, &ppv4, &cam->Source);
|
|
t3dVectSub(&ppv3, &ppv3, &cam->Source);
|
|
t3dVectSub(&ppv2, &ppv2, &cam->Source);
|
|
t3dVectSub(&ppv1, &ppv1, &cam->Source);
|
|
t3dVectTransform(&ppv1, &ppv1, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv2, &ppv2, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv3, &ppv3, &t3dCurViewMatrix);
|
|
t3dVectTransform(&ppv4, &ppv4, &t3dCurViewMatrix);
|
|
t3dVectFill(&c0, 0.0f);
|
|
|
|
// t3dVectCopy(&c0,&cam->Source);
|
|
|
|
t3dPlaneNormal(&ClipPlanes[RIGHTCLIP], &c0, &ppv3, &ppv4);
|
|
t3dPlaneNormal(&ClipPlanes[LEFTCLIP], &c0, &ppv1, &ppv2);
|
|
t3dPlaneNormal(&ClipPlanes[TOPCLIP], &c0, &ppv4, &ppv1);
|
|
t3dPlaneNormal(&ClipPlanes[BOTTOMCLIP], &c0, &ppv2, &ppv3);
|
|
|
|
mesh->VBptr = nullptr;
|
|
|
|
for (auto &rejectedMesh : mesh->RejectedMeshes) {
|
|
rejectedMesh->Flags |= T3D_MESH_INVISIBLEFROMSECT;
|
|
}
|
|
|
|
if (mesh->Flags & T3D_MESH_VIEWONLYPORTAL) bViewOnlyPortal = TRUE;
|
|
if (!t3dTransformBody(mesh->PortalList)) {
|
|
DebugLogWindow("Can't transform %s", mesh->PortalList->name.c_str());
|
|
}
|
|
bViewOnlyPortal = FALSE;
|
|
|
|
for (auto &rejectedMesh : mesh->RejectedMeshes) {
|
|
rejectedMesh->Flags &= ~T3D_MESH_INVISIBLEFROMSECT;
|
|
}
|
|
|
|
memcpy(ClipPlanes, OldClipPlanes, sizeof(t3dNORMAL)*NUMCLIPPLANES);
|
|
}
|
|
|
|
|
|
/* -----------------10/06/99 15.51-------------------
|
|
* t3dProcessPortals
|
|
* --------------------------------------------------*/
|
|
void t3dProcessPortals() {
|
|
uint32 i;
|
|
|
|
if (t3dNumPortals > 5)
|
|
DebugLogWindow("Current numportals: %d", t3dNumPortals);
|
|
|
|
bPortalRoom = TRUE;
|
|
for (i = 0; i < t3dNumPortals; i++)
|
|
t3dProcessPortal(t3dPortalList[i], t3dCurCamera);
|
|
bPortalRoom = FALSE;
|
|
}
|
|
|
|
/* -----------------10/06/99 15.47-------------------
|
|
* t3dAddTriangle
|
|
* --------------------------------------------------*/
|
|
void t3dAddTriangle(t3dF32 x1, t3dF32 y1, t3dF32 x2, t3dF32 y2, t3dF32 x3, t3dF32 y3,
|
|
int32 r, int32 g, int32 b, int32 a) {
|
|
rAddTrianglesArray(x1, y1, r, g, b, a);
|
|
rAddTrianglesArray(x2, y2, r, g, b, a);
|
|
rAddTrianglesArray(x3, y3, r, g, b, a);
|
|
}
|
|
|
|
/* -----------------10/06/99 15.47-------------------
|
|
* t3dAddQuad
|
|
* --------------------------------------------------*/
|
|
void t3dAddQuad(t3dF32 x1, t3dF32 y1, t3dF32 x2, t3dF32 y2, t3dF32 x3, t3dF32 y3, t3dF32 x4, t3dF32 y4,
|
|
int32 r, int32 g, int32 b, int32 a) {
|
|
t3dAddTriangle(x1, y1, x2, y2, x3, y3, r, g, b, a);
|
|
t3dAddTriangle(x2, y2, x4, y4, x3, y3, r, g, b, a);
|
|
}
|
|
|
|
} // End of namespace Watchmaker
|