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.
1127 lines
27 KiB
C++
1127 lines
27 KiB
C++
#include "MLRHeaders.hpp"
|
|
#include <MLR\GOSVertex3UV.hpp>
|
|
|
|
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
|
|
BitTrace *MLR_BumpyWater_Clip;
|
|
#endif
|
|
|
|
extern DWORD gEnableLightMaps;
|
|
|
|
//#############################################################################
|
|
//############################## Bumpmaped watersurface ######################
|
|
//#############################################################################
|
|
|
|
DynamicArrayOf<Vector2DScalar>
|
|
*MLR_BumpyWater::texCoords2, *MLR_BumpyWater::texCoords3;
|
|
DynamicArrayOf<Vector2DScalar>
|
|
*MLR_BumpyWater::clipExtraTexCoords2, *MLR_BumpyWater::clipExtraTexCoords3;
|
|
|
|
Stuff::UnitVector3D
|
|
MLR_BumpyWater::sunLight;
|
|
|
|
|
|
MLR_BumpyWater::ClassData*
|
|
MLR_BumpyWater::DefaultData = NULL;
|
|
|
|
extern DynamicArrayOf<Vector2DScalar> *lightMapUVs;
|
|
extern DynamicArrayOf<Scalar> *lightMapSqFalloffs;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
Verify(gos_GetCurrentHeap() == StaticHeap);
|
|
DefaultData =
|
|
new ClassData(
|
|
MLR_BumpyWaterClassID,
|
|
"MidLevelRenderer::MLR_BumpyWater",
|
|
MLR_I_C_TMesh::DefaultData,
|
|
(MLRPrimitiveBase::Factory)&Make
|
|
);
|
|
Register_Object(DefaultData);
|
|
|
|
texCoords2 = new DynamicArrayOf<Vector2DScalar> (Limits::Max_Number_Vertices_Per_Mesh);
|
|
Register_Object(texCoords2);
|
|
|
|
texCoords3 = new DynamicArrayOf<Vector2DScalar> (Limits::Max_Number_Vertices_Per_Mesh);
|
|
Register_Object(texCoords3);
|
|
|
|
clipExtraTexCoords2 = new DynamicArrayOf<Vector2DScalar> (2*Limits::Max_Number_Vertices_Per_Mesh);
|
|
Register_Object(clipExtraTexCoords2);
|
|
|
|
clipExtraTexCoords3 = new DynamicArrayOf<Vector2DScalar> (2*Limits::Max_Number_Vertices_Per_Mesh);
|
|
Register_Object(clipExtraTexCoords3);
|
|
|
|
Vector3D sl(1.0f, -1.0f, -1.0f);
|
|
|
|
sl.Normalize(sl);
|
|
|
|
sunLight = sl;
|
|
|
|
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
|
|
MLR_BumpyWater_Clip = new BitTrace("MLR_BumpyWater_Clip");
|
|
Register_Object(MLR_BumpyWater_Clip);
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
|
|
Unregister_Object(texCoords2);
|
|
delete texCoords2;
|
|
|
|
Unregister_Object(texCoords3);
|
|
delete texCoords3;
|
|
|
|
Unregister_Object(clipExtraTexCoords2);
|
|
delete clipExtraTexCoords2;
|
|
|
|
Unregister_Object(clipExtraTexCoords3);
|
|
delete clipExtraTexCoords3;
|
|
|
|
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
|
|
Unregister_Object(MLR_BumpyWater_Clip);
|
|
delete MLR_BumpyWater_Clip;
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLR_BumpyWater::MLR_BumpyWater(
|
|
ClassData *class_data,
|
|
MemoryStream *stream,
|
|
int version
|
|
):
|
|
MLR_I_C_TMesh(class_data, stream, version)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Pointer(stream);
|
|
|
|
referenceState.SetLightingMode(MLRState::LightMapLightingMode);
|
|
|
|
facePlanes.SetLength(0);
|
|
|
|
if (!dataStore)
|
|
dataStore = new DataStorage;
|
|
Check_Pointer(dataStore);
|
|
|
|
if (!colors.GetLength())
|
|
{
|
|
#if COLOR_AS_DWORD
|
|
dataStore->colors.AssignValue(0xFFFFFFFF, coords.GetLength());
|
|
#else
|
|
dataStore->colors.AssignValue(RGBAColor::White, coords.GetLength());
|
|
#endif
|
|
colors.AssignData(dataStore->colors.GetData(), dataStore->colors.GetLength());
|
|
}
|
|
Verify(colors.GetData() == dataStore->colors.GetData());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLR_BumpyWater::MLR_BumpyWater(ClassData *class_data):
|
|
MLR_I_C_TMesh(class_data)
|
|
{
|
|
Check_Pointer(this);
|
|
|
|
facePlanes.SetLength(0);
|
|
|
|
if (!dataStore)
|
|
dataStore = new DataStorage;
|
|
Check_Pointer(dataStore);
|
|
|
|
if (!colors.GetLength())
|
|
{
|
|
#if COLOR_AS_DWORD
|
|
dataStore->colors.AssignValue(0xFFFFFFFF, coords.GetLength());
|
|
#else
|
|
dataStore->colors.AssignValue(RGBAColor::White, coords.GetLength());
|
|
#endif
|
|
colors.AssignData(dataStore->colors.GetData(), dataStore->colors.GetLength());
|
|
}
|
|
Verify(colors.GetData() == dataStore->colors.GetData());
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLR_BumpyWater::~MLR_BumpyWater()
|
|
{
|
|
Check_Object(this);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLR_BumpyWater*
|
|
MLR_BumpyWater::Make(
|
|
MemoryStream *stream,
|
|
int version
|
|
)
|
|
{
|
|
Check_Object(stream);
|
|
|
|
gos_PushCurrentHeap(PrimitiveHeap);
|
|
MLR_BumpyWater *water = new MLR_BumpyWater(DefaultData, stream, version);
|
|
gos_PopCurrentHeap();
|
|
|
|
return water;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::Save(MemoryStream *stream)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(stream);
|
|
|
|
MLR_I_C_TMesh::Save(stream);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::Copy(MLR_Water *tMesh)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(tMesh);
|
|
|
|
int len;
|
|
const BYTE *_index;
|
|
const Point3D *_coords;
|
|
const Vector2DScalar *_texCoords;
|
|
const ColorType *_colors;
|
|
|
|
if(tMesh->dataStore!=NULL && tMesh->dataStore->coords.GetLength()>0)
|
|
{
|
|
tMesh->GetCoordData(&_coords, &len);
|
|
dataStore->coords.SetLength(len);
|
|
Mem_Copy(dataStore->coords.GetData(), _coords, len*sizeof(Point3D), dataStore->coords.GetSize());
|
|
SetCoordData(dataStore->coords.GetData(), len);
|
|
}
|
|
else
|
|
{
|
|
tMesh->GetCoordData(&_coords, &len);
|
|
SetCoordData(_coords, len);
|
|
}
|
|
|
|
if(tMesh->dataStore!=NULL && tMesh->dataStore->index.GetLength()>0)
|
|
{
|
|
tMesh->GetIndexData(&_index, &len);
|
|
dataStore->index.SetLength(len);
|
|
Mem_Copy(dataStore->index.GetData(), _index, len*sizeof(BYTE), dataStore->index.GetSize());
|
|
SetIndexData(dataStore->index.GetData(), len);
|
|
}
|
|
else
|
|
{
|
|
tMesh->GetIndexData(&_index, &len);
|
|
SetIndexData(_index, len);
|
|
}
|
|
|
|
SetSubprimitiveLengths(NULL, tMesh->GetNumPrimitives());
|
|
|
|
if(tMesh->dataStore!=NULL && tMesh->dataStore->texCoords.GetLength()>0)
|
|
{
|
|
tMesh->GetTexCoordData(&_texCoords, &len);
|
|
dataStore->texCoords.SetLength(len);
|
|
Mem_Copy(dataStore->texCoords.GetData(), _texCoords, len*sizeof(Vector2DScalar), dataStore->texCoords.GetSize());
|
|
SetTexCoordData(dataStore->texCoords.GetData(), len);
|
|
}
|
|
else
|
|
{
|
|
tMesh->GetTexCoordData(&_texCoords, &len);
|
|
SetTexCoordData(_texCoords, len);
|
|
}
|
|
|
|
texCoords2->SetLength(len);
|
|
texCoords3->SetLength(len);
|
|
|
|
referenceState = tMesh->GetReferenceState();
|
|
referenceState.SetBumpMapOn();
|
|
|
|
visibleIndexedVerticesKey = false;
|
|
|
|
if(tMesh->dataStore!=NULL && tMesh->dataStore->colors.GetLength()>0)
|
|
{
|
|
tMesh->GetColorData(&_colors, &len);
|
|
dataStore->colors.SetLength(len);
|
|
Mem_Copy(dataStore->colors.GetData(), _colors, len*sizeof(ColorType), dataStore->colors.GetSize());
|
|
SetColorData(dataStore->colors.GetData(), len);
|
|
}
|
|
else
|
|
{
|
|
tMesh->GetColorData(&_colors, &len);
|
|
SetColorData(_colors, len);
|
|
}
|
|
|
|
facePlanes.SetLength(0);
|
|
}
|
|
|
|
extern int tCounter;
|
|
|
|
|
|
inline DWORD ConvertVectorToColor(UnitVector3D &vect)
|
|
{
|
|
int r,g,b;
|
|
|
|
r=(int)(vect.x*0x7f+0x80); // x
|
|
g=(int)(vect.z*0x7f+0x80); // z
|
|
b=(int)(vect.y*0x7f+0x80); // y
|
|
Verify(r<0x100 && g<0x100 && b<0x100);
|
|
|
|
|
|
|
|
return ((0xff&0xff)<<24)|
|
|
((r&0xff)<<16)|
|
|
((g&0xff)<<8)|
|
|
((b&0xff)<<0);
|
|
/*
|
|
return 0xff808080 +
|
|
((0x7f & (int)(vect.x*127))<<0)+
|
|
((0x7f & (int)(vect.z*127))<<8);
|
|
((0x7f & (int)(vect.y*127))<<16);
|
|
|
|
|
|
return 0xffffffff;
|
|
*/
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
MLR_BumpyWater::FindBackFace(const Point3D& u, const Normal3D& n)
|
|
{
|
|
Check_Object(this);
|
|
|
|
Start_Timer(Find_Backface_Time);
|
|
|
|
BYTE *iPtr;
|
|
|
|
Vector3D v;
|
|
UnitVector3D vn, hn;
|
|
|
|
if(numOfTriangles <= 0)
|
|
{
|
|
visible = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
ColorType *cols = dataStore->colors.GetData();
|
|
int i, len = dataStore->colors.GetLength();
|
|
|
|
for(i=0;i<len;i++)
|
|
{
|
|
v.Subtract(coords[i], u);
|
|
|
|
vn.Normalize(v);
|
|
|
|
hn.x = -(vn.x + sunLight.x)*0.5f;
|
|
hn.y = -(vn.y + sunLight.y)*0.5f;
|
|
hn.z = -(vn.z + sunLight.z)*0.5f;
|
|
|
|
// Scalar intens = vn * sunLight;
|
|
|
|
#if COLOR_AS_DWORD
|
|
cols[i] = ConvertVectorToColor(hn);
|
|
|
|
#else
|
|
#endif
|
|
}
|
|
|
|
len = texCoords.GetLength();
|
|
|
|
Scalar r = 1.0f;
|
|
|
|
if(MLRState::GetCanBumpEnvMap() != 0)
|
|
{
|
|
r = bumpRatio;
|
|
}
|
|
else if(MLRState::GetCanBumpDotMap())
|
|
{
|
|
r = bumpNormRatio;
|
|
}
|
|
|
|
for(i=0;i<len;i++)
|
|
{
|
|
(*texCoords2)[i][0] = r*texCoords[i][0];
|
|
(*texCoords2)[i][1] = r*texCoords[i][1];
|
|
|
|
(*texCoords3)[i][0] = envRatio*texCoords[i][0];
|
|
(*texCoords3)[i][1] = envRatio*texCoords[i][1];
|
|
}
|
|
|
|
#if 0
|
|
MLRTexture *tex = (*MLRTexturePool::Instance)[referenceState.GetTextureHandle()];
|
|
tex->SetAnimateTexture(true);
|
|
|
|
AffineMatrix4D &textureMatrix = tex->GetTextureMatrix();
|
|
textureMatrix(3, 0) = tCounter * 0.0004f;
|
|
textureMatrix(3, 1) = tCounter * 0.0005f;
|
|
|
|
tex = (*MLRTexturePool::Instance)[textureNorm];
|
|
tex->SetAnimateTexture(true);
|
|
|
|
AffineMatrix4D &textureMatrix2 = tex->GetTextureMatrix();
|
|
textureMatrix2(3, 0) = -tCounter * 0.0002f;
|
|
textureMatrix2(3, 1) = tCounter * 0.0004f;
|
|
#endif
|
|
|
|
iPtr = testList->GetData();
|
|
memset(iPtr, 1, numOfTriangles);
|
|
|
|
visible = 1;
|
|
|
|
FindVisibleVertices();
|
|
|
|
passes = 1;
|
|
|
|
Stop_Timer(Find_Backface_Time);
|
|
|
|
return 1;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
/*
|
|
int
|
|
MLR_BumpyWater::GetNumPasses()
|
|
{
|
|
Check_Object(this);
|
|
|
|
return 2;
|
|
}
|
|
*/
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
#define I_SAY_YES_TO_COLOR
|
|
#define I_SAY_YES_TO_BUMP_TEXTURE
|
|
|
|
#undef I_SAY_YES_TO_DETAIL_TEXTURES
|
|
#undef I_SAY_YES_TO_TERRAIN2
|
|
#undef I_SAY_YES_TO_DUAL_TEXTURES
|
|
#undef I_SAY_YES_TO_TERRAIN
|
|
#undef I_SAY_YES_TO_LIGHTING
|
|
#undef I_SAY_YES_TO_WATER
|
|
#undef CALCULATEuvONtheFLY
|
|
|
|
#define CLASSNAME MLR_BumpyWater
|
|
#define CLASSNAMENOCOLOR MLR_I_TMesh
|
|
|
|
#if defined(TRACE_ENABLED) && defined(MLR_TRACE)
|
|
#define SET_MLR_TMESH_CLIP() MLR_BumpyWater_Clip->Set()
|
|
#define CLEAR_MLR_TMESH_CLIP() MLR_BumpyWater_Clip->Clear()
|
|
#else
|
|
#define SET_MLR_TMESH_CLIP()
|
|
#define CLEAR_MLR_TMESH_CLIP()
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// This include contains follwing functions:
|
|
// void MLR_BumpyWater::TransformNoClip(Matrix4D*, GOSVertexPool*);
|
|
// int MLR_BumpyWater::Clip(MLRClippingState, GOSVertexPool*);
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
#include <MLR\MLRTriangleClipping.hpp>
|
|
|
|
#undef I_SAY_YES_TO_COLOR
|
|
#undef I_SAY_YES_TO_BUMP_TEXTURE
|
|
|
|
#undef CLASSNAME
|
|
#undef CLASSNAMENOCOLOR
|
|
|
|
extern RGBAColor errorColor;
|
|
extern bool
|
|
CheckForBigTriangles(DynamicArrayOf<Vector2DScalar> *lightMapUVs, int stride);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLR_BumpyWater::LightMapLighting(MLRLight *light)
|
|
{
|
|
MLRLightMap *lightMap = light->GetLightMap();
|
|
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;
|
|
|
|
Scalar waterHeight = coords[0].z;
|
|
|
|
BYTE addedVertices = 0;
|
|
BYTE addedIndicies = 0;
|
|
|
|
int tooBig = 0;
|
|
Scalar bigUV = MLRState::GetMaxUV();
|
|
|
|
switch(light->GetLightType())
|
|
{
|
|
case MLRLight::PointLight:
|
|
{
|
|
Check_Object(lightMap);
|
|
|
|
light->GetInShapePosition(lightPosInShape);
|
|
|
|
Scalar n, f;
|
|
Cast_Object(MLRPointLight*, light)->GetFalloffDistance(n, f);
|
|
|
|
Scalar One_Over_Falloff = 1.0f/f;
|
|
|
|
for(i=0,j=0,k=0;i<len;i++,j += 3)
|
|
{
|
|
if((*testList)[i] == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
f = lightPosInShape.z - waterHeight;
|
|
|
|
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 = Vector3D(0.0f, 1.0f, 0.0f);
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MLRLight::SpotLight:
|
|
{
|
|
int behindCount = 0, falloffCount = 0;
|
|
|
|
Check_Object(lightMap);
|
|
|
|
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 1
|
|
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 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
|
|
#else
|
|
if(tooBig != 0)
|
|
{
|
|
lightMap->SetPolygonMarker(1);
|
|
lightMap->AddUShort(3);
|
|
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddCoord(coords[index[k+j]]);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddColor(RGBAColor(0.0f, 0.0f, 0.5f, 1.0f));
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddUVs(0.5f, 0.5f);
|
|
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
|
|
}
|
|
}
|
|
else if(behindCount != 0)
|
|
{
|
|
lightMap->SetPolygonMarker(1);
|
|
lightMap->AddUShort(3);
|
|
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddCoord(coords[index[k+j]]);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddColor(RGBAColor(0.5f, 0.0f, 0.0f, 1.0f));
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddUVs(0.5f, 0.5f);
|
|
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
|
|
}
|
|
}
|
|
else if(behindCount == 0 && (lm == true || CheckForBigTriangles(&lightMapUVs, 3) == true) )
|
|
{
|
|
lightMap->SetPolygonMarker(1);
|
|
lightMap->AddUShort(3);
|
|
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddCoord(coords[index[k+j]]);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddColor(lightMapSqFalloffs[k], lightMapSqFalloffs[k], lightMapSqFalloffs[k], 1.0f);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddUVs(lightMapUVs[k][0]+0.5f, lightMapUVs[k][1]+0.5f);
|
|
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
|
|
}
|
|
|
|
}
|
|
else if(CheckForBigTriangles(&lightMapUVs, 3) == false)
|
|
{
|
|
lightMap->SetPolygonMarker(1);
|
|
lightMap->AddUShort(3);
|
|
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddCoord(coords[index[k+j]]);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddColor(errorColor);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddUVs(0.5f, 0.5f);
|
|
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
case MLRLight::ProjectLight:
|
|
#if 1
|
|
{
|
|
Check_Object(lightMap);
|
|
|
|
MLRProjectLight *pLight = Cast_Object(MLRProjectLight*, light);
|
|
|
|
light->GetInShapePosition(lightPosInShape);
|
|
|
|
Scalar n, f;
|
|
pLight->GetFalloffDistance(n, f);
|
|
|
|
UnitVector3D dir, rot;
|
|
light->GetInShapeDirection(dir);
|
|
rot = dir;
|
|
rot.y = 0.0f;
|
|
rot.Normalize(rot);
|
|
|
|
// Scalar One_Over_Falloff = 1.0f/(3.0f*f);
|
|
if(lightPosInShape.y <= SMALL)
|
|
{
|
|
break;
|
|
}
|
|
Scalar oneOverRadius = 1.0f / (pLight->GetTanSpreadAngle() * lightPosInShape.y);
|
|
|
|
if(pLight->GetFalloff(lightPosInShape.y, falloff))
|
|
{
|
|
for(i=0,j=0,k=0;i<len;i++,j += 3)
|
|
{
|
|
if((*testList)[i] == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(dir.y>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
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
|
|
{
|
|
int behindCount = 0, falloffCount = 0;
|
|
|
|
light->GetInShapePosition(lightPosInShape);
|
|
|
|
MLRProjectLight *pLight = Cast_Object(MLRProjectLight*, light);
|
|
static Point3D texUV[Limits::Max_Number_Vertices_Per_Mesh];
|
|
|
|
Matrix4D m4;
|
|
m4.Multiply(pLight->GetInversMatrix(), pLight->GetProjectMatrix());
|
|
|
|
Vector4D v4;
|
|
|
|
for(i=0;i<coords.GetLength();i++)
|
|
{
|
|
v4.Multiply(coords[i], m4);
|
|
Scalar rhw = 1.0f/v4.w;
|
|
|
|
texUV[i].x = v4.x*rhw;
|
|
texUV[i].y = v4.y*rhw;
|
|
texUV[i].z = v4.z*rhw;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int tooBig = 0;
|
|
for(k=0;k<3;k++)
|
|
{
|
|
(*lightMapUVs)[k][0] = texUV[index[k+j]][0];
|
|
(*lightMapUVs)[k][1] = texUV[index[k+j]][1];
|
|
|
|
/* if(
|
|
// (*lightMapUVs)[k][0] >= -0.5f && (*lightMapUVs)[k][0] <= 0.5f &&
|
|
// (*lightMapUVs)[k][1] >= -0.5f && (*lightMapUVs)[k][1] <= 0.5f
|
|
// )
|
|
{
|
|
lm = true;
|
|
}
|
|
if(
|
|
(*lightMapUVs)[k][0] < -1.5f || (*lightMapUVs)[k][0] > 1.5f ||
|
|
(*lightMapUVs)[k][1] < -1.5f && (*lightMapUVs)[k][1] > 1.5f
|
|
|
|
)
|
|
{
|
|
tooBig++;
|
|
}
|
|
*/
|
|
lm = true;
|
|
}
|
|
|
|
if(
|
|
tooBig == 0 &&
|
|
behindCount == 0 &&
|
|
falloffCount < 3 &&
|
|
(lm == true || CheckForBigTriangles(lightMapUVs, 3) == true)
|
|
)
|
|
{
|
|
lightMap->SetPolygonMarker(1);
|
|
lightMap->AddUShort(3);
|
|
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddCoord(coords[index[k+j]]);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
// lightMap->AddColor((*lightMapSqFalloffs)[k], (*lightMapSqFalloffs)[k], (*lightMapSqFalloffs)[k], 1.0f);
|
|
lightMap->AddColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
for(k=0;k<3;k++)
|
|
{
|
|
lightMap->AddUVs((*lightMapUVs)[k][0], (*lightMapUVs)[k][1]);
|
|
// lightMap->AddUVs((*lightMapUVs)[k][0]+0.5f, (*lightMapUVs)[k][1]+0.5f);
|
|
// DEBUG_STREAM << k << " " << lightMapUVs[k][0] << " " << lightMapUVs[k][0] << "\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
case MLRLight::ShadowLight:
|
|
break;
|
|
default:
|
|
STOP(("MLR_BumpyWater::LightMapLighting: What you want me to do ?"));
|
|
break;
|
|
}
|
|
|
|
if(addedIndicies && addedVertices)
|
|
{
|
|
lightMap->AddMesh(referenceState.GetPriority()+1, addedVertices, addedIndicies);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
MLR_BumpyWater::FindFacePlanes()
|
|
{
|
|
Check_Object(this);
|
|
|
|
int i, j, numPrimitives = GetNumPrimitives();
|
|
Vector3D v;
|
|
|
|
Verify(index.GetLength() > 0);
|
|
|
|
for(i=0,j=0;i<numPrimitives;++i,j+=3)
|
|
{
|
|
facePlanes[i].BuildPlane(
|
|
coords[index[j]],
|
|
coords[index[j+1]],
|
|
coords[index[j+2]]
|
|
);
|
|
|
|
;
|
|
}
|
|
}
|
|
|