309 lines
7.8 KiB
C++
Executable File
309 lines
7.8 KiB
C++
Executable File
//-----------------------------------------------
|
|
// Synapse Gaming - Lighting System
|
|
// Copyright © Synapse Gaming 2003
|
|
// Written by John Kabus
|
|
//-----------------------------------------------
|
|
#include "lightingSystem/sgLighting.h"
|
|
#include "lightingSystem/sgDecalProjector.h"
|
|
#include "sim/decalManager.h"
|
|
#include "sim/netConnection.h"
|
|
#include "sceneGraph/sceneState.h"
|
|
|
|
extern bool gEditingMission;
|
|
|
|
|
|
class sgDecalProjector : public GameBase
|
|
{
|
|
typedef GameBase Parent;
|
|
DecalData *mDataBlock;
|
|
bool onNewDataBlock(GameBaseData* dptr);
|
|
protected:
|
|
bool sgInitNeeded;
|
|
bool sgProjection;
|
|
Point3F sgProjectionPoint;
|
|
Point3F sgProjectionNormal;
|
|
bool onAdd();
|
|
void onRemove();
|
|
void sgResetProjection();
|
|
void sgProject();
|
|
public:
|
|
sgDecalProjector();
|
|
void inspectPostApply();
|
|
void setTransform(const MatrixF &mat);
|
|
bool prepRenderImage(SceneState* state, const U32 stateKey,
|
|
const U32 startZone, const bool modifyBaseZoneState);
|
|
void renderObject(SceneState *state, SceneRenderImage *image);
|
|
U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
|
|
void unpackUpdate(NetConnection *con, BitStream *stream);
|
|
DECLARE_CONOBJECT(sgDecalProjector);
|
|
};
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1(sgDecalProjector);
|
|
|
|
sgDecalProjector::sgDecalProjector()
|
|
{
|
|
mTypeMask |= StaticObjectType | StaticTSObjectType | StaticRenderedObjectType;
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
mDataBlock = NULL;
|
|
sgProjection = false;
|
|
sgProjectionPoint = Point3F(0.0f, 0.0f, 0.0f);
|
|
sgProjectionNormal = Point3F(0.0f, 0.0f, 0.0f);
|
|
|
|
// for after load relinking...
|
|
sgInitNeeded = true;
|
|
}
|
|
|
|
bool sgDecalProjector::onAdd()
|
|
{
|
|
if(!Parent::onAdd())
|
|
return false;
|
|
|
|
mObjBox.min.set( -0.5, -0.5, -0.5 );
|
|
mObjBox.max.set( 0.5, 0.5, 0.5 );
|
|
resetWorldBox();
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
addToScene();
|
|
return true;
|
|
}
|
|
|
|
void sgDecalProjector::onRemove()
|
|
{
|
|
if(isClientObject())
|
|
gDecalManager->ageDecal(getId());
|
|
|
|
removeFromScene();
|
|
Parent::onRemove();
|
|
}
|
|
|
|
bool sgDecalProjector::onNewDataBlock(GameBaseData* dptr)
|
|
{
|
|
mDataBlock = dynamic_cast<DecalData *>(dptr);
|
|
return Parent::onNewDataBlock(dptr);
|
|
}
|
|
|
|
bool sgDecalProjector::prepRenderImage(SceneState* state, const U32 stateKey,
|
|
const U32 startZone, const bool modifyBaseZoneState)
|
|
{
|
|
if(!gEditingMission)
|
|
return false;
|
|
if(isLastState(state, stateKey))
|
|
return false;
|
|
|
|
setLastState(state, stateKey);
|
|
|
|
if(state->isObjectRendered(this))
|
|
{
|
|
SceneRenderImage* image = new SceneRenderImage;
|
|
image->obj = this;
|
|
image->isTranslucent = true;
|
|
image->sortType = SceneRenderImage::EndSort;
|
|
state->insertRenderImage(image);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void sgDecalProjector::renderObject(SceneState *state, SceneRenderImage *image)
|
|
{
|
|
if(gEditingMission)
|
|
{
|
|
// render the directional line...
|
|
glBlendFunc(GL_ONE,GL_ZERO);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
Point3F vector = SG_STATIC_SPOT_VECTOR_NORMALIZED * 10.0f;
|
|
Point3F origin = Point3F(0, 0, 0);
|
|
Point3F point = vector;
|
|
mObjToWorld.mulP(origin);
|
|
mObjToWorld.mulP(point);
|
|
glColor3f(0, 1, 0);
|
|
glBegin(GL_LINES);
|
|
glVertex3fv(origin);
|
|
glVertex3fv(point);
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
void sgDecalProjector::sgResetProjection()
|
|
{
|
|
sgProjection = false;
|
|
sgProjectionPoint = Point3F(0.0f, 0.0f, 0.0f);
|
|
sgProjectionNormal = Point3F(0.0f, 0.0f, 0.0f);
|
|
|
|
if(isClientObject())
|
|
return;
|
|
|
|
Point3F pos = getPosition();
|
|
Point3F normal = SG_STATIC_SPOT_VECTOR_NORMALIZED * 100.0f;
|
|
getTransform().mulV(normal);
|
|
|
|
RayInfo info;
|
|
if(!gServerContainer.castRay(pos, (pos + normal),
|
|
InteriorObjectType | TerrainObjectType, &info))
|
|
{
|
|
Con::errorf("Error in _sgDropDecal: no drop object found.");
|
|
return;
|
|
}
|
|
|
|
sgProjection = true;
|
|
sgProjectionPoint = info.point;
|
|
sgProjectionNormal = info.normal;
|
|
|
|
setMaskBits(0xffffffff);
|
|
}
|
|
|
|
void sgDecalProjector::sgProject()
|
|
{
|
|
if((isServerObject()) || (!mDataBlock))
|
|
return;
|
|
|
|
// use the instead of getId()...
|
|
// id's are flaky in zones...
|
|
U32 ownerid = U32(this);
|
|
|
|
gDecalManager->ageDecal(ownerid);
|
|
|
|
if(!sgProjection)
|
|
return;
|
|
|
|
Point3F tandir;
|
|
getTransform().getColumn(0, &tandir);
|
|
|
|
gDecalManager->addDecal(sgProjectionPoint, tandir, sgProjectionNormal, getScale(), mDataBlock, ownerid);
|
|
}
|
|
|
|
void sgDecalProjector::setTransform(const MatrixF & mat)
|
|
{
|
|
Parent::setTransform(mat);
|
|
sgResetProjection();
|
|
setMaskBits(0xffffffff);
|
|
}
|
|
|
|
U32 sgDecalProjector::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|
{
|
|
U32 res = Parent::packUpdate(con, mask, stream);
|
|
|
|
if(sgInitNeeded && isServerObject())
|
|
{
|
|
sgInitNeeded = false;
|
|
sgResetProjection();
|
|
}
|
|
|
|
stream->writeAffineTransform(mObjToWorld);
|
|
|
|
if(stream->writeFlag(sgProjection))
|
|
{
|
|
// this is a joke right (no Point3F support)?!?
|
|
stream->write(sgProjectionPoint.x);
|
|
stream->write(sgProjectionPoint.y);
|
|
stream->write(sgProjectionPoint.z);
|
|
stream->write(sgProjectionNormal.x);
|
|
stream->write(sgProjectionNormal.y);
|
|
stream->write(sgProjectionNormal.z);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void sgDecalProjector::unpackUpdate(NetConnection *con, BitStream *stream)
|
|
{
|
|
Parent::unpackUpdate(con, stream);
|
|
|
|
MatrixF ObjectMatrix;
|
|
stream->readAffineTransform(&ObjectMatrix);
|
|
setTransform(ObjectMatrix);
|
|
|
|
sgProjection = stream->readFlag();
|
|
if(sgProjection)
|
|
{
|
|
// this is a joke right (no Point3F support)?!?
|
|
stream->read(&sgProjectionPoint.x);
|
|
stream->read(&sgProjectionPoint.y);
|
|
stream->read(&sgProjectionPoint.z);
|
|
stream->read(&sgProjectionNormal.x);
|
|
stream->read(&sgProjectionNormal.y);
|
|
stream->read(&sgProjectionNormal.z);
|
|
}
|
|
|
|
sgProject();
|
|
}
|
|
|
|
void sgDecalProjector::inspectPostApply()
|
|
{
|
|
Parent::inspectPostApply();
|
|
sgResetProjection();
|
|
setMaskBits(0xffffffff);
|
|
}
|
|
|
|
//-----------------------------------------------
|
|
|
|
ConsoleFunction(_sgCreateDecal, void, 6, 6, "(Point3F pos, Point3F tandir, Point3F norm, "
|
|
"Point3F scale, decalDataBlock) - this method must be called on the client side!")
|
|
{
|
|
// is this the client side?
|
|
// doesn't work...
|
|
//if(gDecalManager->isServerObject())
|
|
// return;
|
|
|
|
Point3F pos = Point3F(0, 0, 0);
|
|
Point3F tandir = Point3F(1, 0, 0);
|
|
Point3F normal = Point3F(0, 0, 1);
|
|
Point3F scale = Point3F(1, 1, 1);
|
|
DecalData *decaldata = NULL;
|
|
|
|
dSscanf(argv[1],"%f %f %f",&pos.x,&pos.y,&pos.z);
|
|
dSscanf(argv[2],"%f %f %f",&tandir.x,&tandir.y,&tandir.z);
|
|
dSscanf(argv[3],"%f %f %f",&normal.x,&normal.y,&normal.z);
|
|
dSscanf(argv[4],"%f %f %f",&scale.x,&scale.y,&scale.z);
|
|
|
|
decaldata = dynamic_cast<DecalData *>(Sim::findObject(argv[5]));
|
|
|
|
if(!decaldata)
|
|
return;
|
|
|
|
gDecalManager->addDecal(pos, tandir, normal, scale, decaldata);
|
|
}
|
|
|
|
ConsoleFunction(_sgDropDecal, void, 6, 6, "(Point3F pos, Point3F tandir, Point3F norm, "
|
|
"Point3F scale, decalDataBlock) - this method must be called on the client side! "
|
|
"This method drops a decal onto the interior or "
|
|
"terrain directly below the given position.")
|
|
{
|
|
// is this the client side?
|
|
// doesn't work...
|
|
//if(!gDecalManager->isGhost())
|
|
// return;
|
|
|
|
Point3F pos = Point3F(0, 0, 0);
|
|
Point3F tandir = Point3F(1, 0, 0);
|
|
Point3F normal = Point3F(0, 0, 1);
|
|
Point3F scale = Point3F(1, 1, 1);
|
|
DecalData *decaldata = NULL;
|
|
|
|
dSscanf(argv[1],"%f %f %f",&pos.x,&pos.y,&pos.z);
|
|
dSscanf(argv[2],"%f %f %f",&tandir.x,&tandir.y,&tandir.z);
|
|
dSscanf(argv[3],"%f %f %f",&normal.x,&normal.y,&normal.z);
|
|
dSscanf(argv[4],"%f %f %f",&scale.x,&scale.y,&scale.z);
|
|
|
|
decaldata = dynamic_cast<DecalData *>(Sim::findObject(argv[5]));
|
|
|
|
if(!decaldata)
|
|
return;
|
|
|
|
RayInfo info;
|
|
if(!gClientContainer.castRay(pos, (pos + Point3F(0, 0, -100)),
|
|
InteriorObjectType | TerrainObjectType, &info))
|
|
{
|
|
Con::errorf("Error in _sgDropDecal: no drop object found.");
|
|
return;
|
|
}
|
|
|
|
pos = info.point;
|
|
normal = info.normal;
|
|
|
|
gDecalManager->addDecal(pos, tandir, normal, scale, decaldata);
|
|
}
|
|
|