674 lines
18 KiB
C++
Executable File
674 lines
18 KiB
C++
Executable File
/////////////////////////////////////////////////////////////////
|
|
// Parashar Krishnamachari
|
|
// Volume Light class for integration into Torque Game Engine
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
#include "console/consoleTypes.h"
|
|
#include "dgl/dgl.h"
|
|
#include "core/bitStream.h"
|
|
#include "game/gameConnection.h"
|
|
#include "sceneGraph/sceneGraph.h"
|
|
#include "volLight.h"
|
|
|
|
#include "platform/event.h"
|
|
#include "platform/gameInterface.h"
|
|
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1(volumeLight);
|
|
|
|
volumeLight::volumeLight()
|
|
{
|
|
// Setup NetObject.
|
|
mTypeMask |= StaticObjectType | StaticTSObjectType | StaticRenderedObjectType;
|
|
mNetFlags.set(Ghostable | ScopeAlways);
|
|
mAddedToScene = false;
|
|
|
|
mLastRenderTime = 0;
|
|
mLightHandle = NULL;
|
|
mLTextureName = StringTable->insert("");
|
|
|
|
mlpDistance = 8.0f;
|
|
mShootDistance = 15.0f;
|
|
mXextent = 6.0f;
|
|
mYextent = 6.0f;
|
|
|
|
mSubdivideU = 32;
|
|
mSubdivideV = 32;
|
|
|
|
mfootColour = ColorF(1.f, 1.f, 1.f, 0.2f);
|
|
mtailColour = ColorF(0.f, 0.f, 0.f, 0.0f);
|
|
}
|
|
|
|
volumeLight::~volumeLight()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// NetObject functions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
U32 volumeLight::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
|
|
{
|
|
// Pack Parent.
|
|
U32 retMask = Parent::packUpdate(con, mask, stream);
|
|
|
|
// Position.and rotation from Parent
|
|
stream->writeAffineTransform(mObjToWorld);
|
|
|
|
// Light Field Image
|
|
stream->writeString(mLTextureName);
|
|
|
|
// Dimensions
|
|
stream->write(mlpDistance);
|
|
stream->write(mShootDistance);
|
|
stream->write(mXextent);
|
|
stream->write(mYextent);
|
|
|
|
// Subdivisions
|
|
stream->write(mSubdivideU);
|
|
stream->write(mSubdivideV);
|
|
|
|
// Colors
|
|
stream->write(mfootColour);
|
|
stream->write(mtailColour);
|
|
|
|
return retMask;
|
|
}
|
|
|
|
void volumeLight::unpackUpdate(NetConnection * con, BitStream * stream)
|
|
{
|
|
// Unpack Parent.
|
|
Parent::unpackUpdate(con, stream);
|
|
|
|
MatrixF ObjectMatrix;
|
|
|
|
// Position.and rotation
|
|
stream->readAffineTransform(&ObjectMatrix);
|
|
|
|
// Light Field Image
|
|
setLtexture(stream->readSTString());
|
|
|
|
// Dimensions
|
|
stream->read(&mlpDistance);
|
|
stream->read(&mShootDistance);
|
|
stream->read(&mXextent);
|
|
stream->read(&mYextent);
|
|
|
|
// Subdivisions
|
|
stream->read(&mSubdivideU);
|
|
stream->read(&mSubdivideV);
|
|
|
|
// Colors
|
|
stream->read(&mfootColour);
|
|
stream->read(&mtailColour);
|
|
|
|
// Set Transform.
|
|
setTransform(ObjectMatrix);
|
|
|
|
// Very rough, and not complete estimate of the bounding box.
|
|
// A complete one would actually shoot out rays from the hypothetical lightpoint
|
|
// through the vertices to find the extents of the light volume.
|
|
|
|
// But there's no point doing so here. There's no real collision with
|
|
// beams of light.
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Set Value functions (internal to class)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void volumeLight::setLtexture(const char *name)
|
|
{
|
|
mLTextureName = StringTable->insert(name);
|
|
mLightHandle = NULL;
|
|
|
|
if (*mLTextureName)
|
|
{
|
|
mLightHandle = TextureHandle(mLTextureName, BitmapTexture, true);
|
|
}
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setlpDistance(F32 Dist)
|
|
{
|
|
mlpDistance = Dist;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setShootDistance(F32 Dist)
|
|
{
|
|
mShootDistance = Dist;
|
|
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setXextent(F32 extent)
|
|
{
|
|
mXextent = extent;
|
|
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setYextent(F32 extent)
|
|
{
|
|
mYextent = extent;
|
|
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setSubdivideU(U32 val)
|
|
{
|
|
mSubdivideU = val;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setSubdivideV(U32 val)
|
|
{
|
|
mSubdivideV = val;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::setfootColour(ColorF col)
|
|
{
|
|
mfootColour = col;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
void volumeLight::settailColour(ColorF col)
|
|
{
|
|
mtailColour = col;
|
|
// Set Config Change Mask.
|
|
if (isServerObject()) setMaskBits(volLightMask);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Set Value functions (external interfaces for scripts)
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void csetLTexture(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight) return;
|
|
vlight->setLtexture(argv[2]);
|
|
}
|
|
|
|
static void csetlpDistance(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setlpDistance(dAtof(argv[2]));
|
|
}
|
|
|
|
static void csetShootDistance(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setShootDistance(dAtof(argv[2]));
|
|
}
|
|
|
|
static void csetXextent(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setXextent(dAtof(argv[2]));
|
|
}
|
|
|
|
static void csetYextent(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setYextent(dAtof(argv[2]));
|
|
}
|
|
|
|
static void csetSubdivideU(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setSubdivideU(dAtoi(argv[2]));
|
|
}
|
|
|
|
static void csetSubdivideV(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setSubdivideV(dAtoi(argv[2]));
|
|
}
|
|
|
|
static void csetfootColour(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->setfootColour(ColorF(dAtof(argv[2]),dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5])));
|
|
}
|
|
|
|
static void csettailColour(SimObject * obj, S32, const char ** argv)
|
|
{
|
|
volumeLight *vlight = static_cast<volumeLight*>(obj);
|
|
if (!vlight)
|
|
return;
|
|
vlight->settailColour(ColorF(dAtof(argv[2]),dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5])));
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// SimObject functions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool volumeLight::onAdd()
|
|
{
|
|
// Add Parent.
|
|
if(!Parent::onAdd())
|
|
return(false);
|
|
|
|
buildObjectBox();
|
|
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
mAddedToScene = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
void volumeLight::onRemove()
|
|
{
|
|
mAddedToScene = false;
|
|
|
|
// remove the texture handle
|
|
mLightHandle = NULL;
|
|
|
|
// Do Parent.
|
|
Parent::onRemove();
|
|
}
|
|
|
|
void volumeLight::inspectPostApply()
|
|
{
|
|
// Reset the World Box.
|
|
resetWorldBox();
|
|
// Set the Render Transform.
|
|
setRenderTransform(mObjToWorld);
|
|
|
|
// Set Parent.
|
|
Parent::inspectPostApply();
|
|
|
|
setMaskBits(volLightMask);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// SceneObject functions -- The only meaty part
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool volumeLight::prepRenderImage(SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState)
|
|
{
|
|
// Return if last state.
|
|
if (isLastState(state, stateKey))
|
|
return false;
|
|
// Set Last State.
|
|
setLastState(state, stateKey);
|
|
|
|
// no need to render if it isn't enabled
|
|
if((!mEnable) || (!mLightHandle))
|
|
return false;
|
|
|
|
// Is Object Rendered?
|
|
if (state->isObjectRendered(this))
|
|
{
|
|
// Yes, so get a SceneRenderImage.
|
|
SceneRenderImage* image = new SceneRenderImage;
|
|
|
|
// Populate it.
|
|
image->obj = this;
|
|
image->isTranslucent = true;
|
|
image->sortType = SceneRenderImage::Point;
|
|
state->setImageRefPoint(this, image);
|
|
|
|
// Insert it into the scene images.
|
|
state->insertRenderImage(image);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void volumeLight::renderObject(SceneState *state, SceneRenderImage *image)
|
|
{
|
|
Parent::renderObject(state, image);
|
|
|
|
// Check we are in Canonical State.
|
|
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
|
|
|
// Check that we have a texture
|
|
AssertFatal(mLightHandle, "Error : No texture loaded or file failed to open");
|
|
|
|
//////////////////////////// -- Entry assertions
|
|
|
|
// Calculate Elapsed Time and take new Timestamp.
|
|
S32 Time = Platform::getVirtualMilliseconds();
|
|
// F32 ElapsedTime = (Time - mLastRenderTime) * 0.001f;
|
|
mLastRenderTime = Time;
|
|
|
|
RectI viewport;
|
|
MatrixF RXF;
|
|
Point3F position;
|
|
|
|
// Setup out the Projection Matrix/Viewport.
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
dglGetViewport(&viewport);
|
|
state->setupBaseProjection();
|
|
|
|
// Remember -- SetupBaseProjection leaves current matrix mode as MODELVIEW when done.
|
|
// Save ModelView Matrix so we can restore Canonical state at exit.
|
|
glPushMatrix();
|
|
|
|
// Transform by the objects' transform e.g move it.
|
|
RXF = getTransform();
|
|
RXF.getColumn(3, &position);
|
|
dglMultMatrix(&RXF);
|
|
|
|
// Draw the damn thing
|
|
renderGL(state, image);
|
|
|
|
//////////////////////////// -- Exit assertions
|
|
|
|
// Restore rendering state.
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glDisable(GL_BLEND);
|
|
|
|
// Restore our nice, friendly and dull canonical state.
|
|
glPopMatrix();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
dglSetViewport(viewport);
|
|
|
|
// Check we have restored Canonical State.
|
|
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
|
}
|
|
|
|
|
|
void volumeLight::sgRenderY(const Point3F &near1, const Point3F &far1, const Point3F &far2,
|
|
const ColorF &nearcol, const ColorF &farcol, F32 offset)
|
|
{
|
|
glBegin(GL_QUADS);
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(offset, 0.0);
|
|
glVertex3f(near1.x, -near1.y, 0.0f);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(offset, 0.5);
|
|
glVertex3f(near1.x, 0.0f, 0.0f);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(offset, 0.5);
|
|
glVertex3f(far1.x, 0.0, far1.z);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(offset, 0.0);
|
|
glVertex3f(far1.x, far1.y, far1.z);
|
|
glEnd();
|
|
|
|
glBegin(GL_QUADS);
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(offset, 0.5);
|
|
glVertex3f(far1.x, 0.0, far1.z);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(offset, 0.5);
|
|
glVertex3f(near1.x, 0.0f, 0.0f);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(offset, 1.0);
|
|
glVertex3f(near1.x, near1.y, 0.0f);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(offset, 1.0);
|
|
glVertex3f(far2.x, far2.y, far2.z);
|
|
glEnd();
|
|
}
|
|
|
|
void volumeLight::sgRenderX(const Point3F &near1, const Point3F &far1, const Point3F &far2,
|
|
const ColorF &nearcol, const ColorF &farcol, F32 offset)
|
|
{
|
|
glBegin(GL_QUADS);
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(0.0, offset);
|
|
glVertex3f(-near1.x, near1.y, 0.0f);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(0.5, offset);
|
|
glVertex3f(0.0f, near1.y, 0.0f);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(0.5, offset);
|
|
glVertex3f(0.0, far1.y, far1.z);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(0.0, offset);
|
|
glVertex3f(far1.x, far1.y, far1.z);
|
|
glEnd();
|
|
|
|
glBegin(GL_QUADS);
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(0.5, offset);
|
|
glVertex3f(0.0, far1.y, far1.z);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(0.5, offset);
|
|
glVertex3f(0.0f, near1.y, 0.0f);
|
|
|
|
glColor4f(nearcol.red, nearcol.green, nearcol.blue, nearcol.alpha);
|
|
glTexCoord2f(1.0, offset);
|
|
glVertex3f(near1.x, near1.y, 0.0f);
|
|
|
|
glColor4f(farcol.red, farcol.green, farcol.blue, farcol.alpha);
|
|
glTexCoord2f(1.0, offset);
|
|
glVertex3f(far2.x, far2.y, far2.z);
|
|
glEnd();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// GL Render function...
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void volumeLight::renderGL(SceneState *state, SceneRenderImage *image)
|
|
{
|
|
glEnable(GL_TEXTURE_2D);
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
glEnable(GL_BLEND);
|
|
glDepthMask(GL_FALSE);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mLightHandle.getGLName());
|
|
|
|
Point3F lightpoint;
|
|
|
|
// This is where the hypothetical point source of the spot will be
|
|
// The volume slices are projected along the lines from
|
|
lightpoint.x = lightpoint.y = 0.0f;
|
|
lightpoint.z = -mlpDistance;
|
|
|
|
F32 ax = mXextent / 2;
|
|
F32 ay = mYextent / 2;
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthMask(GL_TRUE);
|
|
|
|
// Draw the bottom foot... this is basically the glowing region.
|
|
glBegin(GL_QUADS);
|
|
glColor4f(mfootColour.red, mfootColour.green, mfootColour.blue, 1.0f);
|
|
glTexCoord2f(0.0f, 0.0f);
|
|
glVertex3f(-ax, -ay, 0.0f);
|
|
|
|
glColor4f(mfootColour.red, mfootColour.green, mfootColour.blue, 1.0f);
|
|
glTexCoord2f(1.0f, 0.0f);
|
|
glVertex3f(ax, -ay, 0.0f);
|
|
|
|
glColor4f(mfootColour.red, mfootColour.green, mfootColour.blue, 1.0f);
|
|
glTexCoord2f(1.0f, 1.0f);
|
|
glVertex3f(ax, ay, 0.0f);
|
|
|
|
glColor4f(mfootColour.red, mfootColour.green, mfootColour.blue, 1.0f);
|
|
glTexCoord2f(0.0f, 1.0f);
|
|
glVertex3f(-ax, ay, 0.0f);
|
|
glEnd();
|
|
|
|
S32 i;
|
|
|
|
glDepthMask(GL_FALSE);
|
|
|
|
// Slices in X/U space
|
|
for(i = mSubdivideU; i >= 0; i--)
|
|
{
|
|
F32 k = ((F32)i) / mSubdivideU; // use for the texture coord
|
|
F32 bx = i * mXextent / mSubdivideU - ax; // use for point positions
|
|
|
|
// These are the two endpoints for a slice at the foot
|
|
Point3F end1(bx, -ay, 0.0f);
|
|
Point3F end2(bx, ay, 0.0f);
|
|
|
|
end1 -= lightpoint; // get a vector from point to lightsource
|
|
end1.normalize(); // normalize vector
|
|
end1 *= mShootDistance; // multiply it out by shootlength
|
|
|
|
end1.x += bx; // Add the original point location to the vector
|
|
end1.y -= ay;
|
|
|
|
// Do it again for the other point.
|
|
end2 -= lightpoint;
|
|
end2.normalize();
|
|
end2 *= mShootDistance;
|
|
|
|
end2.x += bx;
|
|
end2.y += ay;
|
|
|
|
sgRenderY(Point3F(bx, ay, 0.0f), end1, end2, mfootColour, mtailColour, k);
|
|
}
|
|
|
|
// Slices in Y/V space
|
|
for(i = 0; i <= mSubdivideV; i++)
|
|
{
|
|
F32 k = ((F32)i) / mSubdivideV; // use for the texture coord
|
|
F32 by = i * mXextent / mSubdivideV - ay; // use for point positions
|
|
|
|
// These are the two endpoints for a slice at the foot
|
|
Point3F end1(-ax, by, 0.0f);
|
|
Point3F end2(ax, by, 0.0f);
|
|
|
|
end1 -= lightpoint; // get a vector from point to lightsource
|
|
end1.normalize(); // normalize vector
|
|
end1 *= mShootDistance; // extend it out by shootlength
|
|
|
|
end1.x -= ax; // Add the original point location to the vector
|
|
end1.y += by;
|
|
|
|
|
|
// Do it again for the other point.
|
|
end2 -= lightpoint;
|
|
end2.normalize();
|
|
end2 *= mShootDistance;
|
|
|
|
end2.x += ax;
|
|
end2.y += by;
|
|
|
|
sgRenderX(Point3F(ax, by, 0.0f), end1, end2, mfootColour, mtailColour, k);
|
|
}
|
|
|
|
glDepthMask(GL_TRUE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// ConObject functions
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void volumeLight::initPersistFields()
|
|
{
|
|
// Initialise parents' persistent fields.
|
|
Parent::initPersistFields();
|
|
|
|
// Our own persistent fields
|
|
|
|
// Light Field Image
|
|
addField( "Texture", TypeFilename, Offset( mLTextureName, volumeLight ) );
|
|
|
|
// Dimensions
|
|
addField( "lpDistance", TypeF32, Offset( mlpDistance, volumeLight ) );
|
|
addField( "ShootDistance", TypeF32, Offset( mShootDistance, volumeLight ) );
|
|
addField( "Xextent", TypeF32, Offset( mXextent, volumeLight ) );
|
|
addField( "Yextent", TypeF32, Offset( mYextent, volumeLight ) );
|
|
|
|
// Subdivisions
|
|
addField( "SubdivideU", TypeS32, Offset( mSubdivideU, volumeLight ) );
|
|
addField( "SubdivideV", TypeS32, Offset( mSubdivideV, volumeLight ) );
|
|
|
|
// Colors
|
|
addField( "FootColour", TypeColorF, Offset( mfootColour, volumeLight ) );
|
|
addField( "TailColour", TypeColorF, Offset( mtailColour, volumeLight ) );
|
|
}
|
|
|
|
void volumeLight::consoleInit()
|
|
{
|
|
// Light Field Image
|
|
Con::addCommand("volumeLight", "setLTexture", csetLTexture, "vlight.setTexture(bitmap)", 3, 3);
|
|
|
|
// Dimensions
|
|
Con::addCommand("volumeLight", "setlpDistance", csetlpDistance, "vlight.setlpDistance(value)", 3, 3);
|
|
Con::addCommand("volumeLight", "setShootDistance", csetShootDistance, "vlight.setShootDistance(value)", 3, 3);
|
|
Con::addCommand("volumeLight", "setXextent", csetXextent, "vlight.setXextent(value)", 3, 3);
|
|
Con::addCommand("volumeLight", "setYextent", csetYextent, "vlight.setYextent(value)", 3, 3);
|
|
|
|
// Subdivisions
|
|
Con::addCommand("volumeLight", "setSubdivideU", csetSubdivideU, "vlight.setSubdivideU(value)", 3, 3);
|
|
Con::addCommand("volumeLight", "setSubdivideV", csetSubdivideV, "vlight.setSubdivideV(value)", 3, 3);
|
|
|
|
// Colors
|
|
Con::addCommand("volumeLight", "setfootColour", csetfootColour, "vlight.setfootColour(r, g, b, a)", 6, 6);
|
|
Con::addCommand("volumeLight", "settailColour", csetfootColour, "vlight.settailColour(r, g, b, a)", 6, 6);
|
|
}
|