Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1282 lines
31 KiB
C++

#include "MLRHeaders.hpp"
#include "Compost\TerrainTextureLogistic.hpp"
//#define HUNT_FOR_THE_RED_TILE "micgaert"
extern DWORD gEnableLightMaps;
//#############################################################################
//## MLRTerrain with no color no lighting w/ detail texture, uv's from xyz ###
//#############################################################################
DynamicArrayOf<Vector2DScalar>
*MLR_Terrain2::detailTexCoords;
MLR_Terrain2::ClassData*
MLR_Terrain2::DefaultData = NULL;
extern DynamicArrayOf<Vector2DScalar> *lightMapUVs;
extern DynamicArrayOf<Scalar> *lightMapSqFalloffs;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::InitializeClass()
{
Verify(!DefaultData);
Verify(gos_GetCurrentHeap() == StaticHeap);
DefaultData =
new ClassData(
MLR_Terrain2ClassID,
"MidLevelRenderer::MLR_Terrain2",
MLR_I_DeT_TMesh::DefaultData,
(MLRPrimitiveBase::Factory)&Make
);
Register_Object(DefaultData);
detailTexCoords = new DynamicArrayOf<Vector2DScalar> (Limits::Max_Number_Vertices_Per_Mesh);
Register_Object(detailTexCoords);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Unregister_Object(detailTexCoords);
delete detailTexCoords;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLR_Terrain2::MLR_Terrain2(
ClassData *class_data,
MemoryStream *stream,
int version
):
MLR_I_DeT_TMesh(class_data, stream, version)
{
Check_Pointer(this);
Check_Pointer(stream);
*stream >> tileX >> tileZ;
*stream >> maxDepth >> maxAllDepth;
int i;
if(version>4)
{
Scalar *fptr = &frame[0][0];
for(int i=0;i<32;i++)
{
*stream >> *fptr++;
}
}
else
{
Scalar xOffset, zOffset, xGrid, zGrid;
*stream >> xOffset >> zOffset;
*stream >> xGrid >> zGrid;
frame[0][0] = xOffset;
frame[0][1] = zOffset;
frame[0][2] = xOffset + 8*xGrid;
frame[0][3] = zOffset + 8*zGrid;
frame[1][0] = xOffset + 4*(tileX/4)*xGrid;
frame[1][1] = zOffset + 4*(tileZ/4)*zGrid;
frame[1][2] = frame[1][0] + 4*xGrid;
frame[1][3] = frame[1][1] + 4*zGrid;
for(i=2;i<8;i++)
{
frame[i][0] = xOffset + tileX*xGrid;
frame[i][1] = zOffset + tileZ*zGrid;
frame[i][2] = frame[i][0] + xGrid;
frame[i][3] = frame[i][1] + zGrid;
}
}
for(i=0;i<8;i++)
{
OneOverX[i] = 1.0f/(frame[i][2] - frame[i][0]);
OneOverZ[i] = 1.0f/(frame[i][3] - frame[i][1]);
}
#ifdef BORDERPIXEL
*stream >> borderPixelFun;
#else
Scalar dummy;
*stream >> dummy;
#endif
BYTE textureFlags, mask = 1;
*stream >> textureFlags;
textureFlags &= 0xff >> (7 - Compost::TerrainTextureLogistic::GetResolution());
for(i=0;i<8;i++)
{
if(textureFlags | mask)
{
textures[i] = 1;
}
else
{
textures[i] = 0;
}
mask <<= 1;
}
Check_Object(MLRTexturePool::Instance);
MLRTexture *orgTexture = (*MLRTexturePool::Instance)[referenceState.GetTextureHandle()];
Check_Object(orgTexture);
const char *texName = orgTexture->GetTextureName();
char texRoot[1024], name[1024];
int len;
if((len = strlen(texName)) > 0)
{
Verify(len>8);
int d = texName[len-6] - '0';
strncpy(texRoot, texName, len-7);
texRoot[len-7] = '\0';
textures[d] = referenceState.GetTextureHandle();
MLRTexture *texture;
BYTE mask = 1;
for(i=0;i<8;i++)
{
if(textureFlags & mask)
{
sprintf(name, "%s_%1d_%02x%02x", texRoot, i, (7-tileX)/(1<<(maxAllDepth-i)), (7-tileZ)/(1<<(maxAllDepth-i)));
texture = (*MLRTexturePool::Instance)(name, 0);
if (!texture)
{
texture = MLRTexturePool::Instance->Add(name, 0);
}
Check_Object(texture);
texture->SetHint(orgTexture->GetHint());
textures[i] = texture->GetTextureHandle();
}
else
{
textures[i] = 0;
}
mask <<= 1;
}
i++;
for(;i<8;i++)
{
textures[i] = 0;
}
}
else
{
for(int i=0;i<8;i++)
{
textures[i] = 0;
}
}
Verify(textures[0]!=0);
currentDepth = -1;
SetCurrentDepth(0);
referenceState.SetLightingMode(MLRState::LightMapLightingMode);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLR_Terrain2::MLR_Terrain2(ClassData *class_data):
MLR_I_DeT_TMesh(class_data)
{
Check_Pointer(this);
tileX = 0;
tileZ = 0;
maxDepth = 0;
maxAllDepth = 0;
#ifdef BORDERPIXEL
borderPixelFun = 0.0f;
#endif
Scalar *fptr = &frame[0][0];
int i;
for(i=0;i<32;i++)
{
*fptr++ = 0.0f;
}
for(i=0;i<8;i++)
{
textures[i] = 0;
OneOverX[i] = 1.0f;
OneOverZ[i] = 1.0f;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLR_Terrain2::~MLR_Terrain2()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLR_Terrain2*
MLR_Terrain2::Make(
MemoryStream *stream,
int version
)
{
Check_Object(stream);
gos_PushCurrentHeap(PrimitiveHeap);
MLR_Terrain2 *terrain = new MLR_Terrain2(DefaultData, stream, version);
gos_PopCurrentHeap();
return terrain;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::Save(MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
#ifndef CALCULATEuvONtheFLY
dynamicUVs.SetLength(0);
#endif
texCoords.AssignData(NULL, 0);
MLR_I_DeT_TMesh::Save(stream);
CalculateUVs();
*stream << tileX << tileZ;
*stream << maxDepth << maxAllDepth;
Scalar *fptr = &frame[0][0];
for(int i=0;i<32;i++)
{
*stream << *fptr++;
}
#ifdef BORDERPIXEL
*stream << borderPixelFun;
#else
*stream << 0.0f;
#endif
BYTE textureFlags = 0;
// HACK
/*
Check_Object(MLRTexturePool::Instance);
MLRTexture *orgTexture = (*MLRTexturePool::Instance)[referenceState.GetTextureHandle()];
const char *texName = orgTexture->GetTextureName();
char texRoot[1024], name[1024];
int len;
if((len = strlen(texName)) > 0)
{
Verify(len>8);
int i, d = texName[len-6] - '0';
Verify(d==maxDepth);
strncpy(texRoot, texName, len-7);
texRoot[len-7] = '\0';
textures[d] = referenceState.GetTextureHandle();
MLRTexture *texture;
BYTE mask = 1;
for(i=0;i<d;i++)
{
sprintf(name, "%s_%1d_%02x%02x", texRoot, i, tileX/(1<<(maxAllDepth-i)), tileZ/(1<<(maxAllDepth-i)));
Verify((1<<i)>(tileX/(1<<(maxAllDepth-i))));
Verify((1<<i)>(tileZ/(1<<(maxAllDepth-i))));
// SPEW(("micgaert", "%s", name));
texture = (*MLRTexturePool::Instance)(name, 0);
if (texture)
{
textureFlags |= mask;
textures[i] = texture->GetTextureHandle();
}
mask <<= 1;
}
}
Verify(textures[0]!=0);
*/
textureFlags = 3;
// HACK
*stream << textureFlags;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::SetCurrentDepth(BYTE d)
{
if(d == currentDepth)
{
return;
}
else
{
Verify(d <= maxAllDepth);
BYTE dt;
dt = d<maxDepth ? d : maxDepth;
while(dt>0 && textures[dt]==0)
{
dt--;
}
currentDepth = dt;
}
CalculateUVs();
#if defined(LAB_ONLY) && defined(HUNT_FOR_THE_RED_TILE)
MLRTexture *tex = (*MLRTexturePool::Instance)[textures[currentDepth]];
GOSImage *image = tex->GetImage();
if(image->GetHandle())
{
const char *tex_name = gos_GetTextureName(image->GetHandle());
if(*tex_name!='l')
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "<2"));
}
else
{
int lev, tX, tZ;
sscanf(tex_name, "l:%d r:%d c:%d", &lev, &tZ, &tX);
if((tZ&0x7)!=(7-tileZ) || (tX&0x7)!=(7-tileX))
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "T2 l:%d r:%d c:%d - N %d %d", lev, tZ, tX, (7-tileZ), (7-tileX)));
}
else
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "T2 l:%d r:%d c:%d - Y", lev, tZ, tX));
}
}
}
else
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "?"));
}
#endif
referenceState.SetTextureHandle(textures[currentDepth]);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::SetLevelTexture(int lev, int handle)
{
Check_Object(this);
Verify(lev>=0 && lev<8);
textures[lev] = handle;
if(lev==currentDepth)
{
#if defined(LAB_ONLY) && defined(HUNT_FOR_THE_RED_TILE)
MLRTexture *tex = (*MLRTexturePool::Instance)[textures[currentDepth]];
GOSImage *image = tex->GetImage();
if(image->GetHandle())
{
const char *tex_name = gos_GetTextureName(image->GetHandle());
if(*tex_name!='l')
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "<2"));
}
else
{
int lev, tX, tZ;
sscanf(tex_name, "l:%d r:%d c:%d", &lev, &tZ, &tX);
if((tZ&0x7)!=(7-tileZ) || (tX&0x7)!=(7-tileX))
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "T2 l:%d r:%d c:%d - N %d %d", lev, tZ, tX, (7-tileZ), (7-tileX)));
}
else
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "T2 l:%d r:%d c:%d - Y", lev, tZ, tX));
}
}
}
else
{
SPEWALWAYS((HUNT_FOR_THE_RED_TILE, "?"));
}
#endif
referenceState.SetTextureHandle(textures[currentDepth]);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::CalculateUVs()
{
#ifdef CALCULATEuvONtheFLY
return;
#else
if(texCoords.GetLength() != coords.GetLength())
{
gos_PushCurrentHeap(PrimitiveHeap);
dynamicUVs.SetLength(coords.GetLength());
texCoords.AssignData(dynamicUVs.GetData(), dynamicUVs.GetLength());
gos_PopCurrentHeap();
}
Scalar maxX = frame[currentDepth][2];
Scalar maxZ = frame[currentDepth][3];
for(int i=0;i<texCoords.GetLength();i++)
{
#ifdef BORDERPIXEL
dynamicUVs[i][0] = borderPixelFun + (1.0f-2*borderPixelFun)*(maxX - coords[i].x)*OneOverX[currentDepth];
dynamicUVs[i][1] = borderPixelFun + (1.0f-2*borderPixelFun)*(maxZ - coords[i].z)*OneOverZ[currentDepth];
#else
dynamicUVs[i][0] = (maxX - coords[i].x)*OneOverX[currentDepth];
dynamicUVs[i][1] = (maxZ - coords[i].z)*OneOverZ[currentDepth];
#endif
Verify(texCoords[i][0]>=0.0 && texCoords[i][0]<=1.0);
Verify(texCoords[i][1]>=0.0 && texCoords[i][1]<=1.0);
}
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::CalculateUV(int i, Scalar &u, Scalar &v)
{
Scalar maxX = frame[currentDepth][2];
Scalar maxZ = frame[currentDepth][3];
#ifdef BORDERPIXEL
u = borderPixelFun + (1.0f-2*borderPixelFun)*(maxX - coords[i].x)*OneOverX[currentDepth];
v = borderPixelFun + (1.0f-2*borderPixelFun)*(maxZ - coords[i].z)*OneOverZ[currentDepth];
#else
u = (maxX - coords[i].x)*OneOverX[currentDepth];
v = (maxZ - coords[i].z)*OneOverZ[currentDepth];
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define I_SAY_YES_TO_DETAIL_TEXTURES
#define I_SAY_YES_TO_TERRAIN2
#undef I_SAY_YES_TO_DUAL_TEXTURES
#undef I_SAY_YES_TO_COLOR
#undef I_SAY_YES_TO_TERRAIN
#undef I_SAY_YES_TO_LIGHTING
#define CLASSNAME MLR_Terrain2
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This include contains follwing functions:
// void MLR_Terrain2::TransformNoClip(Matrix4D*, GOSVertexPool*);
// int MLR_Terrain2::Clip(MLRClippingState, GOSVertexPool*);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <MLR\MLRTriangleClipping.hpp>
#undef I_SAY_YES_TO_DETAIL_TEXTURES
#undef I_SAY_YES_TO_TERRAIN2
#undef CLASSNAME
extern bool
CheckForBigTriangles(DynamicArrayOf<Vector2DScalar> *lightMapUVs, int stride);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRPrimitiveBase*
MLR_Terrain2::StepOnMe(const Stuff::LinearMatrix4D& foot, Stuff::Scalar radius, MLRTexture *tex)
{
Point3D stepLoc;
stepLoc = foot;
UnitVector3D dir, rot;
foot.GetLocalForwardInWorld(&dir);
rot = dir;
rot.y = 0.0f;
rot.Normalize(rot);
Scalar oneOverRadius = 0.5f / radius;
int i, j, k, tooBig, nrOfPoints=0;
bool lm;
Scalar bigUV = MLRState::GetMaxUV();
//
//------------------------------------------------------------------------
// Look at each polygon in the mesh to see if it could accept the lightmap
//------------------------------------------------------------------------
//
for(i=0,j=0,k=0;i<numOfTriangles;i++,j += 3)
{
/*
if((*testList)[i] == 0)
continue;
Scalar f = dir*facePlanes[i].normal;
if(f>=0.0f)
continue;
*/
lm = false;
tooBig = 0;
for(k=0;k<3;k++)
{
Vector3D vec(coords[index[k+j]]);
vec -= stepLoc;
Scalar u, v;
u = vec.x * oneOverRadius;
v = vec.z * oneOverRadius;
(*lightMapUVs)[k][0] = u*rot.z - v*rot.x;
(*lightMapUVs)[k][1] = v*rot.z + u*rot.x;
if(
(*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
(*lightMapUVs)[k][1] >= -0.5f && (*lightMapUVs)[k][1] <= 0.5f
)
{
lm = true;
}
if(
bigUV > 0.0f &&
(
(*lightMapUVs)[k][0] < -bigUV || (*lightMapUVs)[k][0] > bigUV ||
(*lightMapUVs)[k][1] < -bigUV || (*lightMapUVs)[k][1] > bigUV
)
)
{
tooBig++;
}
}
if(
tooBig == 0
&& ((lm == true) || CheckForBigTriangles(lightMapUVs, 3) == true)
)
{
for(k=0;k<3;k++,nrOfPoints++)
{
SetClipCoord(coords[index[k+j]], nrOfPoints);
(*lightMapUVs)[k][0] += 0.5f;
(*lightMapUVs)[k][1] += 0.5f;
SetClipTexCoord((*lightMapUVs)[k], nrOfPoints);
}
}
}
if(nrOfPoints>0)
{
Verify(nrOfPoints%3==0);
gos_PushCurrentHeap(PrimitiveHeap);
MLR_I_TMesh *ret = new MLR_I_TMesh();
Register_Object(ret);
ret->FlashClipCoords(nrOfPoints);
ret->FlashClipTexCoords(nrOfPoints);
ret->TheIndexer(nrOfPoints);
ret->SetSubprimitiveLengths(NULL, nrOfPoints/3);
ret->FindFacePlanes();
gos_PopCurrentHeap();
MLRState state;
state = referenceState;
state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
state.SetPriority(1);
state.SetBackFaceOn();
state.SetZBufferCompareOn();
state.SetTextureCorrectionOn();
if(tex!=NULL)
{
state.SetTextureHandle(tex->GetTextureHandle());
}
else
{
state.SetTextureHandle(0);
}
state.SetTextureWrapMode(MLRState::TextureClamp);
ret->SetReferenceState(state);
return ret;
}
return NULL;
}
extern RGBAColor errorColor;
extern bool
CheckForBigTriangles(DynamicArrayOf<Vector2DScalar> *lightMapUVs, int stride);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLR_Terrain2::LightMapLighting(MLRLight *light)
{
MLRLightMap *lightMap = light->GetLightMap();
Check_Object(lightMap);
if( (!lightMap) || !gEnableLightMaps || lightMap->IsFull()==true)
{
return;
}
int i, j, k, len = numOfTriangles;
LinearMatrix4D matrix = LinearMatrix4D::Identity;
Point3D lightPosInShape, hitPoint;
UnitVector3D up, left, forward;
bool lm;
Scalar falloff = 1.0f, distance;
BYTE addedVertices = 0;
BYTE addedIndicies = 0;
int tooBig = 0;
Scalar bigUV = MLRState::GetMaxUV();
switch(light->GetLightType())
{
case MLRLight::PointLight:
{
light->GetInShapePosition(lightPosInShape);
Scalar n, f;
Cast_Object(MLRPointLight*, light)->GetFalloffDistance(n, f);
Scalar One_Over_Falloff = 0.5f/f;
for(i=0,j=0,k=0;i<len;i++,j += 3)
{
if((*testList)[i] == 0)
{
continue;
}
f = facePlanes[i].GetDistanceTo(lightPosInShape);
lm = false;
tooBig = 0;
for(k=0;k<3;k++)
{
Vector3D vec(coords[index[k+j]]);
vec-=lightPosInShape;
(*lightMapUVs)[k][0] = vec.x * One_Over_Falloff;
(*lightMapUVs)[k][1] = vec.z * One_Over_Falloff;
falloff = 1.0f;
if(
(*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
(*lightMapUVs)[k][1] >= -0.5f && (*lightMapUVs)[k][1] <= 0.5f
)
{
lm = true;
}
if(
bigUV > 0.0f &&
(
(*lightMapUVs)[k][0] < -bigUV || (*lightMapUVs)[k][0] > bigUV ||
(*lightMapUVs)[k][1] < -bigUV || (*lightMapUVs)[k][1] > bigUV
)
)
{
tooBig++;
}
}
if(tooBig==0 && (lm == true || CheckForBigTriangles(lightMapUVs, 3) == true))
{
#if 0
Vector3D vec(coords[index[j]]);
SPEW(("micgaert", "\nvertex1 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+1]];
SPEW(("micgaert", "vertex2 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+2]];
SPEW(("micgaert", "vertex3 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = facePlanes[i].normal;
SPEW(("micgaert", "normal = %f,%f,%f", vec.x, vec.y, vec.z));
SPEW(("micgaert", "forward = %f,%f,%f", forward.x, forward.y, forward.z));
SPEW(("micgaert", "distance = %f", f));
SPEW(("micgaert", "light = %f,%f,%f", lightPosInShape.x, lightPosInShape.y, lightPosInShape.z));
SPEW(("micgaert", "projection = %f,%f,%f", hitPoint.x, hitPoint.y, hitPoint.z));
#endif
Scalar sq_falloff
= falloff*falloff*light->GetIntensity();
RGBAColor color;
light->GetColor(color);
color.red *= sq_falloff;
color.green *= sq_falloff;
color.blue *= sq_falloff;
color.alpha = 1.0f;
for(k=0;k<3;k++)
{
(*lightMapUVs)[k][0] += 0.5f;
(*lightMapUVs)[k][1] += 0.5f;
if(
lightMap->AddIndex(addedIndicies++, addedVertices)==false ||
#if COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], GOSCopyColor(&color))==false
#else // COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], color)==false
#endif // COLOR_AS_DWORD
)
{
return;
}
if(addedIndicies >= 252 && addedVertices > 0)
{
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
addedIndicies = 0;
addedVertices = 0;
}
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
}
}
}
}
break;
case MLRLight::SpotLight:
{
int behindCount = 0, falloffCount = 0;
light->GetInShapePosition(matrix);
lightPosInShape = matrix;
Scalar tanSpeadAngle = Cast_Object(MLRSpotLight*, light)->GetTanSpreadAngle();
#ifndef TOP_DOWN_ONLY
matrix.GetLocalLeftInWorld(&left);
matrix.GetLocalUpInWorld(&up);
matrix.GetLocalForwardInWorld(&forward);
#else
forward = UnitVector3D(0.0f, -1.0f, 0.0);
up = UnitVector3D(1.0f, 0.0f, 0.0);
left = UnitVector3D(0.0f, 0.0f, 1.0);
#endif
Verify(Small_Enough(up*left));
for(i=0,j=0,k=0;i<len;i++,j += 3)
{
behindCount = 0;
falloffCount = 0;
if((*testList)[i] == 0)
{
continue;
}
lm = false;
if(!facePlanes[i].IsSeenBy(lightPosInShape))
{
continue;
}
#if SPEW_AWAY
Scalar maxX, maxZ;
Scalar minX, minZ;
minX = maxX = coords[index[j]].x;
minZ = maxZ = coords[index[j]].z;
if(minX>coords[index[j+1]].x)
{
minX = coords[index[j+1]].x;
}
if(minX>coords[index[j+2]].x)
{
minX = coords[index[j+2]].x;
}
if(minZ>coords[index[j+1]].z)
{
minZ = coords[index[j+1]].z;
}
if(minX>coords[index[j+2]].z)
{
minZ = coords[index[j+2]].z;
}
if(maxX<coords[index[j+1]].x)
{
maxX = coords[index[j+1]].x;
}
if(maxX<coords[index[j+2]].x)
{
maxX = coords[index[j+2]].x;
}
if(maxZ<coords[index[j+1]].z)
{
maxZ = coords[index[j+1]].z;
}
if(maxX<coords[index[j+2]].z)
{
maxZ = coords[index[j+2]].z;
}
if(lightPosInShape.x > minX && lightPosInShape.x < maxX && lightPosInShape.z > minZ && lightPosInShape.z < maxZ)
{
SPEW(("micgaert", "On Target !!"));
}
#endif
tooBig = 0;
for(k=0;k<3;k++)
{
Vector3D vec;
Scalar oneOver;
vec.Subtract(coords[index[k+j]], lightPosInShape);
#ifndef TOP_DOWN_ONLY
distance = (vec*forward);
#else
distance = -vec.y;
#endif
#if SPEW_AWAY
SPEW(("micgaert", "vertex%d = %f,%f,%f", k, coords[index[k+j]].x, coords[index[k+j]].y, coords[index[k+j]].z));
SPEW(("micgaert", "distance = %f", distance));
#endif
if(distance > SMALL)
{
if(Cast_Object(MLRInfiniteLightWithFalloff*, light)->GetFalloff(distance, falloff) == false)
{
falloffCount++;
}
(*lightMapSqFalloffs)[k] = falloff*falloff*light->GetIntensity();
oneOver
#if 0
= 1.0f/(2.0f*distance*tanSpeadAngle);
#else
= OneOverApproximate(2.0f*distance*tanSpeadAngle);
#endif
}
else
{
behindCount++;
oneOver = 1.0f/50.0f;
(*lightMapSqFalloffs)[k] = 0.0f;
#if SPEW_AWAY
SPEW(("micgaert", "Behind"));
#endif
}
#ifndef TOP_DOWN_ONLY
(*lightMapUVs)[k][0] = (left*vec) * oneOver;
(*lightMapUVs)[k][1] = -(up*vec) * oneOver;
#else
(*lightMapUVs)[k][0] = vec.x * oneOver;
(*lightMapUVs)[k][1] = -vec.z * oneOver;
#endif
#if SPEW_AWAY
SPEW(("micgaert", "uv%d = %f,%f", k, (*lightMapUVs)[k][0], (*lightMapUVs)[k][1]));
#endif
if(
(*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
(*lightMapUVs)[k][1] >= -0.5f && (*lightMapUVs)[k][1] <= 0.5f
)
{
lm = true;
}
if(
bigUV > 0.0f &&
(
(*lightMapUVs)[k][0] < -bigUV || (*lightMapUVs)[k][0] > bigUV ||
(*lightMapUVs)[k][1] < -bigUV || (*lightMapUVs)[k][1] > bigUV
)
)
{
tooBig++;
}
}
if(
tooBig == 0
&& behindCount < 3
&& falloffCount < 3
&& ((lm == true) || CheckForBigTriangles(lightMapUVs, 3) == true)
)
{
for(k=0;k<3;k++)
{
RGBAColor color;
color.red = (*lightMapSqFalloffs)[k];
color.green = (*lightMapSqFalloffs)[k];
color.blue = (*lightMapSqFalloffs)[k];
color.alpha = 1.0f;
(*lightMapUVs)[k][0] += 0.5f;
(*lightMapUVs)[k][1] += 0.5f;
if(
lightMap->AddIndex(addedIndicies++, addedVertices)==false ||
#if COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], GOSCopyColor(&color))==false
#else // COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], color)==false
#endif // COLOR_AS_DWORD
)
{
return;
}
if(addedIndicies >= 252 && addedVertices > 0)
{
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
addedIndicies = 0;
addedVertices = 0;
}
}
#if SPEW_AWAY
SPEW(("micgaert", "See the Light !"));
#endif
}
#if SPEW_AWAY
Vector3D vec = facePlanes[i].normal;
SPEW(("micgaert", "normal = %f,%f,%f", vec.x, vec.y, vec.z));
SPEW(("micgaert", "forward = %f,%f,%f", forward.x, forward.y, forward.z));
SPEW(("micgaert", "left = %f,%f,%f", left.x, left.y, left.z));
SPEW(("micgaert", "up = %f,%f,%f", up.x, up.y, up.z));
SPEW(("micgaert", "light = %f,%f,%f\n", lightPosInShape.x, lightPosInShape.y, lightPosInShape.z));
#endif
}
}
break;
#define TOP_DOWN_ONLY
case MLRLight::ProjectLight:
{
MLRProjectLight *pLight = Cast_Object(MLRProjectLight*, light);
light->GetInShapePosition(lightPosInShape);
Scalar n, f;
pLight->GetFalloffDistance(n, f);
Scalar ray_distance = light->GetIntensity();
UnitVector3D dir, rot;
light->GetInShapeDirection(dir);
lightPosInShape.AddScaled(lightPosInShape, dir, ray_distance);
rot = dir;
rot.y = 0.0f;
rot.Normalize(rot);
if(ray_distance <= SMALL)
{
break;
}
// Scalar One_Over_Falloff = 1.0f/(3.0f*f);
Scalar oneOverRadius = 0.5f / (pLight->GetTanSpreadAngle() * ray_distance);
if(pLight->GetFalloff(ray_distance, falloff))
{
for(i=0,j=0,k=0;i<len;i++,j += 3)
{
if((*testList)[i] == 0)
{
continue;
}
/*
f = dir*facePlanes[i].normal;
if(f>0.0f)
{
continue;
}
*/
lm = false;
tooBig = 0;
for(k=0;k<3;k++)
{
Vector3D vec(coords[index[k+j]]);
vec-=lightPosInShape;
Scalar u, v;
u = vec.x * oneOverRadius;
v = vec.z * oneOverRadius;
(*lightMapUVs)[k][0] = u*rot.z - v*rot.x;
(*lightMapUVs)[k][1] = v*rot.z + u*rot.x;
if(
(*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
(*lightMapUVs)[k][1] >= -0.25f && (*lightMapUVs)[k][1] <= 0.75f
)
{
lm = true;
}
if(
bigUV > 0.0f &&
(
(*lightMapUVs)[k][0] < -bigUV || (*lightMapUVs)[k][0] > bigUV ||
(*lightMapUVs)[k][1] < -bigUV || (*lightMapUVs)[k][1] > bigUV
)
)
{
tooBig++;
}
}
if(tooBig==0 && (lm == true || CheckForBigTriangles(lightMapUVs, 3) == true))
{
#if 0
Vector3D vec(coords[index[j]]);
SPEW(("micgaert", "\nvertex1 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+1]];
SPEW(("micgaert", "vertex2 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+2]];
SPEW(("micgaert", "vertex3 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = facePlanes[i].normal;
SPEW(("micgaert", "normal = %f,%f,%f", vec.x, vec.y, vec.z));
SPEW(("micgaert", "forward = %f,%f,%f", forward.x, forward.y, forward.z));
SPEW(("micgaert", "distance = %f", f));
SPEW(("micgaert", "light = %f,%f,%f", lightPosInShape.x, lightPosInShape.y, lightPosInShape.z));
SPEW(("micgaert", "projection = %f,%f,%f", hitPoint.x, hitPoint.y, hitPoint.z));
#endif
Scalar sq_falloff
= falloff*falloff; //*light->GetIntensity();
RGBAColor color;
light->GetColor(color);
color.red *= sq_falloff;
color.green *= sq_falloff;
color.blue *= sq_falloff;
color.alpha = 1.0f;
for(k=0;k<3;k++)
{
(*lightMapUVs)[k][0] += 0.5f;
(*lightMapUVs)[k][1] += 0.25f;
if(
lightMap->AddIndex(addedIndicies++, addedVertices)==false ||
#if COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], GOSCopyColor(&color))==false
#else // COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], color)==false
#endif // COLOR_AS_DWORD
)
{
return;
}
if(addedIndicies >= 252 && addedVertices > 0)
{
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
addedIndicies = 0;
addedVertices = 0;
}
}
}
}
}
}
break;
case MLRLight::ShadowLight:
{
MLRShadowLight *shadow = Cast_Object(MLRShadowLight*, light);
light->GetInShapePosition(lightPosInShape);
UnitVector3D dir, rot;
light->GetInShapeDirection(dir);
rot = dir;
rot.y = 0.0f;
rot.Normalize(rot);
//
//--------------------------------------------------
// If the light is at or below zero to us, ignore it
//--------------------------------------------------
//
if(lightPosInShape.y <= SMALL)
{
break;
}
Scalar oneOverRadius = 0.5f / shadow->GetFalloffFar();
//
//------------------------------------------------------------------------
// Look at each polygon in the mesh to see if it could accept the lightmap
//------------------------------------------------------------------------
//
for(i=0,j=0,k=0;i<len;i++,j += 3)
{
if((*testList)[i] == 0)
continue;
Scalar f = dir*facePlanes[i].normal;
if(f>=0.0f)
continue;
lm = false;
tooBig = 0;
for(k=0;k<3;k++)
{
Vector3D vec(coords[index[k+j]]);
vec -= lightPosInShape;
Scalar u, v;
u = vec.x * oneOverRadius;
v = vec.z * oneOverRadius;
(*lightMapUVs)[k][0] = u*rot.z - v*rot.x;
(*lightMapUVs)[k][1] = v*rot.z + u*rot.x;
if(
(*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
(*lightMapUVs)[k][1] >= -0.5f && (*lightMapUVs)[k][1] <= 0.5f
)
{
lm = true;
}
if(
bigUV > 0.0f &&
(
(*lightMapUVs)[k][0] < -bigUV || (*lightMapUVs)[k][0] > bigUV ||
(*lightMapUVs)[k][1] < -bigUV || (*lightMapUVs)[k][1] > bigUV
)
)
{
tooBig++;
}
}
if(tooBig==0 && (lm == true || CheckForBigTriangles(lightMapUVs, 3) == true))
{
#if 0
Vector3D vec(coords[index[j]]);
SPEW(("micgaert", "\nvertex1 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+1]];
SPEW(("micgaert", "vertex2 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = coords[index[j+2]];
SPEW(("micgaert", "vertex3 = %f,%f,%f", vec.x, vec.y, vec.z));
vec = facePlanes[i].normal;
SPEW(("micgaert", "normal = %f,%f,%f", vec.x, vec.y, vec.z));
SPEW(("micgaert", "forward = %f,%f,%f", forward.x, forward.y, forward.z));
SPEW(("micgaert", "distance = %f", f));
SPEW(("micgaert", "light = %f,%f,%f", lightPosInShape.x, lightPosInShape.y, lightPosInShape.z));
SPEW(("micgaert", "projection = %f,%f,%f", hitPoint.x, hitPoint.y, hitPoint.z));
#endif
RGBAColor color;
color = RGBAColor::White;
color.alpha = shadow->GetIntensity();
for(k=0;k<3;k++)
{
(*lightMapUVs)[k][0] += 0.5f;
(*lightMapUVs)[k][1] += 0.5f;
if(
lightMap->AddIndex(addedIndicies++, addedVertices)==false ||
#if COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], GOSCopyColor(&color))==false
#else // COLOR_AS_DWORD
lightMap->AddVertex(addedVertices++, coords[index[k+j]], (*lightMapUVs)[k], color)==false
#endif // COLOR_AS_DWORD
)
{
return;
}
if(addedIndicies >= 252 && addedVertices > 0)
{
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
addedIndicies = 0;
addedVertices = 0;
}
}
}
}
}
break;
default:
STOP(("MLR_Terrain2::LightMapLighting: What you want me to do ?"));
break;
}
if(addedIndicies && addedVertices)
{
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
}
}