mirror of
https://github.com/tribes2/engine.git
synced 2026-03-24 22:59:13 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
123
interior/floorPlanRes.cc
Normal file
123
interior/floorPlanRes.cc
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "interior/FloorPlanRes.h"
|
||||
#include "Math/mathIO.h"
|
||||
|
||||
const U32 FloorPlanResource::smFileVersion = 0;
|
||||
|
||||
FloorPlanResource::FloorPlanResource()
|
||||
{
|
||||
}
|
||||
FloorPlanResource::~FloorPlanResource()
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Define these so we can just write two vector IO functions
|
||||
|
||||
static bool mathRead(Stream & S, FloorPlanResource::Area * a){
|
||||
return S.read(&a->pointCount) && S.read(&a->pointStart) && S.read(&a->plane);
|
||||
}
|
||||
static bool mathWrite(Stream & S, const FloorPlanResource::Area & a){
|
||||
return S.write(a.pointCount) && S.write(a.pointStart) && S.write(a.plane);
|
||||
}
|
||||
inline bool mathRead(Stream & S, S32 * s) { return S.read(s); }
|
||||
inline bool mathWrite(Stream & S, S32 s) { return S.write(s); }
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Read a vector of items which define mathRead().
|
||||
template <class T>
|
||||
bool mathReadVector(Vector<T> & vec, Stream & stream, const char * msg)
|
||||
{
|
||||
U32 num, i;
|
||||
bool Ok = true;
|
||||
stream.read( & num );
|
||||
vec.setSize( num );
|
||||
for( i = 0; i < num && Ok; i++ ){
|
||||
Ok = mathRead(stream, & vec[i]);
|
||||
AssertISV( Ok, avar("math vec read error (%s) on elem %d", msg, i) );
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
// Write a vector of items which define mathWrite().
|
||||
template <class T>
|
||||
bool mathWriteVector(const Vector<T> & vec, Stream & stream, const char * msg)
|
||||
{
|
||||
bool Ok = true;
|
||||
stream.write( vec.size() );
|
||||
for( U32 i = 0; i < vec.size() && Ok; i++ ) {
|
||||
Ok = mathWrite(stream, vec[i]);
|
||||
AssertISV( Ok, avar("math vec write error (%s) on elem %d", msg, i) );
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool FloorPlanResource::read(Stream& stream)
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamRead), "FLR::read: non-readable stream");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "FLR::read: Error, weird stream state");
|
||||
|
||||
// Version this stream
|
||||
U32 fileVersion, DohVal;
|
||||
stream.read(&fileVersion);
|
||||
if (fileVersion != smFileVersion) {
|
||||
AssertFatal(false, "FLR::read: incompatible file version found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// For expansion purposes
|
||||
stream.read(&DohVal); stream.read(&DohVal); stream.read(&DohVal);
|
||||
|
||||
// Read the vectors
|
||||
mathReadVector( mPlaneTable, stream, "FLR: mPlaneTable" );
|
||||
mathReadVector( mPointTable, stream, "FLR: mPointTable" );
|
||||
mathReadVector( mPointLists, stream, "FLR: mPointLists" );
|
||||
mathReadVector( mAreas, stream, "FLR: mAreas" );
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool FloorPlanResource::write(Stream& stream) const
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamWrite), "FLR::write: non-writeable stream");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "FLR::write: Error, weird stream state");
|
||||
|
||||
// Version the stream
|
||||
stream.write(smFileVersion);
|
||||
|
||||
U32 Doh = 0xD0bD0b; // So we don't later say Doh!
|
||||
stream.write(Doh); stream.write(Doh); stream.write(Doh);
|
||||
|
||||
// Write the vectors
|
||||
mathWriteVector( mPlaneTable, stream, "FLR: mPlaneTable" );
|
||||
mathWriteVector( mPointTable, stream, "FLR: mPointTable" );
|
||||
mathWriteVector( mPointLists, stream, "FLR: mPointLists" );
|
||||
mathWriteVector( mAreas, stream, "FLR: mAreas" );
|
||||
|
||||
return( stream.getStatus() == Stream::Ok );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// FloorPlan Resource constructor
|
||||
//
|
||||
ResourceInstance * constructFloorPlanFLR(Stream& stream)
|
||||
{
|
||||
FloorPlanResource * pResource = new FloorPlanResource;
|
||||
|
||||
if (pResource->read(stream) == true)
|
||||
return pResource;
|
||||
else {
|
||||
delete pResource;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
52
interior/floorPlanRes.h
Normal file
52
interior/floorPlanRes.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _FLOORPLANRES_H_
|
||||
#define _FLOORPLANRES_H_
|
||||
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "Core/resManager.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "Math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MPLANE_H_
|
||||
#include "Math/mPlane.h"
|
||||
#endif
|
||||
class Stream;
|
||||
|
||||
class FloorPlanResource : public ResourceInstance
|
||||
{
|
||||
typedef ResourceInstance Parent;
|
||||
static const U32 smFileVersion;
|
||||
|
||||
public:
|
||||
struct Area // basically a Winding, the info we need from it
|
||||
{
|
||||
S16 pointCount;
|
||||
S32 pointStart;
|
||||
S32 plane;
|
||||
Area(S16 C, S32 S, S32 P) { pointCount=C; pointStart=S; plane=P; }
|
||||
};
|
||||
|
||||
protected:
|
||||
Vector<PlaneF> mPlaneTable;
|
||||
Vector<Point3F> mPointTable;
|
||||
Vector<S32> mPointLists;
|
||||
Vector<Area> mAreas;
|
||||
|
||||
public:
|
||||
FloorPlanResource();
|
||||
~FloorPlanResource();
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
};
|
||||
|
||||
extern ResourceInstance * constructFloorPlanFLR(Stream& stream);
|
||||
|
||||
#endif // _H_FLOORPLANRES_
|
||||
472
interior/forceField.cc
Normal file
472
interior/forceField.cc
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/forceField.h"
|
||||
#include "Core/stream.h"
|
||||
#include "Math/mathIO.h"
|
||||
#include "console/console.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
#include "Collision/abstractPolyList.h"
|
||||
#include "Sim/sceneObject.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ForceField::ForceField()
|
||||
{
|
||||
mPreppedForRender = false;
|
||||
mWhite = NULL;
|
||||
}
|
||||
|
||||
ForceField::~ForceField()
|
||||
{
|
||||
mPreppedForRender = false;
|
||||
|
||||
delete mWhite;
|
||||
mWhite = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool ForceField::prepForRendering()
|
||||
{
|
||||
if (mPreppedForRender == true)
|
||||
return true;
|
||||
|
||||
mPreppedForRender = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ForceField::render(const ColorF& rColor, const F32 fade)
|
||||
{
|
||||
// All our transform what not has already been specified...
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Point3F), mPoints.address());
|
||||
glEnable(GL_VERTEX_ARRAY);
|
||||
|
||||
for (U32 i = 0; i < mSurfaces.size(); i++) {
|
||||
Surface& rSurface = mSurfaces[i];
|
||||
|
||||
glColor4f(rColor.red, rColor.green, rColor.blue, fade);
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++)
|
||||
glArrayElement(mWindings[j]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-------------------------------------- Persistence interfaces
|
||||
//
|
||||
const U32 ForceField::smFileVersion = 0;
|
||||
|
||||
bool ForceField::read(Stream& stream)
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamRead), "ForceField::read: non-read capable stream passed");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "ForceField::read: Error, stream in inconsistent state");
|
||||
|
||||
U32 i;
|
||||
|
||||
// Version this stream
|
||||
U32 fileVersion;
|
||||
stream.read(&fileVersion);
|
||||
if (fileVersion != smFileVersion) {
|
||||
Con::errorf(ConsoleLogEntry::General, "ForceField::read: incompatible file version found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
mName = stream.readSTString();
|
||||
U32 numTriggers;
|
||||
stream.read(&numTriggers);
|
||||
mTriggers.setSize(numTriggers);
|
||||
for (i = 0; i < mTriggers.size(); i++)
|
||||
mTriggers[i] = stream.readSTString();
|
||||
|
||||
// Geometry factors...
|
||||
mathRead(stream, &mBoundingBox);
|
||||
mathRead(stream, &mBoundingSphere);
|
||||
|
||||
// Now read in our data vectors.
|
||||
U32 vectorSize;
|
||||
// mPlanes
|
||||
readPlaneVector(stream);
|
||||
|
||||
// mPoints
|
||||
stream.read(&vectorSize);
|
||||
mPoints.setSize(vectorSize);
|
||||
for (i = 0; i < mPoints.size(); i++)
|
||||
mathRead(stream, &mPoints[i]);
|
||||
|
||||
// mBSPNodes;
|
||||
stream.read(&vectorSize);
|
||||
mBSPNodes.setSize(vectorSize);
|
||||
for (i = 0; i < mBSPNodes.size(); i++) {
|
||||
stream.read(&mBSPNodes[i].planeIndex);
|
||||
stream.read(&mBSPNodes[i].frontIndex);
|
||||
stream.read(&mBSPNodes[i].backIndex);
|
||||
}
|
||||
|
||||
// mBSPSolidLeaves
|
||||
stream.read(&vectorSize);
|
||||
mBSPSolidLeaves.setSize(vectorSize);
|
||||
for (i = 0; i < mBSPSolidLeaves.size(); i++) {
|
||||
stream.read(&mBSPSolidLeaves[i].surfaceIndex);
|
||||
stream.read(&mBSPSolidLeaves[i].surfaceCount);
|
||||
}
|
||||
|
||||
// mWindings
|
||||
stream.read(&vectorSize);
|
||||
mWindings.setSize(vectorSize);
|
||||
for (i = 0; i < mWindings.size(); i++) {
|
||||
stream.read(&mWindings[i]);
|
||||
}
|
||||
|
||||
// mSurfaces
|
||||
stream.read(&vectorSize);
|
||||
mSurfaces.setSize(vectorSize);
|
||||
for (i = 0; i < mSurfaces.size(); i++) {
|
||||
stream.read(&mSurfaces[i].windingStart);
|
||||
stream.read(&mSurfaces[i].windingCount);
|
||||
stream.read(&mSurfaces[i].planeIndex);
|
||||
stream.read(&mSurfaces[i].surfaceFlags);
|
||||
stream.read(&mSurfaces[i].fanMask);
|
||||
}
|
||||
|
||||
// mSolidLeafSurfaces
|
||||
stream.read(&vectorSize);
|
||||
mSolidLeafSurfaces.setSize(vectorSize);
|
||||
for (i = 0; i < mSolidLeafSurfaces.size(); i++) {
|
||||
stream.read(&mSolidLeafSurfaces[i]);
|
||||
}
|
||||
|
||||
stream.read(&mColor);
|
||||
|
||||
return stream.getStatus() == Stream::Ok;
|
||||
}
|
||||
|
||||
bool ForceField::write(Stream& stream) const
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamWrite), "Interior::write: non-write capable stream passed");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "Interior::write: Error, stream in inconsistent state");
|
||||
|
||||
U32 i;
|
||||
|
||||
// Version this stream
|
||||
stream.write(smFileVersion);
|
||||
|
||||
stream.writeString(mName);
|
||||
stream.write(mTriggers.size());
|
||||
for (i = 0; i < mTriggers.size(); i++)
|
||||
stream.writeString(mTriggers[i]);
|
||||
|
||||
mathWrite(stream, mBoundingBox);
|
||||
mathWrite(stream, mBoundingSphere);
|
||||
|
||||
// Now write out our data vectors. Remember, for cross-platform capability, no
|
||||
// structure writing is allowed...
|
||||
|
||||
// mPlanes
|
||||
writePlaneVector(stream);
|
||||
|
||||
// mPoints
|
||||
stream.write(mPoints.size());
|
||||
for (i = 0; i < mPoints.size(); i++)
|
||||
mathWrite(stream, mPoints[i]);
|
||||
|
||||
// mBSPNodes;
|
||||
stream.write(mBSPNodes.size());
|
||||
for (i = 0; i < mBSPNodes.size(); i++) {
|
||||
stream.write(mBSPNodes[i].planeIndex);
|
||||
stream.write(mBSPNodes[i].frontIndex);
|
||||
stream.write(mBSPNodes[i].backIndex);
|
||||
}
|
||||
|
||||
// mBSPSolidLeaves
|
||||
stream.write(mBSPSolidLeaves.size());
|
||||
for (i = 0; i < mBSPSolidLeaves.size(); i++) {
|
||||
stream.write(mBSPSolidLeaves[i].surfaceIndex);
|
||||
stream.write(mBSPSolidLeaves[i].surfaceCount);
|
||||
}
|
||||
|
||||
// mWindings
|
||||
stream.write(mWindings.size());
|
||||
for (i = 0; i < mWindings.size(); i++) {
|
||||
stream.write(mWindings[i]);
|
||||
}
|
||||
|
||||
// mSurfaces
|
||||
stream.write(mSurfaces.size());
|
||||
for (i = 0; i < mSurfaces.size(); i++) {
|
||||
stream.write(mSurfaces[i].windingStart);
|
||||
stream.write(mSurfaces[i].windingCount);
|
||||
stream.write(mSurfaces[i].planeIndex);
|
||||
stream.write(mSurfaces[i].surfaceFlags);
|
||||
stream.write(mSurfaces[i].fanMask);
|
||||
}
|
||||
|
||||
// mSolidLeafSurfaces
|
||||
stream.write(mSolidLeafSurfaces.size());
|
||||
for (i = 0; i < mSolidLeafSurfaces.size(); i++) {
|
||||
stream.write(mSolidLeafSurfaces[i]);
|
||||
}
|
||||
|
||||
stream.write(mColor);
|
||||
|
||||
return stream.getStatus() == Stream::Ok;
|
||||
}
|
||||
|
||||
bool ForceField::writePlaneVector(Stream& stream) const
|
||||
{
|
||||
// This is pretty slow, but who cares?
|
||||
//
|
||||
Vector<Point3F> uniqueNormals(mPlanes.size());
|
||||
Vector<U16> uniqueIndices(mPlanes.size());
|
||||
|
||||
U32 i;
|
||||
|
||||
for (i = 0; i < mPlanes.size(); i++) {
|
||||
bool inserted = false;
|
||||
for (U32 j = 0; j < uniqueNormals.size(); j++) {
|
||||
if (mPlanes[i] == uniqueNormals[j]) {
|
||||
// Hah! Already have this one...
|
||||
uniqueIndices.push_back(j);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inserted == false) {
|
||||
// Gotta do it ourselves...
|
||||
uniqueIndices.push_back(uniqueNormals.size());
|
||||
uniqueNormals.push_back(Point3F(mPlanes[i].x, mPlanes[i].y, mPlanes[i].z));
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, what we have now, is a list of unique normals, a set of indices into
|
||||
// that vector, and the distances that we still have to write out by hand.
|
||||
// Hop to it!
|
||||
stream.write(uniqueNormals.size());
|
||||
for (i = 0; i < uniqueNormals.size(); i++)
|
||||
mathWrite(stream, uniqueNormals[i]);
|
||||
|
||||
stream.write(mPlanes.size());
|
||||
for (i = 0; i < mPlanes.size(); i++) {
|
||||
stream.write(uniqueIndices[i]);
|
||||
stream.write(mPlanes[i].d);
|
||||
}
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool ForceField::readPlaneVector(Stream& stream)
|
||||
{
|
||||
Vector<Point3F> normals;
|
||||
U32 vectorSize;
|
||||
|
||||
stream.read(&vectorSize);
|
||||
normals.setSize(vectorSize);
|
||||
U32 i;
|
||||
for (i = 0; i < normals.size(); i++)
|
||||
mathRead(stream, &normals[i]);
|
||||
|
||||
U16 index;
|
||||
stream.read(&vectorSize);
|
||||
mPlanes.setSize(vectorSize);
|
||||
for (i = 0; i < mPlanes.size(); i++) {
|
||||
stream.read(&index);
|
||||
stream.read(&mPlanes[i].d);
|
||||
mPlanes[i].x = normals[index].x;
|
||||
mPlanes[i].y = normals[index].y;
|
||||
mPlanes[i].z = normals[index].z;
|
||||
}
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-------------------------------------- Collision support. Essentially
|
||||
// copied from the interiorCollision
|
||||
//
|
||||
void ForceField::collisionFanFromSurface(const Surface& rSurface, U32* fanIndices, U32* numIndices) const
|
||||
{
|
||||
U32 tempIndices[32];
|
||||
|
||||
tempIndices[0] = 0;
|
||||
U32 idx = 1;
|
||||
U32 i;
|
||||
for (i = 1; i < rSurface.windingCount; i += 2)
|
||||
tempIndices[idx++] = i;
|
||||
for (i = ((rSurface.windingCount - 1) & (~0x1)); i > 0; i -= 2)
|
||||
tempIndices[idx++] = i;
|
||||
|
||||
idx = 0;
|
||||
for (i = 0; i < rSurface.windingCount; i++) {
|
||||
if (rSurface.fanMask & (1 << i)) {
|
||||
fanIndices[idx++] = mWindings[rSurface.windingStart + tempIndices[i]];
|
||||
}
|
||||
}
|
||||
*numIndices = idx;
|
||||
}
|
||||
|
||||
bool ForceField::castRay(const Point3F& s, const Point3F& e, RayInfo* info)
|
||||
{
|
||||
bool hit = castRay_r(0, s, e, info);
|
||||
if (hit) {
|
||||
Point3F vec = e - s;
|
||||
F32 len = vec.len();
|
||||
vec /= len;
|
||||
info->t = mDot(info->point - s, vec) / len;
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool ForceField::castRay_r(const U16 node,
|
||||
const Point3F& s,
|
||||
const Point3F& e,
|
||||
RayInfo* info)
|
||||
{
|
||||
if (isBSPLeafIndex(node) == false) {
|
||||
const IBSPNode& rNode = mBSPNodes[node];
|
||||
const PlaneF& rPlane = getPlane(rNode.planeIndex);
|
||||
|
||||
PlaneF::Side sSide = rPlane.whichSide(s);
|
||||
PlaneF::Side eSide = rPlane.whichSide(e);
|
||||
|
||||
switch (PlaneSwitchCode(sSide, eSide)) {
|
||||
case PlaneSwitchCode(PlaneF::Front, PlaneF::Front):
|
||||
case PlaneSwitchCode(PlaneF::Front, PlaneF::On):
|
||||
case PlaneSwitchCode(PlaneF::On, PlaneF::Front):
|
||||
return castRay_r(rNode.frontIndex, s, e, info);
|
||||
break;
|
||||
|
||||
case PlaneSwitchCode(PlaneF::On, PlaneF::Back):
|
||||
case PlaneSwitchCode(PlaneF::Back, PlaneF::On):
|
||||
case PlaneSwitchCode(PlaneF::Back, PlaneF::Back):
|
||||
return castRay_r(rNode.backIndex, s, e, info);
|
||||
break;
|
||||
|
||||
case PlaneSwitchCode(PlaneF::On, PlaneF::On):
|
||||
// Line lies on the plane
|
||||
if (isBSPLeafIndex(rNode.backIndex) == false) {
|
||||
if (castRay_r(rNode.backIndex, s, e, info))
|
||||
return true;
|
||||
}
|
||||
if (isBSPLeafIndex(rNode.frontIndex) == false) {
|
||||
if (castRay_r(rNode.frontIndex, s, e, info))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
|
||||
case PlaneSwitchCode(PlaneF::Front, PlaneF::Back): {
|
||||
Point3F ip;
|
||||
F32 intersectT = rPlane.intersect(s, e);
|
||||
AssertFatal(intersectT != PARALLEL_PLANE, "Error, this should never happen in this case!");
|
||||
ip.interpolate(s, e, intersectT);
|
||||
if (castRay_r(rNode.frontIndex, s, ip, info))
|
||||
return true;
|
||||
return castRay_r(rNode.backIndex, ip, e, info);
|
||||
}
|
||||
break;
|
||||
|
||||
case PlaneSwitchCode(PlaneF::Back, PlaneF::Front): {
|
||||
Point3F ip;
|
||||
F32 intersectT = rPlane.intersect(s, e);
|
||||
AssertFatal(intersectT != PARALLEL_PLANE, "Error, this should never happen in this case!");
|
||||
ip.interpolate(s, e, intersectT);
|
||||
if (castRay_r(rNode.backIndex, s, ip, info))
|
||||
return true;
|
||||
return castRay_r(rNode.frontIndex, ip, e, info);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Misunderstood switchCode in ForceField::castRay_r");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBSPSolidLeaf(node)) {
|
||||
// DMM: Set material info here
|
||||
info->point = s;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ForceField::buildPolyList_r(const U16 node, Vector<U16>& collPlanes, AbstractPolyList* list, SphereF& s)
|
||||
{
|
||||
if (isBSPLeafIndex(node) == false) {
|
||||
const IBSPNode& rNode = mBSPNodes[node];
|
||||
const PlaneF& rPlane = getPlane(rNode.planeIndex);
|
||||
|
||||
F32 dist = rPlane.distToPlane(s.center);
|
||||
if (mFabs(dist) <= s.radius) {
|
||||
// Have to do both, and push the plane back on the list...
|
||||
collPlanes.push_back(rNode.planeIndex);
|
||||
buildPolyList_r(rNode.frontIndex, collPlanes, list, s);
|
||||
buildPolyList_r(rNode.backIndex, collPlanes, list, s);
|
||||
collPlanes.pop_back();
|
||||
} else if (dist > 0.0f) {
|
||||
buildPolyList_r(rNode.frontIndex, collPlanes, list, s);
|
||||
} else {
|
||||
buildPolyList_r(rNode.backIndex, collPlanes, list, s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBSPSolidLeaf(node)) {
|
||||
const IBSPLeafSolid& rLeaf = mBSPSolidLeaves[getBSPSolidLeafIndex(node)];
|
||||
for (U32 i = 0; i < rLeaf.surfaceCount; i++) {
|
||||
U32 surfaceIndex = mSolidLeafSurfaces[rLeaf.surfaceIndex + i];
|
||||
const Surface& rSurface = mSurfaces[surfaceIndex];
|
||||
for (U32 j = 0; j < collPlanes.size(); j++) {
|
||||
if (areEqualPlanes(rSurface.planeIndex, collPlanes[j]) == true) {
|
||||
|
||||
U32 fanVerts[32];
|
||||
U32 numVerts;
|
||||
collisionFanFromSurface(rSurface, fanVerts, &numVerts);
|
||||
|
||||
// DMM: Material here
|
||||
list->begin(0, rSurface.planeIndex);
|
||||
|
||||
U32 vertStart = list->addPoint(mPoints[fanVerts[0]]);
|
||||
list->vertex(vertStart);
|
||||
for (U32 k = 1; k < numVerts; k++) {
|
||||
list->addPoint(mPoints[fanVerts[k]]);
|
||||
list->vertex(vertStart + k);
|
||||
}
|
||||
list->plane(vertStart, vertStart + 1, vertStart + 2);
|
||||
list->end();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ForceField::buildPolyList(AbstractPolyList* list, SphereF& sphere)
|
||||
{
|
||||
Vector<U16> planes;
|
||||
buildPolyList_r(0, planes, list, sphere);
|
||||
AssertFatal(planes.size() == 0, "Error, unbalanced plane stack!");
|
||||
|
||||
return !list->isEmpty();
|
||||
}
|
||||
182
interior/forceField.h
Normal file
182
interior/forceField.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _FORCEFIELD_H_
|
||||
#define _FORCEFIELD_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _MBOX_H_
|
||||
#include "Math/mBox.h"
|
||||
#endif
|
||||
#ifndef _MSPHERE_H_
|
||||
#include "Math/mSphere.h"
|
||||
#endif
|
||||
#ifndef _MPLANE_H_
|
||||
#include "Math/mPlane.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "Math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "Core/color.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------- forward decls.
|
||||
class EditGeometry;
|
||||
class InteriorInstance;
|
||||
class Stream;
|
||||
class TextureHandle;
|
||||
class AbstractPolyList;
|
||||
struct RayInfo;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class ForceField
|
||||
{
|
||||
static const U32 smFileVersion;
|
||||
friend class EditGeometry;
|
||||
friend class InteriorInstance;
|
||||
|
||||
//-------------------------------------- Public interfaces
|
||||
public:
|
||||
ForceField();
|
||||
~ForceField();
|
||||
|
||||
bool prepForRendering();
|
||||
void render(const ColorF& color, const F32 fadeLevel);
|
||||
const Box3F& getBoundingBox() const;
|
||||
|
||||
bool castRay(const Point3F&, const Point3F&, RayInfo*);
|
||||
bool buildPolyList(AbstractPolyList*, SphereF&);
|
||||
//-------------------------------------- Persistence interface
|
||||
public:
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
|
||||
public:
|
||||
static U16 getPlaneIndex(U16 index);
|
||||
static bool planeIsFlipped(U16 index);
|
||||
|
||||
//-------------------------------------- BSP Structures
|
||||
private:
|
||||
struct IBSPNode {
|
||||
U16 planeIndex;
|
||||
U16 frontIndex;
|
||||
U16 backIndex;
|
||||
U16 __padding__;
|
||||
};
|
||||
struct IBSPLeafSolid {
|
||||
U32 surfaceIndex;
|
||||
U16 surfaceCount;
|
||||
U16 __padding__;
|
||||
};
|
||||
|
||||
bool isBSPLeafIndex(U16 index) const;
|
||||
bool isBSPSolidLeaf(U16 index) const;
|
||||
bool isBSPEmptyLeaf(U16 index) const;
|
||||
U16 getBSPSolidLeafIndex(U16 index) const;
|
||||
|
||||
bool writePlaneVector(Stream&) const;
|
||||
bool readPlaneVector(Stream&);
|
||||
|
||||
private:
|
||||
const PlaneF& getPlane(U16 index) const;
|
||||
bool areEqualPlanes(U16, U16) const;
|
||||
|
||||
struct Surface {
|
||||
U32 windingStart;
|
||||
U32 fanMask;
|
||||
|
||||
U16 planeIndex;
|
||||
U8 windingCount;
|
||||
U8 surfaceFlags;
|
||||
};
|
||||
|
||||
protected:
|
||||
StringTableEntry mName;
|
||||
ColorF mColor;
|
||||
Vector<StringTableEntry> mTriggers;
|
||||
|
||||
Box3F mBoundingBox;
|
||||
SphereF mBoundingSphere;
|
||||
Vector<PlaneF> mPlanes;
|
||||
Vector<Point3F> mPoints;
|
||||
|
||||
Vector<IBSPNode> mBSPNodes;
|
||||
Vector<IBSPLeafSolid> mBSPSolidLeaves;
|
||||
Vector<U32> mSolidLeafSurfaces;
|
||||
|
||||
bool mPreppedForRender;
|
||||
TextureHandle* mWhite;
|
||||
|
||||
Vector<U32> mWindings;
|
||||
Vector<Surface> mSurfaces;
|
||||
|
||||
protected:
|
||||
bool castRay_r(const U16, const Point3F&, const Point3F&, RayInfo*);
|
||||
void buildPolyList_r(const U16, Vector<U16>&, AbstractPolyList*, SphereF&);
|
||||
void collisionFanFromSurface(const Surface&, U32* fan, U32* numIndices) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool ForceField::isBSPLeafIndex(U16 index) const
|
||||
{
|
||||
return (index & 0x8000) != 0;
|
||||
}
|
||||
|
||||
inline bool ForceField::isBSPSolidLeaf(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPLeafIndex(index) == true, "Error, only call for leaves!");
|
||||
return (index & 0x4000) != 0;
|
||||
}
|
||||
|
||||
inline bool ForceField::isBSPEmptyLeaf(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPLeafIndex(index) == true, "Error, only call for leaves!");
|
||||
return (index & 0x4000) == 0;
|
||||
}
|
||||
|
||||
inline U16 ForceField::getBSPSolidLeafIndex(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPSolidLeaf(index) == true, "Error, only call for leaves!");
|
||||
return (index & ~0xC000);
|
||||
}
|
||||
|
||||
inline const PlaneF& ForceField::getPlane(U16 index) const
|
||||
{
|
||||
AssertFatal(U32(index & ~0x8000) < mPlanes.size(),
|
||||
"ForceField::getPlane: planeIndex out of range");
|
||||
|
||||
return mPlanes[index & ~0x8000];
|
||||
}
|
||||
|
||||
inline U16 ForceField::getPlaneIndex(U16 index)
|
||||
{
|
||||
return index & ~0x8000;
|
||||
}
|
||||
|
||||
inline bool ForceField::planeIsFlipped(U16 index)
|
||||
{
|
||||
return (index & 0x8000) != 0;
|
||||
}
|
||||
|
||||
inline bool ForceField::areEqualPlanes(U16 o, U16 t) const
|
||||
{
|
||||
return (o & ~0x8000) == (t & ~0x8000);
|
||||
}
|
||||
|
||||
inline const Box3F& ForceField::getBoundingBox() const
|
||||
{
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
#endif // _H_FORCEFIELD_
|
||||
|
||||
2173
interior/interior.cc
Normal file
2173
interior/interior.cc
Normal file
File diff suppressed because it is too large
Load diff
859
interior/interior.h
Normal file
859
interior/interior.h
Normal file
|
|
@ -0,0 +1,859 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIOR_H_
|
||||
#define _INTERIOR_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _COLLISION_H_
|
||||
#include "collision/collision.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "core/resManager.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/tVector.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MPLANE_H_
|
||||
#include "math/mPlane.h"
|
||||
#endif
|
||||
#ifndef _MBOX_H_
|
||||
#include "math/mBox.h"
|
||||
#endif
|
||||
#ifndef _MSPHERE_H_
|
||||
#include "math/mSphere.h"
|
||||
#endif
|
||||
#ifndef _CONVEX_H_
|
||||
#include "collision/convex.h"
|
||||
#endif
|
||||
#ifndef _INTERIORLMMANAGER_H_
|
||||
#include "interior/interiorLMManager.h"
|
||||
#endif
|
||||
|
||||
|
||||
//-------------------------------------- Forward declarations
|
||||
class Stream;
|
||||
class EditGeometry;
|
||||
class InteriorInstance;
|
||||
class GBitmap;
|
||||
class TextureHandle;
|
||||
class RectD;
|
||||
class SphereF;
|
||||
class MatrixF;
|
||||
class SceneState;
|
||||
class MaterialList;
|
||||
class AbstractPolyList;
|
||||
class InteriorSubObject;
|
||||
class TranslucentSubObject;
|
||||
class BitVector;
|
||||
struct RayInfo;
|
||||
struct EdgeList;
|
||||
class SurfaceHash;
|
||||
class InteriorPolytope;
|
||||
class FloorPlan;
|
||||
class LightInfo;
|
||||
class PlaneRange;
|
||||
class EditInteriorResource;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class InteriorConvex : public Convex
|
||||
{
|
||||
typedef Convex Parent;
|
||||
friend class Interior;
|
||||
friend class InteriorInstance;
|
||||
|
||||
protected:
|
||||
Interior* pInterior;
|
||||
public:
|
||||
S32 hullId;
|
||||
Box3F box;
|
||||
|
||||
public:
|
||||
InteriorConvex() { mType = InteriorConvexType; }
|
||||
InteriorConvex(const InteriorConvex& cv) {
|
||||
mObject = cv.mObject;
|
||||
pInterior = cv.pInterior;
|
||||
hullId = cv.hullId;
|
||||
box = box;
|
||||
}
|
||||
|
||||
Box3F getBoundingBox() const;
|
||||
Box3F getBoundingBox(const MatrixF& mat, const Point3F& scale) const;
|
||||
Point3F support(const VectorF& v) const;
|
||||
void getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf);
|
||||
void getPolyList(AbstractPolyList* list);
|
||||
};
|
||||
|
||||
class ZoneVisDeterminer
|
||||
{
|
||||
enum Mode {
|
||||
FromState,
|
||||
FromRects
|
||||
};
|
||||
|
||||
Mode mMode;
|
||||
|
||||
SceneState* mState;
|
||||
U32 mZoneRangeOffset;
|
||||
U32 mParentZone;
|
||||
|
||||
public:
|
||||
ZoneVisDeterminer() : mMode(FromRects), mState(NULL) { }
|
||||
|
||||
void runFromState(SceneState*, U32, U32);
|
||||
void runFromRects(SceneState*, U32, U32);
|
||||
|
||||
bool isZoneVisible(const U32) const;
|
||||
};
|
||||
|
||||
|
||||
struct ItrPaddedPoint
|
||||
{
|
||||
Point3F point;
|
||||
union {
|
||||
F32 fogCoord;
|
||||
U8 fogColor[4];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- CLASS NOTES
|
||||
// Interior: Base for all interior geometries. Contains all lighting, poly,
|
||||
// portal zone, bsp info, etc. to render an interior.
|
||||
//
|
||||
// Internal Structure Notes:
|
||||
// IBSPNode:
|
||||
// planeIndex: Obv.
|
||||
// frontIndex/backIndex: Top bit indicates if children are leaves.
|
||||
// Next bit indicates if leaf children are solid.
|
||||
//
|
||||
// IBSPLeafSolid:
|
||||
// planeIndex: obv.
|
||||
// surfaceIndex/surfaceCount: Polys that are on the faces of this leaf. Only
|
||||
// used for collision/surface info detection.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class Interior
|
||||
{
|
||||
friend class FloorPlan;
|
||||
friend class EditGeometry;
|
||||
friend class InteriorInstance;
|
||||
friend class SceneLighting;
|
||||
friend class InteriorProxy;
|
||||
friend class TranslucentSubObject;
|
||||
friend class MirrorSubObject;
|
||||
friend class InteriorConvex;
|
||||
friend class InteriorLMManager;
|
||||
friend class EditInteriorResource;
|
||||
|
||||
//-------------------------------------- Public interfaces
|
||||
public:
|
||||
Interior();
|
||||
~Interior();
|
||||
|
||||
// Misc
|
||||
U32 getDetailLevel() const;
|
||||
U32 getMinPixels() const;
|
||||
const Box3F& getBoundingBox() const;
|
||||
S32 getNumZones() const;
|
||||
|
||||
// Rendering
|
||||
bool prepForRendering();
|
||||
void rebuildVertexColors(LM_HANDLE instanceHandle,
|
||||
Vector<ColorI>* normal,
|
||||
Vector<ColorI>* alarm);
|
||||
|
||||
bool prepRender(SceneState* state,
|
||||
S32 containingZone,
|
||||
S32 baseZone,
|
||||
U32 zoneOffset,
|
||||
const MatrixF& OSToWS,
|
||||
const Point3F& objScale,
|
||||
const bool modifyBaseState,
|
||||
const bool dontRestrictOutside,
|
||||
const bool flipClipPlanes);
|
||||
void prepTempRender(SceneState* state,
|
||||
S32 containingZone,
|
||||
S32 baseZone,
|
||||
const MatrixF& OSToWS,
|
||||
const Point3F& objScale,
|
||||
const bool flipClipPlanes);
|
||||
|
||||
void render(const bool useAlarmLighting, MaterialList* pMaterials,
|
||||
const LM_HANDLE instanceHandle,
|
||||
const Vector<ColorI>* normalVLights,
|
||||
const Vector<ColorI>* alarmVLights);
|
||||
void render_vc_tf(const bool useAlarmLighting, MaterialList* pMaterials, const LM_HANDLE instanceHandle,
|
||||
const Vector<ColorI>* normalVLights,
|
||||
const Vector<ColorI>* alarmVLights);
|
||||
void render_vc_fc(const bool useAlarmLighting, MaterialList* pMaterials, const LM_HANDLE instanceHandle,
|
||||
const Vector<ColorI>* normalVLights,
|
||||
const Vector<ColorI>* alarmVLights);
|
||||
void renderARB_vc_tf(const bool useAlarmLighting, MaterialList* pMaterials, const LM_HANDLE instanceHandle,
|
||||
const Vector<ColorI>* normalVLights,
|
||||
const Vector<ColorI>* alarmVLights);
|
||||
void renderARB(const bool useAlarmLighting, MaterialList* pMaterials, const LM_HANDLE instanceHandle);
|
||||
void renderARB_FC(const bool useAlarmLighting, MaterialList* pMaterials, const LM_HANDLE instanceHandle);
|
||||
void renderLights(LightInfo* pInfo,
|
||||
const MatrixF& transform,
|
||||
const Point3F& scale,
|
||||
U32* lightSurfaces,
|
||||
U32 numLightSurfaces);
|
||||
|
||||
bool useFogCoord();
|
||||
|
||||
bool scopeZones(const S32 baseZone,
|
||||
const Point3F& interiorRoot,
|
||||
bool* interiorScopingState);
|
||||
|
||||
//-------------------------------------- Collision Interface and zone scans
|
||||
public:
|
||||
bool scanZones(const Box3F&, const MatrixF&, U16* zones, U32* numZones);
|
||||
bool castRay(const Point3F&, const Point3F&, RayInfo*);
|
||||
bool buildPolyList(AbstractPolyList*, const Box3F&, const MatrixF&, const Point3F&);
|
||||
bool buildLightPolyList(U32* lightSurfaces, U32* numLightSurfaces,
|
||||
const Box3F&, const MatrixF&, const Point3F&);
|
||||
|
||||
bool getIntersectingHulls(const Box3F&, U16* hulls, U32* numHulls);
|
||||
bool getIntersectingVehicleHulls(const Box3F&, U16* hulls, U32* numHulls);
|
||||
|
||||
protected:
|
||||
bool castRay_r(const U16, const U16, const Point3F&, const Point3F&, RayInfo*);
|
||||
void buildPolyList_r(InteriorPolytope& polytope,
|
||||
SurfaceHash& hash);
|
||||
void scanZone_r(const U16 node,
|
||||
const Point3F& center,
|
||||
const Point3F& axisx,
|
||||
const Point3F& axisy,
|
||||
const Point3F& axisz,
|
||||
U16* zones,
|
||||
U32* numZones);
|
||||
void scanZoneNew(InteriorPolytope& polytope,
|
||||
U16* zones,
|
||||
U32* numZones);
|
||||
|
||||
void scopeZone(const U32 currZone,
|
||||
bool* interiorScopingState,
|
||||
const Point3F& interiorRoot,
|
||||
Vector<U32>& zoneStack,
|
||||
Vector<PlaneF>& planeStack,
|
||||
Vector<PlaneRange>& planeRangeStack);
|
||||
|
||||
//-------------------------------------- Global rendering control
|
||||
public:
|
||||
enum RenderModes {
|
||||
NormalRender = 0,
|
||||
NormalRenderLines = 1,
|
||||
ShowDetail = 2,
|
||||
ShowAmbiguous = 3,
|
||||
ShowOrphan = 4,
|
||||
ShowLightmaps = 5,
|
||||
ShowTexturesOnly = 6,
|
||||
ShowPortalZones = 7,
|
||||
ShowOutsideVisible = 8,
|
||||
ShowCollisionFans = 9,
|
||||
ShowStrips = 10,
|
||||
ShowNullSurfaces = 11,
|
||||
ShowLargeTextures = 12,
|
||||
ShowHullSurfaces = 13,
|
||||
ShowVehicleHullSurfaces = 14,
|
||||
ShowVertexColors = 15,
|
||||
ShowDetailLevel = 16
|
||||
};
|
||||
enum Constants {
|
||||
NumCoordBins = 16,
|
||||
|
||||
BinsXY = 0,
|
||||
BinsXZ = 1,
|
||||
BinsYZ = 2
|
||||
};
|
||||
|
||||
static U32 smRenderMode;
|
||||
static bool smFocusedDebug;
|
||||
static bool smRenderEnvironmentMaps;
|
||||
static bool smUseVertexLighting;
|
||||
static bool smUseTexturedFog;
|
||||
static bool smLockArrays;
|
||||
|
||||
//-------------------------------------- Persistence interface
|
||||
public:
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
|
||||
bool readVehicleCollision(Stream& stream);
|
||||
bool writeVehicleCollision(Stream& stream) const;
|
||||
|
||||
private:
|
||||
static const U32 smFileVersion;
|
||||
bool writePlaneVector(Stream&) const;
|
||||
bool readPlaneVector(Stream&);
|
||||
bool readLMapTexGen(Stream&, PlaneF&, PlaneF&);
|
||||
bool writeLMapTexGen(Stream&, const PlaneF&, const PlaneF&) const;
|
||||
void setupTexCoords();
|
||||
void setupZonePlanes();
|
||||
|
||||
//-------------------------------------- For morian only...
|
||||
public:
|
||||
void processHullPolyLists();
|
||||
void processVehicleHullPolyLists();
|
||||
|
||||
//-------------------------------------- BSP Structures
|
||||
private:
|
||||
struct IBSPNode {
|
||||
U16 planeIndex;
|
||||
U16 frontIndex;
|
||||
U16 backIndex;
|
||||
|
||||
U16 terminalZone; // if high bit set, then the lower 15 bits are the zone
|
||||
// of any of the subsidiary nodes. Note that this is
|
||||
// going to overestimate some, since an object could be
|
||||
// completely contained in solid, but it's probably
|
||||
// going to turn out alright.
|
||||
};
|
||||
struct IBSPLeafSolid {
|
||||
U32 surfaceIndex;
|
||||
U16 surfaceCount;
|
||||
};
|
||||
|
||||
bool isBSPLeafIndex(U16 index) const;
|
||||
bool isBSPSolidLeaf(U16 index) const;
|
||||
bool isBSPEmptyLeaf(U16 index) const;
|
||||
U16 getBSPSolidLeafIndex(U16 index) const;
|
||||
U16 getBSPEmptyLeafZone(U16 index) const;
|
||||
|
||||
void setupAveTexGenLength();
|
||||
|
||||
void truncateZoneTree();
|
||||
void truncateZoneNode(const U16);
|
||||
bool getUnifiedZone(const U16, S32*);
|
||||
|
||||
public:
|
||||
static U16 getPlaneIndex(U16 index);
|
||||
static bool planeIsFlipped(U16 index);
|
||||
const PlaneF& getPlane(U16 index) const;
|
||||
|
||||
private:
|
||||
bool areEqualPlanes(U16, U16) const;
|
||||
|
||||
bool isNullSurfaceIndex(const U32 index) const;
|
||||
bool isVehicleNullSurfaceIndex(const U32 index) const;
|
||||
U32 getNullSurfaceIndex(const U32 index) const;
|
||||
U32 getVehicleNullSurfaceIndex(const U32 index) const;
|
||||
|
||||
//-------------------------------------- Portals and Zone structures
|
||||
private:
|
||||
struct Zone {
|
||||
U16 portalStart;
|
||||
U16 portalCount;
|
||||
|
||||
U32 surfaceStart;
|
||||
U32 planeStart;
|
||||
|
||||
U16 surfaceCount;
|
||||
U16 planeCount;
|
||||
|
||||
U16 flags;
|
||||
U16 zoneId; // This is ephemeral, not persisted out.
|
||||
};
|
||||
|
||||
struct Portal {
|
||||
U16 planeIndex;
|
||||
|
||||
U16 triFanCount;
|
||||
U32 triFanStart; // portals can have multiple windings
|
||||
|
||||
U16 zoneFront;
|
||||
U16 zoneBack;
|
||||
};
|
||||
|
||||
//-------------------------------------- Poly/Surface structures
|
||||
public:
|
||||
enum SurfaceFlags {
|
||||
SurfaceDetail = 1 << 0,
|
||||
SurfaceAmbiguous = 1 << 1,
|
||||
SurfaceOrphan = 1 << 2,
|
||||
SurfaceSharedLMaps = 1 << 3, // Indicates that the alarm and normal states share a lightmap (for mission lighter)
|
||||
SurfaceOutsideVisible = 1 << 4,
|
||||
SurfaceFlagMask = (SurfaceDetail |
|
||||
SurfaceAmbiguous |
|
||||
SurfaceOrphan |
|
||||
SurfaceSharedLMaps |
|
||||
SurfaceOutsideVisible)
|
||||
};
|
||||
enum ZoneFlags {
|
||||
ZoneInside = 1 << 0
|
||||
};
|
||||
|
||||
const bool isSurfaceOutsideVisible(U32 surface) const;
|
||||
|
||||
public:
|
||||
struct TexGenPlanes {
|
||||
PlaneF planeX;
|
||||
PlaneF planeY;
|
||||
};
|
||||
struct TriFan {
|
||||
U32 windingStart;
|
||||
U32 windingCount;
|
||||
};
|
||||
struct Surface {
|
||||
U32 windingStart; // 1
|
||||
|
||||
U16 planeIndex; // 2
|
||||
U16 textureIndex;
|
||||
|
||||
U32 texGenIndex; // 3
|
||||
|
||||
U16 lightCount; // 4
|
||||
U8 surfaceFlags;
|
||||
U8 windingCount;
|
||||
|
||||
U32 fanMask; // 5
|
||||
|
||||
U32 lightStateInfoStart; // 6
|
||||
|
||||
U8 mapOffsetX; // 7
|
||||
U8 mapOffsetY;
|
||||
U8 mapSizeX;
|
||||
U8 mapSizeY;
|
||||
};
|
||||
struct NullSurface {
|
||||
U32 windingStart;
|
||||
|
||||
U16 planeIndex;
|
||||
U8 surfaceFlags;
|
||||
U8 windingCount;
|
||||
};
|
||||
|
||||
//-------------------------------------- Animated lighting structures
|
||||
enum LightFlags {
|
||||
AnimationAmbient = 1 << 0,
|
||||
AnimationLoop = 1 << 1,
|
||||
AnimationFlicker = 1 << 2,
|
||||
AnimationTypeMask = (1 << 3) - 1,
|
||||
|
||||
AlarmLight = 1 << 3
|
||||
};
|
||||
enum LightType {
|
||||
AmbientLooping = AnimationAmbient | AnimationLoop,
|
||||
AmbientFlicker = AnimationAmbient | AnimationFlicker,
|
||||
|
||||
TriggerableLoop = AnimationLoop,
|
||||
TriggerableFlicker = AnimationFlicker,
|
||||
TriggerableRamp = 0
|
||||
};
|
||||
|
||||
private:
|
||||
struct AnimatedLight {
|
||||
U32 nameIndex; // Light's name
|
||||
U32 stateIndex; // start point in the state list
|
||||
|
||||
U16 stateCount; // number of states in this light
|
||||
U16 flags; // flags (Apply AnimationTypeMask to get type)
|
||||
|
||||
U32 duration; // total duration of animation (ms)
|
||||
};
|
||||
struct LightState {
|
||||
U8 red; // state's color
|
||||
U8 green;
|
||||
U8 blue;
|
||||
U8 _color_padding_;
|
||||
|
||||
U32 activeTime; // Time (ms) at which this state becomes active
|
||||
|
||||
U32 dataIndex; // StateData count and index for this state
|
||||
U16 dataCount;
|
||||
|
||||
U16 __32bit_padding__;
|
||||
};
|
||||
struct LightStateData {
|
||||
U32 surfaceIndex; // Surface affected by this data
|
||||
U32 mapIndex; // Index into StateDataBuffer (0xFFFFFFFF indicates none)
|
||||
U16 lightStateIndex; // Entry to modify in InteriorInstance
|
||||
U16 __32bit_padding__;
|
||||
};
|
||||
|
||||
// convex hull collision structures...
|
||||
protected:
|
||||
struct ConvexHull {
|
||||
F32 minX;
|
||||
F32 maxX;
|
||||
F32 minY;
|
||||
F32 maxY;
|
||||
|
||||
F32 minZ;
|
||||
F32 maxZ;
|
||||
U32 hullStart;
|
||||
U32 surfaceStart;
|
||||
|
||||
U32 planeStart;
|
||||
U16 hullCount;
|
||||
U16 surfaceCount;
|
||||
U32 polyListPlaneStart;
|
||||
|
||||
U32 polyListPointStart;
|
||||
U32 polyListStringStart;
|
||||
U16 searchTag;
|
||||
};
|
||||
|
||||
struct CoordBin {
|
||||
U32 binStart;
|
||||
U32 binCount;
|
||||
};
|
||||
|
||||
//
|
||||
private:
|
||||
LM_HANDLE mLMHandle;
|
||||
public:
|
||||
LM_HANDLE getLMHandle() {return(mLMHandle);}
|
||||
|
||||
// SceneLighting::InteriorProxy interface
|
||||
const Surface & getSurface(const U32 surface) const;
|
||||
const U32 getSurfaceCount() const;
|
||||
const U8 getNormalLMapIndex(const U32 surface) const;
|
||||
const U8 getAlarmLMapIndex(const U32 surface) const;
|
||||
const U32 getWinding(const U32 index) const;
|
||||
const Point3F & getPoint(const U32 index) const;
|
||||
const TexGenPlanes & getLMTexGenEQ(const U32 index) const;
|
||||
bool hasAlarmState() const;
|
||||
const U32 getWindingCount() const;
|
||||
|
||||
//-------------------------------------- Instance Data Members
|
||||
private:
|
||||
U32 mDetailLevel;
|
||||
U32 mMinPixels;
|
||||
F32 mAveTexGenLength; // Set in Interior::read after loading the texgen planes.
|
||||
Box3F mBoundingBox;
|
||||
SphereF mBoundingSphere;
|
||||
|
||||
Vector<PlaneF> mPlanes;
|
||||
Vector<ItrPaddedPoint> mPoints;
|
||||
Vector<U8> mPointVisibility;
|
||||
|
||||
ColorF mBaseAmbient;
|
||||
ColorF mAlarmAmbient;
|
||||
|
||||
Vector<IBSPNode> mBSPNodes;
|
||||
Vector<IBSPLeafSolid> mBSPSolidLeaves;
|
||||
|
||||
bool mPreppedForRender;
|
||||
MaterialList* mMaterialList;
|
||||
TextureHandle* mWhite;
|
||||
TextureHandle* mWhiteRGB;
|
||||
|
||||
TextureHandle* mLightFalloff;
|
||||
|
||||
Vector<TextureHandle*> mEnvironMaps;
|
||||
Vector<F32> mEnvironFactors;
|
||||
U32 mValidEnvironMaps;
|
||||
|
||||
Vector<U32> mWindings;
|
||||
|
||||
Vector<TexGenPlanes> mTexGenEQs;
|
||||
Vector<TexGenPlanes> mLMTexGenEQs;
|
||||
|
||||
Vector<TriFan> mWindingIndices;
|
||||
Vector<Surface> mSurfaces;
|
||||
Vector<NullSurface> mNullSurfaces;
|
||||
Vector<U32> mSolidLeafSurfaces;
|
||||
|
||||
// Portals and zones
|
||||
Vector<Zone> mZones;
|
||||
Vector<U16> mZonePlanes;
|
||||
Vector<U16> mZoneSurfaces;
|
||||
Vector<U16> mZonePortalList;
|
||||
Vector<Portal> mPortals;
|
||||
|
||||
// Subobjects: Doors, translucencies, mirrors, etc.
|
||||
Vector<InteriorSubObject*> mSubObjects;
|
||||
|
||||
// Lighting info
|
||||
bool mHasAlarmState;
|
||||
U32 mNumLightStateEntries;
|
||||
|
||||
Vector<GBitmap*> mLightmaps;
|
||||
Vector<bool> mLightmapKeep;
|
||||
Vector<U8> mNormalLMapIndices;
|
||||
Vector<U8> mAlarmLMapIndices;
|
||||
|
||||
U32 mNumTriggerableLights; // Note: not persisted
|
||||
|
||||
// Persistent animated light structures
|
||||
Vector<AnimatedLight> mAnimatedLights;
|
||||
Vector<LightState> mLightStates;
|
||||
Vector<LightStateData> mStateData;
|
||||
Vector<U8> mStateDataBuffer;
|
||||
|
||||
Vector<char> mNameBuffer;
|
||||
|
||||
Vector<ConvexHull> mConvexHulls;
|
||||
Vector<U8> mConvexHullEmitStrings;
|
||||
Vector<U32> mHullIndices;
|
||||
Vector<U32> mHullEmitStringIndices;
|
||||
Vector<U32> mHullSurfaceIndices;
|
||||
Vector<U16> mHullPlaneIndices;
|
||||
Vector<U16> mPolyListPlanes;
|
||||
Vector<U32> mPolyListPoints;
|
||||
Vector<U8> mPolyListStrings;
|
||||
CoordBin mCoordBins[NumCoordBins * NumCoordBins];
|
||||
Vector<U16> mCoordBinIndices;
|
||||
U32 mCoordBinMode;
|
||||
|
||||
Vector<ConvexHull> mVehicleConvexHulls;
|
||||
Vector<U8> mVehicleConvexHullEmitStrings;
|
||||
Vector<U32> mVehicleHullIndices;
|
||||
Vector<U32> mVehicleHullEmitStringIndices;
|
||||
Vector<U32> mVehicleHullSurfaceIndices;
|
||||
Vector<U16> mVehicleHullPlaneIndices;
|
||||
Vector<U16> mVehiclePolyListPlanes;
|
||||
Vector<U32> mVehiclePolyListPoints;
|
||||
Vector<U8> mVehiclePolyListStrings;
|
||||
Vector<ItrPaddedPoint> mVehiclePoints;
|
||||
Vector<NullSurface> mVehicleNullSurfaces;
|
||||
Vector<PlaneF> mVehiclePlanes;
|
||||
Vector<U32> mVehicleWindings;
|
||||
Vector<TriFan> mVehicleWindingIndices;
|
||||
|
||||
U16 mSearchTag;
|
||||
|
||||
//-------------------------------------- Private interface
|
||||
private:
|
||||
const char* getName(const U32 nameIndex) const;
|
||||
static const char* getLightTypeString(const LightType);
|
||||
S32 getZoneForPoint(const Point3F&) const;
|
||||
|
||||
void debugRender(MaterialList* pMaterials, LM_HANDLE instanceHandle);
|
||||
void debugRenderPortals();
|
||||
void debugNormalRenderLines();
|
||||
void debugShowDetail();
|
||||
void debugShowAmbiguous();
|
||||
void debugShowLightmaps(LM_HANDLE instanceHandle);
|
||||
void debugShowPortalZones();
|
||||
void debugShowCollisionFans();
|
||||
void debugShowOrphan();
|
||||
void debugShowStrips();
|
||||
void debugShowTexturesOnly(MaterialList* pMaterials);
|
||||
void debugShowLargeTextures(MaterialList* pMaterials);
|
||||
void debugShowNullSurfaces(MaterialList* pMaterials);
|
||||
void debugShowOutsideVisible();
|
||||
void debugShowHullSurfaces();
|
||||
void debugShowVehicleHullSurfaces(MaterialList* pMaterials);
|
||||
// void debugShowVertexColors(MaterialList* pMaterials);
|
||||
void debugShowDetailLevel();
|
||||
|
||||
void debugShowOrphansFinish();
|
||||
|
||||
void collisionFanFromSurface(const Surface&, U32* fan, U32* numIndices) const;
|
||||
void fullWindingFromSurface(const Surface&, U32* fan, U32* numIndices) const;
|
||||
bool projectClipAndBoundFan(U32 fanIndex, F64* pResult);
|
||||
void zoneTraversal(S32 baseZone, const bool flipClipPlanes);
|
||||
void createZoneRectVectors();
|
||||
void destroyZoneRectVectors();
|
||||
void traverseZone(const RectD* inRects, const U32 numInputRects, U32 currZone, Vector<U32>& zoneStack);
|
||||
void setupActivePolyList(ZoneVisDeterminer&, SceneState*,
|
||||
const Point3F&, const Point3F& rViewVector,
|
||||
const Point3F&,
|
||||
const F32 worldz, const Point3F& scale);
|
||||
|
||||
void setupFog(SceneState* state);
|
||||
void clearFog();
|
||||
void setOSCamPosition(const Point3F&);
|
||||
|
||||
public:
|
||||
void purgeLODData();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool Interior::isBSPLeafIndex(U16 index) const
|
||||
{
|
||||
return (index & 0x8000) != 0;
|
||||
}
|
||||
|
||||
inline bool Interior::isBSPSolidLeaf(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPLeafIndex(index) == true, "Error, only call for leaves!");
|
||||
return (index & 0x4000) != 0;
|
||||
}
|
||||
|
||||
inline bool Interior::isBSPEmptyLeaf(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPLeafIndex(index) == true, "Error, only call for leaves!");
|
||||
return (index & 0x4000) == 0;
|
||||
}
|
||||
|
||||
inline U16 Interior::getBSPSolidLeafIndex(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPSolidLeaf(index) == true, "Error, only call for leaves!");
|
||||
return U16(index & ~0xC000);
|
||||
}
|
||||
|
||||
inline U16 Interior::getBSPEmptyLeafZone(U16 index) const
|
||||
{
|
||||
AssertFatal(isBSPEmptyLeaf(index) == true, "Error, only call for leaves!");
|
||||
return U16(index & ~0xC000);
|
||||
}
|
||||
|
||||
inline const PlaneF& Interior::getPlane(U16 index) const
|
||||
{
|
||||
AssertFatal(U32(index & ~0x8000) < mPlanes.size(),
|
||||
"Interior::getPlane: planeIndex out of range");
|
||||
|
||||
return mPlanes[index & ~0x8000];
|
||||
}
|
||||
|
||||
inline U16 Interior::getPlaneIndex(U16 index)
|
||||
{
|
||||
return U16(index & ~0x8000);
|
||||
}
|
||||
|
||||
inline bool Interior::planeIsFlipped(U16 index)
|
||||
{
|
||||
return bool(index >> 15);
|
||||
// return (index & 0x8000) != 0;
|
||||
}
|
||||
|
||||
inline bool Interior::areEqualPlanes(U16 o, U16 t) const
|
||||
{
|
||||
return (o & ~0x8000) == (t & ~0x8000);
|
||||
}
|
||||
|
||||
inline U32 Interior::getDetailLevel() const
|
||||
{
|
||||
return mDetailLevel;
|
||||
}
|
||||
|
||||
inline U32 Interior::getMinPixels() const
|
||||
{
|
||||
return mMinPixels;
|
||||
}
|
||||
|
||||
inline const Box3F& Interior::getBoundingBox() const
|
||||
{
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
inline S32 Interior::getNumZones() const
|
||||
{
|
||||
return mZones.size();
|
||||
}
|
||||
|
||||
inline bool Interior::isNullSurfaceIndex(const U32 index) const
|
||||
{
|
||||
return (index & 0x80000000) != 0;
|
||||
}
|
||||
|
||||
inline bool Interior::isVehicleNullSurfaceIndex(const U32 index) const
|
||||
{
|
||||
return (index & 0x40000000) != 0;
|
||||
}
|
||||
|
||||
inline U32 Interior::getNullSurfaceIndex(const U32 index) const
|
||||
{
|
||||
AssertFatal(isNullSurfaceIndex(index), "Not a proper index!");
|
||||
AssertFatal(!isVehicleNullSurfaceIndex(index), "Not a proper index");
|
||||
return (index & ~0x80000000);
|
||||
}
|
||||
|
||||
inline U32 Interior::getVehicleNullSurfaceIndex(const U32 index) const
|
||||
{
|
||||
AssertFatal(isVehicleNullSurfaceIndex(index), "Not a proper index!");
|
||||
return (index & ~(0x80000000 | 0x40000000));
|
||||
}
|
||||
|
||||
inline const char* Interior::getLightTypeString(const LightType type)
|
||||
{
|
||||
switch (type) {
|
||||
case AmbientLooping:
|
||||
return "AmbientLooping";
|
||||
case AmbientFlicker:
|
||||
return "AmbientFlicker";
|
||||
case TriggerableLoop:
|
||||
return "TriggerableLoop";
|
||||
case TriggerableFlicker:
|
||||
return "TriggerableFlicker";
|
||||
case TriggerableRamp:
|
||||
return "TriggerableRamp";
|
||||
|
||||
default:
|
||||
return "<UNKNOWN>";
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* Interior::getName(const U32 nameIndex) const
|
||||
{
|
||||
return &mNameBuffer[nameIndex];
|
||||
}
|
||||
|
||||
inline const U32 Interior::getSurfaceCount() const
|
||||
{
|
||||
return(mSurfaces.size());
|
||||
}
|
||||
|
||||
inline const Interior::Surface & Interior::getSurface(const U32 surface) const
|
||||
{
|
||||
AssertFatal(surface < mSurfaces.size(), "invalid index");
|
||||
return(mSurfaces[surface]);
|
||||
}
|
||||
|
||||
inline const U8 Interior::getNormalLMapIndex(const U32 surface) const
|
||||
{
|
||||
AssertFatal(surface < mNormalLMapIndices.size(), "invalid index");
|
||||
return(mNormalLMapIndices[surface]);
|
||||
}
|
||||
|
||||
inline const U8 Interior::getAlarmLMapIndex(const U32 surface) const
|
||||
{
|
||||
AssertFatal(surface < mAlarmLMapIndices.size(), "invalid index");
|
||||
return(mAlarmLMapIndices[surface]);
|
||||
}
|
||||
|
||||
inline const U32 Interior::getWinding(const U32 index) const
|
||||
{
|
||||
AssertFatal(index < mWindings.size(), "invalid index");
|
||||
return(mWindings[index]);
|
||||
}
|
||||
|
||||
inline const Point3F & Interior::getPoint(const U32 index) const
|
||||
{
|
||||
AssertFatal(index < mPoints.size(), "invalid index");
|
||||
return(mPoints[index].point);
|
||||
}
|
||||
|
||||
inline const Interior::TexGenPlanes & Interior::getLMTexGenEQ(const U32 index) const
|
||||
{
|
||||
AssertFatal(index < mLMTexGenEQs.size(), "invalid index");
|
||||
return(mLMTexGenEQs[index]);
|
||||
}
|
||||
|
||||
inline bool Interior::hasAlarmState() const
|
||||
{
|
||||
return(mHasAlarmState);
|
||||
}
|
||||
|
||||
inline const bool Interior::isSurfaceOutsideVisible(U32 surface) const
|
||||
{
|
||||
AssertFatal(surface < mSurfaces.size(), "Interior::isSrufaceOutsideVisible: Invalid surface index");
|
||||
return(mSurfaces[surface].surfaceFlags & SurfaceOutsideVisible);
|
||||
}
|
||||
|
||||
inline const U32 Interior::getWindingCount() const
|
||||
{
|
||||
return(mWindings.size());
|
||||
}
|
||||
|
||||
#endif //_INTERIOR_H_
|
||||
1623
interior/interiorCollision.cc
Normal file
1623
interior/interiorCollision.cc
Normal file
File diff suppressed because it is too large
Load diff
803
interior/interiorDebug.cc
Normal file
803
interior/interiorDebug.cc
Normal file
|
|
@ -0,0 +1,803 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/interior.h"
|
||||
#include "console/console.h"
|
||||
#include "core/color.h"
|
||||
#include "platformWIN32/platformGL.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "dgl/materialList.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
|
||||
extern U16* sgActivePolyList;
|
||||
extern U32 sgActivePolyListSize;
|
||||
|
||||
namespace {
|
||||
|
||||
void lineLoopFromStrip(Vector<ItrPaddedPoint>& points,
|
||||
Vector<U32>& windings,
|
||||
U32 windingStart,
|
||||
U32 windingCount)
|
||||
{
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(points[windings[windingStart]].point);
|
||||
|
||||
S32 skip = windingStart + 1;
|
||||
while (skip < (windingStart + windingCount)) {
|
||||
glVertex3fv(points[windings[skip]].point);
|
||||
skip += 2;
|
||||
}
|
||||
|
||||
skip -= 1;
|
||||
while (skip > windingStart) {
|
||||
if (skip < (windingStart + windingCount))
|
||||
glVertex3fv(points[windings[skip]].point);
|
||||
skip -= 2;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void lineStrip(Vector<ItrPaddedPoint>& points,
|
||||
Vector<U32>& windings,
|
||||
U32 windingStart,
|
||||
U32 windingCount)
|
||||
{
|
||||
U32 end = 2;
|
||||
|
||||
while (end < windingCount) {
|
||||
// Even
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(points[windings[windingStart + end - 2]].point);
|
||||
glVertex3fv(points[windings[windingStart + end - 1]].point);
|
||||
glVertex3fv(points[windings[windingStart + end - 0]].point);
|
||||
glEnd();
|
||||
|
||||
end++;
|
||||
if (end >= windingCount)
|
||||
break;
|
||||
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(points[windings[windingStart + end - 1]].point);
|
||||
glVertex3fv(points[windings[windingStart + end - 2]].point);
|
||||
glVertex3fv(points[windings[windingStart + end - 0]].point);
|
||||
glEnd();
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace {}
|
||||
|
||||
|
||||
void Interior::debugRender(MaterialList* pMaterials, LM_HANDLE instanceHandle)
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ItrPaddedPoint), mPoints.address());
|
||||
|
||||
switch (smRenderMode) {
|
||||
case NormalRenderLines:
|
||||
debugNormalRenderLines();
|
||||
break;
|
||||
|
||||
case ShowDetail:
|
||||
debugShowDetail();
|
||||
break;
|
||||
|
||||
case ShowAmbiguous:
|
||||
debugShowAmbiguous();
|
||||
break;
|
||||
|
||||
case ShowLightmaps:
|
||||
debugShowLightmaps(instanceHandle);
|
||||
break;
|
||||
|
||||
case ShowPortalZones:
|
||||
debugShowPortalZones();
|
||||
break;
|
||||
|
||||
case ShowCollisionFans:
|
||||
debugShowCollisionFans();
|
||||
break;
|
||||
|
||||
case ShowOrphan:
|
||||
debugShowOrphan();
|
||||
break;
|
||||
|
||||
case ShowStrips:
|
||||
debugShowStrips();
|
||||
break;
|
||||
|
||||
case ShowTexturesOnly:
|
||||
debugShowTexturesOnly(pMaterials);
|
||||
break;
|
||||
|
||||
case ShowNullSurfaces:
|
||||
debugShowNullSurfaces(pMaterials);
|
||||
break;
|
||||
|
||||
case ShowLargeTextures:
|
||||
debugShowLargeTextures(pMaterials);
|
||||
break;
|
||||
|
||||
case ShowOutsideVisible:
|
||||
debugShowOutsideVisible();
|
||||
break;
|
||||
|
||||
case ShowHullSurfaces:
|
||||
debugShowHullSurfaces();
|
||||
break;
|
||||
|
||||
case ShowVehicleHullSurfaces:
|
||||
debugShowVehicleHullSurfaces(pMaterials);
|
||||
break;
|
||||
|
||||
case ShowVertexColors:
|
||||
// debugShowVertexColors(pMaterials);
|
||||
break;
|
||||
|
||||
case ShowDetailLevel:
|
||||
debugShowDetailLevel();
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertWarn(false, "Warning! Misunderstood debug render mode. Defaulting to ShowDetail");
|
||||
debugShowDetail();
|
||||
break;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void Interior::debugNormalRenderLines()
|
||||
{
|
||||
// Ok, our verts are set up, draw our polys.
|
||||
U32 currentlyBound = U32(-1);
|
||||
U32 currentTexGen = U32(-1);
|
||||
|
||||
// Base textures
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(1, 0, 1);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowDetail()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (rSurface.surfaceFlags & SurfaceDetail)
|
||||
glColor3f(1.0f, 0, 0);
|
||||
else {
|
||||
if (smFocusedDebug == true)
|
||||
continue;
|
||||
else
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
if (smFocusedDebug == false) {
|
||||
glColor3f(0, 0, 0);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowAmbiguous()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (rSurface.surfaceFlags & SurfaceAmbiguous)
|
||||
glColor3f(0, 1.0f, 0);
|
||||
else {
|
||||
if (smFocusedDebug == true)
|
||||
continue;
|
||||
else
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
if (smFocusedDebug == false) {
|
||||
glColor3f(0, 0, 0);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowLightmaps(LM_HANDLE instanceHandle)
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
U32 currentlyBound = U32(-1);
|
||||
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (mNormalLMapIndices[sgActivePolyList[i]] != currentlyBound) {
|
||||
glBindTexture(GL_TEXTURE_2D, gInteriorLMManager.getHandle(mLMHandle, instanceHandle, mNormalLMapIndices[sgActivePolyList[i]])->getGLName());
|
||||
currentlyBound = mNormalLMapIndices[sgActivePolyList[i]];
|
||||
}
|
||||
|
||||
// Draw the poly
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++) {
|
||||
glTexCoord2f(mLMTexGenEQs[sgActivePolyList[i]].planeX.distToPlane(mPoints[mWindings[j]].point),
|
||||
mLMTexGenEQs[sgActivePolyList[i]].planeY.distToPlane(mPoints[mWindings[j]].point));
|
||||
glVertex3fv(mPoints[mWindings[j]].point);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(0, 0, 0);
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowPortalZones()
|
||||
{
|
||||
static U8 colors[14][3] = {
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x00, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0x00 },
|
||||
{ 0xFF, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0xFF },
|
||||
{ 0x80, 0x80, 0x80 },
|
||||
{ 0xFF, 0x80, 0x80 },
|
||||
{ 0x80, 0xFF, 0x80 },
|
||||
{ 0x80, 0x80, 0xFF },
|
||||
{ 0x80, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x80, 0xFF },
|
||||
{ 0xFF, 0x80, 0x80 }
|
||||
};
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
for (U32 i = 0; i < mZones.size(); i++) {
|
||||
U8* color;
|
||||
if (i == 0)
|
||||
color = colors[0];
|
||||
else
|
||||
color = colors[(i % 13) + 1];
|
||||
|
||||
for (U32 j = mZones[i].surfaceStart; j < mZones[i].surfaceStart + mZones[i].surfaceCount; j++) {
|
||||
const Surface& rSurface = mSurfaces[mZoneSurfaces[j]];
|
||||
|
||||
glColor3ub(color[0], color[1], color[2]);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
glColor3ub(0, 0, 0);
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
debugRenderPortals();
|
||||
}
|
||||
|
||||
void Interior::debugRenderPortals()
|
||||
{
|
||||
//-------------------------------------- Render portals...
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
for (U32 i = 0; i < mPortals.size(); i++) {
|
||||
const Portal& rPortal = mPortals[i];
|
||||
|
||||
for (U16 j = 0; j < rPortal.triFanCount; j++) {
|
||||
const TriFan& rFan = mWindingIndices[rPortal.triFanStart + j];
|
||||
U32 k;
|
||||
|
||||
glColor4f(0.75, 0.5, 0.75, 0.45);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
for (k = 0; k < rFan.windingCount; k++)
|
||||
glVertex3fv(mPoints[mWindings[rFan.windingStart + k]].point);
|
||||
glEnd();
|
||||
glColor4f(0, 0, 1, 1);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (k = 0; k < rFan.windingCount; k++)
|
||||
glVertex3fv(mPoints[mWindings[rFan.windingStart + k]].point);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interior::debugShowCollisionFans()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 numIndices;
|
||||
U32 fanIndices[32];
|
||||
collisionFanFromSurface(rSurface, fanIndices, &numIndices);
|
||||
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glDrawElements(GL_TRIANGLE_FAN, numIndices, GL_UNSIGNED_INT, fanIndices);
|
||||
}
|
||||
|
||||
glColor3f(0, 0, 0);
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 numIndices;
|
||||
U32 fanIndices[32];
|
||||
collisionFanFromSurface(rSurface, fanIndices, &numIndices);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (U32 j = 0; j < numIndices; j++)
|
||||
glVertex3fv(mPoints[fanIndices[j]].point);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 numIndices;
|
||||
U32 fanIndices[32];
|
||||
collisionFanFromSurface(rSurface, fanIndices, &numIndices);
|
||||
|
||||
glColor3f(1, 0, 0);
|
||||
glBegin(GL_LINES);
|
||||
for (U32 j = 0; j < numIndices; j++) {
|
||||
Point3F up = mPoints[fanIndices[j]].point;
|
||||
Point3F norm = getPlane(rSurface.planeIndex);
|
||||
if (planeIsFlipped(rSurface.planeIndex))
|
||||
up -= norm * 0.4;
|
||||
else
|
||||
up += norm * 0.4;
|
||||
|
||||
glVertex3fv(mPoints[fanIndices[j]].point);
|
||||
glVertex3fv(up);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Interior::debugShowOrphan()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (rSurface.surfaceFlags & SurfaceOrphan)
|
||||
glColor3f(0.0f, 0.0f, 1.0f);
|
||||
else {
|
||||
if (smFocusedDebug == true)
|
||||
continue;
|
||||
else
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
if (smFocusedDebug == false) {
|
||||
glColor3f(0, 0, 0);
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Interior::debugShowOrphansFinish()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Interior::debugShowStrips()
|
||||
{
|
||||
static U8 colors[14][3] = {
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x00, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0x00 },
|
||||
{ 0xFF, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0xFF },
|
||||
{ 0x80, 0x80, 0x80 },
|
||||
{ 0xFF, 0x80, 0x80 },
|
||||
{ 0x80, 0xFF, 0x80 },
|
||||
{ 0x80, 0x80, 0xFF },
|
||||
{ 0x80, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x80, 0xFF },
|
||||
{ 0xFF, 0x80, 0x80 }
|
||||
};
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
U32 color = 0;
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
glColor3ub(colors[sgActivePolyList[i]%14][0],
|
||||
colors[sgActivePolyList[i]%14][1],
|
||||
colors[sgActivePolyList[i]%14][2]);
|
||||
color++;
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
glColor3f(0, 0, 0);
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowNullSurfaces(MaterialList* pMaterials)
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
// Base textures
|
||||
U32 currentlyBound = U32(-1);
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 baseName = pMaterials->getMaterial(rSurface.textureIndex).getGLName();
|
||||
if (baseName != currentlyBound) {
|
||||
glBindTexture(GL_TEXTURE_2D, baseName);
|
||||
currentlyBound = baseName;
|
||||
}
|
||||
|
||||
// Draw the poly
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++) {
|
||||
glTexCoord2f(mTexGenEQs[rSurface.texGenIndex].planeX.distToPlane(mPoints[mWindings[j]].point),
|
||||
mTexGenEQs[rSurface.texGenIndex].planeY.distToPlane(mPoints[mWindings[j]].point));
|
||||
glVertex3fv(mPoints[mWindings[j]].point);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
glColor3f(1, 0, 0);
|
||||
for (i = 0; i < mNullSurfaces.size(); i++) {
|
||||
const NullSurface& rSurface = mNullSurfaces[i];
|
||||
|
||||
glDrawElements(GL_TRIANGLE_FAN, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Interior::debugShowTexturesOnly(MaterialList* pMaterials)
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
// Base textures
|
||||
U32 currentlyBound = U32(-1);
|
||||
U32 i;
|
||||
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (pMaterials->getMaterial(rSurface.textureIndex).getGLName() != currentlyBound) {
|
||||
glBindTexture(GL_TEXTURE_2D, pMaterials->getMaterial(rSurface.textureIndex).getGLName());
|
||||
currentlyBound = mMaterialList->getMaterial(rSurface.textureIndex).getGLName();
|
||||
}
|
||||
|
||||
// Draw the poly
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++) {
|
||||
glTexCoord2f(mTexGenEQs[rSurface.texGenIndex].planeX.distToPlane(mPoints[mWindings[j]].point),
|
||||
mTexGenEQs[rSurface.texGenIndex].planeY.distToPlane(mPoints[mWindings[j]].point));
|
||||
glVertex3fv(mPoints[mWindings[j]].point);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void Interior::debugShowLargeTextures(MaterialList* pMaterials)
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
// Base textures
|
||||
U32 currentlyBound = U32(-1);
|
||||
U32 currentTexGen = U32(-1);
|
||||
U32 i;
|
||||
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 baseName = pMaterials->getMaterial(rSurface.textureIndex).getGLName();
|
||||
if (baseName != currentlyBound) {
|
||||
glBindTexture(GL_TEXTURE_2D, baseName);
|
||||
currentlyBound = baseName;
|
||||
|
||||
U32 width = pMaterials->getMaterial(rSurface.textureIndex).getWidth();
|
||||
U32 height = pMaterials->getMaterial(rSurface.textureIndex).getHeight();
|
||||
if (width >= 256 || height >= 256) {
|
||||
if (width == 256 && height == 256) {
|
||||
// small large
|
||||
glColor3f(0.25, 0.25, 1);
|
||||
} else if (width != 512 || height != 512) {
|
||||
// thin large
|
||||
glColor3f(0.25, 1, 0.25);
|
||||
} else {
|
||||
// oh god.
|
||||
glColor3f(1, 0.25, 0.25);
|
||||
}
|
||||
} else {
|
||||
glColor3f(0.35, 0.35, 0.35);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the poly
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++) {
|
||||
glTexCoord2f(mTexGenEQs[rSurface.texGenIndex].planeX.distToPlane(mPoints[mWindings[j]].point),
|
||||
mTexGenEQs[rSurface.texGenIndex].planeY.distToPlane(mPoints[mWindings[j]].point));
|
||||
glVertex3fv(mPoints[mWindings[j]].point);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Interior::debugShowOutsideVisible()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
if (rSurface.surfaceFlags & SurfaceOutsideVisible)
|
||||
glColor3f(1.0f, 0, 0);
|
||||
else {
|
||||
if (smFocusedDebug == true)
|
||||
continue;
|
||||
else
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
if (smFocusedDebug == false) {
|
||||
glColor3f(0, 0, 0);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Interior::debugShowHullSurfaces()
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
static U8 colors[14][3] = {
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x00, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0x00 },
|
||||
{ 0xFF, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0xFF },
|
||||
{ 0x80, 0x80, 0x80 },
|
||||
{ 0xFF, 0x80, 0x80 },
|
||||
{ 0x80, 0xFF, 0x80 },
|
||||
{ 0x80, 0x80, 0xFF },
|
||||
{ 0x80, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x80, 0xFF },
|
||||
{ 0xFF, 0x80, 0x80 }
|
||||
};
|
||||
U32 color = 0;
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
for (U32 i = 0; i < mConvexHulls.size(); i++) {
|
||||
const ConvexHull& rHull = mConvexHulls[i];
|
||||
for (U32 j = rHull.surfaceStart; j < rHull.surfaceCount + rHull.surfaceStart; j++) {
|
||||
U32 index = mHullSurfaceIndices[j];
|
||||
if (isNullSurfaceIndex(index)) {
|
||||
} else {
|
||||
const Interior::Surface& rSurface = mSurfaces[index];
|
||||
U32 fanVerts[32];
|
||||
U32 numVerts;
|
||||
collisionFanFromSurface(rSurface, fanVerts, &numVerts);
|
||||
|
||||
glColor3ub(colors[(i%13)+1][0], colors[(i%13)+1][1], colors[(i%13)+1][2]);
|
||||
color++;
|
||||
Point3F center(0, 0, 0);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
for (U32 k = 0; k < numVerts; k++) {
|
||||
glVertex3fv(mPoints[fanVerts[k]].point);
|
||||
center += mPoints[fanVerts[k]].point;
|
||||
}
|
||||
glEnd();
|
||||
center /= F32(numVerts);
|
||||
glColor3f(0, 0, 0);
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
|
||||
PlaneF plane;
|
||||
plane.set(mPoints[fanVerts[0]].point, mPoints[fanVerts[1]].point, mPoints[fanVerts[2]].point);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(center);
|
||||
glVertex3fv(center + (plane * 0.25));
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void Interior::debugShowVehicleHullSurfaces(MaterialList* pMaterials)
|
||||
{
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
// Base textures
|
||||
U32 currentlyBound = U32(-1);
|
||||
U32 i;
|
||||
for (i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
U32 baseName = pMaterials->getMaterial(rSurface.textureIndex).getGLName();
|
||||
if (baseName != currentlyBound) {
|
||||
glBindTexture(GL_TEXTURE_2D, baseName);
|
||||
currentlyBound = baseName;
|
||||
}
|
||||
|
||||
// Draw the poly
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++) {
|
||||
glTexCoord2f(mTexGenEQs[rSurface.texGenIndex].planeX.distToPlane(mPoints[mWindings[j]].point),
|
||||
mTexGenEQs[rSurface.texGenIndex].planeY.distToPlane(mPoints[mWindings[j]].point));
|
||||
glVertex3fv(mPoints[mWindings[j]].point);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ItrPaddedPoint), mVehiclePoints.address());
|
||||
|
||||
glColor3f(1, 0, 0);
|
||||
for (i = 0; i < mVehicleNullSurfaces.size(); i++) {
|
||||
const NullSurface& rSurface = mNullSurfaces[i];
|
||||
|
||||
glDrawElements(GL_TRIANGLE_FAN, rSurface.windingCount, GL_UNSIGNED_INT, &mVehicleWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
// void Interior::debugShowVertexColors(MaterialList* /*pMaterials*/)
|
||||
// {
|
||||
// glDisable(GL_TEXTURE_2D);
|
||||
// glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
// for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
// const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
// glBegin(GL_TRIANGLE_STRIP);
|
||||
// for (U32 j = rSurface.windingStart; j < rSurface.windingStart + rSurface.windingCount; j++)
|
||||
// {
|
||||
// const ItrPaddedPoint& rPoint = mPoints[mWindings[j]];
|
||||
// glColor3ub(mVertexColorsNormal[j].red,
|
||||
// mVertexColorsNormal[j].green,
|
||||
// mVertexColorsNormal[j].blue);
|
||||
// glVertex3fv(rPoint.point);
|
||||
// }
|
||||
// glEnd();
|
||||
// }
|
||||
|
||||
// if (smFocusedDebug == false) {
|
||||
// glColor3f(0, 0, 0);
|
||||
// for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
// const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
// lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
// }
|
||||
// }
|
||||
|
||||
// glEnable(GL_TEXTURE_2D);
|
||||
// }
|
||||
|
||||
|
||||
void Interior::debugShowDetailLevel()
|
||||
{
|
||||
static U8 colors[14][3] = {
|
||||
{ 0xFF, 0xFF, 0xFF },
|
||||
{ 0x00, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0x00 },
|
||||
{ 0xFF, 0xFF, 0x00 },
|
||||
{ 0xFF, 0x00, 0xFF },
|
||||
{ 0x00, 0xFF, 0xFF },
|
||||
{ 0x80, 0x80, 0x80 },
|
||||
{ 0xFF, 0x80, 0x80 },
|
||||
{ 0x80, 0xFF, 0x80 },
|
||||
{ 0x80, 0x80, 0xFF },
|
||||
{ 0x80, 0xFF, 0xFF },
|
||||
{ 0xFF, 0x80, 0xFF },
|
||||
{ 0xFF, 0x80, 0x80 }
|
||||
};
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
|
||||
glColor3ubv(colors[getDetailLevel()]);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, rSurface.windingCount, GL_UNSIGNED_INT, &mWindings[rSurface.windingStart]);
|
||||
}
|
||||
|
||||
if (smFocusedDebug == false) {
|
||||
glColor3f(0, 0, 0);
|
||||
for (U32 i = 0; i < sgActivePolyListSize; i++) {
|
||||
const Surface& rSurface = mSurfaces[sgActivePolyList[i]];
|
||||
lineLoopFromStrip(mPoints, mWindings, rSurface.windingStart, rSurface.windingCount);
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
1128
interior/interiorIO.cc
Normal file
1128
interior/interiorIO.cc
Normal file
File diff suppressed because it is too large
Load diff
1965
interior/interiorInstance.cc
Normal file
1965
interior/interiorInstance.cc
Normal file
File diff suppressed because it is too large
Load diff
293
interior/interiorInstance.h
Normal file
293
interior/interiorInstance.h
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIORINSTANCE_H_
|
||||
#define _INTERIORINSTANCE_H_
|
||||
|
||||
//Includes
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "sim/sceneObject.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "core/resManager.h"
|
||||
#endif
|
||||
#ifndef _INTERIORRES_H_
|
||||
#include "interior/interiorRes.h"
|
||||
#endif
|
||||
#ifndef _INTERIORLMMANAGER_H_
|
||||
#include "interior/interiorLMManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _BITVECTOR_H_
|
||||
#include "core/bitVector.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
|
||||
class AbstractPolyList;
|
||||
class LightUpdateGrouper;
|
||||
class InteriorSubObject;
|
||||
class InteriorResTrigger;
|
||||
class MaterialList;
|
||||
class TextureObject;
|
||||
class FloorPlan;
|
||||
class Convex;
|
||||
class AudioProfile;
|
||||
class AudioEnvironment;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class InteriorInstance : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
friend class SceneLighting;
|
||||
friend class FloorPlan;
|
||||
|
||||
public:
|
||||
InteriorInstance();
|
||||
~InteriorInstance();
|
||||
|
||||
static void init();
|
||||
static void destroy();
|
||||
|
||||
// Collision
|
||||
public:
|
||||
bool buildPolyList(AbstractPolyList*, const Box3F&, const SphereF&);
|
||||
bool castRay(const Point3F&, const Point3F&, RayInfo*);
|
||||
virtual void setTransform(const MatrixF&);
|
||||
|
||||
void buildConvex(const Box3F& box,Convex* convex);
|
||||
private:
|
||||
Convex* mConvexList;
|
||||
|
||||
// Lighting control
|
||||
public:
|
||||
bool inAlarmState() {return(mAlarmState);}
|
||||
void setAlarmMode(const bool alarm);
|
||||
void activateLight(const char* pLightName);
|
||||
void deactivateLight(const char* pLightName);
|
||||
void echoTriggerableLights();
|
||||
|
||||
// Subobject access interface
|
||||
public:
|
||||
U32 getNumDetailLevels();
|
||||
Interior* getDetailLevel(const U32);
|
||||
void setDetailLevel(S32 level = -1) { mForcedDetailLevel = level; }
|
||||
|
||||
// Material management for overlays
|
||||
public:
|
||||
void renewOverlays();
|
||||
void setSkinBase(const char*);
|
||||
|
||||
public:
|
||||
static bool smDontRestrictOutside;
|
||||
static F32 smDetailModification;
|
||||
|
||||
|
||||
DECLARE_CONOBJECT(InteriorInstance);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
bool readLightmaps(GBitmap**** lightmaps);
|
||||
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
void inspectPreApply();
|
||||
void inspectPostApply();
|
||||
|
||||
static U32 smLightUpdatePeriod;
|
||||
static bool smRenderDynamicLights;
|
||||
|
||||
U32 mLightUpdatedTime;
|
||||
void setLightUpdatedTime(const U32);
|
||||
U32 getLightUpdatedTime() const;
|
||||
|
||||
bool onSceneAdd(SceneGraph*);
|
||||
void onSceneRemove();
|
||||
U32 getPointZone(const Point3F& p);
|
||||
bool getOverlappingZones(SceneObject* obj, U32* zones, U32* numZones);
|
||||
|
||||
U32 calcDetailLevel(SceneState*, const Point3F&);
|
||||
bool prepRenderImage(SceneState*, const U32, const U32, const bool);
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
bool scopeObject(const Point3F& rootPosition,
|
||||
const F32 rootDistance,
|
||||
bool* zoneScopeState);
|
||||
|
||||
public:
|
||||
void addChildren();
|
||||
static bool getRenderDynamicLights() { return(smRenderDynamicLights); }
|
||||
static void setRenderDynamicLights(bool val) { smRenderDynamicLights = val; }
|
||||
|
||||
private:
|
||||
void activateLight(const U32 detail, const U32 lightIndex);
|
||||
void deactivateLight(const U32 detail, const U32 lightIndex);
|
||||
|
||||
U32 packUpdate(NetConnection *, U32 mask, BitStream *stream);
|
||||
void unpackUpdate(NetConnection *, BitStream *stream);
|
||||
|
||||
|
||||
enum UpdateMaskBits {
|
||||
InitMask = 1 << 0,
|
||||
TransformMask = 1 << 1,
|
||||
AlarmMask = 1 << 2,
|
||||
|
||||
// Reserved for light updates (8 bits for now)
|
||||
_lightupdate0 = 1 << 3,
|
||||
_lightupdate1 = 1 << 4,
|
||||
_lightupdate2 = 1 << 5,
|
||||
_lightupdate3 = 1 << 6,
|
||||
_lightupdate4 = 1 << 7,
|
||||
_lightupdate5 = 1 << 8,
|
||||
_lightupdate6 = 1 << 9,
|
||||
_lightupdate7 = 1 << 10,
|
||||
|
||||
SkinBaseMask = 1 << 11,
|
||||
AudioMask = 1 << 12,
|
||||
NextFreeMask = 1 << 13
|
||||
};
|
||||
enum Constants {
|
||||
LightUpdateBitStart = 3,
|
||||
LightUpdateBitEnd = 10
|
||||
};
|
||||
|
||||
private:
|
||||
StringTableEntry mInteriorFileName;
|
||||
U32 mInteriorFileHash;
|
||||
Resource<InteriorResource> mInteriorRes;
|
||||
Vector<MaterialList*> mMaterialMaps;
|
||||
StringTableEntry mSkinBase;
|
||||
|
||||
Vector< Vector<InteriorSubObject*> > mInteriorSubObjects;
|
||||
bool mShowTerrainInside;
|
||||
LM_HANDLE mLMHandle;
|
||||
AudioProfile * mAudioProfile;
|
||||
AudioEnvironment * mAudioEnvironment;
|
||||
S32 mForcedDetailLevel;
|
||||
U32 mCRC;
|
||||
|
||||
public:
|
||||
LM_HANDLE getLMHandle() { return(mLMHandle); }
|
||||
AudioProfile * getAudioProfile() { return(mAudioProfile); }
|
||||
AudioEnvironment * getAudioEnvironment() { return(mAudioEnvironment); }
|
||||
bool getPointInsideScale(const Point3F & pos, F32 * pScale); // ~0: outside -> 1: inside
|
||||
|
||||
// SceneLighting::InteriorProxy interface
|
||||
Resource<InteriorResource> & getResource() {return(mInteriorRes);}
|
||||
U32 getCRC() { return(mCRC); }
|
||||
|
||||
Vector<Vector<ColorI>*> mVertexColorsNormal;
|
||||
Vector<Vector<ColorI>*> mVertexColorsAlarm;
|
||||
void rebuildVertexColors();
|
||||
Vector<ColorI>* getVertexColorsNormal(U32 detail);
|
||||
Vector<ColorI>* getVertexColorsAlarm(U32 detail);
|
||||
|
||||
// Alarm state information
|
||||
private:
|
||||
enum AlarmState {
|
||||
Normal = 0,
|
||||
Alarm = 1
|
||||
};
|
||||
|
||||
bool mAlarmState;
|
||||
|
||||
// LightingAnimation information
|
||||
private:
|
||||
struct LightInfo {
|
||||
struct Light {
|
||||
U32 curState;
|
||||
U32 curTime;
|
||||
ColorI curColor;
|
||||
|
||||
bool active;
|
||||
bool alarm;
|
||||
};
|
||||
struct StateDataInfo {
|
||||
ColorI curColor;
|
||||
U8* curMap;
|
||||
bool alarm;
|
||||
};
|
||||
|
||||
Vector<Light> mLights;
|
||||
BitVector mSurfaceInvalid;
|
||||
Vector<StateDataInfo> mStateDataInfo;
|
||||
};
|
||||
Vector<LightInfo> mLightInfo; // One for each detail level.
|
||||
LightUpdateGrouper* mUpdateGrouper; // Cuts down on net traffic
|
||||
|
||||
static U32 makeUpdateKey(const U32 detail, const U32 lightIndex);
|
||||
static U32 detailFromUpdateKey(const U32 key);
|
||||
static U32 indexFromUpdateKey(const U32 key);
|
||||
|
||||
// Animated light functions
|
||||
void updateLightTime(const U32 detail, const U32 lightIndex, const U32 ms);
|
||||
void downloadLightmaps(SceneState*, Interior*, LightInfo&);
|
||||
void installLight(const U32 detail, const U32 lightIndex);
|
||||
void updateLoopingLight(Interior*, LightInfo::Light&, const U32 lightIndex, const U32 ms);
|
||||
void updateFlickerLight(Interior*, LightInfo::Light&, const U32 lightIndex, const U32 ms);
|
||||
void updateRampLight(Interior*, LightInfo::Light&, const U32 lightIndex, const U32 ms);
|
||||
void updateAllLights(const U32);
|
||||
|
||||
void updateLightMap(Interior*, LightInfo&, const U32 surfaceIndex);
|
||||
void intensityMapMerge(U8* lightMap,
|
||||
const U32 width, const U32 height,
|
||||
const U8* intensityMap, const ColorI& color);
|
||||
|
||||
private:
|
||||
void createTriggerTransform(const InteriorResTrigger*, MatrixF*);
|
||||
};
|
||||
|
||||
inline void InteriorInstance::setLightUpdatedTime(const U32 now)
|
||||
{
|
||||
mLightUpdatedTime = now;
|
||||
}
|
||||
|
||||
inline U32 InteriorInstance::getLightUpdatedTime() const
|
||||
{
|
||||
return mLightUpdatedTime;
|
||||
}
|
||||
|
||||
inline U32 InteriorInstance::makeUpdateKey(const U32 detail, const U32 lightIndex)
|
||||
{
|
||||
AssertFatal(detail < (1 << 16) && lightIndex < (1 << 16), "Error, out of bounds key params");
|
||||
|
||||
return (detail << 16) | (lightIndex & 0x0000FFFF);
|
||||
}
|
||||
|
||||
inline U32 InteriorInstance::detailFromUpdateKey(const U32 key)
|
||||
{
|
||||
return (key >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
inline U32 InteriorInstance::indexFromUpdateKey(const U32 key)
|
||||
{
|
||||
return (key >> 0) & 0xFFFF;
|
||||
}
|
||||
|
||||
inline Vector<ColorI>* InteriorInstance::getVertexColorsNormal(U32 detail)
|
||||
{
|
||||
if (bool(mInteriorRes) == false || detail > mInteriorRes->getNumDetailLevels())
|
||||
return NULL;
|
||||
|
||||
return mVertexColorsNormal[detail];
|
||||
}
|
||||
|
||||
inline Vector<ColorI>* InteriorInstance::getVertexColorsAlarm(U32 detail)
|
||||
{
|
||||
if (bool(mInteriorRes) == false || detail > mInteriorRes->getNumDetailLevels())
|
||||
return NULL;
|
||||
|
||||
return mVertexColorsAlarm[detail];
|
||||
}
|
||||
|
||||
#endif //_INTERIORBLOCK_H_
|
||||
|
||||
549
interior/interiorLMManager.cc
Normal file
549
interior/interiorLMManager.cc
Normal file
|
|
@ -0,0 +1,549 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/interiorLMManager.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
#include "interior/interiorRes.h"
|
||||
#include "interior/interiorInstance.h"
|
||||
#include "interior/interior.h"
|
||||
#include "sceneGraph/sceneLighting.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Globals
|
||||
InteriorLMManager gInteriorLMManager;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace {
|
||||
void interiorLMTextureCallback(const U32 eventCode, const U32 userData)
|
||||
{
|
||||
AssertFatal(&gInteriorLMManager == reinterpret_cast<InteriorLMManager*>(userData), "Bunk ptr!");
|
||||
gInteriorLMManager.processTextureEvent(eventCode);
|
||||
}
|
||||
|
||||
// '<interior>_<instance index>_lm_<lightmap index>.png'
|
||||
const char * getTextureName(Interior * interior, U32 instance, U32 lightmap)
|
||||
{
|
||||
static char buffer[256];
|
||||
dSprintf(buffer, sizeof(buffer), "%p_%d_lm_%d.png", interior, instance, lightmap);
|
||||
return(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
U32 InteriorLMManager::smTextureCallbackKey = U32(-1);
|
||||
|
||||
// D3D vertex buffers for Interiors are in here so they get dumped/reallocated
|
||||
// along with the lightmaps on the texture events
|
||||
S32 InteriorLMManager::smMTVertexBuffer = -1;
|
||||
S32 InteriorLMManager::smFTVertexBuffer = -1;
|
||||
S32 InteriorLMManager::smFMTVertexBuffer = -1;
|
||||
|
||||
InteriorLMManager::InteriorLMManager()
|
||||
{
|
||||
}
|
||||
|
||||
InteriorLMManager::~InteriorLMManager()
|
||||
{
|
||||
for(U32 i = 0; i < mInteriors.size(); i++)
|
||||
removeInterior(LM_HANDLE(i));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void InteriorLMManager::init()
|
||||
{
|
||||
smTextureCallbackKey = TextureManager::registerEventCallback(interiorLMTextureCallback, reinterpret_cast<U32>(&gInteriorLMManager));
|
||||
}
|
||||
|
||||
void InteriorLMManager::destroy()
|
||||
{
|
||||
if(smTextureCallbackKey != U32(-1))
|
||||
{
|
||||
TextureManager::unregisterEventCallback(smTextureCallbackKey);
|
||||
smTextureCallbackKey = U32(-1);
|
||||
}
|
||||
|
||||
if (smMTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smMTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smMTVertexBuffer = -1;
|
||||
}
|
||||
if (smFTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smFTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smFTVertexBuffer = -1;
|
||||
}
|
||||
if (smFMTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smFMTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smFMTVertexBuffer = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorLMManager::processTextureEvent(U32 eventCode)
|
||||
{
|
||||
switch(eventCode)
|
||||
{
|
||||
case TextureManager::BeginZombification:
|
||||
purgeGLTextures();
|
||||
|
||||
if (smMTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smMTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smMTVertexBuffer = -1;
|
||||
}
|
||||
if (smFTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smFTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smFTVertexBuffer = -1;
|
||||
}
|
||||
if (smFMTVertexBuffer != -1)
|
||||
{
|
||||
if (dglDoesSupportVertexBuffer())
|
||||
glFreeVertexBufferEXT(smFMTVertexBuffer);
|
||||
else
|
||||
AssertFatal(false,"Vertex buffer should have already been freed!");
|
||||
smFMTVertexBuffer = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TextureManager::CacheResurrected:
|
||||
// relighting the scene will take care of things for us
|
||||
if(mInteriors.size())
|
||||
SceneLighting::lightScene(0, SceneLighting::LoadOnly);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void InteriorLMManager::addInterior(LM_HANDLE & interiorHandle, U32 numLightmaps, Interior * interior)
|
||||
{
|
||||
interiorHandle = mInteriors.size();
|
||||
mInteriors.increment();
|
||||
mInteriors.last() = new InteriorLMInfo;
|
||||
|
||||
mInteriors.last()->mInterior = interior;
|
||||
mInteriors.last()->mHandlePtr = &interiorHandle;
|
||||
mInteriors.last()->mNumLightmaps = numLightmaps;
|
||||
|
||||
// create base instance
|
||||
addInstance(interiorHandle, mInteriors.last()->mBaseInstanceHandle, 0);
|
||||
AssertFatal(mInteriors.last()->mBaseInstanceHandle == LM_HANDLE(0), "InteriorLMManager::addInterior: invalid base instance handle");
|
||||
|
||||
// steal the lightmaps from the interior
|
||||
Vector<TextureHandle*>& texHandles = getHandles(interiorHandle, 0);
|
||||
for(U32 i = 0; i < interior->mLightmaps.size(); i++)
|
||||
{
|
||||
AssertFatal(interior->mLightmaps[i], "InteriorLMManager::addInterior: interior missing lightmap");
|
||||
texHandles[i] = new TextureHandle(getTextureName(interior, 0, i), interior->mLightmaps[i], BitmapNoDownloadTexture);
|
||||
}
|
||||
|
||||
interior->mLightmaps.clear();
|
||||
}
|
||||
|
||||
void InteriorLMManager::removeInterior(LM_HANDLE interiorHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::removeInterior: invalid interior handle");
|
||||
AssertFatal(mInteriors[interiorHandle]->mInstances.size() == 1, "InteriorLMManager::removeInterior: cannot remove base interior");
|
||||
|
||||
// remove base instance
|
||||
removeInstance(interiorHandle, 0);
|
||||
|
||||
*mInteriors[interiorHandle]->mHandlePtr = LM_HANDLE(-1);
|
||||
|
||||
delete mInteriors[interiorHandle];
|
||||
|
||||
// last one? otherwise move it
|
||||
if((mInteriors.size()-1) != interiorHandle)
|
||||
{
|
||||
mInteriors[interiorHandle] = mInteriors.last();
|
||||
*(mInteriors[interiorHandle]->mHandlePtr) = interiorHandle;
|
||||
}
|
||||
|
||||
mInteriors.decrement();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void InteriorLMManager::addInstance(LM_HANDLE interiorHandle, LM_HANDLE & instanceHandle, InteriorInstance * instance)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::addInstance: invalid interior handle");
|
||||
AssertFatal(interiorHandle == *(mInteriors[interiorHandle]->mHandlePtr), "InteriorLMManager::addInstance: invalid handle value");
|
||||
|
||||
InteriorLMInfo * interiorInfo = mInteriors[interiorHandle];
|
||||
|
||||
// create the instance info and fill
|
||||
InstanceLMInfo * instanceInfo = new InstanceLMInfo;
|
||||
|
||||
instanceInfo->mInstance = instance;
|
||||
instanceInfo->mHandlePtr = &instanceHandle;
|
||||
instanceHandle = interiorInfo->mInstances.size();
|
||||
|
||||
interiorInfo->mInstances.push_back(instanceInfo);
|
||||
|
||||
// create/clear list
|
||||
instanceInfo->mLightmapHandles.setSize(interiorInfo->mNumLightmaps);
|
||||
dMemset(instanceInfo->mLightmapHandles.address(), 0, sizeof(TextureHandle*) * instanceInfo->mLightmapHandles.size());
|
||||
}
|
||||
|
||||
void InteriorLMManager::removeInstance(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::removeInstance: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::removeInstance: invalid instance handle");
|
||||
AssertFatal(!(instanceHandle == mInteriors[interiorHandle]->mBaseInstanceHandle &&
|
||||
mInteriors[interiorHandle]->mInstances.size() > 1), "InteriorLMManager::removeInstance: invalid base instance");
|
||||
|
||||
InteriorLMInfo * itrInfo = mInteriors[interiorHandle];
|
||||
|
||||
// kill it
|
||||
InstanceLMInfo * instInfo = itrInfo->mInstances[instanceHandle];
|
||||
for(U32 i = 0; i < instInfo->mLightmapHandles.size(); i++)
|
||||
delete instInfo->mLightmapHandles[i];
|
||||
|
||||
// reset on last instance removal only (multi detailed shapes share the same instance handle)
|
||||
if(itrInfo->mInstances.size() == 1)
|
||||
*instInfo->mHandlePtr = LM_HANDLE(-1);
|
||||
|
||||
delete instInfo;
|
||||
|
||||
// last one? otherwise move it
|
||||
if((itrInfo->mInstances.size()-1) != instanceHandle)
|
||||
{
|
||||
itrInfo->mInstances[instanceHandle] = itrInfo->mInstances.last();
|
||||
*(itrInfo->mInstances[instanceHandle]->mHandlePtr) = instanceHandle;
|
||||
}
|
||||
|
||||
itrInfo->mInstances.decrement();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void InteriorLMManager::destroyBitmaps()
|
||||
{
|
||||
for(S32 i = mInteriors.size() - 1; i >= 0; i--)
|
||||
{
|
||||
InteriorLMInfo * interiorInfo = mInteriors[i];
|
||||
for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
|
||||
{
|
||||
InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
|
||||
for(S32 k = instanceInfo->mLightmapHandles.size() - 1; k >= 0; k--)
|
||||
{
|
||||
if(!instanceInfo->mLightmapHandles[k])
|
||||
continue;
|
||||
|
||||
TextureObject * texObj = *instanceInfo->mLightmapHandles[k];
|
||||
if(!texObj || !texObj->bitmap)
|
||||
continue;
|
||||
|
||||
// don't remove 'keep' bitmaps
|
||||
if(!interiorInfo->mInterior->mLightmapKeep[k])
|
||||
{
|
||||
delete texObj->bitmap;
|
||||
texObj->bitmap = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorLMManager::destroyTextures()
|
||||
{
|
||||
for(S32 i = mInteriors.size() - 1; i >= 0; i--)
|
||||
{
|
||||
InteriorLMInfo * interiorInfo = mInteriors[i];
|
||||
for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
|
||||
{
|
||||
InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
|
||||
for(S32 k = interiorInfo->mNumLightmaps - 1; k >= 0; k--)
|
||||
{
|
||||
// will want to remove the vector here eventually... so dont clear
|
||||
delete instanceInfo->mLightmapHandles[k];
|
||||
instanceInfo->mLightmapHandles[k] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorLMManager::purgeGLTextures()
|
||||
{
|
||||
Vector<GLuint> purgeList(4096);
|
||||
|
||||
for(S32 i = mInteriors.size() - 1; i >= 0; i--)
|
||||
{
|
||||
InteriorLMInfo * interiorInfo = mInteriors[i];
|
||||
for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
|
||||
{
|
||||
InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
|
||||
for(S32 k = instanceInfo->mLightmapHandles.size() - 1; k >= 0; k--)
|
||||
{
|
||||
if(!instanceInfo->mLightmapHandles[k])
|
||||
continue;
|
||||
|
||||
TextureObject * texObj = *instanceInfo->mLightmapHandles[k];
|
||||
if(!texObj || !texObj->texGLName)
|
||||
continue;
|
||||
|
||||
#ifdef GATHER_METRICS
|
||||
AssertFatal(texObj->textureSpace <= TextureManager::smTextureSpaceLoaded, "Doh!");
|
||||
TextureManager::smTextureSpaceLoaded -= texObj->textureSpace;
|
||||
texObj->textureSpace = 0;
|
||||
#endif
|
||||
|
||||
purgeList.push_back(texObj->texGLName);
|
||||
texObj->texGLName = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteTextures(purgeList.size(), purgeList.address());
|
||||
}
|
||||
|
||||
void InteriorLMManager::downloadGLTextures()
|
||||
{
|
||||
for(S32 i = mInteriors.size() - 1; i >= 0; i--)
|
||||
{
|
||||
InteriorLMInfo * interiorInfo = mInteriors[i];
|
||||
|
||||
// - skip base texture if all the instances have a texture defined
|
||||
BitVector needTexture;
|
||||
needTexture.setSize(mInteriors[i]->mNumLightmaps);
|
||||
needTexture.clear();
|
||||
|
||||
// walk the instances and have them download their textures
|
||||
for(S32 j = interiorInfo->mInstances.size() - 1; j >= 0; j--)
|
||||
{
|
||||
InstanceLMInfo * instanceInfo = interiorInfo->mInstances[j];
|
||||
for(S32 k = instanceInfo->mLightmapHandles.size() - 1; k >= 0; k--)
|
||||
{
|
||||
// need base instance's texture?
|
||||
if((j == 0) && !needTexture.test(k))
|
||||
continue;
|
||||
|
||||
if(!instanceInfo->mLightmapHandles[k])
|
||||
{
|
||||
needTexture.set(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
TextureObject * texObj = *instanceInfo->mLightmapHandles[k];
|
||||
if(!texObj || !texObj->bitmap || texObj->texGLName)
|
||||
{
|
||||
needTexture.set(k);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef GATHER_METRICS
|
||||
texObj->textureSpace = texObj->downloadedWidth * texObj->downloadedHeight;
|
||||
TextureManager::smTextureSpaceLoaded += texObj->textureSpace;
|
||||
#endif
|
||||
TextureManager::createGLName(texObj->bitmap, texObj->clamp, 0, texObj->type, texObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InteriorLMManager::loadBaseLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::loadBaseLightmaps: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::loadBaseLightmaps: invalid instance handle");
|
||||
|
||||
// must use a valid instance handle
|
||||
if(!instanceHandle)
|
||||
return(false);
|
||||
|
||||
InteriorLMInfo * interiorInfo = mInteriors[interiorHandle];
|
||||
if(!interiorInfo->mNumLightmaps)
|
||||
return(false);
|
||||
|
||||
InstanceLMInfo * baseInstanceInfo = interiorInfo->mInstances[0];
|
||||
|
||||
// already loaded? (if any bitmap is present, then assumed that all will be)
|
||||
TextureHandle * texture = baseInstanceInfo->mLightmapHandles[0];
|
||||
if(texture && texture->getBitmap())
|
||||
return(true);
|
||||
|
||||
InstanceLMInfo * instanceInfo = interiorInfo->mInstances[instanceHandle];
|
||||
|
||||
Resource<InteriorResource> & interiorRes = instanceInfo->mInstance->getResource();
|
||||
if(!bool(interiorRes))
|
||||
return(false);
|
||||
|
||||
GBitmap *** pBitmaps = 0;
|
||||
if(!instanceInfo->mInstance->readLightmaps(&pBitmaps))
|
||||
return(false);
|
||||
|
||||
for(U32 i = 0; i < interiorRes->getNumDetailLevels(); i++)
|
||||
{
|
||||
Interior * interior = interiorRes->getDetailLevel(i);
|
||||
AssertFatal(interior, "InteriorLMManager::loadBaseLightmaps: invalid detail level in resource");
|
||||
AssertFatal(interior->getLMHandle() != LM_HANDLE(-1), "InteriorLMManager::loadBaseLightmaps: interior not added to manager");
|
||||
AssertFatal(interior->getLMHandle() < mInteriors.size(), "InteriorLMManager::loadBaseLightmaps: invalid interior");
|
||||
|
||||
InteriorLMInfo * interiorInfo = mInteriors[interior->getLMHandle()];
|
||||
InstanceLMInfo * baseInstanceInfo = interiorInfo->mInstances[0];
|
||||
|
||||
for(U32 j = 0; j < interiorInfo->mNumLightmaps; j++)
|
||||
{
|
||||
AssertFatal(pBitmaps[i][j], "InteriorLMManager::loadBaseLightmaps: invalid bitmap");
|
||||
|
||||
if (baseInstanceInfo->mLightmapHandles[j])
|
||||
{
|
||||
TextureObject * texObj = *baseInstanceInfo->mLightmapHandles[j];
|
||||
texObj->bitmap = pBitmaps[i][j];
|
||||
}
|
||||
else
|
||||
baseInstanceInfo->mLightmapHandles[j] = new TextureHandle(getTextureName(interior, 0, j), pBitmaps[i][j], BitmapNoDownloadTexture);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pBitmaps;
|
||||
return(true);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
TextureHandle * InteriorLMManager::getHandle(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getHandle: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getHandle: invalid instance handle");
|
||||
AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::getHandle: invalid texture index");
|
||||
|
||||
// valid? if not, then get base lightmap handle
|
||||
if(!mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index])
|
||||
{
|
||||
AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::getHandle: invalid base texture handle");
|
||||
return(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]);
|
||||
}
|
||||
return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index]);
|
||||
}
|
||||
|
||||
GBitmap * InteriorLMManager::getBitmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getBitmap: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getBitmap: invalid instance handle");
|
||||
AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::getBitmap: invalid texture index");
|
||||
|
||||
if(!mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index])
|
||||
{
|
||||
AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::getBitmap: invalid base texture handle");
|
||||
return(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]->getBitmap());
|
||||
}
|
||||
|
||||
return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index]->getBitmap());
|
||||
}
|
||||
|
||||
Vector<TextureHandle*> & InteriorLMManager::getHandles(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getHandles: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::getHandles: invalid instance handle");
|
||||
return(mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
U32 InteriorLMManager::getNumLightmaps(LM_HANDLE interiorHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::getNumLightmaps: invalid interior handle");
|
||||
return(mInteriors[interiorHandle]->mNumLightmaps);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void InteriorLMManager::deleteLightmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::deleteLightmap: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::deleteLightmap: invalid instance handle");
|
||||
AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::deleteLightmap: invalid texture index");
|
||||
|
||||
delete mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index];
|
||||
mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index] = 0;
|
||||
}
|
||||
|
||||
void InteriorLMManager::clearLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::clearLightmaps: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::clearLightmaps: invalid instance handle");
|
||||
|
||||
for(U32 i = 0; i < mInteriors[interiorHandle]->mNumLightmaps; i++)
|
||||
{
|
||||
delete mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[i];
|
||||
mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
TextureHandle * InteriorLMManager::duplicateBaseLightmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index)
|
||||
{
|
||||
AssertFatal(interiorHandle < mInteriors.size(), "InteriorLMManager::duplicateBaseLightmap: invalid interior handle");
|
||||
AssertFatal(instanceHandle < mInteriors[interiorHandle]->mInstances.size(), "InteriorLMManager::duplicateBaseLightmap: invalid instance handle");
|
||||
AssertFatal(index < mInteriors[interiorHandle]->mNumLightmaps, "InteriorLMManager::duplicateBaseLightmap: invalid texture index");
|
||||
|
||||
// already exists?
|
||||
TextureHandle * texHandle = mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index];
|
||||
if(texHandle && static_cast<TextureObject*>(*texHandle)->bitmap)
|
||||
return(texHandle);
|
||||
|
||||
AssertFatal(mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index], "InteriorLMManager::duplicateBaseLightmap: invalid base handle");
|
||||
|
||||
// copy it
|
||||
GBitmap * src = mInteriors[interiorHandle]->mInstances[0]->mLightmapHandles[index]->getBitmap();
|
||||
GBitmap * dest = new GBitmap(*src);
|
||||
|
||||
// don't want this texture to be downloaded yet (SceneLighting will take care of that)
|
||||
TextureHandle * tHandle = new TextureHandle(getTextureName(mInteriors[interiorHandle]->mInterior, instanceHandle, index), dest, BitmapNoDownloadTexture);
|
||||
mInteriors[interiorHandle]->mInstances[instanceHandle]->mLightmapHandles[index] = tHandle;
|
||||
return(tHandle);
|
||||
}
|
||||
|
||||
S32 InteriorLMManager::getVertexBuffer(S32 format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GL_TRIBESMTVFMT_EXT:
|
||||
{
|
||||
if (smMTVertexBuffer != -1)
|
||||
return smMTVertexBuffer;
|
||||
|
||||
smMTVertexBuffer = glAllocateVertexBufferEXT(512,GL_TRIBESMTVFMT_EXT,false);
|
||||
|
||||
return smMTVertexBuffer;
|
||||
}
|
||||
case GL_TRIBESFTVFMT_EXT:
|
||||
{
|
||||
if (smFTVertexBuffer != -1)
|
||||
return smFTVertexBuffer;
|
||||
|
||||
smFTVertexBuffer = glAllocateVertexBufferEXT(512,GL_TRIBESFTVFMT_EXT,false);
|
||||
|
||||
return smFTVertexBuffer;
|
||||
}
|
||||
case GL_TRIBESFMTVFMT_EXT:
|
||||
{
|
||||
if (smFMTVertexBuffer != -1)
|
||||
return smFMTVertexBuffer;
|
||||
|
||||
smFMTVertexBuffer = glAllocateVertexBufferEXT(512,GL_TRIBESFMTVFMT_EXT,false);
|
||||
|
||||
return smFMTVertexBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(false,"What? We should never get here!!!");
|
||||
|
||||
return -1;
|
||||
}
|
||||
90
interior/interiorLMManager.h
Normal file
90
interior/interiorLMManager.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIORLMMANAGER_H_
|
||||
#define _INTERIORLMMANAGER_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
|
||||
class TextureHandle;
|
||||
class GBitmap;
|
||||
class Interior;
|
||||
class InteriorInstance;
|
||||
|
||||
typedef U32 LM_HANDLE;
|
||||
|
||||
class InteriorLMManager
|
||||
{
|
||||
private:
|
||||
|
||||
struct InstanceLMInfo {
|
||||
InteriorInstance * mInstance;
|
||||
LM_HANDLE * mHandlePtr;
|
||||
Vector<TextureHandle*> mLightmapHandles;
|
||||
};
|
||||
|
||||
struct InteriorLMInfo {
|
||||
Interior * mInterior;
|
||||
LM_HANDLE * mHandlePtr;
|
||||
U32 mNumLightmaps;
|
||||
LM_HANDLE mBaseInstanceHandle;
|
||||
Vector<InstanceLMInfo*> mInstances;
|
||||
};
|
||||
|
||||
Vector<InteriorLMInfo*> mInteriors;
|
||||
|
||||
static S32 smMTVertexBuffer;
|
||||
static S32 smFTVertexBuffer;
|
||||
static S32 smFMTVertexBuffer;
|
||||
|
||||
public:
|
||||
|
||||
static U32 smTextureCallbackKey;
|
||||
|
||||
InteriorLMManager();
|
||||
~InteriorLMManager();
|
||||
|
||||
static void init();
|
||||
static void destroy();
|
||||
|
||||
void processTextureEvent(U32 eventCode);
|
||||
|
||||
void destroyBitmaps();
|
||||
void destroyTextures();
|
||||
|
||||
void purgeGLTextures();
|
||||
void downloadGLTextures();
|
||||
bool loadBaseLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle);
|
||||
|
||||
void addInterior(LM_HANDLE & interiorHandle, U32 numLightmaps, Interior * interior);
|
||||
void removeInterior(LM_HANDLE interiorHandle);
|
||||
|
||||
void addInstance(LM_HANDLE interiorHandle, LM_HANDLE & instanceHandle, InteriorInstance * instance);
|
||||
void removeInstance(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle);
|
||||
|
||||
U32 getNumLightmaps(LM_HANDLE interiorHandle);
|
||||
void deleteLightmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index);
|
||||
void clearLightmaps(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle);
|
||||
|
||||
TextureHandle * getHandle(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index);
|
||||
Vector<TextureHandle*> & getHandles(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle);
|
||||
|
||||
// helper's
|
||||
TextureHandle * duplicateBaseLightmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index);
|
||||
GBitmap * getBitmap(LM_HANDLE interiorHandle, LM_HANDLE instanceHandle, U32 index);
|
||||
|
||||
S32 getVertexBuffer(S32 format);
|
||||
};
|
||||
|
||||
extern InteriorLMManager gInteriorLMManager;
|
||||
|
||||
#endif
|
||||
404
interior/interiorLightAnim.cc
Normal file
404
interior/interiorLightAnim.cc
Normal file
|
|
@ -0,0 +1,404 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/interiorInstance.h"
|
||||
#include "interior/lightUpdateGrouper.h"
|
||||
#include "interior/interior.h"
|
||||
#include "Math/mRandom.h"
|
||||
|
||||
void InteriorInstance::echoTriggerableLights()
|
||||
{
|
||||
// DMMFIX: Only the first detail for now...
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(0);
|
||||
|
||||
Con::printf("Interior: %s", mInteriorFileName);
|
||||
Con::printf(" %d Triggerable lights:", pInterior->mNumTriggerableLights);
|
||||
|
||||
// Triggerable lights are always the first in the array...
|
||||
for (U32 i = 0; i < pInterior->mNumTriggerableLights; i++) {
|
||||
const char* pName = pInterior->getName(pInterior->mAnimatedLights[i].nameIndex);
|
||||
U32 type = pInterior->mAnimatedLights[i].flags & Interior::AnimationTypeMask;
|
||||
float duration = pInterior->mAnimatedLights[i].duration;
|
||||
U32 numStates = pInterior->mAnimatedLights[i].stateCount;
|
||||
|
||||
Con::printf(" - %s [%s, Duration: %f, NumStates: %d]",
|
||||
pName, Interior::getLightTypeString(Interior::LightType(type)),
|
||||
duration, numStates);
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorInstance::activateLight(const char* pLightName)
|
||||
{
|
||||
if (bool(mInteriorRes) == false) {
|
||||
AssertWarn(false, "Activating a light on an unloaded interior!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now, it's a real pain in the ass to try to keep track of light states on detail
|
||||
// changes as we did in tribes 1. There, we analyzed the state on a detail change
|
||||
// and tried to duplicate that state on the detail level we were switching to.
|
||||
// Inspiration: forget that, and just animate the lights on all the details all
|
||||
// the time. Unless the detail is rendering, the lightmap data will never be
|
||||
// downloaded, and the amount of time necessary to keep the lights updated on
|
||||
// a detail level is absolutely miniscule. Much easier.
|
||||
//
|
||||
for (U32 i = 0; i < mInteriorRes->getNumDetailLevels(); i++) {
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(i);
|
||||
|
||||
for (U32 j = 0; j < pInterior->mNumTriggerableLights; j++) {
|
||||
const char* pILightName = pInterior->getName(pInterior->mAnimatedLights[j].nameIndex);
|
||||
if (dStricmp(pLightName, pILightName) == 0) {
|
||||
activateLight(i, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorInstance::deactivateLight(const char* pLightName)
|
||||
{
|
||||
if (bool(mInteriorRes) == false) {
|
||||
AssertWarn(false, "Deactivating a light on an unloaded interior!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->getNumDetailLevels(); i++) {
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(i);
|
||||
|
||||
for (U32 j = 0; j < pInterior->mNumTriggerableLights; j++) {
|
||||
const char* pILightName = pInterior->getName(pInterior->mAnimatedLights[j].nameIndex);
|
||||
if (dStricmp(pLightName, pILightName) == 0) {
|
||||
deactivateLight(i, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteriorInstance::updateAllLights(const U32 ms)
|
||||
{
|
||||
if (bool(mInteriorRes) == false)
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < mInteriorRes->getNumDetailLevels(); i++) {
|
||||
LightInfo& rLightInfo = mLightInfo[i];
|
||||
|
||||
for (U32 j = 0; j < rLightInfo.mLights.size(); j++) {
|
||||
if (mAlarmState == Normal) {
|
||||
if (rLightInfo.mLights[j].active == true && rLightInfo.mLights[j].alarm == false)
|
||||
updateLightTime(i, j, ms);
|
||||
} else {
|
||||
if (rLightInfo.mLights[j].alarm == true)
|
||||
updateLightTime(i, j, ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::activateLight(const U32 detail, const U32 lightIndex)
|
||||
{
|
||||
AssertFatal(bool(mInteriorRes) && detail < mInteriorRes->getNumDetailLevels(), "Error, no interior resource, or out of range detail level");
|
||||
AssertFatal(lightIndex < mInteriorRes->getDetailLevel(detail)->mAnimatedLights.size(), "Error, out of bounds light index");
|
||||
|
||||
LightInfo& rLightInfo = mLightInfo[detail];
|
||||
LightInfo::Light& rLight = rLightInfo.mLights[lightIndex];
|
||||
|
||||
if (rLight.active == false) {
|
||||
rLight.active = true;
|
||||
rLight.curState = 0;
|
||||
rLight.curTime = 0;
|
||||
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(detail);
|
||||
Interior::LightState& rState = pInterior->mLightStates[pInterior->mAnimatedLights[lightIndex].stateIndex];
|
||||
rLight.curColor.set(rState.red, rState.green, rState.blue);
|
||||
|
||||
installLight(detail, lightIndex);
|
||||
|
||||
if (isServerObject() && lightIndex < pInterior->mNumTriggerableLights) {
|
||||
U32 key = makeUpdateKey(detail, lightIndex);
|
||||
U32 mask = mUpdateGrouper->getKeyMask(key);
|
||||
setMaskBits(mask);
|
||||
}
|
||||
} else {
|
||||
// Light is already active, no need to play around further...
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::deactivateLight(const U32 detail, const U32 lightIndex)
|
||||
{
|
||||
AssertFatal(bool(mInteriorRes) && detail < mInteriorRes->getNumDetailLevels(), "Error, no interior resource, or out of range detail level");
|
||||
AssertFatal(lightIndex < mInteriorRes->getDetailLevel(detail)->mAnimatedLights.size(), "Error, out of bounds light index");
|
||||
|
||||
LightInfo& rLightInfo = mLightInfo[detail];
|
||||
LightInfo::Light& rLight = rLightInfo.mLights[lightIndex];
|
||||
|
||||
if (rLight.active == true) {
|
||||
// DMMFIX
|
||||
|
||||
rLight.active = false;
|
||||
rLight.curState = 0;
|
||||
rLight.curTime = 0;
|
||||
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(detail);
|
||||
Interior::LightState& rState = pInterior->mLightStates[pInterior->mAnimatedLights[lightIndex].stateIndex];
|
||||
rLight.curColor.set(rState.red, rState.green, rState.blue);
|
||||
|
||||
installLight(detail, lightIndex);
|
||||
|
||||
if (isServerObject() && lightIndex < pInterior->mNumTriggerableLights) {
|
||||
U32 key = makeUpdateKey(detail, lightIndex);
|
||||
U32 mask = mUpdateGrouper->getKeyMask(key);
|
||||
setMaskBits(mask);
|
||||
}
|
||||
} else {
|
||||
// Light is already inactive, no need to play around further...
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::updateLightTime(const U32 detail, const U32 lightIndex, const U32 ms)
|
||||
{
|
||||
AssertFatal(bool(mInteriorRes) && detail < mInteriorRes->getNumDetailLevels(), "Error, no interior resource, or out of range detail level");
|
||||
AssertFatal(lightIndex < mInteriorRes->getDetailLevel(detail)->mAnimatedLights.size(), "Error, out of bounds light index");
|
||||
|
||||
LightInfo& rLightInfo = mLightInfo[detail];
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(detail);
|
||||
|
||||
LightInfo::Light& rLight = rLightInfo.mLights[lightIndex];
|
||||
Interior::AnimatedLight& rILight = pInterior->mAnimatedLights[lightIndex];
|
||||
|
||||
U32 oldState = rLight.curState;
|
||||
ColorI oldColor = rLight.curColor;
|
||||
|
||||
// Ok, now we need to break this down a bit. We pass the update along to
|
||||
// the specialized updating functions based on lightType.
|
||||
switch (rILight.flags & Interior::AnimationTypeMask) {
|
||||
case Interior::AmbientLooping:
|
||||
case Interior::TriggerableLoop:
|
||||
updateLoopingLight(pInterior, rLight, lightIndex, ms);
|
||||
break;
|
||||
|
||||
case Interior::AmbientFlicker:
|
||||
case Interior::TriggerableFlicker:
|
||||
updateFlickerLight(pInterior, rLight, lightIndex, ms);
|
||||
break;
|
||||
|
||||
case Interior::TriggerableRamp:
|
||||
updateRampLight(pInterior, rLight, lightIndex, ms);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(false, "Bad light type in updateLightTime");
|
||||
}
|
||||
|
||||
if (rLight.curState != oldState ||
|
||||
rLight.curColor != oldColor) {
|
||||
// Need to reinstall the light
|
||||
installLight(detail, lightIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::updateLoopingLight(Interior* interior, LightInfo::Light& light,
|
||||
const U32 lightIndex, const U32 ms)
|
||||
{
|
||||
AssertISV( lightIndex < interior->mAnimatedLights.size( ), "out of bounds array access in InteriorInstance::updateLoopingLight" );
|
||||
Interior::AnimatedLight& rILight = interior->mAnimatedLights[lightIndex];
|
||||
|
||||
light.curTime += ms;
|
||||
light.curTime %= rILight.duration;
|
||||
|
||||
// Find the last state that has a active time below this new time...
|
||||
light.curState = 0;
|
||||
for (U32 i = 1; i < rILight.stateCount; i++) {
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + i];
|
||||
if (rState.activeTime <= light.curTime)
|
||||
light.curState = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// interpolate the color
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + light.curState];
|
||||
Interior::LightState* pNextState;
|
||||
|
||||
U32 msIntoState = light.curTime - rState.activeTime;
|
||||
U32 msTotal;
|
||||
if (light.curState != (rILight.stateCount - 1)) {
|
||||
// Have one more good state
|
||||
pNextState = &interior->mLightStates[rILight.stateIndex + light.curState + 1];
|
||||
msTotal = pNextState->activeTime - rState.activeTime;
|
||||
} else {
|
||||
// Have to interpolate against the first state...
|
||||
pNextState = &interior->mLightStates[rILight.stateIndex];
|
||||
msTotal = rILight.duration - rState.activeTime;
|
||||
}
|
||||
|
||||
F32 interp = F32(msIntoState) / F32(msTotal);
|
||||
F32 red = F32(rState.red) * (1.0f - interp) + F32(pNextState->red) * interp;
|
||||
F32 green = F32(rState.green) * (1.0f - interp) + F32(pNextState->green) * interp;
|
||||
F32 blue = F32(rState.blue) * (1.0f - interp) + F32(pNextState->blue) * interp;
|
||||
|
||||
light.curColor.set(U8(red + 0.5f), U8(green + 0.5f), U8(blue + 0.5f));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::updateFlickerLight(Interior* interior, LightInfo::Light& light,
|
||||
const U32 lightIndex, const U32 ms)
|
||||
{
|
||||
Interior::AnimatedLight& rILight = interior->mAnimatedLights[lightIndex];
|
||||
|
||||
U32 switchPeriod = interior->mLightStates[interior->mAnimatedLights[lightIndex].stateIndex + 1].activeTime;
|
||||
U32 oldTime = light.curTime;
|
||||
light.curTime += ms;
|
||||
if (light.curTime < switchPeriod)
|
||||
return;
|
||||
|
||||
light.curTime = 0;
|
||||
|
||||
// Ok, pick a random number from 0 to the light duration, and find the state that
|
||||
// it falls in.
|
||||
|
||||
static MRandomLCG randomGen;
|
||||
U32 pickedTime = randomGen.randI(0, rILight.duration);
|
||||
|
||||
light.curState = 0;
|
||||
for (U32 i = 1; i < rILight.stateCount; i++) {
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + i];
|
||||
if (rState.activeTime <= pickedTime)
|
||||
light.curState = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + light.curState];
|
||||
light.curColor.set(rState.red, rState.green, rState.blue);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::updateRampLight(Interior* interior, LightInfo::Light& light,
|
||||
const U32 lightIndex, const U32 ms)
|
||||
{
|
||||
Interior::AnimatedLight& rILight = interior->mAnimatedLights[lightIndex];
|
||||
|
||||
light.curTime += ms;
|
||||
if (light.curTime > rILight.duration)
|
||||
light.curTime = rILight.duration;
|
||||
|
||||
// Find the last state that has a active time below this new time...
|
||||
light.curState = 0;
|
||||
for (U32 i = 1; i < rILight.stateCount; i++) {
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + i];
|
||||
if (rState.activeTime <= light.curTime)
|
||||
light.curState = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// interpolate the color
|
||||
Interior::LightState& rState = interior->mLightStates[rILight.stateIndex + light.curState];
|
||||
Interior::LightState* pNextState;
|
||||
|
||||
U32 msIntoState = light.curTime - rState.activeTime;
|
||||
U32 msTotal;
|
||||
if (light.curState != (rILight.stateCount - 1)) {
|
||||
// Have one more good state
|
||||
pNextState = &interior->mLightStates[rILight.stateIndex + light.curState + 1];
|
||||
msTotal = pNextState->activeTime - rState.activeTime;
|
||||
} else {
|
||||
// A ramp light does NOT NOT NOT interp against the first state
|
||||
pNextState = &rState;
|
||||
msTotal = msIntoState;
|
||||
}
|
||||
|
||||
F32 interp = F32(msIntoState) / F32(msTotal);
|
||||
F32 red = F32(rState.red) * (1.0f - interp) + F32(pNextState->red) * interp;
|
||||
F32 green = F32(rState.green) * (1.0f - interp) + F32(pNextState->green) * interp;
|
||||
F32 blue = F32(rState.blue) * (1.0f - interp) + F32(pNextState->blue) * interp;
|
||||
|
||||
light.curColor.set(U8(red + 0.5f), U8(green + 0.5f), U8(blue + 0.5f));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::installLight(const U32 detail, const U32 lightIndex)
|
||||
{
|
||||
AssertFatal(bool(mInteriorRes) && detail < mInteriorRes->getNumDetailLevels(), "Error, no interior resource, or out of range detail level");
|
||||
AssertFatal(lightIndex < mInteriorRes->getDetailLevel(detail)->mAnimatedLights.size(), "Error, out of bounds light index");
|
||||
|
||||
LightInfo& rLightInfo = mLightInfo[detail];
|
||||
LightInfo::Light& rLight = rLightInfo.mLights[lightIndex];
|
||||
|
||||
// All we are allowed to assume is that the light time, color, and state are
|
||||
// correct here. We must install all statedata, and invalidate all surfaces.
|
||||
// First, let's retrieve the actual light from the Interior
|
||||
//
|
||||
Interior* pInterior = mInteriorRes->getDetailLevel(detail);
|
||||
Interior::AnimatedLight& rILight = pInterior->mAnimatedLights[lightIndex];
|
||||
Interior::LightState& rIState = pInterior->mLightStates[rILight.stateIndex + rLight.curState];
|
||||
|
||||
// Ok. Now, cycle through the light's state data, and install it
|
||||
for (U32 i = rIState.dataIndex; i < (rIState.dataIndex + rIState.dataCount); i++) {
|
||||
Interior::LightStateData& rIData = pInterior->mStateData[i];
|
||||
LightInfo::StateDataInfo& rData = rLightInfo.mStateDataInfo[rIData.lightStateIndex];
|
||||
|
||||
if (rIData.mapIndex != 0xFFFFFFFFF) {
|
||||
rData.curMap = &pInterior->mStateDataBuffer[rIData.mapIndex];
|
||||
} else {
|
||||
rData.curMap = NULL;
|
||||
}
|
||||
rData.curColor = rLight.curColor;
|
||||
rData.alarm = (rILight.flags & Interior::AlarmLight) != 0;
|
||||
rLightInfo.mSurfaceInvalid.set(rIData.surfaceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void InteriorInstance::intensityMapMerge(U8* lightMap,
|
||||
const U32 width,
|
||||
const U32 height,
|
||||
const U8* intensityMap,
|
||||
const ColorI& color)
|
||||
{
|
||||
// lightmap is a 24bit RGB texture, intensitymap is an 8 bit intensity
|
||||
// map. We want lightmap = [lightmap + (intensityMap * color)]
|
||||
|
||||
// DMMFIX: SLOWSLOWSLOW! Need MMX version of this at the very least,
|
||||
// this version is only for clarity;
|
||||
for (U32 y = 0; y < height; y++) {
|
||||
for (U32 x = 0; x < width; x++) {
|
||||
U8* data = &lightMap[(y * width + x) * 3];
|
||||
U32 intensity = intensityMap[(y * width + x)];
|
||||
|
||||
U32 newRed = data[0];
|
||||
U32 newGreen = data[1];
|
||||
U32 newBlue = data[2];
|
||||
|
||||
U32 addRed = (U32(color.red) * intensity + 0x80) >> 8;
|
||||
U32 addGreen = (U32(color.green) * intensity + 0x80) >> 8;
|
||||
U32 addBlue = (U32(color.blue) * intensity + 0x80) >> 8;
|
||||
|
||||
newRed += addRed;
|
||||
newGreen += addGreen;
|
||||
newBlue += addBlue;
|
||||
|
||||
data[0] = (newRed <= 255) ? U8(newRed) : 0xFF;
|
||||
data[1] = (newGreen <= 255) ? U8(newGreen) : 0xFF;
|
||||
data[2] = (newBlue <= 255) ? U8(newBlue) : 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
1330
interior/interiorRender.cc
Normal file
1330
interior/interiorRender.cc
Normal file
File diff suppressed because it is too large
Load diff
320
interior/interiorRes.cc
Normal file
320
interior/interiorRes.cc
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "console/console.h"
|
||||
#include "Core/stream.h"
|
||||
#include "interior/interior.h"
|
||||
#include "interior/interiorResObjects.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "interior/forceField.h"
|
||||
|
||||
#include "interior/interiorRes.h"
|
||||
|
||||
const U32 InteriorResource::smFileVersion = 44;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
InteriorResource::InteriorResource()
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(mDetailLevels);
|
||||
VECTOR_SET_ASSOCIATION(mSubObjects);
|
||||
VECTOR_SET_ASSOCIATION(mTriggers);
|
||||
VECTOR_SET_ASSOCIATION(mPaths);
|
||||
VECTOR_SET_ASSOCIATION(mInteriorPathFollowers);
|
||||
VECTOR_SET_ASSOCIATION(mForceFields);
|
||||
VECTOR_SET_ASSOCIATION(mAISpecialNodes);
|
||||
|
||||
mPreviewBitmap = NULL;
|
||||
}
|
||||
|
||||
InteriorResource::~InteriorResource()
|
||||
{
|
||||
U32 i;
|
||||
|
||||
for (i = 0; i < mDetailLevels.size(); i++)
|
||||
delete mDetailLevels[i];
|
||||
for (i = 0; i < mSubObjects.size(); i++)
|
||||
delete mSubObjects[i];
|
||||
for (i = 0; i < mTriggers.size(); i++)
|
||||
delete mTriggers[i];
|
||||
for (i = 0; i < mPaths.size(); i++)
|
||||
delete mPaths[i];
|
||||
for (i = 0; i < mInteriorPathFollowers.size(); i++)
|
||||
delete mInteriorPathFollowers[i];
|
||||
for (i = 0; i < mForceFields.size(); i++)
|
||||
delete mForceFields[i];
|
||||
for (i = 0; i < mAISpecialNodes.size(); i++)
|
||||
delete mAISpecialNodes[i];
|
||||
|
||||
delete mPreviewBitmap;
|
||||
mPreviewBitmap = NULL;
|
||||
}
|
||||
|
||||
bool InteriorResource::read(Stream& stream)
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamRead), "Interior::read: non-read capable stream passed");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "Interior::read: Error, stream in inconsistent state");
|
||||
|
||||
U32 i;
|
||||
|
||||
// Version this stream
|
||||
U32 fileVersion;
|
||||
stream.read(&fileVersion);
|
||||
if (fileVersion != smFileVersion) {
|
||||
Con::errorf(ConsoleLogEntry::General, "InteriorResource::read: incompatible file version found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle preview
|
||||
bool previewIncluded;
|
||||
stream.read(&previewIncluded);
|
||||
if (previewIncluded) {
|
||||
GBitmap bmp;
|
||||
bmp.readPNG(stream);
|
||||
}
|
||||
|
||||
// Details
|
||||
U32 numDetailLevels;
|
||||
stream.read(&numDetailLevels);
|
||||
mDetailLevels.setSize(numDetailLevels);
|
||||
for (i = 0; i < mDetailLevels.size(); i++)
|
||||
mDetailLevels[i] = NULL;
|
||||
|
||||
for (i = 0; i < mDetailLevels.size(); i++) {
|
||||
mDetailLevels[i] = new Interior;
|
||||
if (mDetailLevels[i]->read(stream) == false) {
|
||||
Con::errorf(ConsoleLogEntry::General, "Unable to read detail level %d in interior resource", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Subobjects: mirrors, translucencies
|
||||
U32 numSubObjects;
|
||||
stream.read(&numSubObjects);
|
||||
mSubObjects.setSize(numSubObjects);
|
||||
for (i = 0; i < mSubObjects.size(); i++)
|
||||
mSubObjects[i] = NULL;
|
||||
|
||||
for (i = 0; i < mSubObjects.size(); i++) {
|
||||
mSubObjects[i] = new Interior;
|
||||
if (mSubObjects[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read subobject %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Triggers
|
||||
U32 numTriggers;
|
||||
stream.read(&numTriggers);
|
||||
mTriggers.setSize(numTriggers);
|
||||
for (i = 0; i < mTriggers.size(); i++)
|
||||
mTriggers[i] = NULL;
|
||||
|
||||
for (i = 0; i < mTriggers.size(); i++) {
|
||||
mTriggers[i] = new InteriorResTrigger;
|
||||
if (mTriggers[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read trigger %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Paths
|
||||
U32 numPaths;
|
||||
stream.read(&numPaths);
|
||||
mPaths.setSize(numPaths);
|
||||
for (i = 0; i < mPaths.size(); i++)
|
||||
mPaths[i] = NULL;
|
||||
|
||||
for (i = 0; i < mPaths.size(); i++) {
|
||||
mPaths[i] = new InteriorPath;
|
||||
if (mPaths[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read path %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U32 numChildren;
|
||||
stream.read(&numChildren);
|
||||
mInteriorPathFollowers.setSize(numChildren);
|
||||
for (i = 0; i < mInteriorPathFollowers.size(); i++)
|
||||
mInteriorPathFollowers[i] = NULL;
|
||||
|
||||
for (i = 0; i < mInteriorPathFollowers.size(); i++) {
|
||||
mInteriorPathFollowers[i] = new InteriorPathFollower;
|
||||
if (mInteriorPathFollowers[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read child %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U32 numFields;
|
||||
stream.read(&numFields);
|
||||
mForceFields.setSize(numFields);
|
||||
for (i = 0; i < mForceFields.size(); i++)
|
||||
mForceFields[i] = NULL;
|
||||
|
||||
for (i = 0; i < mForceFields.size(); i++) {
|
||||
mForceFields[i] = new ForceField;
|
||||
if (mForceFields[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read field %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U32 numSpecNodes;
|
||||
stream.read(&numSpecNodes);
|
||||
mAISpecialNodes.setSize(numSpecNodes);
|
||||
for (i = 0; i < mAISpecialNodes.size(); i++)
|
||||
mAISpecialNodes[i] = NULL;
|
||||
|
||||
for (i = 0; i < mAISpecialNodes.size(); i++) {
|
||||
mAISpecialNodes[i] = new AISpecialNode;
|
||||
if (mAISpecialNodes[i]->read(stream) == false) {
|
||||
AssertISV(false, avar("Unable to read SpecNode %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U32 dummyInt;
|
||||
stream.read(&dummyInt);
|
||||
if (dummyInt == 1)
|
||||
{
|
||||
if (mDetailLevels.size() != 0)
|
||||
getDetailLevel(0)->readVehicleCollision(stream);
|
||||
}
|
||||
|
||||
// For expansion purposes
|
||||
stream.read(&dummyInt);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool InteriorResource::write(Stream& stream) const
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamWrite), "Interior::write: non-write capable stream passed");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "Interior::write: Error, stream in inconsistent state");
|
||||
|
||||
// Version the stream
|
||||
stream.write(smFileVersion);
|
||||
|
||||
// Handle preview
|
||||
//
|
||||
if (mPreviewBitmap != NULL) {
|
||||
stream.write(bool(true));
|
||||
mPreviewBitmap->writePNG(stream);
|
||||
} else {
|
||||
stream.write(bool(false));
|
||||
}
|
||||
|
||||
// Write out the interiors
|
||||
stream.write(mDetailLevels.size());
|
||||
U32 i;
|
||||
for (i = 0; i < mDetailLevels.size(); i++) {
|
||||
if (mDetailLevels[i]->write(stream) == false) {
|
||||
AssertISV(false, "Unable to write detail level to stream");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mSubObjects.size());
|
||||
for (i = 0; i < mSubObjects.size(); i++) {
|
||||
if (mSubObjects[i]->write(stream) == false) {
|
||||
AssertISV(false, "Unable to write subobject to stream");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mTriggers.size());
|
||||
for (i = 0; i < mTriggers.size(); i++) {
|
||||
if (mTriggers[i]->write(stream) == false) {
|
||||
AssertISV(false, "Unable to write trigger to stream");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mPaths.size());
|
||||
for (i = 0; i < mPaths.size(); i++) {
|
||||
if (mPaths[i]->write(stream) == false) {
|
||||
AssertISV(false, "Unable to write path to stream");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mInteriorPathFollowers.size());
|
||||
for (i = 0; i < mInteriorPathFollowers.size(); i++) {
|
||||
if (mInteriorPathFollowers[i]->write(stream) == false) {
|
||||
AssertISV(false, avar("Unable to write child %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mForceFields.size());
|
||||
for (i = 0; i < mForceFields.size(); i++) {
|
||||
if (mForceFields[i]->write(stream) == false) {
|
||||
AssertISV(false, avar("Unable to write field %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(mAISpecialNodes.size());
|
||||
for (i = 0; i < mAISpecialNodes.size(); i++) {
|
||||
if (mAISpecialNodes[i]->write(stream) == false) {
|
||||
AssertISV(false, avar("Unable to write SpecNode %d in interior resource", i));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream.write(U32(1));
|
||||
if (mDetailLevels.size() != 0)
|
||||
const_cast<Interior*>(mDetailLevels[0])->writeVehicleCollision(stream);
|
||||
|
||||
// For expansion purposes
|
||||
stream.write(U32(0));
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
GBitmap* InteriorResource::extractPreview(Stream& stream)
|
||||
{
|
||||
AssertFatal(stream.hasCapability(Stream::StreamRead), "Interior::read: non-read capable stream passed");
|
||||
AssertFatal(stream.getStatus() == Stream::Ok, "Interior::read: Error, stream in inconsistent state");
|
||||
|
||||
// Version this stream
|
||||
U32 fileVersion;
|
||||
stream.read(&fileVersion);
|
||||
if (fileVersion != smFileVersion) {
|
||||
Con::errorf(ConsoleLogEntry::General, "InteriorResource::read: incompatible file version found.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Handle preview
|
||||
bool previewIncluded;
|
||||
stream.read(&previewIncluded);
|
||||
if (previewIncluded) {
|
||||
GBitmap* pBmp = new GBitmap;
|
||||
if (pBmp->readPNG(stream) == true)
|
||||
return pBmp;
|
||||
|
||||
delete pBmp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//-------------------------------------- Interior Resource constructor
|
||||
ResourceInstance* constructInteriorDIF(Stream& stream)
|
||||
{
|
||||
InteriorResource* pResource = new InteriorResource;
|
||||
|
||||
if (pResource->read(stream) == true)
|
||||
return pResource;
|
||||
else {
|
||||
delete pResource;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
152
interior/interiorRes.h
Normal file
152
interior/interiorRes.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIORRES_H_
|
||||
#define _INTERIORRES_H_
|
||||
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "Core/resManager.h"
|
||||
#endif
|
||||
|
||||
class Stream;
|
||||
class Interior;
|
||||
class GBitmap;
|
||||
class InteriorResTrigger;
|
||||
class InteriorPath;
|
||||
class InteriorPathFollower;
|
||||
class ForceField;
|
||||
class AISpecialNode;
|
||||
|
||||
class InteriorResource : public ResourceInstance
|
||||
{
|
||||
typedef ResourceInstance Parent;
|
||||
static const U32 smFileVersion;
|
||||
|
||||
protected:
|
||||
Vector<Interior*> mDetailLevels;
|
||||
Vector<Interior*> mSubObjects;
|
||||
Vector<InteriorResTrigger*> mTriggers;
|
||||
Vector<InteriorPath*> mPaths;
|
||||
Vector<InteriorPathFollower*> mInteriorPathFollowers;
|
||||
Vector<ForceField*> mForceFields;
|
||||
Vector<AISpecialNode*> mAISpecialNodes;
|
||||
|
||||
GBitmap* mPreviewBitmap;
|
||||
|
||||
public:
|
||||
InteriorResource();
|
||||
~InteriorResource();
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
static GBitmap* extractPreview(Stream&);
|
||||
|
||||
S32 getNumDetailLevels() const;
|
||||
S32 getNumSubObjects() const;
|
||||
S32 getNumTriggers() const;
|
||||
S32 getNumPaths() const;
|
||||
S32 getNumInteriorPathFollowers() const;
|
||||
S32 getNumForceFields() const;
|
||||
S32 getNumSpecialNodes() const;
|
||||
|
||||
Interior* getDetailLevel(const U32);
|
||||
Interior* getSubObject(const U32);
|
||||
InteriorResTrigger* getTrigger(const U32);
|
||||
InteriorPath* getPath(const U32);
|
||||
InteriorPathFollower* getInteriorPathFollower(const U32);
|
||||
ForceField* getForceField(const U32);
|
||||
AISpecialNode* getSpecialNode(const U32);
|
||||
};
|
||||
extern ResourceInstance* constructInteriorDIF(Stream& stream);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline S32 InteriorResource::getNumDetailLevels() const
|
||||
{
|
||||
return mDetailLevels.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumSubObjects() const
|
||||
{
|
||||
return mSubObjects.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumTriggers() const
|
||||
{
|
||||
return mTriggers.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumPaths() const
|
||||
{
|
||||
return mPaths.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumSpecialNodes() const
|
||||
{
|
||||
return mAISpecialNodes.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumInteriorPathFollowers() const
|
||||
{
|
||||
return mInteriorPathFollowers.size();
|
||||
}
|
||||
|
||||
inline S32 InteriorResource::getNumForceFields() const
|
||||
{
|
||||
return mForceFields.size();
|
||||
}
|
||||
|
||||
inline Interior* InteriorResource::getDetailLevel(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumDetailLevels(), "Error, out of bounds detail level!");
|
||||
|
||||
return mDetailLevels[idx];
|
||||
}
|
||||
|
||||
inline Interior* InteriorResource::getSubObject(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumSubObjects(), "Error, out of bounds subObject!");
|
||||
|
||||
return mSubObjects[idx];
|
||||
}
|
||||
|
||||
inline InteriorResTrigger* InteriorResource::getTrigger(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumTriggers(), "Error, out of bounds trigger!");
|
||||
|
||||
return mTriggers[idx];
|
||||
}
|
||||
|
||||
inline InteriorPath* InteriorResource::getPath(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumPaths(), "Error, out of bounds path!");
|
||||
|
||||
return mPaths[idx];
|
||||
}
|
||||
|
||||
inline InteriorPathFollower* InteriorResource::getInteriorPathFollower(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumInteriorPathFollowers(), "Error, out of bounds path follower!");
|
||||
|
||||
return mInteriorPathFollowers[idx];
|
||||
}
|
||||
|
||||
inline ForceField* InteriorResource::getForceField(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumForceFields(), "Error, out of bounds force field!");
|
||||
|
||||
return mForceFields[idx];
|
||||
}
|
||||
|
||||
inline AISpecialNode* InteriorResource::getSpecialNode(const U32 idx)
|
||||
{
|
||||
AssertFatal(idx < getNumSpecialNodes(), "Error, out of bounds Special Nodes!");
|
||||
|
||||
return mAISpecialNodes[idx];
|
||||
}
|
||||
|
||||
#endif // _H_INTERIORRES_
|
||||
|
||||
200
interior/interiorResObjects.cc
Normal file
200
interior/interiorResObjects.cc
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/interiorResObjects.h"
|
||||
#include "Core/stream.h"
|
||||
#include "Math/mathIO.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
bool InteriorResTrigger::read(Stream& stream)
|
||||
{
|
||||
U32 i, size;
|
||||
stream.readString(mName);
|
||||
|
||||
// Read the polyhedron
|
||||
stream.read(&size);
|
||||
mPolyhedron.pointList.setSize(size);
|
||||
for (i = 0; i < mPolyhedron.pointList.size(); i++)
|
||||
mathRead(stream, &mPolyhedron.pointList[i]);
|
||||
|
||||
stream.read(&size);
|
||||
mPolyhedron.planeList.setSize(size);
|
||||
for (i = 0; i < mPolyhedron.planeList.size(); i++)
|
||||
mathRead(stream, &mPolyhedron.planeList[i]);
|
||||
|
||||
stream.read(&size);
|
||||
mPolyhedron.edgeList.setSize(size);
|
||||
for (i = 0; i < mPolyhedron.edgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = mPolyhedron.edgeList[i];
|
||||
|
||||
stream.read(&rEdge.face[0]);
|
||||
stream.read(&rEdge.face[1]);
|
||||
stream.read(&rEdge.vertex[0]);
|
||||
stream.read(&rEdge.vertex[1]);
|
||||
}
|
||||
|
||||
// And the offset
|
||||
mathRead(stream, &mOffset);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool InteriorResTrigger::write(Stream& stream) const
|
||||
{
|
||||
U32 i;
|
||||
|
||||
stream.writeString(mName);
|
||||
|
||||
// Write the polyhedron
|
||||
stream.write(mPolyhedron.pointList.size());
|
||||
for (i = 0; i < mPolyhedron.pointList.size(); i++)
|
||||
mathWrite(stream, mPolyhedron.pointList[i]);
|
||||
|
||||
stream.write(mPolyhedron.planeList.size());
|
||||
for (i = 0; i < mPolyhedron.planeList.size(); i++)
|
||||
mathWrite(stream, mPolyhedron.planeList[i]);
|
||||
|
||||
stream.write(mPolyhedron.edgeList.size());
|
||||
for (i = 0; i < mPolyhedron.edgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mPolyhedron.edgeList[i];
|
||||
|
||||
stream.write(rEdge.face[0]);
|
||||
stream.write(rEdge.face[1]);
|
||||
stream.write(rEdge.vertex[0]);
|
||||
stream.write(rEdge.vertex[1]);
|
||||
}
|
||||
|
||||
// And the offset
|
||||
mathWrite(stream, mOffset);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--------------------------------------
|
||||
//
|
||||
InteriorPath::InteriorPath()
|
||||
{
|
||||
mName[0] = '\0';
|
||||
mWayPoints = NULL;
|
||||
mNumWayPoints = 0;
|
||||
mLooping = false;
|
||||
}
|
||||
|
||||
InteriorPath::~InteriorPath()
|
||||
{
|
||||
delete [] mWayPoints;
|
||||
mWayPoints = NULL;
|
||||
mNumWayPoints = 0;
|
||||
}
|
||||
|
||||
bool InteriorPath::read(Stream& stream)
|
||||
{
|
||||
AssertFatal(mWayPoints == NULL, "Hm, this is probably going to cause problems, reading a path twice...");
|
||||
|
||||
stream.readString(mName);
|
||||
|
||||
stream.read(&mNumWayPoints);
|
||||
mWayPoints = new WayPoint[mNumWayPoints];
|
||||
for (U32 i = 0; i < mNumWayPoints; i++) {
|
||||
mathRead(stream, &mWayPoints[i].pos);
|
||||
mathRead(stream, &mWayPoints[i].rot);
|
||||
stream.read(&mWayPoints[i].msToNext);
|
||||
}
|
||||
stream.read(&mTotalMS);
|
||||
stream.read(&mLooping);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool InteriorPath::write(Stream& stream) const
|
||||
{
|
||||
stream.writeString(mName);
|
||||
|
||||
stream.write(mNumWayPoints);
|
||||
for (U32 i = 0; i < mNumWayPoints; i++) {
|
||||
mathWrite(stream, mWayPoints[i].pos);
|
||||
mathWrite(stream, mWayPoints[i].rot);
|
||||
stream.write(mWayPoints[i].msToNext);
|
||||
}
|
||||
stream.write(mTotalMS);
|
||||
stream.write(mLooping);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
|
||||
InteriorPathFollower::InteriorPathFollower()
|
||||
{
|
||||
mName = "";
|
||||
mPathIndex = 0;
|
||||
mOffset.set(0, 0, 0);
|
||||
}
|
||||
|
||||
InteriorPathFollower::~InteriorPathFollower()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool InteriorPathFollower::read(Stream& stream)
|
||||
{
|
||||
mName = stream.readSTString();
|
||||
stream.read(&mInteriorResIndex);
|
||||
stream.read(&mPathIndex);
|
||||
mathRead(stream, &mOffset);
|
||||
|
||||
U32 numTriggers;
|
||||
stream.read(&numTriggers);
|
||||
mTriggers.setSize(numTriggers);
|
||||
for (U32 i = 0; i < mTriggers.size(); i++)
|
||||
mTriggers[i] = stream.readSTString();
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool InteriorPathFollower::write(Stream& stream) const
|
||||
{
|
||||
stream.writeString(mName);
|
||||
stream.write(mInteriorResIndex);
|
||||
stream.write(mPathIndex);
|
||||
mathWrite(stream, mOffset);
|
||||
|
||||
stream.write(mTriggers.size());
|
||||
for (U32 i = 0; i < mTriggers.size(); i++)
|
||||
stream.writeString(mTriggers[i]);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
AISpecialNode::AISpecialNode()
|
||||
{
|
||||
mName = "";
|
||||
mPos.set(0, 0, 0);
|
||||
}
|
||||
|
||||
AISpecialNode::~AISpecialNode()
|
||||
{
|
||||
}
|
||||
|
||||
bool AISpecialNode::read(Stream& stream)
|
||||
{
|
||||
mName = stream.readSTString();
|
||||
mathRead(stream, &mPos);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool AISpecialNode::write(Stream& stream) const
|
||||
{
|
||||
stream.writeString(mName);
|
||||
mathWrite(stream, mPos);
|
||||
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
115
interior/interiorResObjects.h
Normal file
115
interior/interiorResObjects.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIORRESOBJECTS_H_
|
||||
#define _INTERIORRESOBJECTS_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "Math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MBOX_H_
|
||||
#include "Math/mBox.h"
|
||||
#endif
|
||||
#ifndef _MMATRIX_H_
|
||||
#include "Math/mMatrix.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
#ifndef _POLYHEDRON_H_
|
||||
#include "Collision/polyhedron.h"
|
||||
#endif
|
||||
|
||||
class Stream;
|
||||
|
||||
class InteriorResTrigger
|
||||
{
|
||||
public:
|
||||
enum Constants {
|
||||
MaxNameChars = 255
|
||||
};
|
||||
|
||||
char mName[MaxNameChars+1];
|
||||
|
||||
Point3F mOffset;
|
||||
Polyhedron mPolyhedron;
|
||||
|
||||
public:
|
||||
InteriorResTrigger() { }
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
};
|
||||
|
||||
class InteriorPath
|
||||
{
|
||||
public:
|
||||
struct WayPoint {
|
||||
Point3F pos;
|
||||
QuatF rot;
|
||||
U32 msToNext;
|
||||
};
|
||||
|
||||
public:
|
||||
char mName[256];
|
||||
WayPoint* mWayPoints;
|
||||
U32 mNumWayPoints;
|
||||
U32 mTotalMS;
|
||||
bool mLooping;
|
||||
|
||||
public:
|
||||
InteriorPath();
|
||||
~InteriorPath();
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
};
|
||||
|
||||
class InteriorPathFollower
|
||||
{
|
||||
public:
|
||||
StringTableEntry mName;
|
||||
U32 mInteriorResIndex;
|
||||
U32 mPathIndex;
|
||||
Point3F mOffset;
|
||||
Vector<StringTableEntry> mTriggers;
|
||||
|
||||
public:
|
||||
InteriorPathFollower();
|
||||
~InteriorPathFollower();
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
};
|
||||
|
||||
|
||||
class AISpecialNode
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
chute = 0,
|
||||
};
|
||||
|
||||
public:
|
||||
StringTableEntry mName;
|
||||
Point3F mPos;
|
||||
//U32 mType;
|
||||
|
||||
public:
|
||||
AISpecialNode();
|
||||
~AISpecialNode();
|
||||
|
||||
bool read(Stream& stream);
|
||||
bool write(Stream& stream) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // _H_INTERIORRESOBJECTS_
|
||||
93
interior/interiorSubObject.cc
Normal file
93
interior/interiorSubObject.cc
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Core/stream.h"
|
||||
#include "interior/interiorInstance.h"
|
||||
|
||||
#include "interior/interiorSubObject.h"
|
||||
#include "interior/mirrorSubObject.h"
|
||||
|
||||
|
||||
InteriorSubObject::InteriorSubObject()
|
||||
{
|
||||
mInteriorInstance = NULL;
|
||||
}
|
||||
|
||||
InteriorSubObject::~InteriorSubObject()
|
||||
{
|
||||
mInteriorInstance = NULL;
|
||||
}
|
||||
|
||||
InteriorSubObject* InteriorSubObject::readISO(Stream& stream)
|
||||
{
|
||||
U32 soKey;
|
||||
stream.read(&soKey);
|
||||
|
||||
InteriorSubObject* pObject = NULL;
|
||||
switch (soKey) {
|
||||
case MirrorSubObjectKey:
|
||||
pObject = new MirrorSubObject;
|
||||
break;
|
||||
|
||||
default:
|
||||
Con::errorf(ConsoleLogEntry::General, "Bad key in subObject stream!");
|
||||
return NULL;
|
||||
};
|
||||
|
||||
if (pObject) {
|
||||
bool readSuccess = pObject->_readISO(stream);
|
||||
if (readSuccess == false) {
|
||||
delete pObject;
|
||||
pObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
bool InteriorSubObject::writeISO(Stream& stream) const
|
||||
{
|
||||
stream.write(getSubObjectKey());
|
||||
return _writeISO(stream);
|
||||
}
|
||||
|
||||
bool InteriorSubObject::_readISO(Stream& stream)
|
||||
{
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
bool InteriorSubObject::_writeISO(Stream& stream) const
|
||||
{
|
||||
return (stream.getStatus() == Stream::Ok);
|
||||
}
|
||||
|
||||
const MatrixF& InteriorSubObject::getSOTransform() const
|
||||
{
|
||||
static const MatrixF csBadMatrix(true);
|
||||
|
||||
if (mInteriorInstance != NULL) {
|
||||
return mInteriorInstance->getTransform();
|
||||
} else {
|
||||
AssertWarn(false, "Returning bad transform for subobject");
|
||||
return csBadMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
const Point3F& InteriorSubObject::getSOScale() const
|
||||
{
|
||||
return mInteriorInstance->getScale();
|
||||
}
|
||||
|
||||
InteriorInstance* InteriorSubObject::getInstance()
|
||||
{
|
||||
return mInteriorInstance;
|
||||
}
|
||||
|
||||
void InteriorSubObject::noteTransformChange()
|
||||
{
|
||||
//
|
||||
}
|
||||
65
interior/interiorSubObject.h
Normal file
65
interior/interiorSubObject.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _INTERIORSUBOBJECT_H_
|
||||
#define _INTERIORSUBOBJECT_H_
|
||||
|
||||
#ifndef _SCENESTATE_H_
|
||||
#include "sceneGraph/sceneState.h"
|
||||
#endif
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "Sim/sceneObject.h"
|
||||
#endif
|
||||
|
||||
class InteriorInstance;
|
||||
|
||||
class SubObjectRenderImage : public SceneRenderImage
|
||||
{
|
||||
public:
|
||||
U32 mDetailLevel;
|
||||
};
|
||||
|
||||
class InteriorSubObject : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
protected:
|
||||
InteriorInstance* mInteriorInstance; // Should NOT be set by derived except in clone
|
||||
|
||||
protected:
|
||||
enum SubObjectKeys {
|
||||
TranslucentSubObjectKey = 0,
|
||||
MirrorSubObjectKey = 1
|
||||
};
|
||||
|
||||
virtual U32 getSubObjectKey() const = 0;
|
||||
virtual bool _readISO(Stream&);
|
||||
virtual bool _writeISO(Stream&) const;
|
||||
|
||||
InteriorInstance* getInstance();
|
||||
const MatrixF& getSOTransform() const;
|
||||
const Point3F& getSOScale() const;
|
||||
|
||||
public:
|
||||
InteriorSubObject();
|
||||
virtual ~InteriorSubObject();
|
||||
|
||||
// Render control. A sub-object should return false from renderDetailDependant if
|
||||
// it exists only at the level-0 detail level, ie, doors, elevators, etc., true
|
||||
// if should only render at the interiors detail, ie, translucencies.
|
||||
virtual SubObjectRenderImage* getRenderImage(SceneState*, const Point3F& osPoint) = 0;
|
||||
virtual bool renderDetailDependant() const = 0;
|
||||
virtual U32 getZone() const = 0;
|
||||
|
||||
virtual void noteTransformChange();
|
||||
virtual InteriorSubObject* clone(InteriorInstance*) const = 0;
|
||||
|
||||
static InteriorSubObject* readISO(Stream&);
|
||||
bool writeISO(Stream&) const;
|
||||
};
|
||||
|
||||
#endif // _H_INTERIORSUBOBJECT_
|
||||
104
interior/itf.h
Normal file
104
interior/itf.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _ITF_H_
|
||||
#define _ITF_H_
|
||||
|
||||
#ifndef _TYPES_H_
|
||||
#include "platform/types.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
|
||||
#ifndef _INTERIOR_H_
|
||||
// redecl struct here for now... interior.h brings in the whole fricking codebase.
|
||||
struct ItrPaddedPoint
|
||||
{
|
||||
Point3F point;
|
||||
union {
|
||||
F32 fogCoord;
|
||||
U8 fogColor[4];
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
struct OutputPoint
|
||||
{
|
||||
Point3F point;
|
||||
union {
|
||||
F32 fogCoord;
|
||||
U8 fogColor[4];
|
||||
};
|
||||
Point2F texCoord;
|
||||
Point2F lmCoord;
|
||||
};
|
||||
|
||||
struct OutputPointFC_VB
|
||||
{
|
||||
Point3F point;
|
||||
U8 currentColor[4];
|
||||
U8 fogColor[4];
|
||||
Point2F texCoord;
|
||||
Point2F lmCoord;
|
||||
};
|
||||
|
||||
struct OutputPointSP_FC_VB
|
||||
{
|
||||
Point3F point;
|
||||
U8 lmColor[4];
|
||||
U8 fogColor[4];
|
||||
Point2F texCoord;
|
||||
};
|
||||
|
||||
|
||||
#ifndef TARG_MACCARB // don't bracket on mac.
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void processTriFan(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices);
|
||||
void processTriFanSP(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors);
|
||||
void processTriFanVC_TF(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors);
|
||||
void processTriFanSP_FC(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors);
|
||||
void processTriFanFC_VB(OutputPointFC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices);
|
||||
void processTriFanSP_FC_VB(OutputPointSP_FC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors);
|
||||
|
||||
extern F32 texGen0[8];
|
||||
extern F32 texGen1[8];
|
||||
extern void* fogCoordinatePointer;
|
||||
|
||||
#ifndef TARG_MACCARB // don't bracket on mac.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
657
interior/itfdump.asm
Normal file
657
interior/itfdump.asm
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
;
|
||||
; NASM version of tribes2/src/interior/itfdump.asm
|
||||
;
|
||||
|
||||
|
||||
segment .data
|
||||
|
||||
storeebp dd 0
|
||||
|
||||
srcPoints dd 0
|
||||
srcColors dd 0
|
||||
srcIndices dd 0
|
||||
numPoints dd 0
|
||||
two55 dd 0x437F0000
|
||||
alpha dd 0
|
||||
|
||||
%ifdef __linux
|
||||
; No underscore needed for ELF object files
|
||||
%define _texGen0 texGen0
|
||||
%define _texGen1 texGen1
|
||||
%define _fogCoordinatePointer fogCoordinatePointer
|
||||
%endif
|
||||
extern _texGen0
|
||||
extern _texGen1
|
||||
extern _fogCoordinatePointer
|
||||
|
||||
|
||||
segment .text
|
||||
|
||||
;
|
||||
; these macros are good for both functions
|
||||
;
|
||||
|
||||
%define in_dst [ebp+8]
|
||||
%define in_src_points [ebp+12]
|
||||
%define in_src_indices [ebp+16]
|
||||
%define in_numpoints [ebp+20]
|
||||
|
||||
%define in_srcColors [ebp+24] ; Valid only for SP
|
||||
|
||||
; CodeWarrior sucks :P
|
||||
%ifdef __linux
|
||||
global processTriFan
|
||||
|
||||
processTriFan:
|
||||
%else
|
||||
global _processTriFan
|
||||
|
||||
_processTriFan:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp1:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov edx, [esi + 12] ; f
|
||||
mov [edi + 0], eax ; <- x
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov [edi + 8], ecx ; <- z
|
||||
mov [edi + 12], edx ; <- f
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 16] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 20] ; tc0.t
|
||||
|
||||
; tc1.s
|
||||
fld dword [_texGen1 + 0] ; tg1.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen1 + 4] ; tg1.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen1 + 8] ; tg1.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen1 + 12] ; tg1.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 24] ; tc1.s
|
||||
|
||||
; tc1.t
|
||||
fld dword [_texGen1 + 16] ; tg1.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen1 + 20] ; tg1.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen1 + 24] ; tg1.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen1 + 28] ; tg1.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 28] ; tc1.t
|
||||
|
||||
add edi, 32
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp1
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
; More suckage
|
||||
%ifdef __linux
|
||||
global processTriFanSP
|
||||
|
||||
processTriFanSP:
|
||||
%else
|
||||
global _processTriFanSP
|
||||
|
||||
_processTriFanSP:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
mov eax, in_srcColors
|
||||
mov [srcColors], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp2:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov edx, [srcColors] ; color
|
||||
mov [edi + 0], eax ; <- x
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov edx, [edx] ; color
|
||||
mov [edi + 8], ecx ; <- z
|
||||
mov [edi + 12], edx ; color
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 16] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 20] ; tc0.t
|
||||
|
||||
add edi, 32
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp2
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
; More suckage
|
||||
%ifdef __linux
|
||||
global processTriFanVC_TF
|
||||
|
||||
processTriFanVC_TF:
|
||||
%else
|
||||
global _processTriFanVC_TF
|
||||
|
||||
_processTriFanVC_TF:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
mov eax, in_srcColors
|
||||
mov [srcColors], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp4:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
; Fog tex coord
|
||||
mov ebx, [_fogCoordinatePointer]
|
||||
shr eax, 1 ; idx /= 2
|
||||
lea ebx, [ebx + eax]
|
||||
mov ecx, [ebx + 0];
|
||||
mov edx, [ebx + 4];
|
||||
mov [edi + 16], ecx
|
||||
mov [edi + 20], edx
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov edx, [srcColors] ; color
|
||||
mov [edi + 0], eax ; <- x
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov edx, [edx] ; color
|
||||
mov [edi + 8], ecx ; <- z
|
||||
mov [edi + 12], edx ; color
|
||||
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 24] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 28] ; tc0.t
|
||||
|
||||
add edi, 32
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp4
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
; More suckagea
|
||||
%ifdef __linux
|
||||
global processTriFanSP_FC
|
||||
|
||||
processTriFanSP_FC:
|
||||
%else
|
||||
global _processTriFanSP_FC
|
||||
|
||||
_processTriFanSP_FC:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
mov eax, in_srcColors
|
||||
mov [srcColors], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp2_fc:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov edx, [esi + 12] ; fc
|
||||
mov [edi + 0], eax ; <- x
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov [edi + 8], ecx ; <- z
|
||||
mov [edi + 24], edx ; <- fc (lmcoord.x)
|
||||
mov edx, [srcColors] ; color
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov edx, [edx] ; color
|
||||
mov [edi + 12], edx ; color
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 16] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 20] ; tc0.t
|
||||
|
||||
add edi, 32
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp2_fc
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; CodeWarrior still sucks :P
|
||||
%ifdef __linux
|
||||
global processTriFanFC_VB
|
||||
|
||||
processTriFanFC_VB:
|
||||
%else
|
||||
global _processTriFanFC_VB
|
||||
|
||||
_processTriFanFC_VB:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp1_fc_vb:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov edx, 0xFFFFFFFF ; c
|
||||
mov [edi + 0], eax ; <- x
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov [edi + 8], ecx ; <- z
|
||||
mov [edi + 12], edx ; <- c
|
||||
|
||||
fld dword [esi + 12]
|
||||
fld dword [two55]
|
||||
fmulp st1, st0
|
||||
fistp dword [alpha]
|
||||
mov eax, 255
|
||||
sub eax, [alpha]
|
||||
cmp eax, 0
|
||||
jge near procPointLp1a_fc_vb
|
||||
mov eax, 0
|
||||
procPointLp1a_fc_vb:
|
||||
shl eax, 24
|
||||
mov [edi + 16], eax ; <- f
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 28] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 32] ; tc0.t
|
||||
|
||||
; tc1.s
|
||||
fld dword [_texGen1 + 0] ; tg1.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen1 + 4] ; tg1.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen1 + 8] ; tg1.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen1 + 12] ; tg1.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 20] ; tc1.s
|
||||
|
||||
; tc1.t
|
||||
fld dword [_texGen1 + 16] ; tg1.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen1 + 20] ; tg1.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen1 + 24] ; tg1.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen1 + 28] ; tg1.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 24] ; tc1.t
|
||||
|
||||
add edi, 36
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp1_fc_vb
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
||||
; More suckagea
|
||||
%ifdef __linux
|
||||
global processTriFanSP_FC_VB
|
||||
|
||||
processTriFanSP_FC_VB:
|
||||
%else
|
||||
global _processTriFanSP_FC_VB
|
||||
|
||||
_processTriFanSP_FC_VB:
|
||||
%endif
|
||||
|
||||
; prologue
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
; Store the destination and source pointers
|
||||
mov eax, in_src_points
|
||||
mov [srcPoints], eax
|
||||
mov eax, in_src_indices
|
||||
mov [srcIndices], eax
|
||||
mov eax, in_numpoints
|
||||
mov [numPoints], eax
|
||||
mov eax, in_srcColors
|
||||
mov [srcColors], eax
|
||||
|
||||
mov edi, in_dst
|
||||
|
||||
mov [storeebp], ebp
|
||||
xor ebp, ebp
|
||||
procPointLp2_fc_vb:
|
||||
; This could be faster
|
||||
mov esi, [srcIndices]
|
||||
lea esi, [esi + ebp*4]
|
||||
mov eax, dword [esi]
|
||||
shl eax, 4 ; idx *= 16
|
||||
mov esi, [srcPoints]
|
||||
lea esi, [esi + eax]
|
||||
|
||||
mov eax, [esi + 0] ; x
|
||||
mov ebx, [esi + 4] ; y
|
||||
mov ecx, [esi + 8] ; z
|
||||
mov [edi + 0], eax ; <- x
|
||||
mov [edi + 4], ebx ; <- y
|
||||
mov [edi + 8], ecx ; <- z
|
||||
|
||||
fld dword [esi + 12]
|
||||
fld dword [two55]
|
||||
fmulp st1, st0
|
||||
fistp dword [alpha]
|
||||
mov eax, 255
|
||||
sub eax, [alpha]
|
||||
cmp eax, 0
|
||||
jge near procPointLp2a_fc_vb
|
||||
mov eax, 0
|
||||
procPointLp2a_fc_vb:
|
||||
shl eax, 24
|
||||
mov [edi + 16], eax ; <- fc
|
||||
|
||||
mov edx, [srcColors] ; color
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov edx, [edx] ; color
|
||||
mov eax, edx
|
||||
mov ebx, 0x00FF00FF
|
||||
and edx, ebx
|
||||
not ebx
|
||||
rol edx, 16
|
||||
and eax, ebx
|
||||
or edx, eax
|
||||
mov [edi + 12], edx ; color
|
||||
|
||||
; tc0.s
|
||||
fld dword [_texGen0 + 0] ; tg0.s.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 4] ; tg0.s.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 8] ; tg0.s.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 12] ; tg0.s.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 20] ; tc0.s
|
||||
|
||||
; tc0.t
|
||||
fld dword [_texGen0 + 16] ; tg0.t.x
|
||||
fmul dword [esi + 0]
|
||||
fld dword [_texGen0 + 20] ; tg0.t.y
|
||||
fmul dword [esi + 4]
|
||||
fld dword [_texGen0 + 24] ; tg0.t.z
|
||||
fmul dword [esi + 8]
|
||||
fld dword [_texGen0 + 28] ; tg0.t.w
|
||||
faddp st3, st0
|
||||
faddp st1, st0
|
||||
faddp st1, st0
|
||||
fstp dword [edi + 24] ; tc0.t
|
||||
|
||||
add edi, 28
|
||||
|
||||
inc ebp
|
||||
cmp ebp, [numPoints]
|
||||
jl near procPointLp2_fc_vb
|
||||
|
||||
mov ebp, [storeebp]
|
||||
|
||||
; epilogue
|
||||
pop ebp
|
||||
ret
|
||||
311
interior/itfdump.cc
Normal file
311
interior/itfdump.cc
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/itf.h"
|
||||
|
||||
//two55 dd 0x437F0000
|
||||
//alpha dd 0
|
||||
|
||||
//============================================================
|
||||
void processTriFan(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices)
|
||||
{
|
||||
U32 i, j;
|
||||
F32 x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogCoord = srcPoints[j].fogCoord;
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
|
||||
dst->lmCoord.x = (texGen1[0]*x)
|
||||
+ (texGen1[1]*y)
|
||||
+ (texGen1[2]*z)
|
||||
+ (texGen1[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen1[4]*x)
|
||||
+ (texGen1[5]*y)
|
||||
+ (texGen1[6]*z)
|
||||
+ (texGen1[7]);
|
||||
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void processTriFanSP(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void processTriFanVC_TF(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
|
||||
// dc - I >think< I got this right...
|
||||
dst->texCoord.x = fogCoordinatePointer[j].x;
|
||||
dst->texCoord.y = fogCoordinatePointer[j].y;
|
||||
|
||||
dst->lmCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void processTriFanSP_FC(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
dst->lmCoord.x = srcPoints[j].fogCoord;
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// helpers:
|
||||
const float two55 = (F32)0x473F0000; // !!!!!!TBD -- not sure this is right...
|
||||
|
||||
#define ALPHA_CALC(a, c) \
|
||||
a = c * two55; \
|
||||
a = 255 - a; /* flip direction of value. */ \
|
||||
if (a < 0) a = 0;
|
||||
|
||||
/* ASM for previous calculation:
|
||||
fld dword [esi + 12]
|
||||
fld dword [two55]
|
||||
fmulp st1, st0
|
||||
fistp dword [alpha]
|
||||
mov eax, 255
|
||||
sub eax, [alpha]
|
||||
cmp eax, 0
|
||||
jge near procPointLp1a_fc_vb
|
||||
mov eax, 0
|
||||
procPointLp1a_fc_vb:
|
||||
shl eax, 24 // left this in the function instead of the macro.
|
||||
mov [edi + 16], eax ; <- f
|
||||
*/
|
||||
|
||||
|
||||
//============================================================
|
||||
void processTriFanFC_VB(OutputPointFC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices)
|
||||
{
|
||||
S32 alpha;
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->currentColors = 0xFFFFFFFF;
|
||||
|
||||
ALPHA_CALC(alpha, srcPoints[j].fogCoord);
|
||||
dst->fogColors = ((U32)alpha)<<24; // move into alpha position.
|
||||
|
||||
// dc - note the texGens are used in reverse order. that's what the ASM did...
|
||||
dst->texCoord.x = (texGen1[0]*x)
|
||||
+ (texGen1[1]*y)
|
||||
+ (texGen1[2]*z)
|
||||
+ (texGen1[3]);
|
||||
|
||||
dst->texCoord.y = (texGen1[4]*x)
|
||||
+ (texGen1[5]*y)
|
||||
+ (texGen1[6]*z)
|
||||
+ (texGen1[7]);
|
||||
|
||||
dst->lmCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//!!!!!!TBD -- is there a rotate intrinsic?????
|
||||
#define ROL16(x) (x) = ((((x)<<16)&0xFFFF0000) | (((x)>>16)&0x0000FFFF))
|
||||
|
||||
//============================================================
|
||||
void processTriFanSP_FC_VB(OutputPointSP_FC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
S32 alpha;
|
||||
U32 i, j, tmp, tmp2;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
|
||||
/*
|
||||
mov edx, [srcColors] ; color
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov edx, [edx] ; color
|
||||
mov eax, edx
|
||||
mov ebx, 0x00FF00FF
|
||||
and edx, ebx
|
||||
not ebx
|
||||
and eax, ebx
|
||||
rol edx, 16
|
||||
or edx, eax
|
||||
mov [edi + 12], edx ; color
|
||||
*/
|
||||
|
||||
tmp = srcColors[j].getARGBEndian();
|
||||
tmp2 = tmp;
|
||||
|
||||
tmp = (tmp & 0x00FF00FF);
|
||||
tmp2 = (tmp2 & 0xFF00FF00);
|
||||
|
||||
ROL16(tmp);
|
||||
|
||||
dst->lmColors = (tmp | tmp2);
|
||||
|
||||
ALPHA_CALC(alpha, srcPoints[j].fogCoord);
|
||||
dst->fogColors = ((U32)alpha)<<24; // move into alpha position.
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
311
interior/itfdump_c.cc
Normal file
311
interior/itfdump_c.cc
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/itf.h"
|
||||
|
||||
//two55 dd 0x437F0000
|
||||
//alpha dd 0
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFan(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices)
|
||||
{
|
||||
U32 i, j;
|
||||
F32 x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogCoord = srcPoints[j].fogCoord;
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
|
||||
dst->lmCoord.x = (texGen1[0]*x)
|
||||
+ (texGen1[1]*y)
|
||||
+ (texGen1[2]*z)
|
||||
+ (texGen1[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen1[4]*x)
|
||||
+ (texGen1[5]*y)
|
||||
+ (texGen1[6]*z)
|
||||
+ (texGen1[7]);
|
||||
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFanSP(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFanVC_TF(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
|
||||
// dc - I >think< I got this right...
|
||||
dst->texCoord.x = fogCoordinatePointer[j].x;
|
||||
dst->texCoord.y = fogCoordinatePointer[j].y;
|
||||
|
||||
dst->lmCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFanSP_FC(OutputPoint* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->fogColors = srcColors[j].getARGBEndian();
|
||||
dst->lmCoord.x = srcPoints[j].fogCoord;
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================
|
||||
// helpers:
|
||||
const float two55 = (F32)0x473F0000; // !!!!!!TBD -- not sure this is right...
|
||||
|
||||
#define ALPHA_CALC(a, c) \
|
||||
a = c * two55; \
|
||||
a = 255 - a; /* flip direction of value. */ \
|
||||
if (a < 0) a = 0;
|
||||
|
||||
/* ASM for previous calculation:
|
||||
fld dword [esi + 12]
|
||||
fld dword [two55]
|
||||
fmulp st1, st0
|
||||
fistp dword [alpha]
|
||||
mov eax, 255
|
||||
sub eax, [alpha]
|
||||
cmp eax, 0
|
||||
jge near procPointLp1a_fc_vb
|
||||
mov eax, 0
|
||||
procPointLp1a_fc_vb:
|
||||
shl eax, 24 // left this in the function instead of the macro.
|
||||
mov [edi + 16], eax ; <- f
|
||||
*/
|
||||
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFanFC_VB(OutputPointFC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices)
|
||||
{
|
||||
S32 alpha;
|
||||
U32 i, j;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
dst->currentColors = 0xFFFFFFFF;
|
||||
|
||||
ALPHA_CALC(alpha, srcPoints[j].fogCoord);
|
||||
dst->fogColors = ((U32)alpha)<<24; // move into alpha position.
|
||||
|
||||
// dc - note the texGens are used in reverse order. that's what the ASM did...
|
||||
dst->texCoord.x = (texGen1[0]*x)
|
||||
+ (texGen1[1]*y)
|
||||
+ (texGen1[2]*z)
|
||||
+ (texGen1[3]);
|
||||
|
||||
dst->texCoord.y = (texGen1[4]*x)
|
||||
+ (texGen1[5]*y)
|
||||
+ (texGen1[6]*z)
|
||||
+ (texGen1[7]);
|
||||
|
||||
dst->lmCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->lmCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//!!!!!!TBD -- is there a rotate intrinsic?????
|
||||
#define ROL16(x) (x) = ((((x)<<16)&0xFFFF0000) | (((x)>>16)&0x0000FFFF))
|
||||
|
||||
//============================================================
|
||||
void FN_CDECL processTriFanSP_FC_VB(OutputPointSP_FC_VB* dst,
|
||||
const ItrPaddedPoint* srcPoints,
|
||||
const U32* srcIndices,
|
||||
const U32 numIndices,
|
||||
const ColorI* srcColors)
|
||||
{
|
||||
S32 alpha;
|
||||
U32 i, j, tmp, tmp2;
|
||||
float x,y,z;
|
||||
for (i=0; i<numIndices; i++)
|
||||
{
|
||||
j = srcIndices[i];
|
||||
x = srcPoints[j].point.x;
|
||||
y = srcPoints[j].point.y;
|
||||
z = srcPoints[j].point.z;
|
||||
|
||||
dst->point.x = x;
|
||||
dst->point.y = y;
|
||||
dst->point.z = z;
|
||||
|
||||
/*
|
||||
mov edx, [srcColors] ; color
|
||||
lea edx, [edx + ebp*4] ; color
|
||||
mov edx, [edx] ; color
|
||||
mov eax, edx
|
||||
mov ebx, 0x00FF00FF
|
||||
and edx, ebx
|
||||
not ebx
|
||||
and eax, ebx
|
||||
rol edx, 16
|
||||
or edx, eax
|
||||
mov [edi + 12], edx ; color
|
||||
*/
|
||||
|
||||
tmp = srcColors[j].getARGBEndian();
|
||||
tmp2 = tmp;
|
||||
|
||||
tmp = (tmp & 0x00FF00FF);
|
||||
tmp2 = (tmp2 & 0xFF00FF00);
|
||||
|
||||
ROL16(tmp);
|
||||
|
||||
dst->lmColors = (tmp | tmp2);
|
||||
|
||||
ALPHA_CALC(alpha, srcPoints[j].fogCoord);
|
||||
dst->fogColors = ((U32)alpha)<<24; // move into alpha position.
|
||||
|
||||
dst->texCoord.x = (texGen0[0]*x)
|
||||
+ (texGen0[1]*y)
|
||||
+ (texGen0[2]*z)
|
||||
+ (texGen0[3]);
|
||||
|
||||
dst->texCoord.y = (texGen0[4]*x)
|
||||
+ (texGen0[5]*y)
|
||||
+ (texGen0[6]*z)
|
||||
+ (texGen0[7]);
|
||||
// move to next ptr.
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
77
interior/lightUpdateGrouper.cc
Normal file
77
interior/lightUpdateGrouper.cc
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/lightUpdateGrouper.h"
|
||||
|
||||
LightUpdateGrouper::LightUpdateGrouper(const U32 bitStart, const U32 bitEnd)
|
||||
{
|
||||
AssertFatal(bitEnd >= bitStart, "Error, bitend must be greater than bit start");
|
||||
AssertFatal(bitEnd < 32, "Error, bitend too large. must be in the range 0..31");
|
||||
|
||||
mBitStart = bitStart;
|
||||
mBitEnd = bitEnd;
|
||||
}
|
||||
|
||||
|
||||
LightUpdateGrouper::~LightUpdateGrouper()
|
||||
{
|
||||
mBitStart = 0xFFFFFFFF;
|
||||
mBitEnd = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
void LightUpdateGrouper::addKey(const U32 key)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (U32 i = 0; i < mKeys.size(); i++)
|
||||
AssertFatal(mKeys[i] != key, "Error, key already in the array!");
|
||||
#endif
|
||||
|
||||
mKeys.push_back(key);
|
||||
}
|
||||
|
||||
U32 LightUpdateGrouper::getKeyMask(const U32 key) const
|
||||
{
|
||||
U32 numBits = mBitEnd - mBitStart + 1;
|
||||
for (U32 i = 0; i < mKeys.size(); i++) {
|
||||
if (mKeys[i] == key) {
|
||||
U32 idx = i % numBits;
|
||||
return (1 << (idx + mBitStart));
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(false, "Error, key not in the array!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LightUpdateGrouper::BitIterator LightUpdateGrouper::begin()
|
||||
{
|
||||
BitIterator itr;
|
||||
itr.mGrouper = this;
|
||||
itr.mCurrBit = mBitStart;
|
||||
itr.resetKeyArray();
|
||||
|
||||
return itr;
|
||||
}
|
||||
|
||||
void LightUpdateGrouper::BitIterator::resetKeyArray()
|
||||
{
|
||||
mKeyArray.clear();
|
||||
if (valid() == false)
|
||||
return;
|
||||
|
||||
// Ok, we need to select out every (mBitEnd - mBitStart - 1)th key,
|
||||
// starting at mCurrBit.
|
||||
|
||||
U32 numBits = mGrouper->mBitEnd - mGrouper->mBitStart + 1;
|
||||
U32 numKeys = mGrouper->mKeys.size();
|
||||
|
||||
for (U32 i = mCurrBit - mGrouper->mBitStart; i < numKeys; i += numBits) {
|
||||
mKeyArray.push_back(mGrouper->mKeys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
108
interior/lightUpdateGrouper.h
Normal file
108
interior/lightUpdateGrouper.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LIGHTUPDATEGROUPER_H_
|
||||
#define _LIGHTUPDATEGROUPER_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "Platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "Core/tVector.h"
|
||||
#endif
|
||||
|
||||
class LightUpdateGrouper
|
||||
{
|
||||
Vector<U32> mKeys;
|
||||
U32 mBitStart;
|
||||
U32 mBitEnd;
|
||||
|
||||
public:
|
||||
class BitIterator {
|
||||
friend class LightUpdateGrouper;
|
||||
|
||||
private:
|
||||
Vector<U32> mKeyArray;
|
||||
U32 mCurrBit;
|
||||
LightUpdateGrouper* mGrouper;
|
||||
|
||||
void resetKeyArray();
|
||||
|
||||
public:
|
||||
typedef U32 const* iterator;
|
||||
|
||||
bool valid();
|
||||
U32 getNumKeys();
|
||||
U32 getMask();
|
||||
|
||||
BitIterator& operator++(int);
|
||||
BitIterator& operator++();
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
};
|
||||
friend class BitIterator;
|
||||
|
||||
public:
|
||||
LightUpdateGrouper(const U32 bitStart, const U32 bitEnd);
|
||||
~LightUpdateGrouper();
|
||||
|
||||
void addKey(const U32 key);
|
||||
U32 getKeyMask(const U32 key) const;
|
||||
|
||||
BitIterator begin();
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline LightUpdateGrouper::BitIterator& LightUpdateGrouper::BitIterator::operator++()
|
||||
{
|
||||
mCurrBit++;
|
||||
resetKeyArray();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline LightUpdateGrouper::BitIterator& LightUpdateGrouper::BitIterator::operator++(int)
|
||||
{
|
||||
return operator++();
|
||||
}
|
||||
|
||||
inline LightUpdateGrouper::BitIterator::iterator LightUpdateGrouper::BitIterator::begin()
|
||||
{
|
||||
if (valid() == false)
|
||||
return NULL;
|
||||
|
||||
return mKeyArray.begin();
|
||||
}
|
||||
|
||||
inline LightUpdateGrouper::BitIterator::iterator LightUpdateGrouper::BitIterator::end()
|
||||
{
|
||||
if (valid() == false)
|
||||
return NULL;
|
||||
|
||||
return mKeyArray.end();
|
||||
}
|
||||
|
||||
inline bool LightUpdateGrouper::BitIterator::valid()
|
||||
{
|
||||
return mCurrBit <= mGrouper->mBitEnd;
|
||||
}
|
||||
|
||||
inline U32 LightUpdateGrouper::BitIterator::getNumKeys()
|
||||
{
|
||||
return mKeyArray.size();
|
||||
}
|
||||
|
||||
inline U32 LightUpdateGrouper::BitIterator::getMask()
|
||||
{
|
||||
return (1 << mCurrBit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // _H_LIGHTUPDATEGROUPER_
|
||||
532
interior/mirrorSubObject.cc
Normal file
532
interior/mirrorSubObject.cc
Normal file
|
|
@ -0,0 +1,532 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "interior/mirrorSubObject.h"
|
||||
#include "interior/interiorInstance.h"
|
||||
#include "interior/interior.h"
|
||||
#include "dgl/materialList.h"
|
||||
#include "Core/stream.h"
|
||||
#include "PlatformWin32/platformGL.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "sceneGraph/sgUtil.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(MirrorSubObject);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
MirrorSubObject::MirrorSubObject()
|
||||
{
|
||||
mTypeMask = StaticObjectType;
|
||||
|
||||
mInitialized = false;
|
||||
mWhite = NULL;
|
||||
}
|
||||
|
||||
MirrorSubObject::~MirrorSubObject()
|
||||
{
|
||||
delete mWhite;
|
||||
mWhite = NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::renderObject(SceneState* state, SceneRenderImage* image)
|
||||
{
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
||||
|
||||
SubObjectRenderImage* sori = static_cast<SubObjectRenderImage*>(image);
|
||||
|
||||
if (mZone == 0) {
|
||||
state->setupZoneProjection(getInstance()->getCurrZone(0));
|
||||
} else {
|
||||
state->setupZoneProjection(mZone + getInstance()->getZoneRangeStart() - 1);
|
||||
}
|
||||
|
||||
RectI viewport;
|
||||
dglGetViewport(&viewport);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
dglMultMatrix(&getSOTransform());
|
||||
glScalef(getSOScale().x, getSOScale().y, getSOScale().z);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_TEXTURE_GEN_S); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glColor4f(1, 1, 1, mAlphaLevel);
|
||||
|
||||
Interior* interior = getInstance()->getDetailLevel(sori->mDetailLevel);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ItrPaddedPoint), interior->mPoints.address());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, interior->mMaterialList->getMaterial(interior->mSurfaces[surfaceStart].textureIndex).getGLName());
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, (GLfloat*)interior->mTexGenEQs[interior->mSurfaces[surfaceStart].texGenIndex].planeX);
|
||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, (GLfloat*)interior->mTexGenEQs[interior->mSurfaces[surfaceStart].texGenIndex].planeY);
|
||||
|
||||
for (U32 i = 0; i < surfaceCount; i++) {
|
||||
glDrawElements(GL_TRIANGLE_STRIP,
|
||||
interior->mSurfaces[surfaceStart+i].windingCount,
|
||||
GL_UNSIGNED_INT,
|
||||
&interior->mWindings[interior->mSurfaces[surfaceStart+i].windingStart]);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
dglSetViewport(viewport);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
dglSetCanonicalState();
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::transformModelview(const U32 portalIndex, const MatrixF& oldMV, MatrixF* pNewMV)
|
||||
{
|
||||
AssertFatal(isInitialized() == true, "Error, we should have been initialized by this point!");
|
||||
AssertFatal(portalIndex == 0, "Error, we only have one portal!");
|
||||
|
||||
*pNewMV = oldMV;
|
||||
pNewMV->mul(mReflectionMatrix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::transformPosition(const U32 portalIndex, Point3F& ioPosition)
|
||||
{
|
||||
AssertFatal(isInitialized() == true, "Error, we should have been initialized by this point!");
|
||||
AssertFatal(portalIndex == 0, "Error, we only have one portal!");
|
||||
|
||||
mReflectionMatrix.mulP(ioPosition);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool MirrorSubObject::computeNewFrustum(const U32 portalIndex,
|
||||
const F64* oldFrustum,
|
||||
const F64 nearPlane,
|
||||
const F64 farPlane,
|
||||
const RectI& oldViewport,
|
||||
F64* newFrustum,
|
||||
RectI& newViewport,
|
||||
const bool flippedMatrix)
|
||||
{
|
||||
AssertFatal(isInitialized() == true, "Error, we should have been initialized by this point!");
|
||||
AssertFatal(portalIndex == 0, "Error, mirrortests only have one portal!");
|
||||
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
|
||||
static Vector<SGWinding> mirrorWindings;
|
||||
mirrorWindings.setSize(surfaceCount);
|
||||
|
||||
for (U32 i = 0; i < surfaceCount; i++) {
|
||||
SGWinding& rSGWinding = mirrorWindings[i];
|
||||
const Interior::Surface& rSurface = interior->mSurfaces[surfaceStart + i];
|
||||
|
||||
U32 fanIndices[32];
|
||||
U32 numFanIndices = 0;
|
||||
interior->collisionFanFromSurface(rSurface, fanIndices, &numFanIndices);
|
||||
|
||||
for (U32 j = 0; j < numFanIndices; j++)
|
||||
rSGWinding.points[j] = interior->mPoints[fanIndices[j]].point;
|
||||
rSGWinding.numPoints = numFanIndices;
|
||||
}
|
||||
|
||||
MatrixF finalModelView;
|
||||
dglGetModelview(&finalModelView);
|
||||
finalModelView.mul(getSOTransform());
|
||||
finalModelView.scale(getSOScale());
|
||||
|
||||
return sgComputeNewFrustum(oldFrustum, nearPlane, farPlane,
|
||||
oldViewport,
|
||||
mirrorWindings.address(), mirrorWindings.size(),
|
||||
finalModelView,
|
||||
newFrustum, newViewport,
|
||||
flippedMatrix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::openPortal(const U32 portalIndex,
|
||||
SceneState* pCurrState,
|
||||
SceneState* pParentState)
|
||||
{
|
||||
AssertFatal(isInitialized() == true, "Error, we should have been initialized by this point!");
|
||||
AssertFatal(portalIndex == 0, "Error, mirrortests only have one portal!");
|
||||
|
||||
RectI viewport;
|
||||
dglGetViewport(&viewport);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
const SceneState::ZoneState& baseState = pCurrState->getBaseZoneState();
|
||||
dglSetViewport(baseState.viewport);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
glColor3f(1, 0, 0);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex3f(-1, -1, 0);
|
||||
glVertex3f(-1, 1, 0);
|
||||
glVertex3f( 1, 1, 0);
|
||||
glVertex3f( 1, -1, 0);
|
||||
glEnd();
|
||||
|
||||
// This is fairly tricky-tricky, so here's what's going on. We need this poly
|
||||
// to be at the far plane, but have it's rasterization coords be exactly that of
|
||||
// the final poly. So we copy the w-coord post projection into the z coord. this
|
||||
// ensures that after the w divide, we have the z coord == 1. This would screw
|
||||
// up texturing, but we don't really care, do we?
|
||||
|
||||
if (mZone == 0)
|
||||
pParentState->setupZoneProjection(getInstance()->getCurrZone(0));
|
||||
else
|
||||
pParentState->setupZoneProjection(mZone + getInstance()->getZoneRangeStart() - 1);
|
||||
|
||||
MatrixF finalProj(true);
|
||||
MatrixF currProj;
|
||||
dglGetProjection(&currProj);
|
||||
((F32*)finalProj)[10] = 0.0f;
|
||||
((F32*)finalProj)[11] = 0.9999f;
|
||||
finalProj.mul(currProj);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
dglLoadMatrix(&finalProj);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glPushMatrix();
|
||||
dglMultMatrix(&getSOTransform());
|
||||
glScalef(getSOScale().x, getSOScale().y, getSOScale().z);
|
||||
|
||||
glColor3f(0, 1, 0);
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ItrPaddedPoint), interior->mPoints.address());
|
||||
|
||||
for (U32 i = 0; i < surfaceCount; i++) {
|
||||
const Interior::Surface& rSurface = interior->mSurfaces[surfaceStart + i];
|
||||
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 j = 0; j < rSurface.windingCount; j++) {
|
||||
const Point3F& rPoint = interior->mPoints[interior->mWindings[rSurface.windingStart + j]].point;
|
||||
glVertex3fv(rPoint);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
dglSetViewport(viewport);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
dglSetCanonicalState();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::closePortal(const U32 portalIndex,
|
||||
SceneState* pCurrState,
|
||||
SceneState* pParentState)
|
||||
{
|
||||
AssertFatal(isInitialized() == true, "Error, we should have been initialized by this point!");
|
||||
AssertFatal(portalIndex == 0, "Error, mirrortests only have one portal!");
|
||||
|
||||
RectI viewport;
|
||||
dglGetViewport(&viewport);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
const SceneState::ZoneState& baseState = pCurrState->getBaseZoneState();
|
||||
dglSetViewport(baseState.viewport);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
glColor3f(0, 0, 1);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex3f(-1, -1, 1);
|
||||
glVertex3f(-1, 1, 1);
|
||||
glVertex3f( 1, 1, 1);
|
||||
glVertex3f( 1, -1, 1);
|
||||
glEnd();
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
if (mZone == 0) {
|
||||
pParentState->setupZoneProjection(getInstance()->getCurrZone(0));
|
||||
} else {
|
||||
pParentState->setupZoneProjection(mZone + getInstance()->getZoneRangeStart() - 1);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
dglLoadMatrix(&pParentState->mModelview);
|
||||
dglMultMatrix(&getSOTransform());
|
||||
glScalef(getSOScale().x, getSOScale().y, getSOScale().z);
|
||||
|
||||
// Need to have texturing turned on because of lame LSB z buffer errors
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, mWhite->getGLName());
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glColor3f(1, 0, 1);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ItrPaddedPoint), interior->mPoints.address());
|
||||
for (U32 i = 0; i < surfaceCount; i++) {
|
||||
glDrawElements(GL_TRIANGLE_STRIP,
|
||||
interior->mSurfaces[surfaceStart+i].windingCount,
|
||||
GL_UNSIGNED_INT,
|
||||
&interior->mWindings[interior->mSurfaces[surfaceStart+i].windingStart]);
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
dglSetViewport(viewport);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
dglSetCanonicalState();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void MirrorSubObject::getWSPortalPlane(const U32 portalIndex, PlaneF* pPlane)
|
||||
{
|
||||
AssertFatal(portalIndex == 0, "Error, mirrortests only have one portal!");
|
||||
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
const Interior::Surface& rSurface = interior->mSurfaces[surfaceStart];
|
||||
|
||||
PlaneF temp = interior->getPlane(rSurface.planeIndex);
|
||||
if (Interior::planeIsFlipped(rSurface.planeIndex))
|
||||
temp.neg();
|
||||
|
||||
mTransformPlane(getSOTransform(), getSOScale(), temp, pPlane);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
U32 MirrorSubObject::getSubObjectKey() const
|
||||
{
|
||||
return InteriorSubObject::MirrorSubObjectKey;
|
||||
}
|
||||
|
||||
|
||||
bool MirrorSubObject::_readISO(Stream& stream)
|
||||
{
|
||||
AssertFatal(isInitialized() == false, "Error, should not be initialized here!");
|
||||
|
||||
if (Parent::_readISO(stream) == false)
|
||||
return false;
|
||||
|
||||
stream.read(&mDetailLevel);
|
||||
stream.read(&mZone);
|
||||
stream.read(&mAlphaLevel);
|
||||
stream.read(&surfaceCount);
|
||||
stream.read(&surfaceStart);
|
||||
|
||||
stream.read(&mCentroid.x);
|
||||
stream.read(&mCentroid.y);
|
||||
stream.read(&mCentroid.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MirrorSubObject::_writeISO(Stream& stream) const
|
||||
{
|
||||
if (Parent::_writeISO(stream) == false)
|
||||
return false;
|
||||
|
||||
stream.write(mDetailLevel);
|
||||
stream.write(mZone);
|
||||
stream.write(mAlphaLevel);
|
||||
stream.write(surfaceCount);
|
||||
stream.write(surfaceStart);
|
||||
|
||||
stream.write(mCentroid.x);
|
||||
stream.write(mCentroid.y);
|
||||
stream.write(mCentroid.z);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SubObjectRenderImage* MirrorSubObject::getRenderImage(SceneState* state,
|
||||
const Point3F& osPoint)
|
||||
{
|
||||
if (isInitialized() == false)
|
||||
setupTransforms();
|
||||
|
||||
|
||||
// Check to make sure that we're on the right side of the plane...
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
const Interior::Surface& rSurface = interior->mSurfaces[surfaceStart];
|
||||
|
||||
PlaneF plane = interior->getPlane(rSurface.planeIndex);
|
||||
if (Interior::planeIsFlipped(rSurface.planeIndex))
|
||||
plane.neg();
|
||||
|
||||
if (plane.whichSide(osPoint) != PlaneF::Front)
|
||||
return NULL;
|
||||
|
||||
// On the right side, guess we have to return an image and a portal...
|
||||
//
|
||||
SubObjectRenderImage* ri = new SubObjectRenderImage;
|
||||
|
||||
ri->obj = this;
|
||||
ri->isTranslucent = false;
|
||||
|
||||
U32 realZone;
|
||||
if (getInstance()->getZoneRangeStart() == 0xFFFFFFFF || mZone == 0) {
|
||||
realZone = getInstance()->getCurrZone(0);
|
||||
} else {
|
||||
realZone = getInstance()->getZoneRangeStart() + mZone - 1;
|
||||
}
|
||||
|
||||
// Create the WS start point. this will be the centroid of the first poly in os space,
|
||||
// transformed out for the sceneGraph, with a smidge of our normal added in to pull
|
||||
// it off the surface plane...
|
||||
|
||||
Point3F startPoint = mCentroid;
|
||||
PlaneF temp = interior->getPlane(rSurface.planeIndex);
|
||||
if (Interior::planeIsFlipped(rSurface.planeIndex))
|
||||
temp.neg();
|
||||
startPoint += Point3F(temp.x, temp.y, temp.z) * 0.01f;
|
||||
getSOTransform().mulP(mCentroid);
|
||||
startPoint.convolve(getSOScale());
|
||||
|
||||
state->insertTransformPortal(this, 0, realZone, startPoint, true);
|
||||
|
||||
return ri;
|
||||
}
|
||||
|
||||
|
||||
bool MirrorSubObject::renderDetailDependant() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
U32 MirrorSubObject::getZone() const
|
||||
{
|
||||
return mZone;
|
||||
}
|
||||
|
||||
|
||||
void MirrorSubObject::setupTransforms()
|
||||
{
|
||||
mInitialized = true;
|
||||
|
||||
// This is really bad, but it's just about the only good place for this...
|
||||
if (getInstance()->isClientObject() && mWhite == NULL)
|
||||
mWhite = new TextureHandle("special/whiteAlpha0", MeshTexture);
|
||||
|
||||
Interior* interior = getInstance()->getDetailLevel(mDetailLevel);
|
||||
const Interior::Surface& rSurface = interior->mSurfaces[surfaceStart];
|
||||
|
||||
PlaneF plane = interior->getPlane(rSurface.planeIndex);
|
||||
if (Interior::planeIsFlipped(rSurface.planeIndex))
|
||||
plane.neg();
|
||||
|
||||
Point3F n(plane.x, plane.y, plane.z);
|
||||
Point3F q = n;
|
||||
q *= -plane.d;
|
||||
|
||||
MatrixF t(true);
|
||||
t.scale(getSOScale());
|
||||
t.mul(getSOTransform());
|
||||
|
||||
t.mulV(n);
|
||||
t.mulP(q);
|
||||
|
||||
F32* ra = mReflectionMatrix;
|
||||
|
||||
ra[0] = 1.0f - 2.0f*(n.x*n.x); ra[1] = 0.0f - 2.0f*(n.x*n.y); ra[2] = 0.0f - 2.0f*(n.x*n.z); ra[3] = 0.0f;
|
||||
ra[4] = 0.0f - 2.0f*(n.y*n.x); ra[5] = 1.0f - 2.0f*(n.y*n.y); ra[6] = 0.0f - 2.0f*(n.y*n.z); ra[7] = 0.0f;
|
||||
ra[8] = 0.0f - 2.0f*(n.z*n.x); ra[9] = 0.0f - 2.0f*(n.z*n.y); ra[10] = 1.0f - 2.0f*(n.z*n.z); ra[11] = 0.0f;
|
||||
|
||||
Point3F qnn = n * mDot(n, q);
|
||||
|
||||
ra[12] = qnn.x * 2.0f;
|
||||
ra[13] = qnn.y * 2.0f;
|
||||
ra[14] = qnn.z * 2.0f;
|
||||
ra[15] = 1.0f;
|
||||
|
||||
// Now, the GGems series (as of v1) uses row vectors (arg)
|
||||
mReflectionMatrix.transpose();
|
||||
}
|
||||
|
||||
void MirrorSubObject::noteTransformChange()
|
||||
{
|
||||
setupTransforms();
|
||||
Parent::noteTransformChange();
|
||||
}
|
||||
|
||||
InteriorSubObject* MirrorSubObject::clone(InteriorInstance* instance) const
|
||||
{
|
||||
MirrorSubObject* pClone = new MirrorSubObject;
|
||||
|
||||
pClone->mDetailLevel = mDetailLevel;
|
||||
pClone->mZone = mZone;
|
||||
pClone->mAlphaLevel = mAlphaLevel;
|
||||
pClone->mCentroid = mCentroid;
|
||||
pClone->surfaceCount = surfaceCount;
|
||||
pClone->surfaceStart = surfaceStart;
|
||||
|
||||
pClone->mInteriorInstance = instance;
|
||||
|
||||
return pClone;
|
||||
}
|
||||
87
interior/mirrorSubObject.h
Normal file
87
interior/mirrorSubObject.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MIRRORSUBOBJECT_H_
|
||||
#define _MIRRORSUBOBJECT_H_
|
||||
|
||||
#ifndef _INTERIORSUBOBJECT_H_
|
||||
#include "interior/interiorSubObject.h"
|
||||
#endif
|
||||
|
||||
class TextureHandle;
|
||||
|
||||
class MirrorSubObject : public InteriorSubObject
|
||||
{
|
||||
typedef InteriorSubObject Parent;
|
||||
|
||||
public:
|
||||
U32 mDetailLevel;
|
||||
U32 mZone;
|
||||
|
||||
F32 mAlphaLevel;
|
||||
Point3F mCentroid;
|
||||
|
||||
U32 surfaceCount;
|
||||
U32 surfaceStart;
|
||||
|
||||
private:
|
||||
bool mInitialized;
|
||||
TextureHandle* mWhite;
|
||||
MatrixF mReflectionMatrix;
|
||||
|
||||
bool isInitialized() const { return mInitialized; }
|
||||
void setupTransforms();
|
||||
|
||||
|
||||
// ISO overrides
|
||||
protected:
|
||||
U32 getSubObjectKey() const;
|
||||
bool _readISO(Stream&);
|
||||
bool _writeISO(Stream&) const;
|
||||
|
||||
// Render control. A sub-object should return false from renderDetailDependant if
|
||||
// it exists only at the level-0 detail level, ie, doors, elevators, etc., true
|
||||
// if should only render at the interiors detail, ie, translucencies.
|
||||
SubObjectRenderImage* getRenderImage(SceneState*, const Point3F&);
|
||||
bool renderDetailDependant() const;
|
||||
U32 getZone() const;
|
||||
void noteTransformChange();
|
||||
|
||||
InteriorSubObject* clone(InteriorInstance*) const;
|
||||
|
||||
// Rendering
|
||||
protected:
|
||||
void renderObject(SceneState*, SceneRenderImage*);
|
||||
void transformModelview(const U32, const MatrixF&, MatrixF*);
|
||||
void transformPosition(const U32, Point3F&);
|
||||
bool computeNewFrustum(const U32 portalIndex,
|
||||
const F64* oldFrustum,
|
||||
const F64 nearPlane,
|
||||
const F64 farPlane,
|
||||
const RectI& oldViewport,
|
||||
F64* newFrustum,
|
||||
RectI& newViewport,
|
||||
const bool flippedMatrix);
|
||||
void openPortal(const U32 portalIndex,
|
||||
SceneState* pCurrState,
|
||||
SceneState* pParentState);
|
||||
void closePortal(const U32 portalIndex,
|
||||
SceneState* pCurrState,
|
||||
SceneState* pParentState);
|
||||
void getWSPortalPlane(const U32 portalIndex, PlaneF*);
|
||||
|
||||
|
||||
public:
|
||||
MirrorSubObject();
|
||||
~MirrorSubObject();
|
||||
|
||||
DECLARE_CONOBJECT(MirrorSubObject);
|
||||
static void initPersistFields();
|
||||
};
|
||||
|
||||
#endif // _H_MIRRORSUBOBJECT
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue