JS Interface to entities. It even partially works now.

This was SVN commit r469.
This commit is contained in:
MarkT 2004-06-10 22:24:03 +00:00
parent 663f25f6b6
commit e4fe4ed602
58 changed files with 3454 additions and 3046 deletions

View file

@ -1,5 +1,4 @@
#include "precompiled.h" #include "precompiled.h"
#include "ogl.h" #include "ogl.h"
#include "res/tex.h" #include "res/tex.h"
#include "TextureEntry.h" #include "TextureEntry.h"

View file

@ -28,6 +28,7 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
// block := power-of-two sized chunk of a file. // block := power-of-two sized chunk of a file.

View file

@ -42,10 +42,14 @@
#include "PathfindEngine.h" #include "PathfindEngine.h"
#include "XML.h" #include "XML.h"
#include "ConfigDB.h" #include "scripting/JSInterface_Entity.h"
#include "scripting/JSInterface_BaseEntity.h"
#include "scripting/JSInterface_Vector3D.h"
#include "ConfigDB.h"
#include "CLogger.h" #include "CLogger.h"
#ifndef NO_GUI #ifndef NO_GUI
#include "gui/GUI.h" #include "gui/GUI.h"
#endif #endif
@ -431,7 +435,7 @@ void ParseArgs(int argc, char* argv[])
} }
break; break;
case 'e': case 'e':
g_EntGraph = true; g_EntGraph = true; break;
case 'v': case 'v':
g_VSync = true; g_VSync = true;
break; break;
@ -622,7 +626,7 @@ PREVTSC=TSC;
font = font_load("fonts/verdana.fnt"); font = font_load("fonts/verdana.fnt");
g_Console = new CConsole(0, g_yres-600.f, 800.f, 600.f); g_Console = new CConsole(0, g_yres-600.f, g_xres, 600.f);
// create renderer // create renderer
new CRenderer; new CRenderer;
@ -653,6 +657,10 @@ PREVTSC=TSC;
g_EntityTemplateCollection.loadTemplates(); g_EntityTemplateCollection.loadTemplates();
// Register the JavaScript interfaces with the runtime
JSI_Entity::init();
JSI_BaseEntity::init();
JSI_Vector3D::init();
// if no map name specified, load test01.pmp (for convenience during // if no map name specified, load test01.pmp (for convenience during
// development. that means loading no map at all is currently impossible. // development. that means loading no map at all is currently impossible.

View file

@ -22,7 +22,7 @@ class CVector3D
float X, Y, Z; float X, Y, Z;
public: public:
CVector3D () { } CVector3D () { X = 0.0f; Y = 0.0f; Z = 0.0f; }
CVector3D (float x, float y, float z); CVector3D (float x, float y, float z);
int operator ! () const ; int operator ! () const ;

View file

@ -0,0 +1,138 @@
#include "precompiled.h"
#include "JSInterface_Vector3D.h"
JSClass JSI_Vector3D::JSI_class = {
"Vector3D", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
JSI_Vector3D::getProperty, JSI_Vector3D::setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, JSI_Vector3D::finalize,
NULL, NULL, NULL, NULL
};
JSPropertySpec JSI_Vector3D::JSI_props[] =
{
{ "x", JSI_Vector3D::component_x, JSPROP_ENUMERATE },
{ "y", JSI_Vector3D::component_y, JSPROP_ENUMERATE },
{ "z", JSI_Vector3D::component_z, JSPROP_ENUMERATE },
{ 0 }
};
JSFunctionSpec JSI_Vector3D::JSI_methods[] =
{
{ "toString", JSI_Vector3D::toString, 0, 0, 0 },
{ 0 }
};
void JSI_Vector3D::init()
{
g_ScriptingHost.DefineCustomObjectType( &JSI_class, JSI_Vector3D::construct, 0, JSI_props, JSI_methods, NULL, NULL );
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info()
{
owner = NULL;
vector = new CVector3D();
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info( float x, float y, float z )
{
owner = NULL;
vector = new CVector3D( x, y, z );
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner )
{
owner = _owner;
updateFn = NULL;
vector = copy;
}
JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner, void( IPropertyOwner::*_updateFn )(void) )
{
owner = _owner;
updateFn = _updateFn;
vector = copy;
}
JSI_Vector3D::Vector3D_Info::~Vector3D_Info()
{
if( !owner ) delete( vector );
}
JSBool JSI_Vector3D::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
if( !JSVAL_IS_INT( id ) )
return( JS_TRUE );
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
if( !vectorInfo ) return( JS_TRUE );
CVector3D* vectorData = vectorInfo->vector;
switch( g_ScriptingHost.ValueToInt( id ) )
{
case component_x: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->X ) ); return( JS_TRUE );
case component_y: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Y ) ); return( JS_TRUE );
case component_z: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Z ) ); return( JS_TRUE );
}
return( JS_FALSE );
}
JSBool JSI_Vector3D::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
if( !JSVAL_IS_INT( id ) )
return( JS_TRUE );
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
if( !vectorInfo ) return( JS_TRUE );
CVector3D* vectorData = vectorInfo->vector;
switch( g_ScriptingHost.ValueToInt( id ) )
{
case component_x: vectorData->X = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
case component_y: vectorData->Y = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
case component_z: vectorData->Z = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
}
if( vectorInfo->owner && vectorInfo->updateFn ) ( (vectorInfo->owner)->*(vectorInfo->updateFn) )();
return( JS_TRUE );
return( JS_FALSE );
}
JSBool JSI_Vector3D::construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
{
if( ( argc != 0 ) && ( argc != 3 ) ) return( JS_FALSE );
if( argc == 0 )
{
JS_SetPrivate( cx, obj, new Vector3D_Info() );
return( JS_TRUE );
}
else if( argc == 3 )
{
float x = (float)g_ScriptingHost.ValueToDouble( argv[0] );
float y = (float)g_ScriptingHost.ValueToDouble( argv[1] );
float z = (float)g_ScriptingHost.ValueToDouble( argv[2] );
JS_SetPrivate( cx, obj, new Vector3D_Info( x, y, z ) );
}
return( JS_TRUE );
}
void JSI_Vector3D::finalize( JSContext* cx, JSObject* obj )
{
delete( JS_GetPrivate( cx, obj ) );
}
JSBool JSI_Vector3D::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
{
char buffer[256];
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
if( !vectorInfo ) return( JS_TRUE );
CVector3D* vectorData = vectorInfo->vector;
snprintf( buffer, 256, "[object Vector3D: ( %f, %f, %f )]", vectorData->X, vectorData->Y, vectorData->Z );
buffer[255] = 0;
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
return( JS_TRUE );
}

View file

@ -0,0 +1,49 @@
// JSInterface_Entity.h
//
// Last modified: 03 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
//
// A JavaScript class representing a Prometheus CVector3D object.
//
// Usage: Used when manipulating objects of class 'Vector3D' in JavaScript.
//
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
#include "scripting/ScriptingHost.h"
#include "Vector3D.h"
#ifndef JSI_VECTOR3_INCLUDED
#define JSI_VECTOR3_INCLUDED
class IPropertyOwner;
namespace JSI_Vector3D
{
enum
{
component_x,
component_y,
component_z
};
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
struct Vector3D_Info
{
IPropertyOwner* owner;
void ( IPropertyOwner::*updateFn )();
CVector3D* vector;
Vector3D_Info();
Vector3D_Info( float x, float y, float z );
Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner );
Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner, void (IPropertyOwner::*_updateFn)() );
~Vector3D_Info();
};
extern JSClass JSI_class;
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
void finalize( JSContext* cx, JSObject* obj );
JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
void init();
};
#endif

View file

@ -5,6 +5,8 @@
#include "Prometheus.h" #include "Prometheus.h"
#include "sysdep/sysdep.h" #include "sysdep/sysdep.h"
#include "scripting/ScriptingHost.h"
CConsole::CConsole(float X, float Y, float W, float H) CConsole::CConsole(float X, float Y, float W, float H)
: m_fX(X), m_fY(Y), m_fWidth(W), m_fHeight(H) : m_fX(X), m_fY(Y), m_fWidth(W), m_fHeight(H)
{ {
@ -242,7 +244,7 @@ void CConsole::DrawCursor(void)
//Inserts a character into the buffer. //Inserts a character into the buffer.
void CConsole::InsertChar(const int szChar) void CConsole::InsertChar(const int szChar, const int cooked )
{ {
static int iHistoryPos = -1; static int iHistoryPos = -1;
@ -321,15 +323,16 @@ void CConsole::InsertChar(const int szChar)
default: //Insert a character default: //Insert a character
if (IsFull()) return; if (IsFull()) return;
if (!isprint(szChar)) return; if( cooked >= 255 ) return;
if (!isprint( cooked )) return;
if (IsEOB()) //are we at the end of the buffer? if (IsEOB()) //are we at the end of the buffer?
m_szBuffer[m_iBufferPos] = szChar; //cat char onto end m_szBuffer[m_iBufferPos] = cooked; //cat char onto end
else{ //we need to insert else{ //we need to insert
int i; int i;
for(i=m_iBufferLength; i>m_iBufferPos; i--) for(i=m_iBufferLength; i>m_iBufferPos; i--)
m_szBuffer[i] = m_szBuffer[i-1]; // move chars to right m_szBuffer[i] = m_szBuffer[i-1]; // move chars to right
m_szBuffer[i] = szChar; m_szBuffer[i] = cooked;
} }
m_iBufferPos++; m_iBufferPos++;
@ -410,6 +413,18 @@ void CConsole::ProcessBuffer(const char* szLine){
} }
} }
} }
else if( szLine[0] == ':' )
{
// Process it as JavaScript
g_ScriptingHost.ExecuteScript( szLine + 1 );
}
else if( szLine[0] == '?' )
{
// Process it as JavaScript and display the result
jsval rval = g_ScriptingHost.ExecuteScript( szLine + 1 );
if( rval )
InsertMessage( g_ScriptingHost.ValueToString( rval ).c_str() );
}
else InsertMessage("<say>: %s", szLine); else InsertMessage("<say>: %s", szLine);
delete[] szCommand; delete[] szCommand;
@ -425,6 +440,6 @@ bool conInputHandler(const SDL_Event& ev)
if(ev.type != SDL_KEYDOWN) if(ev.type != SDL_KEYDOWN)
return false; return false;
g_Console->InsertChar(ev.key.keysym.sym); g_Console->InsertChar(ev.key.keysym.sym, ev.key.keysym.unicode );
return g_Console->IsActive(); return g_Console->IsActive();
} }

View file

@ -12,7 +12,7 @@
#ifndef CCONSOLE_H #ifndef CCONSOLE_H
#define CCONSOLE_H #define CCONSOLE_H
#define BUFFER_SIZE 50 #define BUFFER_SIZE 100
#define FONT_HEIGHT 18 #define FONT_HEIGHT 18
typedef void(*fptr)(void); typedef void(*fptr)(void);
@ -70,7 +70,7 @@ public:
void Render(); void Render();
void InsertMessage(const char* szMessage, ...); void InsertMessage(const char* szMessage, ...);
void InsertChar(const int szChar); void InsertChar(const int szChar, const int cooked);
void SetBuffer(const char* szMessage, ...); void SetBuffer(const char* szMessage, ...);
void FlushBuffer(); void FlushBuffer();
@ -80,4 +80,7 @@ public:
bool IsActive() { return m_bVisible; } bool IsActive() { return m_bVisible; }
}; };
// TODO MT: Better solution to character translation than 'const int cooked'? Anyone?
#endif #endif

View file

@ -193,7 +193,7 @@ public:
virtual u8 *Serialize(u8 *buffer) const; virtual u8 *Serialize(u8 *buffer) const;
virtual const u8 *Deserialize(const u8 *buffer, const u8 *bufferend); virtual const u8 *Deserialize(const u8 *buffer, const u8 *bufferend);
private: protected:
tstring m_String; tstring m_String;
TCHAR m_ConversionBuffer[CONVERSION_BUFFER_SIZE]; TCHAR m_ConversionBuffer[CONVERSION_BUFFER_SIZE];
}; };

View file

@ -8,12 +8,12 @@
#include "ModelRData.h" #include "ModelRData.h"
#include "Model.h" #include "Model.h"
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// shared list of all submitted models this frame // shared list of all submitted models this frame
std::vector<CModel*> CModelRData::m_Models; std::vector<CModel*> CModelRData::m_Models;
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// CModelRData constructor // CModelRData constructor
CModelRData::CModelRData(CModel* model) CModelRData::CModelRData(CModel* model)
: m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0), m_Flags(0) : m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0), m_Flags(0)
{ {
@ -22,16 +22,16 @@ CModelRData::CModelRData(CModel* model)
Build(); Build();
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// CModelRData destructor // CModelRData destructor
CModelRData::~CModelRData() CModelRData::~CModelRData()
{ {
// clean up system copies of data // clean up system copies of data
delete[] m_Indices; delete[] m_Indices;
delete[] m_Vertices; delete[] m_Vertices;
delete[] m_Normals; delete[] m_Normals;
if (m_VB) { if (m_VB) {
// release vertex buffer chunks // release vertex buffer chunks
g_VBMan.Release(m_VB); g_VBMan.Release(m_VB);
} }
} }
@ -51,19 +51,19 @@ void CModelRData::Build()
void CModelRData::BuildIndices() void CModelRData::BuildIndices()
{ {
CModelDef* mdef=m_Model->GetModelDef(); CModelDef* mdef=m_Model->GetModelDef();
assert(mdef); assert(mdef);
// must have a valid vertex buffer by this point so we know where indices are supposed to start // must have a valid vertex buffer by this point so we know where indices are supposed to start
assert(m_VB); assert(m_VB);
// allocate indices if we haven't got any already // allocate indices if we haven't got any already
if (!m_Indices) { if (!m_Indices) {
m_Indices=new u16[mdef->GetNumFaces()*3]; m_Indices=new u16[mdef->GetNumFaces()*3];
} }
// build indices // build indices
u32 base=m_VB->m_Index; u32 base=m_VB->m_Index;
u32 indices=0; u32 indices=0;
SModelFace* faces=mdef->GetFaces(); SModelFace* faces=mdef->GetFaces();
for (int j=0; j<mdef->GetNumFaces(); j++) { for (int j=0; j<mdef->GetNumFaces(); j++) {
@ -91,40 +91,40 @@ static SColor4ub ConvertColor(const RGBColor& src)
return result; return result;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SkinPoint: skin the vertex position using it's blend data and given bone matrices // SkinPoint: skin the vertex position using it's blend data and given bone matrices
static void SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices,CVector3D& result) static void SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices,CVector3D& result)
{ {
CVector3D tmp; CVector3D tmp;
const SVertexBlend& blend=vertex.m_Blend; const SVertexBlend& blend=vertex.m_Blend;
// must have at least one valid bone if we're using SkinPoint // must have at least one valid bone if we're using SkinPoint
assert(blend.m_Bone[0]!=0xff); assert(blend.m_Bone[0]!=0xff);
const CMatrix3D& m=matrices[blend.m_Bone[0]]; const CMatrix3D& m=matrices[blend.m_Bone[0]];
m.Transform(vertex.m_Coords,result); m.Transform(vertex.m_Coords,result);
result*=blend.m_Weight[0]; result*=blend.m_Weight[0];
for (u32 i=1;blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) { for (u32 i=1;blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
const CMatrix3D& m=matrices[blend.m_Bone[i]]; const CMatrix3D& m=matrices[blend.m_Bone[i]];
m.Transform(vertex.m_Coords,tmp); m.Transform(vertex.m_Coords,tmp);
result+=tmp*blend.m_Weight[i]; result+=tmp*blend.m_Weight[i];
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SkinPoint: skin the vertex normal using it's blend data and given bone matrices // SkinPoint: skin the vertex normal using it's blend data and given bone matrices
static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,CVector3D& result) static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,CVector3D& result)
{ {
CVector3D tmp; CVector3D tmp;
const SVertexBlend& blend=vertex.m_Blend; const SVertexBlend& blend=vertex.m_Blend;
// must have at least one valid bone if we're using SkinNormal // must have at least one valid bone if we're using SkinNormal
assert(blend.m_Bone[0]!=0xff); assert(blend.m_Bone[0]!=0xff);
const CMatrix3D& m=invmatrices[blend.m_Bone[0]]; const CMatrix3D& m=invmatrices[blend.m_Bone[0]];
m.RotateTransposed(vertex.m_Norm,result); m.RotateTransposed(vertex.m_Norm,result);
result*=blend.m_Weight[0]; result*=blend.m_Weight[0];
for (u32 i=1;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) { for (u32 i=1;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
const CMatrix3D& m=invmatrices[blend.m_Bone[i]]; const CMatrix3D& m=invmatrices[blend.m_Bone[i]];
@ -146,9 +146,9 @@ void CModelRData::BuildVertices()
// build vertices // build vertices
u32 numVertices=mdef->GetNumVertices(); u32 numVertices=mdef->GetNumVertices();
SModelVertex* vertices=mdef->GetVertices(); SModelVertex* vertices=mdef->GetVertices();
const CMatrix3D* bonematrices=m_Model->GetBoneMatrices(); const CMatrix3D* bonematrices=m_Model->GetBoneMatrices();
if (bonematrices) { if (bonematrices) {
// boned model - calculate skinned vertex positions/normals // boned model - calculate skinned vertex positions/normals
const CMatrix3D* invbonematrices=m_Model->GetInvBoneMatrices(); const CMatrix3D* invbonematrices=m_Model->GetInvBoneMatrices();
for (uint j=0; j<numVertices; j++) { for (uint j=0; j<numVertices; j++) {
SkinPoint(vertices[j],bonematrices,m_Vertices[j].m_Position); SkinPoint(vertices[j],bonematrices,m_Vertices[j].m_Position);
@ -156,7 +156,7 @@ void CModelRData::BuildVertices()
} }
} else { } else {
// just copy regular positions, transform normals to world space // just copy regular positions, transform normals to world space
const CMatrix3D& transform=m_Model->GetTransform(); const CMatrix3D& transform=m_Model->GetTransform();
const CMatrix3D& invtransform=m_Model->GetInvTransform(); const CMatrix3D& invtransform=m_Model->GetInvTransform();
for (uint j=0; j<numVertices; j++) { for (uint j=0; j<numVertices; j++) {
transform.Transform(vertices[j].m_Coords,m_Vertices[j].m_Position); transform.Transform(vertices[j].m_Coords,m_Vertices[j].m_Position);
@ -170,11 +170,11 @@ void CModelRData::BuildVertices()
m_Vertices[j].m_UVs[1]=1-vertices[j].m_V; m_Vertices[j].m_UVs[1]=1-vertices[j].m_V;
g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j],m_Vertices[j].m_Color); g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j],m_Vertices[j].m_Color);
} }
// upload everything to vertex buffer - create one if necessary // upload everything to vertex buffer - create one if necessary
if (!m_VB) { if (!m_VB) {
m_VB=g_VBMan.Allocate(sizeof(SVertex),mdef->GetNumVertices(),mdef->GetNumBones() ? true : false); m_VB=g_VBMan.Allocate(sizeof(SVertex),mdef->GetNumVertices(),mdef->GetNumBones() ? true : false);
} }
m_VB->m_Owner->UpdateChunkVertices(m_VB,m_Vertices); m_VB->m_Owner->UpdateChunkVertices(m_VB,m_Vertices);
} }
@ -275,88 +275,88 @@ float CModelRData::BackToFrontIndexSort(CMatrix3D& objToCam)
return mindist; return mindist;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// SubmitBatches: submit batches for this model to the vertex buffer // SubmitBatches: submit batches for this model to the vertex buffer
void CModelRData::SubmitBatches() void CModelRData::SubmitBatches()
{ {
assert(m_VB); assert(m_VB);
m_VB->m_Owner->AppendBatch(m_VB,m_Model->GetTexture()->GetHandle(),m_Model->GetModelDef()->GetNumFaces()*3,m_Indices); m_VB->m_Owner->AppendBatch(m_VB,m_Model->GetTexture()->GetHandle(),m_Model->GetModelDef()->GetNumFaces()*3,m_Indices);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// RenderModels: render all submitted models; assumes necessary client states already enabled, // RenderModels: render all submitted models; assumes necessary client states already enabled,
// and texture environment already setup as required // and texture environment already setup as required
void CModelRData::RenderModels(u32 streamflags) void CModelRData::RenderModels(u32 streamflags)
{ {
uint i; uint i;
#if 1 #if 1
// submit batches for each model to the vertex buffer // submit batches for each model to the vertex buffer
for (i=0;i<m_Models.size();++i) { for (i=0;i<m_Models.size();++i) {
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData(); CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
modeldata->SubmitBatches(); modeldata->SubmitBatches();
} }
// step through all accumulated batches // step through all accumulated batches
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList(); const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
std::list<CVertexBuffer*>::const_iterator iter; std::list<CVertexBuffer*>::const_iterator iter;
for (iter=buffers.begin();iter!=buffers.end();++iter) { for (iter=buffers.begin();iter!=buffers.end();++iter) {
CVertexBuffer* buffer=*iter; CVertexBuffer* buffer=*iter;
// any batches in this VB? // any batches in this VB?
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches(); const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
if (batches.size()>0) { if (batches.size()>0) {
u8* base=buffer->Bind(); u8* base=buffer->Bind();
// setup data pointers // setup data pointers
u32 stride=sizeof(SVertex); u32 stride=sizeof(SVertex);
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position)); glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position));
if (streamflags & STREAM_COLOR) glColorPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Color)); if (streamflags & STREAM_COLOR) glColorPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Color));
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs[0])); if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs[0]));
// render each batch // render each batch
for (i=0;i<batches.size();++i) { for (i=0;i<batches.size();++i) {
const CVertexBuffer::Batch* batch=batches[i]; const CVertexBuffer::Batch* batch=batches[i];
if (batch->m_IndexData.size()>0) { if (batch->m_IndexData.size()>0) {
if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
for (uint j=0;j<batch->m_IndexData.size();j++) { for (uint j=0;j<batch->m_IndexData.size();j++) {
glDrawElements(GL_TRIANGLES,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second); glDrawElements(GL_TRIANGLES,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_ModelTris+=batch->m_IndexData[j].first/2; g_Renderer.m_Stats.m_ModelTris+=batch->m_IndexData[j].first/2;
} }
} }
} }
} }
} }
// everything rendered; empty out batch lists // everything rendered; empty out batch lists
g_VBMan.ClearBatchIndices(); g_VBMan.ClearBatchIndices();
#else #else
for (i=0;i<m_Models.size();++i) { for (i=0;i<m_Models.size();++i) {
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData(); CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
modeldata->RenderStreams(streamflags); modeldata->RenderStreams(streamflags);
} }
#endif #endif
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Submit: submit a model to render this frame // Submit: submit a model to render this frame
void CModelRData::Submit(CModel* model) void CModelRData::Submit(CModel* model)
{ {
CModelRData* data=(CModelRData*) model->GetRenderData(); CModelRData* data=(CModelRData*) model->GetRenderData();
if (data==0) { if (data==0) {
// no renderdata for model, create it now // no renderdata for model, create it now
data=new CModelRData(model); data=new CModelRData(model);
model->SetRenderData(data); model->SetRenderData(data);
} else { } else {
data->Update(); data->Update();
} }
if (data->GetFlags() & MODELRDATA_FLAG_TRANSPARENT) { if (data->GetFlags() & MODELRDATA_FLAG_TRANSPARENT) {
// add this mode to the transparency renderer for later processing - calculate // add this mode to the transparency renderer for later processing - calculate
// transform matrix // transform matrix
g_TransparencyRenderer.Add(model); g_TransparencyRenderer.Add(model);
} else { } else {
// add to regular model list // add to regular model list
m_Models.push_back(model); m_Models.push_back(model);
} }
} }

View file

@ -26,14 +26,14 @@ public:
// sort indices of this object from back to front according to given // sort indices of this object from back to front according to given
// object to camera space transform; return sqrd distance to centre of nearest triangle // object to camera space transform; return sqrd distance to centre of nearest triangle
float BackToFrontIndexSort(CMatrix3D& objToCam); float BackToFrontIndexSort(CMatrix3D& objToCam);
// submit a model to render this frame // submit a model to render this frame
static void Submit(CModel* model); static void Submit(CModel* model);
// clear per frame patch list // clear per frame patch list
static void ClearSubmissions() { m_Models.clear(); } static void ClearSubmissions() { m_Models.clear(); }
// render all submitted models // render all submitted models
static void RenderModels(u32 streamflags); static void RenderModels(u32 streamflags);
private: private:
// build this renderdata object // build this renderdata object
@ -42,8 +42,8 @@ private:
void BuildVertices(); void BuildVertices();
void BuildIndices(); void BuildIndices();
// submit batches for this model to the vertex buffer // submit batches for this model to the vertex buffer
void SubmitBatches(); void SubmitBatches();
struct SVertex { struct SVertex {
// vertex position // vertex position
@ -66,8 +66,8 @@ private:
u16* m_Indices; u16* m_Indices;
// model render flags // model render flags
u32 m_Flags; u32 m_Flags;
// list of all submitted models // list of all submitted models
static std::vector<CModel*> m_Models; static std::vector<CModel*> m_Models;
}; };

View file

@ -7,11 +7,11 @@
#include "Renderer.h" #include "Renderer.h"
#include "PatchRData.h" #include "PatchRData.h"
#include "AlphaMapCalculator.h" #include "AlphaMapCalculator.h"
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// shared list of all submitted patches this frame // shared list of all submitted patches this frame
std::vector<CPatch*> CPatchRData::m_Patches; std::vector<CPatch*> CPatchRData::m_Patches;
const int BlendOffsets[8][2] = { const int BlendOffsets[8][2] = {
{ 0, -1 }, { 0, -1 },
@ -24,40 +24,40 @@ const int BlendOffsets[8][2] = {
{ 1, -1 } { 1, -1 }
}; };
inline int clamp(int x,int min,int max) inline int clamp(int x,int min,int max)
{ {
if (x<min) return min; if (x<min) return min;
else if (x>max) return max; else if (x>max) return max;
else return x; else return x;
} }
static SColor4ub ConvertColor(const RGBColor& src)
{
SColor4ub result;
result.R=clamp(int(src.X*255),0,255);
result.G=clamp(int(src.Y*255),0,255);
result.B=clamp(int(src.Z*255),0,255);
result.A=0xff;
return result;
}
/////////////////////////////////////////////////////////////////// static SColor4ub ConvertColor(const RGBColor& src)
// CPatchRData constructor {
SColor4ub result;
result.R=clamp(int(src.X*255),0,255);
result.G=clamp(int(src.Y*255),0,255);
result.B=clamp(int(src.Z*255),0,255);
result.A=0xff;
return result;
}
///////////////////////////////////////////////////////////////////
// CPatchRData constructor
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_Vertices(0), m_VBBase(0), m_VBBlends(0) CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_Vertices(0), m_VBBase(0), m_VBBlends(0)
{ {
assert(patch); assert(patch);
Build(); Build();
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// CPatchRData destructor // CPatchRData destructor
CPatchRData::~CPatchRData() CPatchRData::~CPatchRData()
{ {
// delete copy of vertex data // delete copy of vertex data
delete[] m_Vertices; delete[] m_Vertices;
// release vertex buffer chunks // release vertex buffer chunks
if (m_VBBase) g_VBMan.Release(m_VBBase); if (m_VBBase) g_VBMan.Release(m_VBBase);
if (m_VBBlends) g_VBMan.Release(m_VBBlends); if (m_VBBlends) g_VBMan.Release(m_VBBlends);
} }
@ -253,47 +253,47 @@ void CPatchRData::BuildBlends()
} }
} }
} }
// build vertex data // build vertex data
if (m_VBBlends) { if (m_VBBlends) {
// release existing vertex buffer chunk // release existing vertex buffer chunk
g_VBMan.Release(m_VBBlends); g_VBMan.Release(m_VBBlends);
} }
m_VBBlends=g_VBMan.Allocate(sizeof(SBlendVertex),m_BlendVertices.size(),false); m_VBBlends=g_VBMan.Allocate(sizeof(SBlendVertex),m_BlendVertices.size(),false);
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]); m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]);
// now build outgoing splats // now build outgoing splats
m_BlendSplats.resize(splatTextures.size()); m_BlendSplats.resize(splatTextures.size());
int splatCount=0; int splatCount=0;
u32 base=m_VBBlends->m_Index; u32 base=m_VBBlends->m_Index;
std::set<Handle>::iterator iter=splatTextures.begin(); std::set<Handle>::iterator iter=splatTextures.begin();
for (;iter!=splatTextures.end();++iter) { for (;iter!=splatTextures.end();++iter) {
Handle tex=*iter; Handle tex=*iter;
SSplat& splat=m_BlendSplats[splatCount]; SSplat& splat=m_BlendSplats[splatCount];
splat.m_IndexStart=m_BlendIndices.size(); splat.m_IndexStart=m_BlendIndices.size();
splat.m_Texture=tex; splat.m_Texture=tex;
for (uint k=0;k<splats.size();k++) { for (uint k=0;k<splats.size();k++) {
if (splats[k].m_Texture==tex) { if (splats[k].m_Texture==tex) {
m_BlendIndices.push_back(splats[k].m_Indices[0]+base); m_BlendIndices.push_back(splats[k].m_Indices[0]+base);
m_BlendIndices.push_back(splats[k].m_Indices[1]+base); m_BlendIndices.push_back(splats[k].m_Indices[1]+base);
m_BlendIndices.push_back(splats[k].m_Indices[2]+base); m_BlendIndices.push_back(splats[k].m_Indices[2]+base);
m_BlendIndices.push_back(splats[k].m_Indices[3]+base); m_BlendIndices.push_back(splats[k].m_Indices[3]+base);
splat.m_IndexCount+=4; splat.m_IndexCount+=4;
} }
} }
splatCount++; splatCount++;
} }
} }
void CPatchRData::BuildIndices() void CPatchRData::BuildIndices()
{ {
// must have allocated some vertices before trying to build corresponding indices // must have allocated some vertices before trying to build corresponding indices
assert(m_VBBase); assert(m_VBBase);
// number of vertices in each direction in each patch // number of vertices in each direction in each patch
int vsize=PATCH_SIZE+1; int vsize=PATCH_SIZE+1;
@ -318,7 +318,7 @@ void CPatchRData::BuildIndices()
// now build base splats from interior textures // now build base splats from interior textures
m_Splats.resize(textures.size()); m_Splats.resize(textures.size());
// build indices for base splats // build indices for base splats
u32 base=m_VBBase->m_Index; u32 base=m_VBBase->m_Index;
for (uint i=0;i<m_Splats.size();i++) { for (uint i=0;i<m_Splats.size();i++) {
Handle h=textures[i]; Handle h=textures[i];
@ -337,25 +337,25 @@ void CPatchRData::BuildIndices()
} }
} }
splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart; splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart;
} }
// build indices for the shadow map pass // build indices for the shadow map pass
for (int j=0;j<PATCH_SIZE;j++) { for (int j=0;j<PATCH_SIZE;j++) {
for (int i=0;i<PATCH_SIZE;i++) { for (int i=0;i<PATCH_SIZE;i++) {
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+0))+base); m_ShadowMapIndices.push_back(((j+0)*vsize+(i+0))+base);
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+1))+base); m_ShadowMapIndices.push_back(((j+0)*vsize+(i+1))+base);
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+1))+base); m_ShadowMapIndices.push_back(((j+1)*vsize+(i+1))+base);
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+0))+base); m_ShadowMapIndices.push_back(((j+1)*vsize+(i+0))+base);
} }
} }
} }
void CPatchRData::BuildVertices() void CPatchRData::BuildVertices()
{ {
CVector3D normal; CVector3D normal;
RGBColor c; RGBColor c;
// number of vertices in each direction in each patch // number of vertices in each direction in each patch
int vsize=PATCH_SIZE+1; int vsize=PATCH_SIZE+1;
@ -372,25 +372,25 @@ void CPatchRData::BuildVertices()
CTerrain* terrain=m_Patch->m_Parent; CTerrain* terrain=m_Patch->m_Parent;
u32 mapSize=terrain->GetVerticesPerSide(); u32 mapSize=terrain->GetVerticesPerSide();
// build vertices // build vertices
for (int j=0;j<vsize;j++) { for (int j=0;j<vsize;j++) {
for (int i=0;i<vsize;i++) { for (int i=0;i<vsize;i++) {
int ix=px*PATCH_SIZE+i; int ix=px*PATCH_SIZE+i;
int iz=pz*PATCH_SIZE+j; int iz=pz*PATCH_SIZE+j;
int v=(j*vsize)+i; int v=(j*vsize)+i;
terrain->CalcPosition(ix,iz,vertices[v].m_Position); terrain->CalcPosition(ix,iz,vertices[v].m_Position);
terrain->CalcNormal(ix,iz,normal); terrain->CalcNormal(ix,iz,normal);
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal,c); g_Renderer.m_SHCoeffsTerrain.Evaluate(normal,c);
vertices[v].m_Color=ConvertColor(c); vertices[v].m_Color=ConvertColor(c);
vertices[v].m_UVs[0]=i*0.125f; vertices[v].m_UVs[0]=i*0.125f;
vertices[v].m_UVs[1]=j*0.125f; vertices[v].m_UVs[1]=j*0.125f;
} }
} }
if (!m_VBBase) { if (!m_VBBase) {
m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,false); m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,false);
} }
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices); m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
} }
@ -464,7 +464,7 @@ void CPatchRData::RenderBlends()
if (m_BlendVertices.size()==0) return; if (m_BlendVertices.size()==0) return;
u8* base=m_VBBlends->m_Owner->Bind(); u8* base=m_VBBlends->m_Owner->Bind();
// setup data pointers // setup data pointers
u32 stride=sizeof(SBlendVertex); u32 stride=sizeof(SBlendVertex);
@ -491,7 +491,7 @@ void CPatchRData::RenderBlends()
void CPatchRData::RenderOutline() void CPatchRData::RenderOutline()
{ {
// TODO, RC - fixme, only works for PATCH_SIZE = 16 // TODO, RC - fixme, only works for PATCH_SIZE = 16
const u16 EdgeIndices[PATCH_SIZE*4] = { const u16 EdgeIndices[PATCH_SIZE*4] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
33, 50, 67, 84, 101, 118, 135, 152, 169, 186, 203, 220, 237, 254, 271, 288, 33, 50, 67, 84, 101, 118, 135, 152, 169, 186, 203, 220, 237, 254, 271, 288,
@ -510,298 +510,298 @@ void CPatchRData::RenderOutline()
g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris+=numIndices/2; g_Renderer.m_Stats.m_TerrainTris+=numIndices/2;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// SubmitBaseBatches: submit base batches for this patch to the vertex buffer // SubmitBaseBatches: submit base batches for this patch to the vertex buffer
void CPatchRData::SubmitBaseBatches() void CPatchRData::SubmitBaseBatches()
{ {
assert(m_VBBase); assert(m_VBBase);
for (uint i=0;i<m_Splats.size();i++) { for (uint i=0;i<m_Splats.size();i++) {
const SSplat& splat=m_Splats[i]; const SSplat& splat=m_Splats[i];
m_VBBase->m_Owner->AppendBatch(m_VBBase,splat.m_Texture,splat.m_IndexCount,&m_Indices[splat.m_IndexStart]); m_VBBase->m_Owner->AppendBatch(m_VBBase,splat.m_Texture,splat.m_IndexCount,&m_Indices[splat.m_IndexStart]);
} }
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// SubmitBlendBatches: submit next set of blend batches for this patch to the vertex buffer; // SubmitBlendBatches: submit next set of blend batches for this patch to the vertex buffer;
// return true if all blends on this patch have been submitted, else false // return true if all blends on this patch have been submitted, else false
bool CPatchRData::SubmitBlendBatches() bool CPatchRData::SubmitBlendBatches()
{ {
if (m_NextBlendSplat<m_BlendSplats.size()) { if (m_NextBlendSplat<m_BlendSplats.size()) {
for (uint i=m_NextBlendSplat;i<m_BlendSplats.size();i++) { for (uint i=m_NextBlendSplat;i<m_BlendSplats.size();i++) {
const SSplat& splat=m_BlendSplats[i]; const SSplat& splat=m_BlendSplats[i];
m_VBBlends->m_Owner->AppendBatch(m_VBBlends,splat.m_Texture,splat.m_IndexCount,&m_BlendIndices[splat.m_IndexStart]); m_VBBlends->m_Owner->AppendBatch(m_VBBlends,splat.m_Texture,splat.m_IndexCount,&m_BlendIndices[splat.m_IndexStart]);
} }
return true; return true;
} }
return true; return true;
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// RenderBaseSplats: render all base passes of all patches; assumes vertex, texture and color // RenderBaseSplats: render all base passes of all patches; assumes vertex, texture and color
// client states are enabled // client states are enabled
void CPatchRData::RenderBaseSplats() void CPatchRData::RenderBaseSplats()
{ {
uint i; uint i;
// set up texture environment for base pass // set up texture environment for base pass
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
#if 1 #if 1
// submit base batches for each patch to the vertex buffer // submit base batches for each patch to the vertex buffer
for (i=0;i<m_Patches.size();++i) { for (i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
patchdata->SubmitBaseBatches(); patchdata->SubmitBaseBatches();
} }
// render base passes for each patch // render base passes for each patch
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList(); const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
std::list<CVertexBuffer*>::const_iterator iter; std::list<CVertexBuffer*>::const_iterator iter;
for (iter=buffers.begin();iter!=buffers.end();++iter) { for (iter=buffers.begin();iter!=buffers.end();++iter) {
CVertexBuffer* buffer=*iter; CVertexBuffer* buffer=*iter;
// any batches in this VB? // any batches in this VB?
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches(); const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
if (batches.size()>0) { if (batches.size()>0) {
u8* base=buffer->Bind(); u8* base=buffer->Bind();
// setup data pointers // setup data pointers
u32 stride=sizeof(SBaseVertex); u32 stride=sizeof(SBaseVertex);
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position)); glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color)); glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_UVs[0])); glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_UVs[0]));
// render each batch // render each batch
for (i=0;i<batches.size();++i) { for (i=0;i<batches.size();++i) {
const CVertexBuffer::Batch* batch=batches[i]; const CVertexBuffer::Batch* batch=batches[i];
if (batch->m_IndexData.size()>0) { if (batch->m_IndexData.size()>0) {
g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
for (uint j=0;j<batch->m_IndexData.size();j++) { for (uint j=0;j<batch->m_IndexData.size();j++) {
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second); glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2; g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
} }
} }
} }
} }
} }
// everything rendered; empty out batch lists // everything rendered; empty out batch lists
g_VBMan.ClearBatchIndices(); g_VBMan.ClearBatchIndices();
#else #else
for (i=0;i<m_Patches.size();++i) { for (i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
patchdata->RenderBase(); patchdata->RenderBase();
} }
#endif #endif
} }
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
// RenderBlendSplats: render all blend passes of all patches; assumes vertex, texture and color // RenderBlendSplats: render all blend passes of all patches; assumes vertex, texture and color
// client states are enabled // client states are enabled
void CPatchRData::RenderBlendSplats() void CPatchRData::RenderBlendSplats()
{ {
uint i; uint i;
// switch on second uv set // switch on second uv set
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0); glClientActiveTexture(GL_TEXTURE0);
// switch on the composite alpha map texture // switch on the composite alpha map texture
g_Renderer.BindTexture(1,g_Renderer.m_CompositeAlphaMap); g_Renderer.BindTexture(1,g_Renderer.m_CompositeAlphaMap);
// setup additional texenv required by blend pass // setup additional texenv required by blend pass
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
// switch on blending // switch on blending
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// no need to write to the depth buffer a second time // no need to write to the depth buffer a second time
glDepthMask(0); glDepthMask(0);
#if 1 #if 1
// submit blend batches for each patch to the vertex buffer // submit blend batches for each patch to the vertex buffer
for (i=0;i<m_Patches.size();++i) { for (i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
patchdata->SetupBlendBatches(); patchdata->SetupBlendBatches();
} }
bool finished=true; bool finished=true;
do do
{ {
for (i=0;i<m_Patches.size();++i) { for (i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
if (!patchdata->SubmitBlendBatches()) finished=false; if (!patchdata->SubmitBlendBatches()) finished=false;
} }
} while (!finished); } while (!finished);
// render blend passes for each patch // render blend passes for each patch
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList(); const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
std::list<CVertexBuffer*>::const_iterator iter; std::list<CVertexBuffer*>::const_iterator iter;
for (iter=buffers.begin();iter!=buffers.end();++iter) { for (iter=buffers.begin();iter!=buffers.end();++iter) {
CVertexBuffer* buffer=*iter; CVertexBuffer* buffer=*iter;
// any batches in this VB? // any batches in this VB?
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches(); const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
if (batches.size()>0) { if (batches.size()>0) {
u8* base=buffer->Bind(); u8* base=buffer->Bind();
// setup data pointers // setup data pointers
u32 stride=sizeof(SBlendVertex); u32 stride=sizeof(SBlendVertex);
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position)); glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color)); glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color));
glClientActiveTexture(GL_TEXTURE0); glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0])); glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
glClientActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0])); glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0]));
// render each batch // render each batch
for (i=0;i<batches.size();++i) { for (i=0;i<batches.size();++i) {
const CVertexBuffer::Batch* batch=batches[i]; const CVertexBuffer::Batch* batch=batches[i];
if (batch->m_IndexData.size()>0) { if (batch->m_IndexData.size()>0) {
g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
for (uint j=0;j<batch->m_IndexData.size();j++) { for (uint j=0;j<batch->m_IndexData.size();j++) {
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second); glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2; g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
} }
} }
} }
} }
} }
// everything rendered; empty out batch lists // everything rendered; empty out batch lists
g_VBMan.ClearBatchIndices(); g_VBMan.ClearBatchIndices();
#else #else
// render blend passes for each patch // render blend passes for each patch
for (i=0;i<m_TerrainPatches.size();++i) { for (i=0;i<m_TerrainPatches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
patchdata->RenderBlends(); patchdata->RenderBlends();
} }
#endif #endif
// restore depth writes // restore depth writes
glDepthMask(1); glDepthMask(1);
// restore default state: switch off blending // restore default state: switch off blending
glDisable(GL_BLEND); glDisable(GL_BLEND);
// switch off texture unit 1, make unit 0 active texture // switch off texture unit 1, make unit 0 active texture
g_Renderer.BindTexture(1,0); g_Renderer.BindTexture(1,0);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
// tidy up client states // tidy up client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0_ARB); glClientActiveTexture(GL_TEXTURE0_ARB);
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Submit: submit a patch to render this frame // Submit: submit a patch to render this frame
void CPatchRData::Submit(CPatch* patch) void CPatchRData::Submit(CPatch* patch)
{ {
CPatchRData* data=(CPatchRData*) patch->GetRenderData(); CPatchRData* data=(CPatchRData*) patch->GetRenderData();
if (data==0) { if (data==0) {
// no renderdata for patch, create it now // no renderdata for patch, create it now
data=new CPatchRData(patch); data=new CPatchRData(patch);
patch->SetRenderData(data); patch->SetRenderData(data);
} else { } else {
data->Update(); data->Update();
} }
m_Patches.push_back(patch); m_Patches.push_back(patch);
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// ApplyShadowMap: apply given shadow map to all terrain patches; assume the texture matrix // ApplyShadowMap: apply given shadow map to all terrain patches; assume the texture matrix
// has been correctly setup on unit 1 to handle the projection // has been correctly setup on unit 1 to handle the projection
void CPatchRData::ApplyShadowMap(GLuint shadowmaphandle) void CPatchRData::ApplyShadowMap(GLuint shadowmaphandle)
{ {
uint i; uint i;
// glEnable(GL_ALPHA_TEST); // glEnable(GL_ALPHA_TEST);
// glAlphaFunc(GL_GREATER,0.0f); // glAlphaFunc(GL_GREATER,0.0f);
g_Renderer.BindTexture(0,shadowmaphandle); g_Renderer.BindTexture(0,shadowmaphandle);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glColor3f(1,1,1); glColor3f(1,1,1);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR,GL_ZERO); glBlendFunc(GL_DST_COLOR,GL_ZERO);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#if 1 #if 1
// submit base batches for each patch to the vertex buffer // submit base batches for each patch to the vertex buffer
for (i=0;i<m_Patches.size();++i) { for (i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData(); CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
patchdata->m_VBBase->m_Owner->AppendBatch(patchdata->m_VBBase,0,patchdata->m_ShadowMapIndices.size(), patchdata->m_VBBase->m_Owner->AppendBatch(patchdata->m_VBBase,0,patchdata->m_ShadowMapIndices.size(),
&patchdata->m_ShadowMapIndices[0]); &patchdata->m_ShadowMapIndices[0]);
} }
// render base passes for each patch // render base passes for each patch
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList(); const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
std::list<CVertexBuffer*>::const_iterator iter; std::list<CVertexBuffer*>::const_iterator iter;
for (iter=buffers.begin();iter!=buffers.end();++iter) { for (iter=buffers.begin();iter!=buffers.end();++iter) {
CVertexBuffer* buffer=*iter; CVertexBuffer* buffer=*iter;
// any batches in this VB? // any batches in this VB?
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches(); const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
if (batches.size()>0) { if (batches.size()>0) {
u8* base=buffer->Bind(); u8* base=buffer->Bind();
// setup data pointers // setup data pointers
u32 stride=sizeof(SBaseVertex); u32 stride=sizeof(SBaseVertex);
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position)); glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color)); glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
glTexCoordPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position)); glTexCoordPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position));
// render batch (can only be one per buffer, since all batches are flagged as using a null texture) // render batch (can only be one per buffer, since all batches are flagged as using a null texture)
const CVertexBuffer::Batch* batch=batches[0]; const CVertexBuffer::Batch* batch=batches[0];
for (uint j=0;j<batch->m_IndexData.size();j++) { for (uint j=0;j<batch->m_IndexData.size();j++) {
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second); glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
g_Renderer.m_Stats.m_DrawCalls++; g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2; g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
} }
} }
} }
// everything rendered; empty out batch lists // everything rendered; empty out batch lists
g_VBMan.ClearBatchIndices(); g_VBMan.ClearBatchIndices();
#else #else
for (uint i=0;i<m_Patches.size();++i) { for (uint i=0;i<m_Patches.size();++i) {
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();; CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();;
patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0); patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0);
} }
#endif #endif
glDisable(GL_ALPHA_TEST); glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
} }

View file

@ -6,12 +6,12 @@
#include "Color.h" #include "Color.h"
#include "Vector3D.h" #include "Vector3D.h"
#include "RenderableObject.h" #include "RenderableObject.h"
#include "VertexBufferManager.h" #include "VertexBufferManager.h"
class CPatch; class CPatch;
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
// CPatchRData: class encapsulating logic for rendering terrain patches; holds per // CPatchRData: class encapsulating logic for rendering terrain patches; holds per
// patch data, plus some supporting static functions for batching, etc // patch data, plus some supporting static functions for batching, etc
class CPatchRData : public CRenderData class CPatchRData : public CRenderData
{ {
@ -24,68 +24,68 @@ public:
void RenderBlends(); void RenderBlends();
void RenderOutline(); void RenderOutline();
void RenderStreams(u32 streamflags); void RenderStreams(u32 streamflags);
// submit a patch to render this frame // submit a patch to render this frame
static void Submit(CPatch* patch); static void Submit(CPatch* patch);
// clear per frame patch list // clear per frame patch list
static void ClearSubmissions() { m_Patches.clear(); } static void ClearSubmissions() { m_Patches.clear(); }
// render the base pass of all patches // render the base pass of all patches
static void RenderBaseSplats(); static void RenderBaseSplats();
// render the blend pass of all patches // render the blend pass of all patches
static void RenderBlendSplats(); static void RenderBlendSplats();
// apply given shadow map to all terrain patches // apply given shadow map to all terrain patches
static void ApplyShadowMap(GLuint handle); static void ApplyShadowMap(GLuint handle);
// submit base batches for this patch to the vertex buffer // submit base batches for this patch to the vertex buffer
void SubmitBaseBatches(); void SubmitBaseBatches();
// submit next set of blend batches for this patch to the vertex buffer; // submit next set of blend batches for this patch to the vertex buffer;
// return true if all blends on this patch have been submitted, else false // return true if all blends on this patch have been submitted, else false
bool SubmitBlendBatches(); bool SubmitBlendBatches();
// perform necessary initialisation prior to rendering blend splats // perform necessary initialisation prior to rendering blend splats
void SetupBlendBatches() { m_NextBlendSplat=0; } void SetupBlendBatches() { m_NextBlendSplat=0; }
private: private:
struct SSplat { struct SSplat {
SSplat() : m_Texture(0), m_IndexCount(0) {} SSplat() : m_Texture(0), m_IndexCount(0) {}
// handle of texture to apply during splat // handle of texture to apply during splat
Handle m_Texture; Handle m_Texture;
// offset into the index array for this patch where splat starts // offset into the index array for this patch where splat starts
u32 m_IndexStart; u32 m_IndexStart;
// number of indices used by splat // number of indices used by splat
u32 m_IndexCount; u32 m_IndexCount;
}; };
struct SBaseVertex { struct SBaseVertex {
// vertex position // vertex position
CVector3D m_Position; CVector3D m_Position;
// vertex color // vertex color
SColor4ub m_Color; SColor4ub m_Color;
// vertex uvs for base texture // vertex uvs for base texture
float m_UVs[2]; float m_UVs[2];
}; };
struct SBlendVertex { struct SBlendVertex {
// vertex position // vertex position
CVector3D m_Position; CVector3D m_Position;
// vertex color // vertex color
SColor4ub m_Color; SColor4ub m_Color;
// vertex uvs for base texture // vertex uvs for base texture
float m_UVs[2]; float m_UVs[2];
// vertex uvs for alpha texture // vertex uvs for alpha texture
float m_AlphaUVs[2]; float m_AlphaUVs[2];
}; };
struct STex { struct STex {
bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; } bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; }
bool operator<(const STex& rhs) const { return m_Priority<rhs.m_Priority; } bool operator<(const STex& rhs) const { return m_Priority<rhs.m_Priority; }
Handle m_Handle; Handle m_Handle;
int m_Priority; int m_Priority;
}; };
// build this renderdata object // build this renderdata object
void Build(); void Build();
@ -103,8 +103,8 @@ private:
SBaseVertex* m_Vertices; SBaseVertex* m_Vertices;
// indices into base vertices for the base splats // indices into base vertices for the base splats
std::vector<unsigned short> m_Indices; std::vector<unsigned short> m_Indices;
// indices into base vertices for the shadow map pass // indices into base vertices for the shadow map pass
std::vector<unsigned short> m_ShadowMapIndices; std::vector<unsigned short> m_ShadowMapIndices;
// list of base splats to apply to this patch // list of base splats to apply to this patch
std::vector<SSplat> m_Splats; std::vector<SSplat> m_Splats;
// vertices to use for blending transition texture passes // vertices to use for blending transition texture passes
@ -112,10 +112,10 @@ private:
// indices into blend vertices for the blend splats // indices into blend vertices for the blend splats
std::vector<unsigned short> m_BlendIndices; std::vector<unsigned short> m_BlendIndices;
// splats used in blend pass // splats used in blend pass
std::vector<SSplat> m_BlendSplats; std::vector<SSplat> m_BlendSplats;
// index of the next blend splat to render // index of the next blend splat to render
u32 m_NextBlendSplat; u32 m_NextBlendSplat;
// list of all submitted patches // list of all submitted patches
static std::vector<CPatch*> m_Patches; static std::vector<CPatch*> m_Patches;
}; };

View file

@ -25,7 +25,7 @@
#include "PatchRData.h" #include "PatchRData.h"
#include "Texture.h" #include "Texture.h"
#include "LightEnv.h" #include "LightEnv.h"
#include "CLogger.h" #include "CLogger.h"
#include "Model.h" #include "Model.h"
#include "ModelDef.h" #include "ModelDef.h"
@ -74,8 +74,8 @@ static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned c
header.d_y_origin=0; header.d_y_origin=0;
header.width=width; header.width=width;
header.height=height; header.height=height;
header.bpp=bpp; header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0; header.image_descriptor=(bpp==32) ? 8 : 0;
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) { if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
fclose(fp); fclose(fp);
@ -94,8 +94,8 @@ static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned c
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// CRenderer destructor // CRenderer destructor
CRenderer::CRenderer() CRenderer::CRenderer()
{ {
m_Width=0; m_Width=0;
@ -106,18 +106,18 @@ CRenderer::CRenderer()
m_ModelRenderMode=SOLID; m_ModelRenderMode=SOLID;
m_ClearColor[0]=m_ClearColor[1]=m_ClearColor[2]=m_ClearColor[3]=0; m_ClearColor[0]=m_ClearColor[1]=m_ClearColor[2]=m_ClearColor[3]=0;
m_ShadowMap=0; m_ShadowMap=0;
m_Options.m_NoVBO=false; m_Options.m_NoVBO=false;
m_Options.m_Shadows=true; m_Options.m_Shadows=true;
m_Options.m_ShadowColor=RGBAColor(0.4f,0.4f,0.4f,1.0f); m_Options.m_ShadowColor=RGBAColor(0.4f,0.4f,0.4f,1.0f);
for (uint i=0;i<MaxTextureUnits;i++) { for (uint i=0;i<MaxTextureUnits;i++) {
m_ActiveTextures[i]=0; m_ActiveTextures[i]=0;
} }
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
// CRenderer destructor // CRenderer destructor
CRenderer::~CRenderer() CRenderer::~CRenderer()
{ {
} }
@ -166,13 +166,13 @@ bool CRenderer::Open(int width, int height, int depth)
// query card capabilities // query card capabilities
EnumCaps(); EnumCaps();
GLint bits; GLint bits;
glGetIntegerv(GL_DEPTH_BITS,&bits); glGetIntegerv(GL_DEPTH_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits); CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits);
glGetIntegerv(GL_STENCIL_BITS,&bits); glGetIntegerv(GL_STENCIL_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits); CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits);
glGetIntegerv(GL_ALPHA_BITS,&bits); glGetIntegerv(GL_ALPHA_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits); CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits);
return true; return true;
} }
@ -184,10 +184,10 @@ void CRenderer::Close()
// resize renderer view // resize renderer view
void CRenderer::Resize(int width,int height) void CRenderer::Resize(int width,int height)
{ {
if (m_ShadowMap && (width>m_Width || height>m_Height)) { if (m_ShadowMap && (width>m_Width || height>m_Height)) {
glDeleteTextures(1,(GLuint*) &m_ShadowMap); glDeleteTextures(1,(GLuint*) &m_ShadowMap);
m_ShadowMap=0; m_ShadowMap=0;
} }
m_Width=width; m_Width=width;
m_Height=height; m_Height=height;
} }
@ -270,7 +270,7 @@ void CRenderer::BeginFrame()
} }
// init per frame stuff // init per frame stuff
m_ShadowRendered=false; m_ShadowRendered=false;
m_ShadowBound.SetEmpty(); m_ShadowBound.SetEmpty();
} }
@ -400,7 +400,7 @@ void CRenderer::CalcShadowMatrices()
// shift near and far clip planes slightly to avoid artifacts with points // shift near and far clip planes slightly to avoid artifacts with points
// exactly on the clip planes // exactly on the clip planes
znear=(znear<m_Camera.GetNearPlane()+0.01f) ? m_Camera.GetNearPlane() : znear-0.01f; znear=(znear<m_Camera.GetNearPlane()+0.01f) ? m_Camera.GetNearPlane() : znear-0.01f;
zfar+=0.01f; zfar+=0.01f;
m_LightProjection.SetZero(); m_LightProjection.SetZero();
@ -551,19 +551,19 @@ void CRenderer::CreateShadowMap()
{ {
// get shadow map size as next power of two up from view width and height // get shadow map size as next power of two up from view width and height
m_ShadowMapWidth=m_Width; m_ShadowMapWidth=m_Width;
m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth); m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth);
m_ShadowMapHeight=m_Height; m_ShadowMapHeight=m_Height;
m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight); m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight);
// create texture object - initially filled with white, so clamp to edge clamps to correct color // create texture object - initially filled with white, so clamp to edge clamps to correct color
glGenTextures(1,(GLuint*) &m_ShadowMap); glGenTextures(1,(GLuint*) &m_ShadowMap);
BindTexture(0,(GLuint) m_ShadowMap); BindTexture(0,(GLuint) m_ShadowMap);
u32 size=m_ShadowMapWidth*m_ShadowMapHeight; u32 size=m_ShadowMapWidth*m_ShadowMapHeight;
u32* buf=new u32[size]; u32* buf=new u32[size];
for (uint i=0;i<size;i++) buf[i]=0x00ffffff; for (uint i=0;i<size;i++) buf[i]=0x00ffffff;
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_ShadowMapWidth,m_ShadowMapHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,buf); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_ShadowMapWidth,m_ShadowMapHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
delete[] buf; delete[] buf;
// set texture parameters // set texture parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -578,7 +578,7 @@ void CRenderer::RenderShadowMap()
if (!m_ShadowMap) CreateShadowMap(); if (!m_ShadowMap) CreateShadowMap();
// clear buffers // clear buffers
glClearColor(1,1,1,0); glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// build required matrices // build required matrices
@ -636,27 +636,27 @@ void CRenderer::RenderShadowMap()
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glScissor(1,1,m_Width-2,m_Height-2); glScissor(1,1,m_Width-2,m_Height-2);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glColor4fv(m_Options.m_ShadowColor); glColor4fv(m_Options.m_ShadowColor);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
// render models // render models
CModelRData::RenderModels(STREAM_POS); CModelRData::RenderModels(STREAM_POS);
// call on the transparency renderer to render all the transparent stuff // call on the transparency renderer to render all the transparent stuff
g_TransparencyRenderer.RenderShadows(); g_TransparencyRenderer.RenderShadows();
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glColor3f(1.0f,1.0f,1.0f); glColor3f(1.0f,1.0f,1.0f);
@ -675,46 +675,46 @@ void CRenderer::RenderShadowMap()
if (0) if (0)
{ {
#if 1 #if 1
// debug aid - dump generated shadow map to file; helps verify shadow map // debug aid - dump generated shadow map to file; helps verify shadow map
// space being well used (not that it is at the minute .. (TODO, RC)) // space being well used (not that it is at the minute .. (TODO, RC))
unsigned char* data=new unsigned char[m_ShadowMapWidth*m_ShadowMapHeight*3]; unsigned char* data=new unsigned char[m_ShadowMapWidth*m_ShadowMapHeight*3];
glGetTexImage(GL_TEXTURE_2D,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,data); glGetTexImage(GL_TEXTURE_2D,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,data);
saveTGA("d:\\test4.tga",m_ShadowMapWidth,m_ShadowMapHeight,24,data); saveTGA("d:\\test4.tga",m_ShadowMapWidth,m_ShadowMapHeight,24,data);
delete[] data; delete[] data;
#else #else
unsigned char* data=new unsigned char[m_Width*m_Height*4]; unsigned char* data=new unsigned char[m_Width*m_Height*4];
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data); glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data);
saveTGA("d:\\test3.tga",m_Width,m_Height,32,data); saveTGA("d:\\test3.tga",m_Width,m_Height,32,data);
delete[] data; delete[] data;
#endif #endif
} }
} }
void CRenderer::ApplyShadowMap() void CRenderer::ApplyShadowMap()
{ {
CMatrix3D tmp2; CMatrix3D tmp2;
CMatrix3D texturematrix; CMatrix3D texturematrix;
float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth); float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth);
float dy=0.5f*float(m_Height)/float(m_ShadowMapHeight); float dy=0.5f*float(m_Height)/float(m_ShadowMapHeight);
texturematrix.SetTranslation(dx,dy,0); // transform (-0.5, 0.5) to (0,1) - texture space texturematrix.SetTranslation(dx,dy,0); // transform (-0.5, 0.5) to (0,1) - texture space
tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5) tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5)
texturematrix=texturematrix*tmp2; texturematrix=texturematrix*tmp2;
texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1) texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1)
texturematrix=texturematrix*m_LightTransform; // transform world -> light space texturematrix=texturematrix*m_LightTransform; // transform world -> light space
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glLoadMatrixf(&texturematrix._11); glLoadMatrixf(&texturematrix._11);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
CPatchRData::ApplyShadowMap(m_ShadowMap); CPatchRData::ApplyShadowMap(m_ShadowMap);
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glLoadIdentity(); glLoadIdentity();
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
} }
void CRenderer::RenderPatches() void CRenderer::RenderPatches()
@ -731,8 +731,8 @@ void CRenderer::RenderPatches()
// switch wireframe off again // switch wireframe off again
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
} else if (m_TerrainRenderMode==EDGED_FACES) { } else if (m_TerrainRenderMode==EDGED_FACES) {
/* /*
// TODO, RC - fix this // TODO, RC - fix this
// edged faces: need to make a second pass over the data: // edged faces: need to make a second pass over the data:
// first switch on wireframe // first switch on wireframe
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
@ -778,42 +778,42 @@ void CRenderer::RenderPatches()
// restore fill mode, and we're done // restore fill mode, and we're done
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
*/ */
} }
} }
void CRenderer::RenderModelSubmissions() void CRenderer::RenderModelSubmissions()
{ {
// set up texture environment for base pass - modulate texture and primary color // set up texture environment for base pass - modulate texture and primary color
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// pass one through as alpha; transparent textures handled specially by CTransparencyRenderer // pass one through as alpha; transparent textures handled specially by CTransparencyRenderer
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ONE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ONE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
// setup client states // setup client states
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render models // render models
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0); CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
// switch off client states // switch off client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
} }
void CRenderer::RenderModels() void CRenderer::RenderModels()
{ {
// switch on wireframe if we need it // switch on wireframe if we need it
if (m_ModelRenderMode==WIREFRAME) { if (m_ModelRenderMode==WIREFRAME) {
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
@ -887,11 +887,11 @@ void CRenderer::FlushFrame()
// render submitted patches and models // render submitted patches and models
RenderPatches(); RenderPatches();
RenderModels(); RenderModels();
if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap(); if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap();
m_ShadowRendered=true; m_ShadowRendered=true;
// call on the transparency renderer to render all the transparent stuff // call on the transparency renderer to render all the transparent stuff
g_TransparencyRenderer.Render(); g_TransparencyRenderer.Render();
// empty lists // empty lists
g_TransparencyRenderer.Clear(); g_TransparencyRenderer.Clear();
@ -899,22 +899,22 @@ void CRenderer::FlushFrame()
CModelRData::ClearSubmissions(); CModelRData::ClearSubmissions();
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// EndFrame: signal frame end; implicitly flushes batched objects // EndFrame: signal frame end; implicitly flushes batched objects
void CRenderer::EndFrame() void CRenderer::EndFrame()
{ {
FlushFrame(); FlushFrame();
g_Renderer.SetTexture(0,0); g_Renderer.SetTexture(0,0);
static bool once=false; static bool once=false;
if (!once && glGetError()) { if (!once && glGetError()) {
CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n"); CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n");
once=true; once=true;
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// SetCamera: setup projection and transform of camera and adjust viewport to current view // SetCamera: setup projection and transform of camera and adjust viewport to current view
void CRenderer::SetCamera(CCamera& camera) void CRenderer::SetCamera(CCamera& camera)
{ {
CMatrix3D view; CMatrix3D view;
@ -935,16 +935,16 @@ void CRenderer::SetCamera(CCamera& camera)
void CRenderer::Submit(CPatch* patch) void CRenderer::Submit(CPatch* patch)
{ {
CPatchRData::Submit(patch); CPatchRData::Submit(patch);
} }
void CRenderer::Submit(CModel* model) void CRenderer::Submit(CModel* model)
{ {
if (1 /*ThisModelCastsShadows*/) { if (1 /*ThisModelCastsShadows*/) {
m_ShadowBound+=model->GetBounds(); m_ShadowBound+=model->GetBounds();
} }
CModelRData::Submit(model); CModelRData::Submit(model);
} }
void CRenderer::Submit(CSprite* sprite) void CRenderer::Submit(CSprite* sprite)
@ -966,14 +966,14 @@ void CRenderer::RenderPatchSubmissions()
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render everything // render everything
CPatchRData::RenderBaseSplats(); CPatchRData::RenderBaseSplats();
CPatchRData::RenderBlendSplats(); CPatchRData::RenderBlendSplats();
// switch off all client states // switch off all client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
} }
@ -990,72 +990,72 @@ bool CRenderer::LoadTexture(CTexture* texture,u32 wrapflags)
} else { } else {
h=tex_load(texture->GetName()); h=tex_load(texture->GetName());
if (!h) { if (!h) {
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\"",(const char*) texture->GetName()); CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\"",(const char*) texture->GetName());
texture->SetHandle(0xffffffff); texture->SetHandle(0xffffffff);
return false; return false;
} else { } else {
int tw,th; int tw,th;
tex_info(h, &tw, &th, NULL, NULL, NULL); tex_info(h, &tw, &th, NULL, NULL, NULL);
tw&=(tw-1); tw&=(tw-1);
th&=(th-1); th&=(th-1);
if (tw || th) { if (tw || th) {
texture->SetHandle(0xffffffff); texture->SetHandle(0xffffffff);
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName()); CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
return false; return false;
} else { } else {
BindTexture(0,tex_id(h)); BindTexture(0,tex_id(h));
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR); tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
if (wrapflags) { if (wrapflags) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
} else { } else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} }
texture->SetHandle(h); texture->SetHandle(h);
return true; return true;
} }
} }
} }
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BindTexture: bind a GL texture object to current active unit // BindTexture: bind a GL texture object to current active unit
void CRenderer::BindTexture(int unit,GLuint tex) void CRenderer::BindTexture(int unit,GLuint tex)
{ {
#if 0 #if 0
glActiveTexture(GL_TEXTURE0+unit); glActiveTexture(GL_TEXTURE0+unit);
if (tex==m_ActiveTextures[unit]) return; if (tex==m_ActiveTextures[unit]) return;
if (tex) { if (tex) {
glBindTexture(GL_TEXTURE_2D,tex); glBindTexture(GL_TEXTURE_2D,tex);
if (!m_ActiveTextures[unit]) { if (!m_ActiveTextures[unit]) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
} }
} else if (m_ActiveTextures[unit]) { } else if (m_ActiveTextures[unit]) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
m_ActiveTextures[unit]=tex; m_ActiveTextures[unit]=tex;
#endif #endif
glActiveTexture(GL_TEXTURE0+unit); glActiveTexture(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D,tex); glBindTexture(GL_TEXTURE_2D,tex);
if (tex) { if (tex) {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
} else { } else {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} }
m_ActiveTextures[unit]=tex; m_ActiveTextures[unit]=tex;
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SetTexture: set the given unit to reference the given texture; pass a null texture to disable texturing on any unit // SetTexture: set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
void CRenderer::SetTexture(int unit,CTexture* texture) void CRenderer::SetTexture(int unit,CTexture* texture)
{ {
if (texture) { if (texture) {
Handle h=texture->GetHandle(); Handle h=texture->GetHandle();
BindTexture(unit,tex_id(h)); BindTexture(unit,tex_id(h));

View file

@ -126,9 +126,9 @@ public:
// set/get boolean renderer option // set/get boolean renderer option
void SetOptionBool(enum Option opt,bool value); void SetOptionBool(enum Option opt,bool value);
bool GetOptionBool(enum Option opt) const; bool GetOptionBool(enum Option opt) const;
// set/get RGBA color renderer option // set/get RGBA color renderer option
void SetOptionColor(enum Option opt,const RGBAColor& value); void SetOptionColor(enum Option opt,const RGBAColor& value);
const RGBAColor& GetOptionColor(enum Option opt) const; const RGBAColor& GetOptionColor(enum Option opt) const;
// return view width // return view width
int GetWidth() const { return m_Width; } int GetWidth() const { return m_Width; }
@ -194,7 +194,7 @@ public:
// try and load the given texture // try and load the given texture
bool LoadTexture(CTexture* texture,u32 wrapflags); bool LoadTexture(CTexture* texture,u32 wrapflags);
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit; // set the given unit to reference the given texture; pass a null texture to disable texturing on any unit;
// active texture unit always set to given unit on exit // active texture unit always set to given unit on exit
void SetTexture(int unit,CTexture* texture); void SetTexture(int unit,CTexture* texture);
// bind a GL texture object to active unit // bind a GL texture object to active unit
@ -209,7 +209,7 @@ public:
const Stats& GetStats() { return m_Stats; } const Stats& GetStats() { return m_Stats; }
protected: protected:
friend class CVertexBuffer; friend class CVertexBuffer;
friend class CPatchRData; friend class CPatchRData;
friend class CModelRData; friend class CModelRData;
friend class CTransparencyRenderer; friend class CTransparencyRenderer;
@ -268,8 +268,8 @@ protected:
u32 m_ShadowMap; u32 m_ShadowMap;
// width, height of shadow map // width, height of shadow map
u32 m_ShadowMapWidth,m_ShadowMapHeight; u32 m_ShadowMapWidth,m_ShadowMapHeight;
// object space bound of shadow casting objects // object space bound of shadow casting objects
CBound m_ShadowBound; CBound m_ShadowBound;
// per-frame flag: has the shadow map been rendered this frame? // per-frame flag: has the shadow map been rendered this frame?
bool m_ShadowRendered; bool m_ShadowRendered;
// projection matrix of shadow casting light // projection matrix of shadow casting light
@ -295,7 +295,7 @@ protected:
// build card cap bits // build card cap bits
void EnumCaps(); void EnumCaps();
// per-frame renderer stats // per-frame renderer stats
Stats m_Stats; Stats m_Stats;
// active textures on each unit // active textures on each unit
GLuint m_ActiveTextures[MaxTextureUnits]; GLuint m_ActiveTextures[MaxTextureUnits];
}; };

View file

@ -1,11 +1,11 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: TransparencyRenderer.cpp // Name: TransparencyRenderer.cpp
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h" #include "precompiled.h"
#include <algorithm> #include <algorithm>
@ -38,8 +38,8 @@ void CTransparencyRenderer::Sort()
// Render: render all deferred passes; call Sort before using to ensure passes // Render: render all deferred passes; call Sort before using to ensure passes
// are drawn in correct order // are drawn in correct order
void CTransparencyRenderer::Render() void CTransparencyRenderer::Render()
{ {
if (m_Objects.size()==0) return; if (m_Objects.size()==0) return;
// switch on wireframe if we need it // switch on wireframe if we need it
if (g_Renderer.m_ModelRenderMode==WIREFRAME) { if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
@ -63,24 +63,24 @@ void CTransparencyRenderer::Render()
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.975f); glAlphaFunc(GL_GREATER,0.975f);
// render everything with color writes off to setup depth buffer correctly // render everything with color writes off to setup depth buffer correctly
glColorMask(0,0,0,0); glColorMask(0,0,0,0);
RenderObjectsStreams(STREAM_POS|STREAM_UV0); RenderObjectsStreams(STREAM_POS|STREAM_UV0);
glColorMask(1,1,1,1); glColorMask(1,1,1,1);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(0); glDepthMask(0);
glAlphaFunc(GL_GREATER,0); glAlphaFunc(GL_GREATER,0);
// setup texture environment to modulate diffuse color with texture color // setup texture environment to modulate diffuse color with texture color
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0); RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0);
@ -155,8 +155,8 @@ void CTransparencyRenderer::Add(CModel* model)
void CTransparencyRenderer::RenderShadows() void CTransparencyRenderer::RenderShadows()
{ {
if (m_Objects.size()==0) return; if (m_Objects.size()==0) return;
// switch on client states // switch on client states
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -174,7 +174,7 @@ void CTransparencyRenderer::RenderShadows()
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
RenderObjectsStreams(STREAM_POS|STREAM_UV0); RenderObjectsStreams(STREAM_POS|STREAM_UV0);
glDepthMask(1); glDepthMask(1);
glDisable(GL_BLEND); glDisable(GL_BLEND);

View file

@ -1,11 +1,11 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: TransparencyRenderer.h // Name: TransparencyRenderer.h
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef __TRANSPARENCYRENDERER_H #ifndef __TRANSPARENCYRENDERER_H
#define __TRANSPARENCYRENDERER_H #define __TRANSPARENCYRENDERER_H

View file

@ -1,184 +1,185 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: VertexBuffer.cpp // Name: VertexBuffer.cpp
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include "ogl.h" #include "precompiled.h"
#include "Renderer.h" #include "ogl.h"
#include "VertexBuffer.h" #include "Renderer.h"
#include "VertexBuffer.h"
///////////////////////////////////////////////////////////////////////////////
// shared list of all free batch objects ///////////////////////////////////////////////////////////////////////////////
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches; // shared list of all free batch objects
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches;
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer constructor ///////////////////////////////////////////////////////////////////////////////
CVertexBuffer::CVertexBuffer(size_t vertexSize,bool dynamic) // CVertexBuffer constructor
: m_VertexSize(vertexSize), m_Dynamic(dynamic), m_SysMem(0), m_Handle(0) CVertexBuffer::CVertexBuffer(size_t vertexSize,bool dynamic)
{ : m_VertexSize(vertexSize), m_Dynamic(dynamic), m_SysMem(0), m_Handle(0)
// store max/free vertex counts {
m_MaxVertices=m_FreeVertices=MAX_VB_SIZE_BYTES/vertexSize; // store max/free vertex counts
m_MaxVertices=m_FreeVertices=MAX_VB_SIZE_BYTES/vertexSize;
// allocate raw buffer
if (g_Renderer.m_Caps.m_VBO) { // allocate raw buffer
glGenBuffersARB(1,&m_Handle); if (g_Renderer.m_Caps.m_VBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle); glGenBuffersARB(1,&m_Handle);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
} else { glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
m_SysMem=new u8[MAX_VB_SIZE_BYTES]; } else {
} m_SysMem=new u8[MAX_VB_SIZE_BYTES];
}
// create sole free chunk
VBChunk* chunk=new VBChunk; // create sole free chunk
chunk->m_Owner=this; VBChunk* chunk=new VBChunk;
chunk->m_Count=m_FreeVertices; chunk->m_Owner=this;
chunk->m_Index=0; chunk->m_Count=m_FreeVertices;
m_FreeList.push_front(chunk); chunk->m_Index=0;
} m_FreeList.push_front(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer destructor ///////////////////////////////////////////////////////////////////////////////
CVertexBuffer::~CVertexBuffer() // CVertexBuffer destructor
{ CVertexBuffer::~CVertexBuffer()
if (m_Handle) { {
glDeleteBuffersARB(1,&m_Handle); if (m_Handle) {
} else if (m_SysMem) { glDeleteBuffersARB(1,&m_Handle);
delete[] m_SysMem; } else if (m_SysMem) {
} delete[] m_SysMem;
} }
}
///////////////////////////////////////////////////////////////////////////////
// Allocate: try to allocate a buffer of given number of vertices (each of ///////////////////////////////////////////////////////////////////////////////
// given size), with the given type, and using the given texture - return null // Allocate: try to allocate a buffer of given number of vertices (each of
// if no free chunks available // given size), with the given type, and using the given texture - return null
CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize,size_t numVertices,bool dynamic) // if no free chunks available
{ CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
// check this is the right kind of buffer {
if (dynamic!=m_Dynamic || vertexSize!=m_VertexSize) return 0; // check this is the right kind of buffer
if (dynamic!=m_Dynamic || vertexSize!=m_VertexSize) return 0;
// quick check there's enough vertices spare to allocate
if (numVertices>m_FreeVertices) return 0; // quick check there's enough vertices spare to allocate
if (numVertices>m_FreeVertices) return 0;
// trawl free list looking for first free chunk with enough space
VBChunk* chunk=0; // trawl free list looking for first free chunk with enough space
typedef std::list<VBChunk*>::iterator Iter; VBChunk* chunk=0;
for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) { typedef std::list<VBChunk*>::iterator Iter;
chunk=*iter; for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) {
if (numVertices<=chunk->m_Count) { chunk=*iter;
// remove this chunk from the free list if (numVertices<=chunk->m_Count) {
size_t size1=m_FreeList.size(); // remove this chunk from the free list
m_FreeList.erase(iter); size_t size1=m_FreeList.size();
size_t size2=m_FreeList.size(); m_FreeList.erase(iter);
// no need to search further .. size_t size2=m_FreeList.size();
break; // no need to search further ..
} break;
} }
}
if (!chunk) {
// no big enough spare chunk available if (!chunk) {
return 0; // no big enough spare chunk available
} return 0;
}
// split chunk into two; - allocate a new chunk using all unused vertices in the
// found chunk, and add it to the free list // split chunk into two; - allocate a new chunk using all unused vertices in the
VBChunk* newchunk=new VBChunk; // found chunk, and add it to the free list
newchunk->m_Owner=this; VBChunk* newchunk=new VBChunk;
newchunk->m_Count=chunk->m_Count-numVertices; newchunk->m_Owner=this;
newchunk->m_Index=chunk->m_Index+numVertices; newchunk->m_Count=chunk->m_Count-numVertices;
m_FreeList.push_front(newchunk); newchunk->m_Index=chunk->m_Index+numVertices;
m_FreeList.push_front(newchunk);
// resize given chunk, resize total available free vertices
chunk->m_Count=numVertices; // resize given chunk, resize total available free vertices
m_FreeVertices-=numVertices; chunk->m_Count=numVertices;
m_FreeVertices-=numVertices;
// return found chunk
return chunk; // return found chunk
} return chunk;
}
///////////////////////////////////////////////////////////////////////////////
// Release: return given chunk to this buffer ///////////////////////////////////////////////////////////////////////////////
void CVertexBuffer::Release(VBChunk* chunk) // Release: return given chunk to this buffer
{ void CVertexBuffer::Release(VBChunk* chunk)
// add to free list {
// TODO, RC - need to merge available chunks where possible to avoid // add to free list
// excessive fragmentation of vertex buffer space // TODO, RC - need to merge available chunks where possible to avoid
m_FreeList.push_front(chunk); // excessive fragmentation of vertex buffer space
m_FreeVertices+=chunk->m_Count; m_FreeList.push_front(chunk);
} m_FreeVertices+=chunk->m_Count;
}
///////////////////////////////////////////////////////////////////////////////
// ClearBatchIndices: clear lists of all batches ///////////////////////////////////////////////////////////////////////////////
void CVertexBuffer::ClearBatchIndices() // ClearBatchIndices: clear lists of all batches
{ void CVertexBuffer::ClearBatchIndices()
for (uint i=0;i<m_Batches.size();i++) { {
m_Batches[i]->m_IndexData.clear(); for (uint i=0;i<m_Batches.size();i++) {
m_FreeBatches.push_back(m_Batches[i]); m_Batches[i]->m_IndexData.clear();
} m_FreeBatches.push_back(m_Batches[i]);
m_Batches.clear(); }
} m_Batches.clear();
}
///////////////////////////////////////////////////////////////////////////////
// AppendBatch: add a batch to the render list for this buffer ///////////////////////////////////////////////////////////////////////////////
void CVertexBuffer::AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices) // AppendBatch: add a batch to the render list for this buffer
{ void CVertexBuffer::AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices)
// try and find a batch using this texture {
size_t i; // try and find a batch using this texture
Batch* batch=0; size_t i;
for (i=0;i<m_Batches.size();++i) { Batch* batch=0;
if (m_Batches[i]->m_Texture==texture) { for (i=0;i<m_Batches.size();++i) {
batch=m_Batches[i]; if (m_Batches[i]->m_Texture==texture) {
break; batch=m_Batches[i];
} break;
} }
if (!batch) { }
if (m_FreeBatches.size()) { if (!batch) {
batch=m_FreeBatches.back(); if (m_FreeBatches.size()) {
m_FreeBatches.pop_back(); batch=m_FreeBatches.back();
} else { m_FreeBatches.pop_back();
batch=new Batch; } else {
} batch=new Batch;
m_Batches.push_back(batch); }
batch->m_Texture=texture; m_Batches.push_back(batch);
} batch->m_Texture=texture;
}
// resize the chunk's batch to fit it's indices
size_t cursize=batch->m_IndexData.size(); // resize the chunk's batch to fit it's indices
batch->m_IndexData.resize(cursize+1); size_t cursize=batch->m_IndexData.size();
// store batch batch->m_IndexData.resize(cursize+1);
batch->m_IndexData[cursize]=std::pair<size_t,u16*>(numIndices,indices); // store batch
// memcpy(&batch->m_Indices[0]+cursize,indices,sizeof(u16)*numIndices); batch->m_IndexData[cursize]=std::pair<size_t,u16*>(numIndices,indices);
} // memcpy(&batch->m_Indices[0]+cursize,indices,sizeof(u16)*numIndices);
}
///////////////////////////////////////////////////////////////////////////////
// UpdateChunkVertices: update vertex data for given chunk ///////////////////////////////////////////////////////////////////////////////
void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk,void* data) // UpdateChunkVertices: update vertex data for given chunk
{ void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk,void* data)
if (g_Renderer.m_Caps.m_VBO) { {
assert(m_Handle); if (g_Renderer.m_Caps.m_VBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle); assert(m_Handle);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data); glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
} else { glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data);
assert(m_SysMem); } else {
memcpy(m_SysMem+chunk->m_Index*m_VertexSize,data,chunk->m_Count*m_VertexSize); assert(m_SysMem);
} memcpy(m_SysMem+chunk->m_Index*m_VertexSize,data,chunk->m_Count*m_VertexSize);
} }
}
///////////////////////////////////////////////////////////////////////////////
// Bind: bind to this buffer; return pointer to address required as parameter ///////////////////////////////////////////////////////////////////////////////
// to glVertexPointer ( + etc) calls // Bind: bind to this buffer; return pointer to address required as parameter
u8* CVertexBuffer::Bind() // to glVertexPointer ( + etc) calls
{ u8* CVertexBuffer::Bind()
u8* base; {
if (g_Renderer.m_Caps.m_VBO) { u8* base;
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle); if (g_Renderer.m_Caps.m_VBO) {
base=(u8*) 0; glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
} else { base=(u8*) 0;
base=(u8*) m_SysMem; } else {
} base=(u8*) m_SysMem;
return base; }
return base;
} }

View file

@ -1,100 +1,100 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: VertexBuffer.h // Name: VertexBuffer.h
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef _VERTEXBUFFER_H #ifndef _VERTEXBUFFER_H
#define _VERTEXBUFFER_H #define _VERTEXBUFFER_H
#include "lib.h" #include "lib.h"
#include "res/tex.h" #include "res/tex.h"
#include <list> #include <list>
#include <vector> #include <vector>
// absolute maximum (bytewise) size of each GL vertex buffer object // absolute maximum (bytewise) size of each GL vertex buffer object
#define MAX_VB_SIZE_BYTES (32*8192) #define MAX_VB_SIZE_BYTES (32*8192)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying // CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying
// some additional functionality for batching and sharing buffers between // some additional functionality for batching and sharing buffers between
// multiple objects // multiple objects
class CVertexBuffer class CVertexBuffer
{ {
public: public:
// Batch: batch definition - defines indices into the VB to use when rendering, // Batch: batch definition - defines indices into the VB to use when rendering,
// and the texture used when doing so // and the texture used when doing so
struct Batch { struct Batch {
// list of indices into the vertex buffer of primitives within the batch // list of indices into the vertex buffer of primitives within the batch
std::vector<std::pair<size_t,u16*> > m_IndexData; std::vector<std::pair<size_t,u16*> > m_IndexData;
// texture to apply when rendering batch // texture to apply when rendering batch
Handle m_Texture; Handle m_Texture;
}; };
// VBChunk: describes a portion of this vertex buffer // VBChunk: describes a portion of this vertex buffer
struct VBChunk struct VBChunk
{ {
// owning buffer // owning buffer
CVertexBuffer* m_Owner; CVertexBuffer* m_Owner;
// start index of this chunk in owner // start index of this chunk in owner
size_t m_Index; size_t m_Index;
// number of vertices used by chunk // number of vertices used by chunk
size_t m_Count; size_t m_Count;
}; };
public: public:
// constructor, destructor // constructor, destructor
CVertexBuffer(size_t vertexSize,bool dynamic); CVertexBuffer(size_t vertexSize,bool dynamic);
~CVertexBuffer(); ~CVertexBuffer();
// bind to this buffer; return pointer to address required as parameter // bind to this buffer; return pointer to address required as parameter
// to glVertexPointer ( + etc) calls // to glVertexPointer ( + etc) calls
u8* Bind(); u8* Bind();
// clear lists of all batches // clear lists of all batches
void ClearBatchIndices(); void ClearBatchIndices();
// add a batch to the render list for this buffer // add a batch to the render list for this buffer
void AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices); void AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices);
// update vertex data for given chunk // update vertex data for given chunk
void UpdateChunkVertices(VBChunk* chunk,void* data); void UpdateChunkVertices(VBChunk* chunk,void* data);
// return this VBs batch list // return this VBs batch list
const std::vector<Batch*>& GetBatches() const { return m_Batches; } const std::vector<Batch*>& GetBatches() const { return m_Batches; }
protected: protected:
friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager
// try to allocate a buffer of given number of vertices (each of given size), // try to allocate a buffer of given number of vertices (each of given size),
// and with the given type - return null if no free chunks available // and with the given type - return null if no free chunks available
VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic); VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
// return given chunk to this buffer // return given chunk to this buffer
void Release(VBChunk* chunk); void Release(VBChunk* chunk);
private: private:
// set of all possible batches that can be used by this VB // set of all possible batches that can be used by this VB
std::vector<Batch*> m_Batches; std::vector<Batch*> m_Batches;
// vertex size of this vertex buffer // vertex size of this vertex buffer
size_t m_VertexSize; size_t m_VertexSize;
// number of vertices of above size in this buffer // number of vertices of above size in this buffer
size_t m_MaxVertices; size_t m_MaxVertices;
// list of free chunks in this buffer // list of free chunks in this buffer
std::list<VBChunk*> m_FreeList; std::list<VBChunk*> m_FreeList;
// available free vertices - total of all free vertices in the free list // available free vertices - total of all free vertices in the free list
size_t m_FreeVertices; size_t m_FreeVertices;
// handle to the actual GL vertex buffer object // handle to the actual GL vertex buffer object
GLuint m_Handle; GLuint m_Handle;
// raw system memory for systems not supporting VBOs // raw system memory for systems not supporting VBOs
u8* m_SysMem; u8* m_SysMem;
// type of the buffer - dynamic? // type of the buffer - dynamic?
bool m_Dynamic; bool m_Dynamic;
// list of all spare batches, shared between all vbs // list of all spare batches, shared between all vbs
static std::vector<Batch*> m_FreeBatches; static std::vector<Batch*> m_FreeBatches;
}; };
#endif #endif

View file

@ -1,64 +1,65 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: VertexBufferManager.cpp // Name: VertexBufferManager.cpp
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include <assert.h> #include "precompiled.h"
#include "ogl.h" #include <assert.h>
#include "VertexBufferManager.h" #include "ogl.h"
#include "VertexBufferManager.h"
CVertexBufferManager g_VBMan;
CVertexBufferManager g_VBMan;
///////////////////////////////////////////////////////////////////////////////
// Allocate: try to allocate a buffer of given number of vertices (each of ///////////////////////////////////////////////////////////////////////////////
// given size), with the given type, and using the given texture - return null // Allocate: try to allocate a buffer of given number of vertices (each of
// if no free chunks available // given size), with the given type, and using the given texture - return null
CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic) // if no free chunks available
{ CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
CVertexBuffer::VBChunk* result=0; {
CVertexBuffer::VBChunk* result=0;
// TODO, RC - run some sanity checks on allocation request
// TODO, RC - run some sanity checks on allocation request
// iterate through all existing buffers testing for one that'll
// satisfy the allocation // iterate through all existing buffers testing for one that'll
typedef std::list<CVertexBuffer*>::iterator Iter; // satisfy the allocation
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) { typedef std::list<CVertexBuffer*>::iterator Iter;
CVertexBuffer* buffer=*iter; for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
result=buffer->Allocate(vertexSize,numVertices,dynamic); CVertexBuffer* buffer=*iter;
if (result) return result; result=buffer->Allocate(vertexSize,numVertices,dynamic);
} if (result) return result;
}
// got this far; need to allocate a new buffer
CVertexBuffer* buffer=new CVertexBuffer(vertexSize,dynamic); // got this far; need to allocate a new buffer
m_Buffers.push_front(buffer); CVertexBuffer* buffer=new CVertexBuffer(vertexSize,dynamic);
result=buffer->Allocate(vertexSize,numVertices,dynamic); m_Buffers.push_front(buffer);
result=buffer->Allocate(vertexSize,numVertices,dynamic);
// TODO, RC - assert not really suitable? probably need to handle "failed to create
// VBO case" better // TODO, RC - assert not really suitable? probably need to handle "failed to create
assert(result); // VBO case" better
assert(result);
return result;
} return result;
}
///////////////////////////////////////////////////////////////////////////////
// Release: return given chunk to it's owner ///////////////////////////////////////////////////////////////////////////////
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk) // Release: return given chunk to it's owner
{ void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
assert(chunk); {
chunk->m_Owner->Release(chunk); assert(chunk);
} chunk->m_Owner->Release(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// ClearBatchIndices: empty out the batch lists of all vertex buffers ///////////////////////////////////////////////////////////////////////////////
void CVertexBufferManager::ClearBatchIndices() // ClearBatchIndices: empty out the batch lists of all vertex buffers
{ void CVertexBufferManager::ClearBatchIndices()
typedef std::list<CVertexBuffer*>::iterator Iter; {
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) { typedef std::list<CVertexBuffer*>::iterator Iter;
CVertexBuffer* buffer=*iter; for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
buffer->ClearBatchIndices(); CVertexBuffer* buffer=*iter;
} buffer->ClearBatchIndices();
}
} }

View file

@ -1,41 +1,41 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// Name: VertexBufferManager.h // Name: VertexBufferManager.h
// Author: Rich Cross // Author: Rich Cross
// Contact: rich@wildfiregames.com // Contact: rich@wildfiregames.com
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#ifndef _VERTEXBUFFERMANAGER_H #ifndef _VERTEXBUFFERMANAGER_H
#define _VERTEXBUFFERMANAGER_H #define _VERTEXBUFFERMANAGER_H
#include "VertexBuffer.h" #include "VertexBuffer.h"
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CVertexBufferManager: owner object for CVertexBuffer objects; acts as // CVertexBufferManager: owner object for CVertexBuffer objects; acts as
// 'front end' for their allocation and destruction // 'front end' for their allocation and destruction
class CVertexBufferManager class CVertexBufferManager
{ {
public: public:
// try to allocate a buffer of given number of vertices (each of given size), // try to allocate a buffer of given number of vertices (each of given size),
// and with the given type - return null if no free chunks available // and with the given type - return null if no free chunks available
CVertexBuffer::VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic); CVertexBuffer::VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
// return given chunk to it's owner // return given chunk to it's owner
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk); void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk);
// empty out the batch lists of all vertex buffers // empty out the batch lists of all vertex buffers
void ClearBatchIndices(); void ClearBatchIndices();
// return list of all buffers // return list of all buffers
const std::list<CVertexBuffer*>& GetBufferList() const { return m_Buffers; } const std::list<CVertexBuffer*>& GetBufferList() const { return m_Buffers; }
private: private:
// list of all known vertex buffers // list of all known vertex buffers
std::list<CVertexBuffer*> m_Buffers; std::list<CVertexBuffer*> m_Buffers;
}; };
extern CVertexBufferManager g_VBMan; extern CVertexBufferManager g_VBMan;
#endif #endif

View file

@ -1,9 +1,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "ogl.h" #include "ogl.h"
#include "Renderer.h" #include "Renderer.h"
#include "BrushShapeEditorTool.h" #include "BrushShapeEditorTool.h"
// default tool instance // default tool instance
CBrushShapeEditorTool CBrushShapeEditorTool::m_BrushShapeEditorTool; CBrushShapeEditorTool CBrushShapeEditorTool::m_BrushShapeEditorTool;

View file

@ -53,7 +53,7 @@ static void RenderTileOutline(int gx,int gz)
void CBrushTool::OnDraw() void CBrushTool::OnDraw()
{ {
g_Renderer.SetTexture(0,0); g_Renderer.SetTexture(0,0);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

File diff suppressed because it is too large Load diff

View file

@ -6,67 +6,67 @@
#include "ogl.h" #include "ogl.h"
extern CTerrain g_Terrain; extern CTerrain g_Terrain;
struct TGAHeader { struct TGAHeader {
// header stuff // header stuff
unsigned char iif_size; unsigned char iif_size;
unsigned char cmap_type; unsigned char cmap_type;
unsigned char image_type; unsigned char image_type;
unsigned char pad[5]; unsigned char pad[5];
// origin : unused // origin : unused
unsigned short d_x_origin; unsigned short d_x_origin;
unsigned short d_y_origin; unsigned short d_y_origin;
// dimensions // dimensions
unsigned short width; unsigned short width;
unsigned short height; unsigned short height;
// bits per pixel : 16, 24 or 32 // bits per pixel : 16, 24 or 32
unsigned char bpp; unsigned char bpp;
// image descriptor : Bits 3-0: size of alpha channel // image descriptor : Bits 3-0: size of alpha channel
// Bit 4: must be 0 (reserved) // Bit 4: must be 0 (reserved)
// Bit 5: should be 0 (origin) // Bit 5: should be 0 (origin)
// Bits 6-7: should be 0 (interleaving) // Bits 6-7: should be 0 (interleaving)
unsigned char image_descriptor; unsigned char image_descriptor;
}; };
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data) static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
{ {
FILE* fp=fopen(filename,"wb"); FILE* fp=fopen(filename,"wb");
if (!fp) return false; if (!fp) return false;
// fill file header // fill file header
TGAHeader header; TGAHeader header;
header.iif_size=0; header.iif_size=0;
header.cmap_type=0; header.cmap_type=0;
header.image_type=2; header.image_type=2;
memset(header.pad,0,sizeof(header.pad)); memset(header.pad,0,sizeof(header.pad));
header.d_x_origin=0; header.d_x_origin=0;
header.d_y_origin=0; header.d_y_origin=0;
header.width=width; header.width=width;
header.height=height; header.height=height;
header.bpp=bpp; header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0; header.image_descriptor=(bpp==32) ? 8 : 0;
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) { if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
fclose(fp); fclose(fp);
return false; return false;
} }
// write data // write data
if (fwrite(data,width*height*bpp/8,1,fp)!=1) { if (fwrite(data,width*height*bpp/8,1,fp)!=1) {
fclose(fp); fclose(fp);
return false; return false;
} }
// return success .. // return success ..
fclose(fp); fclose(fp);
return true; return true;
} }
static unsigned int ScaleColor(unsigned int color,float x) static unsigned int ScaleColor(unsigned int color,float x)
{ {
@ -94,7 +94,7 @@ void CMiniMap::Initialise()
{ {
// get rid of existing texture, if we've got one // get rid of existing texture, if we've got one
if (m_Handle) { if (m_Handle) {
glDeleteTextures(1,(GLuint*) &m_Handle); glDeleteTextures(1,(GLuint*) &m_Handle);
delete[] m_Data; delete[] m_Data;
} }
@ -103,12 +103,12 @@ void CMiniMap::Initialise()
g_Renderer.BindTexture(0,m_Handle); g_Renderer.BindTexture(0,m_Handle);
// allocate an image big enough to fit the entire map into // allocate an image big enough to fit the entire map into
m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide()); m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide());
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_Size,m_Size,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,0); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_Size,m_Size,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,0);
// allocate local copy // allocate local copy
m_Data=new u32[(mapSize-1)*(mapSize-1)]; m_Data=new u32[(mapSize-1)*(mapSize-1)];
// set texture parameters // set texture parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
@ -139,7 +139,7 @@ void CMiniMap::Render()
int h=g_Renderer.GetHeight(); int h=g_Renderer.GetHeight();
glOrtho(0,w,0,h,-1,1); glOrtho(0,w,0,h,-1,1);
// bind to the minimap // bind to the minimap
g_Renderer.BindTexture(0,m_Handle); g_Renderer.BindTexture(0,m_Handle);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
@ -207,18 +207,18 @@ void CMiniMap::Update(int x,int y,unsigned int color)
int val=(hmap/3)+170; int val=(hmap/3)+170;
// get modulated color // get modulated color
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
*(m_Data+(y*(mapSize-1)+x))=ScaleColor(color,float(val)/255.0f); *(m_Data+(y*(mapSize-1)+x))=ScaleColor(color,float(val)/255.0f);
UpdateTexture(); UpdateTexture();
} }
void CMiniMap::Update(int x,int y,int w,int h,unsigned int color) void CMiniMap::Update(int x,int y,int w,int h,unsigned int color)
{ {
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
for (int j=0;j<h;j++) { for (int j=0;j<h;j++) {
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x; u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
for (int i=0;i<w;i++) { for (int i=0;i<w;i++) {
// get height at this pixel // get height at this pixel
int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8; int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8;
@ -228,33 +228,33 @@ void CMiniMap::Update(int x,int y,int w,int h,unsigned int color)
*dataptr++=ScaleColor(color,float(val)/255.0f); *dataptr++=ScaleColor(color,float(val)/255.0f);
} }
} }
UpdateTexture(); UpdateTexture();
} }
void CMiniMap::Rebuild() void CMiniMap::Rebuild()
{ {
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
Rebuild(0,0,mapSize-1,mapSize-1); Rebuild(0,0,mapSize-1,mapSize-1);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UpdateTexture: send data to GL; update stored texture data // UpdateTexture: send data to GL; update stored texture data
void CMiniMap::UpdateTexture() void CMiniMap::UpdateTexture()
{ {
// bind to the minimap // bind to the minimap
g_Renderer.BindTexture(0,m_Handle); g_Renderer.BindTexture(0,m_Handle);
// subimage to update pixels // subimage to update pixels
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data);
} }
void CMiniMap::Rebuild(int x,int y,int w,int h) void CMiniMap::Rebuild(int x,int y,int w,int h)
{ {
u32 mapSize=g_Terrain.GetVerticesPerSide(); u32 mapSize=g_Terrain.GetVerticesPerSide();
for (int j=0;j<h;j++) { for (int j=0;j<h;j++) {
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x; u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
for (int i=0;i<w;i++) { for (int i=0;i<w;i++) {
// get height at this pixel // get height at this pixel
int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8; int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8;
@ -276,6 +276,6 @@ void CMiniMap::Rebuild(int x,int y,int w,int h)
*dataptr++=ScaleColor(color,float(val)/255.0f); *dataptr++=ScaleColor(color,float(val)/255.0f);
} }
} }
UpdateTexture(); UpdateTexture();
} }

View file

@ -1,7 +1,7 @@
#ifndef _MINIMAP_H #ifndef _MINIMAP_H
#define _MINIMAP_H #define _MINIMAP_H
#include "lib.h" #include "lib.h"
class CMiniMap class CMiniMap
{ {
@ -18,14 +18,14 @@ public:
// current viewing frustum, in minimap coordinate space // current viewing frustum, in minimap coordinate space
float m_ViewRect[4][2]; float m_ViewRect[4][2];
private: private:
// send data to GL; update stored texture data // send data to GL; update stored texture data
void UpdateTexture(); void UpdateTexture();
// texture handle // texture handle
u32 m_Handle; u32 m_Handle;
// size of the map texture // size of the map texture
u32 m_Size; u32 m_Size;
// raw BGRA_EXT data for the minimap // raw BGRA_EXT data for the minimap
u32* m_Data; u32* m_Data;
}; };

View file

@ -1,7 +1,7 @@
#ifndef _RAISEELEVATIONTOOL_H #ifndef _RAISEELEVATIONTOOL_H
#define _RAISEELEVATIONTOOL_H #define _RAISEELEVATIONTOOL_H
#include <set> #include <set>
#include "lib.h" #include "lib.h"
#include "res/res.h" #include "res/res.h"
#include "BrushTool.h" #include "BrushTool.h"

View file

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#define _IGNORE_WGL_H_ #define _IGNORE_WGL_H_
#include "MainFrm.h" #include "MainFrm.h"
#include "EditorData.h" #include "EditorData.h"
#include "BrushShapeEditorTool.h" #include "BrushShapeEditorTool.h"

View file

@ -15,14 +15,14 @@ inline void ColorRefToRGBColor(COLORREF c,RGBColor& result)
result.Y=((c>>8) & 0xff)/255.0f; result.Y=((c>>8) & 0xff)/255.0f;
result.Z=((c>>16) & 0xff)/255.0f; result.Z=((c>>16) & 0xff)/255.0f;
} }
inline void ColorRefToRGBAColor(COLORREF c,BYTE alpha,RGBAColor& result) inline void ColorRefToRGBAColor(COLORREF c,BYTE alpha,RGBAColor& result)
{ {
result[0]=(c & 0xff)/255.0f; result[0]=(c & 0xff)/255.0f;
result[1]=((c>>8) & 0xff)/255.0f; result[1]=((c>>8) & 0xff)/255.0f;
result[2]=((c>>16) & 0xff)/255.0f; result[2]=((c>>16) & 0xff)/255.0f;
result[3]=alpha/255.0f; result[3]=alpha/255.0f;
} }
inline void RGBColorToColorRef(const RGBColor& c,COLORREF& result) inline void RGBColorToColorRef(const RGBColor& c,COLORREF& result)
{ {
@ -40,27 +40,27 @@ inline void RGBColorToColorRef(const RGBColor& c,COLORREF& result)
result=r | (g<<8) | (b<<16); result=r | (g<<8) | (b<<16);
} }
inline void RGBAColorToColorRef(const RGBAColor& c,COLORREF& result) inline void RGBAColorToColorRef(const RGBAColor& c,COLORREF& result)
{ {
int r=int(c[0]*255); int r=int(c[0]*255);
if (r<0) r=0; if (r<0) r=0;
if (r>255) r=255; if (r>255) r=255;
int g=int(c[1]*255); int g=int(c[1]*255);
if (g<0) g=0; if (g<0) g=0;
if (g>255) g=255; if (g>255) g=255;
int b=int(c[2]*255); int b=int(c[2]*255);
if (b<0) b=0; if (b<0) b=0;
if (b>255) b=255; if (b>255) b=255;
int a=int(c[3]*255); int a=int(c[3]*255);
if (a<0) a=0; if (a<0) a=0;
if (a>255) a=255; if (a>255) a=255;
result=r | (g<<8) | (b<<16) | (a<<24); result=r | (g<<8) | (b<<16) | (a<<24);
} }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// CColorButton window // CColorButton window

View file

@ -1,4 +1,4 @@
#include <assert.h> #include <assert.h>
#include "stdafx.h" #include "stdafx.h"
#include "ToolManager.h" #include "ToolManager.h"
#include "ElevToolsDlgBar.h" #include "ElevToolsDlgBar.h"

View file

@ -2,13 +2,13 @@
// //
#include "stdafx.h" #include "stdafx.h"
#define _IGNORE_WGL_H_ #define _IGNORE_WGL_H_
#include "ogl.h" #include "ogl.h"
#include "res/tex.h" #include "res/tex.h"
#include "res/mem.h" #include "res/mem.h"
#include "res/vfs.h" #include "res/vfs.h"
#undef _IGNORE_WGL_H_ #undef _IGNORE_WGL_H_
#include "ScEd.h" #include "ScEd.h"
#include "ScEdView.h" #include "ScEdView.h"
@ -20,8 +20,8 @@
#include "Unit.h" #include "Unit.h"
#include "UnitManager.h" #include "UnitManager.h"
#include "ObjectManager.h" #include "ObjectManager.h"
#include "TextureManager.h" #include "TextureManager.h"
#include "UIGlobals.h" #include "UIGlobals.h"
#include "MainFrm.h" #include "MainFrm.h"
#include "OptionsPropSheet.h" #include "OptionsPropSheet.h"
@ -57,14 +57,14 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_COMMAND(ID_LIGHTING_SETTINGS, OnLightingSettings) ON_COMMAND(ID_LIGHTING_SETTINGS, OnLightingSettings)
ON_COMMAND(ID_VIEW_SCREENSHOT, OnViewScreenshot) ON_COMMAND(ID_VIEW_SCREENSHOT, OnViewScreenshot)
ON_COMMAND(IDR_TEXTURE_TOOLS, OnTextureTools) ON_COMMAND(IDR_TEXTURE_TOOLS, OnTextureTools)
ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions) ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
ON_COMMAND(ID_EDIT_REDO, OnEditRedo) ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo) ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
ON_COMMAND(IDR_ELEVATION_TOOLS, OnElevationTools) ON_COMMAND(IDR_ELEVATION_TOOLS, OnElevationTools)
ON_COMMAND(IDR_RESIZE_MAP, OnResizeMap) ON_COMMAND(IDR_RESIZE_MAP, OnResizeMap)
ON_COMMAND(ID_VIEW_TERRAIN_GRID, OnViewTerrainGrid) ON_COMMAND(ID_VIEW_TERRAIN_GRID, OnViewTerrainGrid)
ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_GRID, OnUpdateViewTerrainGrid) ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_GRID, OnUpdateViewTerrainGrid)
ON_COMMAND(ID_VIEW_TERRAIN_SOLID, OnViewTerrainSolid) ON_COMMAND(ID_VIEW_TERRAIN_SOLID, OnViewTerrainSolid)
ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_SOLID, OnUpdateViewTerrainSolid) ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_SOLID, OnUpdateViewTerrainSolid)
@ -86,8 +86,8 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_COMMAND(ID_TEST_STOP, OnTestStop) ON_COMMAND(ID_TEST_STOP, OnTestStop)
ON_UPDATE_COMMAND_UI(ID_TEST_STOP, OnUpdateTestStop) ON_UPDATE_COMMAND_UI(ID_TEST_STOP, OnUpdateTestStop)
ON_COMMAND(IDR_UNIT_TOOLS, OnUnitTools) ON_COMMAND(IDR_UNIT_TOOLS, OnUnitTools)
ON_COMMAND(ID_RANDOM_MAP, OnRandomMap) ON_COMMAND(ID_RANDOM_MAP, OnRandomMap)
//}}AFX_MSG_MAP //}}AFX_MSG_MAP
END_MESSAGE_MAP() END_MESSAGE_MAP()
static UINT indicators[] = static UINT indicators[] =
@ -722,127 +722,127 @@ void CMainFrame::OnUpdateTestStop(CCmdUI* pCmdUI)
else else
pCmdUI->Enable(FALSE); pCmdUI->Enable(FALSE);
} }
static float getExactGroundLevel( float x, float y ) static float getExactGroundLevel( float x, float y )
{ {
// TODO MT: If OK with Rich, move to terrain core. Once this works, that is. // TODO MT: If OK with Rich, move to terrain core. Once this works, that is.
x /= 4.0f; x /= 4.0f;
y /= 4.0f; y /= 4.0f;
int xi = (int)floor( x ); int xi = (int)floor( x );
int yi = (int)floor( y ); int yi = (int)floor( y );
float xf = x - (float)xi; float xf = x - (float)xi;
float yf = y - (float)yi; float yf = y - (float)yi;
u16* heightmap = g_Terrain.GetHeightMap(); u16* heightmap = g_Terrain.GetHeightMap();
unsigned long mapsize = g_Terrain.GetVerticesPerSide(); unsigned long mapsize = g_Terrain.GetVerticesPerSide();
float h00 = heightmap[yi*mapsize + xi]; float h00 = heightmap[yi*mapsize + xi];
float h01 = heightmap[yi*mapsize + xi + mapsize]; float h01 = heightmap[yi*mapsize + xi + mapsize];
float h10 = heightmap[yi*mapsize + xi + 1]; float h10 = heightmap[yi*mapsize + xi + 1];
float h11 = heightmap[yi*mapsize + xi + mapsize + 1]; float h11 = heightmap[yi*mapsize + xi + mapsize + 1];
/* /*
if( xf < ( 1.0f - yf ) ) if( xf < ( 1.0f - yf ) )
{ {
return( HEIGHT_SCALE * ( ( 1 - xf - yf ) * h00 + xf * h10 + yf * h01 ) ); return( HEIGHT_SCALE * ( ( 1 - xf - yf ) * h00 + xf * h10 + yf * h01 ) );
} }
else else
return( HEIGHT_SCALE * ( ( xf + yf - 1 ) * h11 + ( 1 - xf ) * h01 + ( 1 - yf ) * h10 ) ); return( HEIGHT_SCALE * ( ( xf + yf - 1 ) * h11 + ( 1 - xf ) * h01 + ( 1 - yf ) * h10 ) );
*/ */
/* /*
if( xf > yf ) if( xf > yf )
{ {
return( HEIGHT_SCALE * ( ( 1 - xf ) * h00 + ( xf - yf ) * h10 + yf * h11 ) ); return( HEIGHT_SCALE * ( ( 1 - xf ) * h00 + ( xf - yf ) * h10 + yf * h11 ) );
} }
else else
return( HEIGHT_SCALE * ( ( 1 - yf ) * h00 + ( yf - xf ) * h01 + xf * h11 ) ); return( HEIGHT_SCALE * ( ( 1 - yf ) * h00 + ( yf - xf ) * h01 + xf * h11 ) );
*/ */
return( HEIGHT_SCALE * ( ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ) ); return( HEIGHT_SCALE * ( ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ) );
} }
static CObjectEntry* GetRandomActorTemplate() static CObjectEntry* GetRandomActorTemplate()
{ {
if (g_ObjMan.m_ObjectTypes.size()==0) return 0; if (g_ObjMan.m_ObjectTypes.size()==0) return 0;
CObjectEntry* found=0; CObjectEntry* found=0;
int checkloop=250; int checkloop=250;
do { do {
u32 type=rand()%g_ObjMan.m_ObjectTypes.size(); u32 type=rand()%g_ObjMan.m_ObjectTypes.size();
u32 actorsoftype=g_ObjMan.m_ObjectTypes[type].m_Objects.size(); u32 actorsoftype=g_ObjMan.m_ObjectTypes[type].m_Objects.size();
if (actorsoftype>0) { if (actorsoftype>0) {
found=g_ObjMan.m_ObjectTypes[type].m_Objects[rand()%actorsoftype]; found=g_ObjMan.m_ObjectTypes[type].m_Objects[rand()%actorsoftype];
if (found && found->m_Model && found->m_Model->GetModelDef()->GetNumBones()>0) { if (found && found->m_Model && found->m_Model->GetModelDef()->GetNumBones()>0) {
} else { } else {
found=0; found=0;
} }
} }
} while (--checkloop && !found); } while (--checkloop && !found);
return found; return found;
} }
static CTextureEntry* GetRandomTexture() static CTextureEntry* GetRandomTexture()
{ {
if (g_TexMan.m_TerrainTextures.size()==0) return 0; if (g_TexMan.m_TerrainTextures.size()==0) return 0;
CTextureEntry* found=0; CTextureEntry* found=0;
do { do {
u32 type=rand()%g_TexMan.m_TerrainTextures.size(); u32 type=rand()%g_TexMan.m_TerrainTextures.size();
u32 texturesoftype=g_TexMan.m_TerrainTextures[type].m_Textures.size(); u32 texturesoftype=g_TexMan.m_TerrainTextures[type].m_Textures.size();
if (texturesoftype>0) { if (texturesoftype>0) {
found=g_TexMan.m_TerrainTextures[type].m_Textures[rand()%texturesoftype]; found=g_TexMan.m_TerrainTextures[type].m_Textures[rand()%texturesoftype];
} }
} while (!found); } while (!found);
return found; return found;
} }
void CMainFrame::OnRandomMap() void CMainFrame::OnRandomMap()
{ {
const u32 count=5000; const u32 count=5000;
const u32 unitsPerDir=u32(sqrt(float(count))); const u32 unitsPerDir=u32(sqrt(float(count)));
u32 i,j; u32 i,j;
u32 vsize=g_Terrain.GetVerticesPerSide()-1; u32 vsize=g_Terrain.GetVerticesPerSide()-1;
for (i=0;i<unitsPerDir;i++) { for (i=0;i<unitsPerDir;i++) {
for (j=0;j<unitsPerDir;j++) { for (j=0;j<unitsPerDir;j++) {
// float x=CELL_SIZE*vsize*float(i+1)/float(unitsPerDir+1); // float x=CELL_SIZE*vsize*float(i+1)/float(unitsPerDir+1);
// float z=CELL_SIZE*vsize*float(j+1)/float(unitsPerDir+1); // float z=CELL_SIZE*vsize*float(j+1)/float(unitsPerDir+1);
float dx=float(rand())/float(RAND_MAX); float dx=float(rand())/float(RAND_MAX);
float x=CELL_SIZE*vsize*dx; float x=CELL_SIZE*vsize*dx;
float dz=float(rand())/float(RAND_MAX); float dz=float(rand())/float(RAND_MAX);
float z=CELL_SIZE*vsize*dz; float z=CELL_SIZE*vsize*dz;
float y=getExactGroundLevel(x,z); float y=getExactGroundLevel(x,z);
CObjectEntry* actortemplate=GetRandomActorTemplate(); CObjectEntry* actortemplate=GetRandomActorTemplate();
if (actortemplate && actortemplate->m_Model) { if (actortemplate && actortemplate->m_Model) {
CUnit* unit=new CUnit(actortemplate,actortemplate->m_Model->Clone()); CUnit* unit=new CUnit(actortemplate,actortemplate->m_Model->Clone());
g_UnitMan.AddUnit(unit); g_UnitMan.AddUnit(unit);
CMatrix3D trans; CMatrix3D trans;
trans.SetIdentity(); trans.SetIdentity();
trans.RotateY(2*PI*float(rand())/float(RAND_MAX)); trans.RotateY(2*PI*float(rand())/float(RAND_MAX));
trans.Translate(x,y,z); trans.Translate(x,y,z);
unit->GetModel()->SetTransform(trans); unit->GetModel()->SetTransform(trans);
} }
} }
} }
/* /*
for (i=0;i<vsize;i++) { for (i=0;i<vsize;i++) {
for (j=0;j<vsize;j++) { for (j=0;j<vsize;j++) {
CTextureEntry* tex=GetRandomTexture(); CTextureEntry* tex=GetRandomTexture();
CMiniPatch* mp=g_Terrain.GetTile(i,j); CMiniPatch* mp=g_Terrain.GetTile(i,j);
mp->Tex1=tex->GetHandle(); mp->Tex1=tex->GetHandle();
mp->Tex1Priority=tex->GetType(); mp->Tex1Priority=tex->GetType();
mp->m_Parent->SetDirty(RENDERDATA_UPDATE_VERTICES | RENDERDATA_UPDATE_INDICES); mp->m_Parent->SetDirty(RENDERDATA_UPDATE_VERTICES | RENDERDATA_UPDATE_INDICES);
} }
} }
g_MiniMap.Rebuild(); g_MiniMap.Rebuild();
*/ */
} }

View file

@ -71,42 +71,42 @@ protected:
void DisableToolbarButtons(); void DisableToolbarButtons();
//{{AFX_MSG(CMainFrame) //{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTerrainLoad(); afx_msg void OnTerrainLoad();
afx_msg void OnLightingSettings(); afx_msg void OnLightingSettings();
afx_msg void OnViewScreenshot(); afx_msg void OnViewScreenshot();
afx_msg void OnTextureTools(); afx_msg void OnTextureTools();
afx_msg void OnToolsOptions(); afx_msg void OnToolsOptions();
afx_msg void OnToolsBrushShapeEditor(); afx_msg void OnToolsBrushShapeEditor();
afx_msg void OnEditUndo(); afx_msg void OnEditUndo();
afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI); afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI);
afx_msg void OnEditRedo(); afx_msg void OnEditRedo();
afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI); afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI);
afx_msg void OnElevationTools(); afx_msg void OnElevationTools();
afx_msg void OnResizeMap(); afx_msg void OnResizeMap();
afx_msg void OnViewTerrainGrid(); afx_msg void OnViewTerrainGrid();
afx_msg void OnUpdateViewTerrainGrid(CCmdUI* pCmdUI); afx_msg void OnUpdateViewTerrainGrid(CCmdUI* pCmdUI);
afx_msg void OnViewTerrainSolid(); afx_msg void OnViewTerrainSolid();
afx_msg void OnUpdateViewTerrainSolid(CCmdUI* pCmdUI); afx_msg void OnUpdateViewTerrainSolid(CCmdUI* pCmdUI);
afx_msg void OnViewTerrainWireframe(); afx_msg void OnViewTerrainWireframe();
afx_msg void OnUpdateViewTerrainWireframe(CCmdUI* pCmdUI); afx_msg void OnUpdateViewTerrainWireframe(CCmdUI* pCmdUI);
afx_msg void OnViewModelGrid(); afx_msg void OnViewModelGrid();
afx_msg void OnUpdateViewModelGrid(CCmdUI* pCmdUI); afx_msg void OnUpdateViewModelGrid(CCmdUI* pCmdUI);
afx_msg void OnViewModelSolid(); afx_msg void OnViewModelSolid();
afx_msg void OnUpdateViewModelSolid(CCmdUI* pCmdUI); afx_msg void OnUpdateViewModelSolid(CCmdUI* pCmdUI);
afx_msg void OnViewModelWireframe(); afx_msg void OnViewModelWireframe();
afx_msg void OnUpdateViewModelWireframe(CCmdUI* pCmdUI); afx_msg void OnUpdateViewModelWireframe(CCmdUI* pCmdUI);
afx_msg void OnFileSaveMap(); afx_msg void OnFileSaveMap();
afx_msg void OnFileLoadMap(); afx_msg void OnFileLoadMap();
afx_msg void OnViewRenderStats(); afx_msg void OnViewRenderStats();
afx_msg void OnUpdateViewRenderStats(CCmdUI* pCmdUI); afx_msg void OnUpdateViewRenderStats(CCmdUI* pCmdUI);
afx_msg LRESULT OnMouseWheel(WPARAM wParam,LPARAM lParam); afx_msg LRESULT OnMouseWheel(WPARAM wParam,LPARAM lParam);
afx_msg void OnTestGo(); afx_msg void OnTestGo();
afx_msg void OnUpdateTestGo(CCmdUI* pCmdUI); afx_msg void OnUpdateTestGo(CCmdUI* pCmdUI);
afx_msg void OnTestStop(); afx_msg void OnTestStop();
afx_msg void OnUpdateTestStop(CCmdUI* pCmdUI); afx_msg void OnUpdateTestStop(CCmdUI* pCmdUI);
afx_msg void OnRandomMap(); afx_msg void OnRandomMap();
//}}AFX_MSG //}}AFX_MSG
DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()
}; };

View file

@ -46,10 +46,10 @@ CScEdApp theApp;
// CScEdApp initialization // CScEdApp initialization
BOOL CScEdApp::InitInstance() BOOL CScEdApp::InitInstance()
{ {
extern void pre_main_init(); extern void pre_main_init();
pre_main_init(); pre_main_init();
AfxEnableControlContainer(); AfxEnableControlContainer();
// Standard initialization // Standard initialization
@ -217,4 +217,4 @@ int main(int argc, char *argv[])
AfxInitialize(); AfxInitialize();
return AfxWinMain(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); return AfxWinMain(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);
} }
#endif #endif

View file

@ -2,7 +2,7 @@
// //
#include "stdafx.h" #include "stdafx.h"
#define _IGNORE_WGL_H_ #define _IGNORE_WGL_H_
#include "ScEd.h" #include "ScEd.h"
#include "ScEdDoc.h" #include "ScEdDoc.h"
@ -14,8 +14,8 @@
#include "timer.h" #include "timer.h"
#include "ogl.h" #include "ogl.h"
#undef _IGNORE_WGL_H_ #undef _IGNORE_WGL_H_
#include "res/vfs.h" #include "res/vfs.h"
int g_ClickMode=0; int g_ClickMode=0;

View file

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#define _IGNORE_WGL_H_ #define _IGNORE_WGL_H_
#include "TexToolsDlgBar.h" #include "TexToolsDlgBar.h"
#include "TextureManager.h" #include "TextureManager.h"
#include "PaintTextureTool.h" #include "PaintTextureTool.h"
@ -8,7 +8,7 @@
#include "ogl.h" #include "ogl.h"
#include "res/tex.h" #include "res/tex.h"
#include "res/vfs.h" #include "res/vfs.h"
#undef _IGNORE_WGL_H_ #undef _IGNORE_WGL_H_
BEGIN_MESSAGE_MAP(CTexToolsDlgBar, CDialogBar) BEGIN_MESSAGE_MAP(CTexToolsDlgBar, CDialogBar)
//{{AFX_MSG_MAP(CTexToolsDlgBar) //{{AFX_MSG_MAP(CTexToolsDlgBar)

View file

@ -1,5 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#define _IGNORE_WGL_H_ #define _IGNORE_WGL_H_
#include "UserConfig.h" #include "UserConfig.h"
#include "MainFrm.h" #include "MainFrm.h"
#include "Model.h" #include "Model.h"
@ -10,7 +10,7 @@
#include "EditorData.h" #include "EditorData.h"
#include "UIGlobals.h" #include "UIGlobals.h"
#undef _IGNORE_WGL_H_ #undef _IGNORE_WGL_H_
BEGIN_MESSAGE_MAP(CUnitPropertiesDlgBar, CDialogBar) BEGIN_MESSAGE_MAP(CUnitPropertiesDlgBar, CDialogBar)
//{{AFX_MSG_MAP(CUnitPropertiesDlgBar) //{{AFX_MSG_MAP(CUnitPropertiesDlgBar)

View file

@ -1,114 +1,114 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file. // Microsoft Developer Studio generated include file.
// Used by ScEd.rc // Used by ScEd.rc
// //
#define IDD_ABOUTBOX 100 #define IDD_ABOUTBOX 100
#define IDD_PROPPAGE_NAVIGATION 102 #define IDD_PROPPAGE_NAVIGATION 102
#define IDD_DIALOGBAR_TEXTURETOOLS 103 #define IDD_DIALOGBAR_TEXTURETOOLS 103
#define IDR_MAINFRAME 128 #define IDR_MAINFRAME 128
#define IDR_SCEDTYPE 129 #define IDR_SCEDTYPE 129
#define IDD_DIALOG_LIGHTSETTINGS 133 #define IDD_DIALOG_LIGHTSETTINGS 133
#define IDD_DIALOGBAR_MODELTOOLS 134 #define IDD_DIALOGBAR_MODELTOOLS 134
#define IDD_DIALOGBAR_UNITTOOLS 134 #define IDD_DIALOGBAR_UNITTOOLS 134
#define IDB_LOGO 135 #define IDB_LOGO 135
#define IDD_DIALOG_OPTIONS 137 #define IDD_DIALOG_OPTIONS 137
#define IDD_DIALOGBAR_ELEVATIONTOOLS 138 #define IDD_DIALOGBAR_ELEVATIONTOOLS 138
#define IDD_DIALOGBAR_UNITPROPERTIES 139 #define IDD_DIALOGBAR_UNITPROPERTIES 139
#define IDD_DIALOG_SIMPLEEDIT 140 #define IDD_DIALOG_SIMPLEEDIT 140
#define IDI_ICON_UNITMODE 141 #define IDI_ICON_UNITMODE 141
#define IDI_ICON_NEWUNIT 142 #define IDI_ICON_NEWUNIT 142
#define IDI_ICON_SELECT 143 #define IDI_ICON_SELECT 143
#define IDD_DIALOG_MAPSIZE 144 #define IDD_DIALOG_MAPSIZE 144
#define IDB_BITMAP_SELECT 146 #define IDB_BITMAP_SELECT 146
#define IDB_BITMAP_TEXTURETOOLS 148 #define IDB_BITMAP_TEXTURETOOLS 148
#define IDB_BITMAP_ELEVATIONTOOLS 149 #define IDB_BITMAP_ELEVATIONTOOLS 149
#define IDB_BITMAP_MODELTOOLS 150 #define IDB_BITMAP_MODELTOOLS 150
#define IDD_DIALOGBAR_BRUSHSHAPEEDITOR 151 #define IDD_DIALOGBAR_BRUSHSHAPEEDITOR 151
#define IDD_PROPPAGE_SHADOWS 152 #define IDD_PROPPAGE_SHADOWS 152
#define IDB_BITMAP_SELECTUNIT 153 #define IDB_BITMAP_SELECTUNIT 153
#define IDD_UNITPROPERTIES_TEXTURES 153 #define IDD_UNITPROPERTIES_TEXTURES 153
#define IDB_BITMAP_ADDUNIT 154 #define IDB_BITMAP_ADDUNIT 154
#define IDD_UNITPROPERTIES_ANIMATIONS 154 #define IDD_UNITPROPERTIES_ANIMATIONS 154
#define IDC_BUTTON_SUNCOLOR 1001 #define IDC_BUTTON_SUNCOLOR 1001
#define IDC_EDIT_MODEL 1001 #define IDC_EDIT_MODEL 1001
#define IDC_BUTTON_TERRAINAMBIENTCOLOR 1002 #define IDC_BUTTON_TERRAINAMBIENTCOLOR 1002
#define IDC_EDIT_TEXTURE 1002 #define IDC_EDIT_TEXTURE 1002
#define IDC_BUTTON_APPLY 1003 #define IDC_BUTTON_APPLY 1003
#define IDC_BUTTON_MODELBROWSE 1004 #define IDC_BUTTON_MODELBROWSE 1004
#define IDC_BUTTON_DIRECTION 1005 #define IDC_BUTTON_DIRECTION 1005
#define IDC_BUTTON_TEXTUREBROWSE 1005 #define IDC_BUTTON_TEXTUREBROWSE 1005
#define IDC_BUTTON_ELEVATION 1006 #define IDC_BUTTON_ELEVATION 1006
#define IDC_BUTTON_REFRESH 1006 #define IDC_BUTTON_REFRESH 1006
#define IDC_EDIT_DIRECTION 1007 #define IDC_EDIT_DIRECTION 1007
#define IDC_EDIT_NAME 1007 #define IDC_EDIT_NAME 1007
#define IDC_BUTTON_UNITSAMBIENTCOLOR 1008 #define IDC_BUTTON_UNITSAMBIENTCOLOR 1008
#define IDC_BUTTON_BACK 1008 #define IDC_BUTTON_BACK 1008
#define IDC_EDIT_ELEVATION 1009 #define IDC_EDIT_ELEVATION 1009
#define IDC_SPIN_DIRECTION 1010 #define IDC_SPIN_DIRECTION 1010
#define IDC_SPIN_ELEVATION 1011 #define IDC_SPIN_ELEVATION 1011
#define IDC_STATIC_VERSION 1011 #define IDC_STATIC_VERSION 1011
#define IDC_EDIT_ANIMATION 1011 #define IDC_EDIT_ANIMATION 1011
#define IDC_BUTTON_LAUNCHWFG 1012 #define IDC_BUTTON_LAUNCHWFG 1012
#define IDC_BUTTON_ANIMATIONBROWSE 1012 #define IDC_BUTTON_ANIMATIONBROWSE 1012
#define IDC_SLIDER_BRUSHSIZE 1013 #define IDC_SLIDER_BRUSHSIZE 1013
#define IDC_SLIDER_BRUSHEFFECT 1014 #define IDC_SLIDER_BRUSHEFFECT 1014
#define IDC_LIST_TEXTUREBROWSER 1015 #define IDC_LIST_TEXTUREBROWSER 1015
#define IDC_BUTTON_ADD 1016 #define IDC_BUTTON_ADD 1016
#define IDC_BUTTON_EDIT 1017 #define IDC_BUTTON_EDIT 1017
#define IDC_STATIC_CURRENTTEXTURE 1018 #define IDC_STATIC_CURRENTTEXTURE 1018
#define IDC_STATIC_CURRENTMODEL 1020 #define IDC_STATIC_CURRENTMODEL 1020
#define IDC_LIST_MODELBROWSER 1021 #define IDC_LIST_MODELBROWSER 1021
#define IDC_LIST_OBJECTBROWSER 1021 #define IDC_LIST_OBJECTBROWSER 1021
#define IDC_SLIDER_RTSSCROLLSPEED 1023 #define IDC_SLIDER_RTSSCROLLSPEED 1023
#define IDC_RADIO_RAISE 1027 #define IDC_RADIO_RAISE 1027
#define IDC_RADIO_SMOOTH 1028 #define IDC_RADIO_SMOOTH 1028
#define IDC_EDIT1 1028 #define IDC_EDIT1 1028
#define IDC_COMBO_TERRAINTYPES 1030 #define IDC_COMBO_TERRAINTYPES 1030
#define IDC_COMBO1 1030 #define IDC_COMBO1 1030
#define IDC_RADIO_SMALL 1031 #define IDC_RADIO_SMALL 1031
#define IDC_RADIO_MEDIUM 1032 #define IDC_RADIO_MEDIUM 1032
#define IDC_COMBO_OBJECTTYPES 1032 #define IDC_COMBO_OBJECTTYPES 1032
#define IDC_RADIO_LARGE 1033 #define IDC_RADIO_LARGE 1033
#define IDC_BUTTON_SELECT 1033 #define IDC_BUTTON_SELECT 1033
#define IDC_RADIO_HUGE 1034 #define IDC_RADIO_HUGE 1034
#define IDC_BUTTON_ELEVATIONTOOLS 1034 #define IDC_BUTTON_ELEVATIONTOOLS 1034
#define IDC_BUTTON_TEXTURETOOLS 1035 #define IDC_BUTTON_TEXTURETOOLS 1035
#define IDC_BUTTON_MODELTOOLS 1036 #define IDC_BUTTON_MODELTOOLS 1036
#define IDC_BUTTON_ADDUNIT 1038 #define IDC_BUTTON_ADDUNIT 1038
#define IDC_CHECK_SHADOWS 1039 #define IDC_CHECK_SHADOWS 1039
#define IDC_BUTTON_SHADOWCOLOR 1040 #define IDC_BUTTON_SHADOWCOLOR 1040
#define IDC_SLIDER_SHADOWQUALITY 1041 #define IDC_SLIDER_SHADOWQUALITY 1041
#define ID_TERRAIN_LOAD 32772 #define ID_TERRAIN_LOAD 32772
#define ID_TERRAIN_RANDOMMAP 32773 #define ID_TERRAIN_RANDOMMAP 32773
#define ID_LIGHTING_SETTINGS 32774 #define ID_LIGHTING_SETTINGS 32774
#define ID_VIEW_GRID 32778 #define ID_VIEW_GRID 32778
#define ID_VIEW_TERRAIN_GRID 32778 #define ID_VIEW_TERRAIN_GRID 32778
#define ID_VIEW_SCREENSHOT 32779 #define ID_VIEW_SCREENSHOT 32779
#define IDR_TEXTURE_TOOLS 32781 #define IDR_TEXTURE_TOOLS 32781
#define ID_TOOLS_OPTIONS 32782 #define ID_TOOLS_OPTIONS 32782
#define IDR_ELEVATION_TOOLS 32783 #define IDR_ELEVATION_TOOLS 32783
#define IDR_UNIT_TOOLS 32785 #define IDR_UNIT_TOOLS 32785
#define IDR_RESIZE_MAP 32786 #define IDR_RESIZE_MAP 32786
#define ID_VIEW_TERRAIN_WIREFRAME 32787 #define ID_VIEW_TERRAIN_WIREFRAME 32787
#define ID_VIEW_TERRAIN_SOLID 32788 #define ID_VIEW_TERRAIN_SOLID 32788
#define ID_FILE_LOADMAP 32789 #define ID_FILE_LOADMAP 32789
#define ID_FILE_SAVEMAP 32790 #define ID_FILE_SAVEMAP 32790
#define ID_VIEW_MODEL_SOLID 32791 #define ID_VIEW_MODEL_SOLID 32791
#define ID_VIEW_MODEL_GRID 32792 #define ID_VIEW_MODEL_GRID 32792
#define ID_VIEW_MODEL_WIREFRAME 32793 #define ID_VIEW_MODEL_WIREFRAME 32793
#define ID_VIEW_RENDERSTATS 32794 #define ID_VIEW_RENDERSTATS 32794
#define ID_TEST_STOP 32797 #define ID_TEST_STOP 32797
#define ID_TEST_GO 32798 #define ID_TEST_GO 32798
#define ID_RANDOM_MAP 32799 #define ID_RANDOM_MAP 32799
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS 1 #define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 156 #define _APS_NEXT_RESOURCE_VALUE 156
#define _APS_NEXT_COMMAND_VALUE 32800 #define _APS_NEXT_COMMAND_VALUE 32800
#define _APS_NEXT_CONTROL_VALUE 1044 #define _APS_NEXT_CONTROL_VALUE 1044
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

View file

@ -1,6 +1,17 @@
#include "precompiled.h" #include "precompiled.h"
#include "ScriptGlue.h" #include "ScriptGlue.h"
#include "CConsole.h"
#include "CStr.h"
#include "EntityHandles.h"
#include "Entity.h"
#include "EntityManager.h"
#include "BaseEntityCollection.h"
#include "scripting/JSInterface_Entity.h"
#include "scripting/JSInterface_BaseEntity.h"
#include "scripting/JSInterface_Vector3D.h"
extern CConsole* g_Console;
// Parameters for the table are: // Parameters for the table are:
@ -12,7 +23,9 @@
JSFunctionSpec ScriptFunctionTable[] = JSFunctionSpec ScriptFunctionTable[] =
{ {
{"WriteLog", WriteLog, 1, 0, 0}, {"WriteLog", WriteLog, 1, 0, 0},
{"writeConsole", writeConsole, 1, 0, 0 },
{"getEntityByHandle", getEntityByHandle, 1, 0, 0 },
{"getEntityTemplate", getEntityTemplate, 1, 0, 0 },
{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0},
}; };
@ -47,3 +60,62 @@ JSBool WriteLog(JSContext * context, JSObject * globalObject, unsigned int argc,
return JS_TRUE; return JS_TRUE;
} }
JSBool writeConsole( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval )
{
assert( argc >= 1 );
CStr output = g_ScriptingHost.ValueToString( argv[0] );
g_Console->InsertMessage( output );
return( JS_TRUE );
}
JSBool getEntityByHandle( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval )
{
assert( argc >= 1 );
i32 handle;
try
{
handle = g_ScriptingHost.ValueToInt( argv[0] );
}
catch( ... )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
HEntity* v = g_EntityManager.getByHandle( (u16)handle );
if( !v )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
JSObject* entity = JS_NewObject( context, &JSI_Entity::JSI_class, NULL, NULL );
JS_SetPrivate( context, entity, v );
*rval = OBJECT_TO_JSVAL( entity );
return( JS_TRUE );
}
JSBool getEntityTemplate( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval )
{
assert( argc >= 1 );
CStr templateName;
try
{
templateName = g_ScriptingHost.ValueToString( argv[0] );
}
catch( ... )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
CBaseEntity* v = g_EntityTemplateCollection.getTemplate( templateName );
if( !v )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
JSObject* baseEntity = JS_NewObject( context, &JSI_BaseEntity::JSI_class, NULL, NULL );
JS_SetPrivate( context, baseEntity, v );
*rval = OBJECT_TO_JSVAL( baseEntity );
return( JS_TRUE );
}

View file

@ -6,6 +6,10 @@
JSBool WriteLog(JSContext * context, JSObject * globalObject, unsigned int argc, jsval *argv, jsval *rval); JSBool WriteLog(JSContext * context, JSObject * globalObject, unsigned int argc, jsval *argv, jsval *rval);
JSBool writeConsole( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval );
JSBool getEntityByHandle( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval );
JSBool getEntityTemplate( JSContext* context, JSObject* globalObject, unsigned int argc, jsval* argv, jsval* rval );
extern JSFunctionSpec ScriptFunctionTable[]; extern JSFunctionSpec ScriptFunctionTable[];
#endif #endif

View file

@ -2,12 +2,16 @@
#include "ScriptingHost.h" #include "ScriptingHost.h"
#include "ScriptGlue.h" #include "ScriptGlue.h"
#include "CConsole.h"
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include "float.h" // <- MT: Just for _finite(), converting certain strings was causing wierd bugs.
#pragma comment (lib, "js32.lib") #pragma comment (lib, "js32.lib")
extern CConsole* g_Console;
namespace namespace
{ {
const int RUNTIME_MEMORY_ALLOWANCE = 16 * 1024 * 1024; const int RUNTIME_MEMORY_ALLOWANCE = 16 * 1024 * 1024;
@ -76,6 +80,11 @@ ScriptingHost::~ScriptingHost()
} }
} }
JSContext* ScriptingHost::getContext()
{
return( m_Context );
}
void ScriptingHost::LoadScriptFromDisk(const std::string & fileName) void ScriptingHost::LoadScriptFromDisk(const std::string & fileName)
{ {
std::string script; std::string script;
@ -124,6 +133,8 @@ jsval ScriptingHost::ExecuteScript(const std::string & script)
JSBool ok = JS_EvaluateScript(m_Context, m_GlobalObject, script.c_str(), (int)script.length(), "Console", 0, &rval); JSBool ok = JS_EvaluateScript(m_Context, m_GlobalObject, script.c_str(), (int)script.length(), "Console", 0, &rval);
if( !ok ) return( NULL );
return rval; return rval;
} }
@ -223,6 +234,13 @@ void ScriptingHost::SetObjectProperty(JSObject * object, const std::string & pro
JS_SetProperty(m_Context, object, propertyName.c_str(), &value); JS_SetProperty(m_Context, object, propertyName.c_str(), &value);
} }
jsval ScriptingHost::GetObjectProperty( JSObject* object, const std::string& propertyName )
{
jsval vp;
JS_GetProperty( m_Context, object, propertyName.c_str(), &vp );
return( vp );
}
int ScriptingHost::ValueToInt(const jsval value) int ScriptingHost::ValueToInt(const jsval value)
{ {
int32 i = 0; int32 i = 0;
@ -264,7 +282,7 @@ double ScriptingHost::ValueToDouble(const jsval value)
JSBool ok = JS_ValueToNumber(m_Context, value, &d); JSBool ok = JS_ValueToNumber(m_Context, value, &d);
if (ok == JS_FALSE) if (ok == JS_FALSE || !_finite( d ) )
{ {
throw (std::string("Convert to double failed")); throw (std::string("Convert to double failed"));
} }
@ -274,6 +292,14 @@ double ScriptingHost::ValueToDouble(const jsval value)
void ScriptingHost::ErrorReporter(JSContext * context, const char * message, JSErrorReport * report) void ScriptingHost::ErrorReporter(JSContext * context, const char * message, JSErrorReport * report)
{ {
g_Console->InsertMessage( "%s ( %d )", report->filename, report->lineno );
if( message )
{
g_Console->InsertMessage( message );
}
else
g_Console->InsertMessage( "No error message available" );
if (report->filename != NULL) if (report->filename != NULL)
{ {
std::cout << report->filename << " (" << report->lineno << ") "; std::cout << report->filename << " (" << report->lineno << ") ";

View file

@ -48,6 +48,8 @@ public:
ScriptingHost(); ScriptingHost();
~ScriptingHost(); ~ScriptingHost();
JSContext* getContext();
void LoadScriptFromDisk(const std::string & fileName); void LoadScriptFromDisk(const std::string & fileName);
@ -65,6 +67,7 @@ public:
JSObject * CreateCustomObject(const std::string & typeName); JSObject * CreateCustomObject(const std::string & typeName);
void SetObjectProperty(JSObject * object, const std::string & propertyName, jsval value); void SetObjectProperty(JSObject * object, const std::string & propertyName, jsval value);
jsval GetObjectProperty( JSObject* object, const std::string& propertyName );
int ValueToInt(const jsval value); int ValueToInt(const jsval value);
bool ValueToBool(const jsval value); bool ValueToBool(const jsval value);

View file

@ -9,21 +9,16 @@
// automatically use namespace .. // automatically use namespace ..
XERCES_CPP_NAMESPACE_USE XERCES_CPP_NAMESPACE_USE
CBaseEntity::CBaseEntity( const CBaseEntity& copy ) CBaseEntity::CBaseEntity()
{ {
m_actorObject = copy.m_actorObject; m_base = NULL;
m_base.associate( this, "super" );
m_name = copy.m_name; m_name.associate( this, "name" );
m_bound_type = copy.m_bound_type; m_speed.associate( this, "speed" );
m_speed = copy.m_speed; m_turningRadius.associate( this, "turningRadius" );
m_turningRadius = copy.m_turningRadius;
m_bound_circle = NULL; m_bound_circle = NULL;
m_bound_box = NULL; m_bound_box = NULL;
if( copy.m_bound_circle )
m_bound_circle = new CBoundingCircle( 0.0f, 0.0f, copy.m_bound_circle );
if( copy.m_bound_box )
m_bound_box = new CBoundingBox( 0.0f, 0.0f, 0.0f, copy.m_bound_box );
} }
CBaseEntity::~CBaseEntity() CBaseEntity::~CBaseEntity()
@ -95,8 +90,6 @@ bool CBaseEntity::loadXML( CStr filename )
DOMNode *value_node= child_element->getChildNodes()->item(0); DOMNode *value_node= child_element->getChildNodes()->item(0);
CStr element_value=value_node ? XMLString::transcode(value_node->getNodeValue()) : ""; CStr element_value=value_node ? XMLString::transcode(value_node->getNodeValue()) : "";
//m_properties[element_name] = element_value;
if( element_name == CStr( "Name" ) ) if( element_name == CStr( "Name" ) )
{ {
m_name = element_value; m_name = element_value;

View file

@ -24,32 +24,25 @@
#include "EntityProperties.h" #include "EntityProperties.h"
#include "BoundingObjects.h" #include "BoundingObjects.h"
class CBaseEntity class CBaseEntity : public IPropertyOwner
{ {
public: public:
CBaseEntity() { m_bound_circle = NULL; m_bound_box = NULL; } CBaseEntity();
CBaseEntity( const CBaseEntity& copy );
~CBaseEntity(); ~CBaseEntity();
// Load from XML // Load from XML
bool loadXML( CStr filename ); bool loadXML( CStr filename );
// Base stats // Base stats
CObjectEntry* m_actorObject; CObjectEntry* m_actorObject;
CStr m_name; CProperty_CStr m_name;
CBoundingCircle* m_bound_circle; CBoundingCircle* m_bound_circle;
CBoundingBox* m_bound_box; CBoundingBox* m_bound_box;
CBoundingObject::EBoundingType m_bound_type; CBoundingObject::EBoundingType m_bound_type;
float m_speed; CProperty_float m_speed;
float m_turningRadius; CProperty_float m_turningRadius;
// Extended properties table
STL_HASH_MAP<CStr,CGenericProperty,CStr_hash_compare> m_properties;
}; };
#endif #endif

View file

@ -18,8 +18,8 @@ void CBaseEntityCollection::loadTemplates()
{ {
while (vfs_next_dirent(handle, &dent, ".xml") == 0) while (vfs_next_dirent(handle, &dent, ".xml") == 0)
{ {
CBaseEntity newTemplate; CBaseEntity* newTemplate = new CBaseEntity();
if( newTemplate.loadXML( pathname + dent.name ) ) if( newTemplate->loadXML( pathname + dent.name ) )
{ {
addTemplate( newTemplate ); addTemplate( newTemplate );
LOG(NORMAL, "CBaseEntityCollection::loadTemplates(): Loaded template \"%s%s\"", pathname.c_str(), dent.name); LOG(NORMAL, "CBaseEntityCollection::loadTemplates(): Loaded template \"%s%s\"", pathname.c_str(), dent.name);
@ -35,13 +35,9 @@ void CBaseEntityCollection::loadTemplates()
LOG(ERROR, "CBaseEntityCollection::loadTemplates(): Failed to enumerate entity template directory\n"); LOG(ERROR, "CBaseEntityCollection::loadTemplates(): Failed to enumerate entity template directory\n");
return; return;
} }
// He's so annoyingly slow...
CBaseEntity* dude = getTemplate( "Prometheus Dude" );
dude->m_speed *= 10.0f;
} }
void CBaseEntityCollection::addTemplate( CBaseEntity& temp ) void CBaseEntityCollection::addTemplate( CBaseEntity* temp )
{ {
m_templates.push_back( temp ); m_templates.push_back( temp );
} }
@ -49,7 +45,7 @@ void CBaseEntityCollection::addTemplate( CBaseEntity& temp )
CBaseEntity* CBaseEntityCollection::getTemplate( CStr name ) CBaseEntity* CBaseEntityCollection::getTemplate( CStr name )
{ {
for( u16 t = 0; t < m_templates.size(); t++ ) for( u16 t = 0; t < m_templates.size(); t++ )
if( m_templates[t].m_name == name ) return( &( m_templates[t] ) ); if( m_templates[t]->m_name == name ) return( m_templates[t] );
return( NULL ); return( NULL );
} }
@ -57,7 +53,13 @@ CBaseEntity* CBaseEntityCollection::getTemplate( CStr name )
CBaseEntity* CBaseEntityCollection::getTemplateByActor( CObjectEntry* actor ) CBaseEntity* CBaseEntityCollection::getTemplateByActor( CObjectEntry* actor )
{ {
for( u16 t = 0; t < m_templates.size(); t++ ) for( u16 t = 0; t < m_templates.size(); t++ )
if( m_templates[t].m_actorObject == actor ) return( &( m_templates[t] ) ); if( m_templates[t]->m_actorObject == actor ) return( m_templates[t] );
return( NULL ); return( NULL );
} }
CBaseEntityCollection::~CBaseEntityCollection()
{
for( u16 t = 0; t < m_templates.size(); t++ )
delete( m_templates[t] );
}

View file

@ -28,11 +28,12 @@
class CBaseEntityCollection : public Singleton<CBaseEntityCollection> class CBaseEntityCollection : public Singleton<CBaseEntityCollection>
{ {
std::vector<CBaseEntity> m_templates; std::vector<CBaseEntity*> m_templates;
public: public:
~CBaseEntityCollection();
CBaseEntity* getTemplate( CStr entityType ); CBaseEntity* getTemplate( CStr entityType );
void loadTemplates(); void loadTemplates();
void addTemplate( CBaseEntity& temp ); void addTemplate( CBaseEntity* temp );
CBaseEntity* getTemplateByActor( CObjectEntry* actor ); CBaseEntity* getTemplateByActor( CObjectEntry* actor );
}; };

View file

@ -11,17 +11,63 @@
#include "Terrain.h" #include "Terrain.h"
#include "Collision.h" #include "Collision.h"
#include "PathfindEngine.h"
CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation ) CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
{ {
m_position = position;
m_orientation = orientation;
m_ahead.x = sin( m_orientation );
m_ahead.y = cos( m_orientation );
m_base.associate( this, "template", ( void( IPropertyOwner::* )() )&CEntity::loadBase );
m_name.associate( this, "name" );
m_speed.associate( this, "speed" );
m_turningRadius.associate( this, "turningRadius" );
m_position.associate( this, "position", ( void( IPropertyOwner::* )() )&CEntity::teleport );
m_orientation.associate( this, "orientation", ( void( IPropertyOwner::* )() )&CEntity::reorient );
// Set our parent unit and build us an actor. // Set our parent unit and build us an actor.
m_actor = NULL;
m_bounds = NULL;
m_base = base; m_base = base;
m_actor = new CUnit(m_base->m_actorObject,m_base->m_actorObject->m_Model->Clone());
loadBase();
snapToGround();
// HACK: Debugging updateActorTransforms();
// assert( m_base->m_name != CStr( "Waypoint" ) );
}
CEntity::~CEntity()
{
for( i32 i = 0; i < m_base->m_inheritors.size(); i++ )
if( m_base->m_inheritors[i] == this )
m_base->m_inheritors.erase( m_base->m_inheritors.begin() + i );
if( m_actor )
{
g_UnitMan.RemoveUnit( m_actor );
delete( m_actor );
}
if( m_bounds ) delete( m_bounds );
}
void CEntity::loadBase()
{
if( m_actor )
{
g_UnitMan.RemoveUnit( m_actor );
delete( m_actor );
}
if( m_bounds )
{
delete( m_bounds );
}
m_actor = new CUnit(m_base->m_actorObject,m_base->m_actorObject->m_Model->Clone());
// Register the actor with the renderer. // Register the actor with the renderer.
@ -29,13 +75,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
// Set up our instance data // Set up our instance data
m_speed = m_base->m_speed; m_base->m_inheritors.push_back( this );
m_turningRadius = m_base->m_turningRadius; rebuild();
m_position = position;
m_orientation = orientation;
m_ahead.x = sin( orientation );
m_ahead.y = cos( orientation );
if( m_base->m_bound_type == CBoundingObject::BOUND_CIRCLE ) if( m_base->m_bound_type == CBoundingObject::BOUND_CIRCLE )
{ {
@ -45,28 +86,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
{ {
m_bounds = new CBoundingBox( m_position.X, m_position.Z, m_ahead, m_base->m_bound_box ); m_bounds = new CBoundingBox( m_position.X, m_position.Z, m_ahead, m_base->m_bound_box );
} }
snapToGround();
updateActorTransforms();
// Register the addresses of our native properties with the properties table
m_properties["speed"].associate( &m_speed );
m_properties["orientation"].associate( &m_orientation );
m_properties["position"].associate( &m_position );
} }
CEntity::~CEntity()
{
if( m_actor )
{
g_UnitMan.RemoveUnit( m_actor );
delete( m_actor );
}
if( m_bounds ) delete( m_bounds );
}
bool isWaypoint( CEntity* e ) bool isWaypoint( CEntity* e )
{ {
return( e->m_base->m_name == CStr( "Waypoint" ) ); return( e->m_base->m_name == CStr( "Waypoint" ) );
@ -105,6 +126,8 @@ float CEntity::getExactGroundLevel( float x, float y )
u16* heightmap = g_Terrain.GetHeightMap(); u16* heightmap = g_Terrain.GetHeightMap();
unsigned long mapsize = g_Terrain.GetVerticesPerSide(); unsigned long mapsize = g_Terrain.GetVerticesPerSide();
assert( ( xi >= 0 ) && ( xi < mapsize ) && ( yi >= 0 ) && ( yi < mapsize ) );
float h00 = heightmap[yi*mapsize + xi]; float h00 = heightmap[yi*mapsize + xi];
float h01 = heightmap[yi*mapsize + xi + mapsize]; float h01 = heightmap[yi*mapsize + xi + mapsize];
float h10 = heightmap[yi*mapsize + xi + 1]; float h10 = heightmap[yi*mapsize + xi + 1];
@ -204,6 +227,39 @@ void CEntity::pushOrder( CEntityOrder& order )
m_orderQueue.push_back( order ); m_orderQueue.push_back( order );
} }
void CEntity::repath()
{
CVector2D destination;
if( m_orderQueue.empty() ) return;
while( !m_orderQueue.empty() &&
( ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_COLLISION )
|| ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_NOPATHING )
|| ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_SMOOTHED ) ) )
{
destination = m_orderQueue.front().m_data[0].location;
m_orderQueue.pop_front();
}
g_Pathfinder.requestPath( me, destination );
}
void CEntity::reorient()
{
m_ahead.x = sin( m_orientation );
m_ahead.y = cos( m_orientation );
if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
updateActorTransforms();
}
void CEntity::teleport()
{
snapToGround();
updateActorTransforms();
m_bounds->setPosition( m_position.X, m_position.Z );
repath();
}
void CEntity::render() void CEntity::render()
{ {
// Rich! Help! ;) // Rich! Help! ;)

View file

@ -47,29 +47,23 @@
class CEntityManager; class CEntityManager;
class CEntity class CEntity : public IPropertyOwner
{ {
friend class CEntityManager; friend class CEntityManager;
private:
// Intrinsic properties
public: public:
CStr m_name; // Intrinsic properties
float m_speed; CProperty_CStr m_name;
float m_turningRadius; CProperty_float m_speed;
CVector3D m_position; CProperty_float m_turningRadius;
CProperty_CVector3D m_position;
CBoundingObject* m_bounds; CBoundingObject* m_bounds;
float m_targetorientation; float m_targetorientation;
CVector2D m_ahead; CVector2D m_ahead;
float m_orientation; CProperty_float m_orientation;
CBaseEntity* m_base;
CUnit* m_actor; CUnit* m_actor;
std::deque<CEntityOrder> m_orderQueue; std::deque<CEntityOrder> m_orderQueue;
// Extended properties table
STL_HASH_MAP<CStr,CGenericProperty,CStr_hash_compare> m_properties;
private: private:
CEntity( CBaseEntity* base, CVector3D position, float orientation ); CEntity( CBaseEntity* base, CVector3D position, float orientation );
@ -88,6 +82,12 @@ public:
void render(); void render();
float getExactGroundLevel( float x, float y ); float getExactGroundLevel( float x, float y );
void snapToGround(); void snapToGround();
void repath();
void loadBase();
void reorient();
void teleport(); // Fixes things if the position is changed by something externally.
void pushOrder( CEntityOrder& order ); void pushOrder( CEntityOrder& order );
}; };

View file

@ -34,6 +34,12 @@ HEntity CEntityManager::create( CStr templatename, CVector3D position, float ori
return( create( templateobj, position, orientation ) ); return( create( templateobj, position, orientation ) );
} }
HEntity* CEntityManager::getByHandle( u16 index )
{
if( index >= MAX_HANDLES ) return( NULL );
if( !m_entities[index].m_refcount ) return( NULL );
return( new HEntity( index ) );
}
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate ) std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate )
{ {
std::vector<HEntity>* matchlist = new std::vector<HEntity>; std::vector<HEntity>* matchlist = new std::vector<HEntity>;

View file

@ -42,10 +42,11 @@ public:
~CEntityManager(); ~CEntityManager();
HEntity create( CBaseEntity* base, CVector3D position, float orientation ); HEntity create( CBaseEntity* base, CVector3D position, float orientation );
HEntity create( CStr templatename, CVector3D position, float orientation ); HEntity create( CStr templatename, CVector3D position, float orientation );
HEntity* getByHandle( u16 index );
void kill( HEntity ent ); void kill( HEntity ent );
void updateAll( float timestep ); void updateAll( float timestep );
void dispatchAll( CMessage* msg ); void dispatchAll( CMessage* msg );
void renderAll(); // TODO MT: What's the correct way to hook this up to the renderer? void renderAll();
std::vector<HEntity>* matches( EntityPredicate predicate ); std::vector<HEntity>* matches( EntityPredicate predicate );
std::vector<HEntity>* getActive(); std::vector<HEntity>* getActive();
static inline bool extant() // True if the singleton is actively maintaining handles. When false, system is shutting down, handles are quietly dumped. static inline bool extant() // True if the singleton is actively maintaining handles. When false, system is shutting down, handles are quietly dumped.

View file

@ -1,621 +1,368 @@
#include "precompiled.h" #include "precompiled.h"
#include "EntityProperties.h" #include "EntityProperties.h"
#include "BaseEntityCollection.h"
#include "scripting/JSInterface_BaseEntity.h"
#include <cassert> void CProperty::associate( IPropertyOwner* owner, const CStr& name )
CGenericProperty::CGenericProperty()
{ {
m_type = PROP_INTEGER; m_owner = owner;
m_integer = 0; owner->m_properties[name] = this;
m_updateFn = NULL;
} }
CGenericProperty::~CGenericProperty() void CProperty::associate( IPropertyOwner* owner, const CStr& name, void (IPropertyOwner::*updateFn)() )
{ {
releaseData(); m_owner = owner;
owner->m_properties[name] = this;
m_updateFn = updateFn;
} }
void CGenericProperty::releaseData() CProperty& CProperty::operator=( jsval value )
{ {
switch( m_type & ~PROP_TYPELOCKED ) set( value );
{
case PROP_STRING:
delete( m_string ); break;
case PROP_VECTOR:
delete( m_vector ); break;
default:
break;
}
}
CGenericProperty::operator i32()
{
return( toInteger() );
}
CGenericProperty::operator float()
{
return( toFloat() );
}
CGenericProperty::operator CStr()
{
return( toString() );
}
CGenericProperty::operator CVector3D()
{
return( toVector() );
}
CGenericProperty::operator void *()
{
return( toVoid() );
}
CGenericProperty& CGenericProperty::operator=( int32_t value )
{
if( m_type & PROP_TYPELOCKED )
{
fromInteger( value );
}
else
{
releaseData();
m_type = PROP_INTEGER;
m_integer = value;
}
return( *this ); return( *this );
} }
CGenericProperty& CGenericProperty::operator=( float value ) CProperty_i32::CProperty_i32()
{ {
if( m_type & PROP_TYPELOCKED ) modifier = NULL;
{ }
fromFloat( value );
} CProperty_i32::~CProperty_i32()
else {
{ if( modifier )
releaseData(); delete( modifier );
m_type = PROP_FLOAT; }
m_float = value;
} inline CProperty_i32& CProperty_i32::operator =( i32 value )
{
if( !modifier )
modifier = new SProperty_NumericModifier();
*modifier = (float)value;
data = value;
return( *this ); return( *this );
} }
CGenericProperty& CGenericProperty::operator=( CStr& value ) void CProperty_i32::set( jsval value )
{ {
if( m_type & PROP_TYPELOCKED ) if( !modifier )
modifier = new SProperty_NumericModifier();
try
{ {
fromString( value ); *modifier = (float)g_ScriptingHost.ValueToInt( value );
} }
else catch( ... )
{ {
releaseData(); *modifier = 0;
m_type = PROP_STRING;
m_string = new CStr( value );
} }
}
bool CProperty_i32::rebuild( CProperty* parent, bool triggerFn )
{
CProperty_i32* _parent = (CProperty_i32*)parent;
i32 newvalue = 0;
if( _parent )
newvalue = *_parent;
if( modifier )
{
newvalue *= modifier->multiplicative;
newvalue += modifier->additive;
}
if( data == newvalue )
return( false ); // No change.
data = newvalue;
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
return( true );
}
inline CProperty_i32::operator i32()
{
return( data );
}
CProperty_i32::operator jsval()
{
return( INT_TO_JSVAL( data ) );
}
CProperty_float::CProperty_float()
{
modifier = NULL;
}
CProperty_float::~CProperty_float()
{
if( modifier )
modifier = NULL;
}
CProperty_float& CProperty_float::operator =( const float& value )
{
if( !modifier )
modifier = new SProperty_NumericModifier();
*modifier = value;
data = value;
return( *this ); return( *this );
} }
CGenericProperty& CGenericProperty::operator=( CVector3D& value ) void CProperty_float::set( const jsval value )
{ {
if( m_type & PROP_TYPELOCKED ) if( !modifier )
modifier = new SProperty_NumericModifier();
try
{ {
fromVector( value ); *modifier = (float)g_ScriptingHost.ValueToDouble( value );
} }
else catch( ... )
{ {
releaseData(); *modifier = 0.0f;
m_type = PROP_VECTOR;
m_vector = new CVector3D( value );
} }
}
bool CProperty_float::rebuild( CProperty* parent, bool triggerFn )
{
CProperty_float* _parent = (CProperty_float*)parent;
float newvalue = 0;
if( _parent )
newvalue = *_parent;
if( modifier )
{
newvalue *= modifier->multiplicative;
newvalue += modifier->additive;
}
if( data == newvalue )
return( false ); // No change.
data = newvalue;
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
return( true );
}
CProperty_float::operator float()
{
return( data );
}
CProperty_float::operator jsval()
{
return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), (jsdouble)data ) ) );
}
CProperty_float::operator bool()
{
return( data );
}
float CProperty_float::operator+( float value )
{
return( data + value );
}
float CProperty_float::operator-( float value )
{
return( data - value );
}
float CProperty_float::operator*( float value )
{
return( data * value );
}
float CProperty_float::operator/( float value )
{
return( data / value );
}
bool CProperty_float::operator<( float value )
{
return( data < value );
}
bool CProperty_float::operator>( float value )
{
return( data > value );
}
bool CProperty_float::operator==( float value )
{
return( data == value );
}
CProperty_CStr::CProperty_CStr()
{
modifier = NULL;
}
CProperty_CStr::~CProperty_CStr()
{
if( modifier )
delete( modifier );
}
CProperty_CStr& CProperty_CStr::operator=( const CStr& value )
{
if( !modifier )
modifier = new SProperty_StringModifier();
*modifier = value;
m_String = value;
return( *this ); return( *this );
} }
CGenericProperty& CGenericProperty::operator =( void* value ) void CProperty_CStr::set( jsval value )
{ {
if( m_type & PROP_TYPELOCKED ) if( !modifier )
modifier = new SProperty_StringModifier();
try
{ {
fromVoid( value ); *modifier = g_ScriptingHost.ValueToString( value );
} }
else catch( ... )
{ {
releaseData(); *modifier = CStr();
m_type = PROP_PTR; m_String.clear();
m_ptr = value;
} }
}
bool CProperty_CStr::rebuild( CProperty* parent, bool triggerFn )
{
CProperty_CStr* _parent = (CProperty_CStr*)parent;
CStr newvalue = "";
if( _parent )
newvalue = *_parent;
if( modifier )
newvalue = modifier->replacement;
if( *this == newvalue )
return( false ); // No change.
m_String = newvalue;
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
return( true );
}
CProperty_CStr::operator jsval()
{
return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.getContext(), m_String.c_str() ) ) );
}
CProperty_CVector3D& CProperty_CVector3D::operator =( const CVector3D& value )
{
*( (CVector3D*)this ) = value;
return( *this ); return( *this );
} }
void CGenericProperty::associate( i32* value ) void CProperty_CVector3D::set( jsval value )
{ {
i32 current = toInteger(); JSObject* vector3d = JSVAL_TO_OBJECT( value );
releaseData(); if( !JSVAL_IS_OBJECT( value ) || ( JS_GetClass( vector3d ) != &JSI_Vector3D::JSI_class ) )
m_type = (EPropTypes)( PROP_INTEGER | PROP_INTRINSIC | PROP_TYPELOCKED );
m_integerptr = value;
//*m_integerptr = current;
}
void CGenericProperty::associate( float* value )
{
float current = toFloat();
releaseData();
m_type = (EPropTypes)( PROP_FLOAT | PROP_INTRINSIC | PROP_TYPELOCKED );
m_floatptr = value;
//*m_floatptr = current;
}
void CGenericProperty::associate( CStr* value )
{
CStr current = toString();
releaseData();
m_type = (EPropTypes)( PROP_STRING | PROP_VECTOR | PROP_TYPELOCKED );
m_string = value;
//*m_string = current;
}
void CGenericProperty::associate( CVector3D* value )
{
CVector3D current = toVector();
releaseData();
m_type = (EPropTypes)( PROP_VECTOR | PROP_INTRINSIC | PROP_TYPELOCKED );
m_vector = value;
//*value = current;
}
void CGenericProperty::typelock( EPropTypes type )
{
if( m_type & PROP_INTRINSIC ) return;
switch( type )
{ {
case PROP_INTEGER: X = 0.0f; Y = 0.0f; Z = 0.0f;
}
else
{
CVector3D* copy = ( (JSI_Vector3D::Vector3D_Info*)JS_GetPrivate( g_ScriptingHost.getContext(), vector3d ) )->vector;
X = copy->X;
Y = copy->Y;
Z = copy->Z;
}
}
bool CProperty_CVector3D::rebuild( CProperty* parent, bool triggerFn )
{
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
return( false ); // Vector properties aren't inheritable.
}
CProperty_CVector3D::operator jsval()
{
JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( this, m_owner, m_updateFn ) );
return( OBJECT_TO_JSVAL( vector3d ) );
}
CProperty_CBaseEntityPtr& CProperty_CBaseEntityPtr::operator =( CBaseEntity* value )
{
data = value;
return( *this );
}
void CProperty_CBaseEntityPtr::set( jsval value )
{
JSObject* baseEntity = JSVAL_TO_OBJECT( value );
if( JSVAL_IS_OBJECT( value ) && ( JS_GetClass( baseEntity ) == &JSI_BaseEntity::JSI_class ) )
data = (CBaseEntity*)JS_GetPrivate( g_ScriptingHost.getContext(), baseEntity );
}
bool CProperty_CBaseEntityPtr::rebuild( CProperty* parent, bool triggerFn )
{
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
return( false ); // CBaseEntity* properties aren't inheritable.
}
CProperty_CBaseEntityPtr::operator jsval()
{
JSObject* baseEntity = JS_NewObject( g_ScriptingHost.getContext(), &JSI_BaseEntity::JSI_class, NULL, NULL );
JS_SetPrivate( g_ScriptingHost.getContext(), baseEntity, data );
return( OBJECT_TO_JSVAL( baseEntity ) );
}
CProperty_CBaseEntityPtr::operator bool()
{
return( data != NULL );
}
CProperty_CBaseEntityPtr::operator CBaseEntity*()
{
return( data );
}
CBaseEntity& CProperty_CBaseEntityPtr::operator *() const
{
return( *data );
}
CBaseEntity* CProperty_CBaseEntityPtr::operator ->() const
{
return( data );
}
void IPropertyOwner::rebuild( CStr propertyName )
{
CProperty* thisProperty = m_properties[propertyName];
CProperty* baseProperty = NULL;
if( m_base )
{
if( m_base->m_properties.find( propertyName ) != m_base->m_properties.end() )
baseProperty = m_base->m_properties[propertyName];
}
if( thisProperty->rebuild( baseProperty ) )
{
std::vector<IPropertyOwner*>::iterator it;
for( it = m_inheritors.begin(); it != m_inheritors.end(); it++ )
(*it)->rebuild( propertyName );
}
}
void IPropertyOwner::rebuild()
{
STL_HASH_MAP<CStr,CProperty*,CStr_hash_compare>::iterator property;
if( m_base )
{
for( property = m_properties.begin(); property != m_properties.end(); property++ )
{ {
i32 current = toInteger(); CProperty* baseProperty = NULL;
releaseData(); if( m_base->m_properties.find( property->first ) != m_base->m_properties.end() )
m_integer = current; baseProperty = m_base->m_properties[property->first];
(property->second)->rebuild( baseProperty, false );
} }
break;
case PROP_FLOAT:
{
float current = toFloat();
releaseData();
m_float = current;
}
break;
case PROP_STRING:
{
CStr* current = new CStr( toString() );
releaseData();
m_string = current;
}
break;
case PROP_VECTOR:
{
CVector3D* current = new CVector3D( toVector() );
releaseData();
m_vector = current;
}
break;
case PROP_PTR:
{
void* current = toVoid();
releaseData();
m_ptr = current;
}
break;
default:
return;
} }
m_type = (EPropTypes)( type | PROP_TYPELOCKED ); else
}
void CGenericProperty::typeloose()
{
if( m_type & PROP_INTRINSIC ) return;
m_type = (EPropTypes)( m_type & ~PROP_TYPELOCKED );
}
i32& CGenericProperty::asInteger()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_INTEGER );
if( m_type & PROP_INTRINSIC )
return( *m_integerptr );
return( m_integer );
}
float& CGenericProperty::asFloat()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_FLOAT );
if( m_type & PROP_INTRINSIC )
return( *m_floatptr );
return( m_float );
}
CStr& CGenericProperty::asString()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_STRING );
return( *m_string );
}
CVector3D& CGenericProperty::asVector()
{
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_VECTOR );
return( *m_vector );
}
i32 CGenericProperty::toInteger()
{
switch( m_type & PROP_STRIPFLAGS )
{ {
case PROP_INTEGER: for( property = m_properties.begin(); property != m_properties.end(); property++ )
return( asInteger() ); (property->second)->rebuild( NULL, false );
case PROP_FLOAT:
return( (i32)asFloat() );
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( (i32)( asString().ToInt() ) );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
case PROP_PTR:
return( 0 );
default:
assert( 0 && "Invalid property type" );
} }
return( 0 );
std::vector<IPropertyOwner*>::iterator it;
for( it = m_inheritors.begin(); it != m_inheritors.end(); it++ )
(*it)->rebuild();
} }
float CGenericProperty::toFloat()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
return( (float)asInteger() );
case PROP_FLOAT:
return( asFloat() );
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( asString().ToFloat() );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
case PROP_PTR:
return( 0.0f );
default:
assert( 0 && "Invalid property type" );
}
return( 0.0f );
}
CStr CGenericProperty::toString()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
return( CStr( asInteger() ) );
case PROP_FLOAT:
return( CStr( asFloat() ) );
case PROP_STRING:
return( CStr( asString() ) );
case PROP_VECTOR:
{
char buffer[256];
snprintf( buffer, 250, "{ %f, %f, %f }", asVector().X, asVector().Y, asVector().Z );
return( CStr( buffer ) );
}
case PROP_PTR:
return CStr();
default:
assert( 0 && "Invalid property type" );
}
return CStr();
}
CVector3D CGenericProperty::toVector()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_VECTOR:
return( CVector3D( asVector() ) );
case PROP_INTEGER:
case PROP_FLOAT:
case PROP_STRING:
case PROP_PTR:
return CVector3D();
default:
assert( 0 && "Invalid property type" );
}
return CVector3D();
}
void* CGenericProperty::toVoid()
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_PTR:
return( m_ptr );
case PROP_INTEGER:
case PROP_INTEGER_INTRINSIC:
case PROP_FLOAT:
case PROP_FLOAT_INTRINSIC:
case PROP_STRING:
case PROP_STRING_INTRINSIC:
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
return( NULL );
default:
assert( 0 && "Invalid property type" );
}
return( NULL );
}
void CGenericProperty::fromInteger( i32 value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = value; return;
case PROP_FLOAT:
asFloat() = (float)value; return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromFloat( float value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = (i32)value; return;
case PROP_FLOAT:
asFloat() = value; return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromString( CStr& value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = value.ToInt(); return;
case PROP_FLOAT:
asFloat() = value.ToFloat(); return;
case PROP_STRING:
asString() = value; return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromVector( CVector3D& value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = 0; return;
case PROP_FLOAT:
asFloat() = 0.0f; return;
case PROP_STRING:
{
char buffer[256];
snprintf( buffer, 250, "{ %f, %f, %f }", value.X, value.Y, value.Z );
asString() = CStr( buffer );
}
return;
case PROP_VECTOR:
asVector() = CVector3D( value ); return;
case PROP_PTR:
m_ptr = NULL; return;
default:
assert( 0 && "Invalid property type" );
}
}
void CGenericProperty::fromVoid( void* value )
{
switch( m_type & PROP_STRIPFLAGS )
{
case PROP_INTEGER:
asInteger() = 0; return;
case PROP_FLOAT:
asFloat() = 0.0f; return;
case PROP_STRING:
asString() = CStr(); return;
case PROP_VECTOR:
asVector() = CVector3D(); return;
case PROP_PTR:
m_ptr = value; return;
default:
assert( 0 && "Invalid property type" );
}
}
/*
Here lies the old version of CGenericProperty. Will remove it when I know the new one works.
CGenericProperty::CGenericProperty()
{
m_type = PROP_INTEGER;
m_integer = 0;
}
CGenericProperty::CGenericProperty( i32 value )
{
m_type = PROP_INTEGER;
m_integer = value;
}
CGenericProperty::CGenericProperty( float value )
{
m_type = PROP_FLOAT;
m_float = value;
}
CGenericProperty::CGenericProperty( CStr& value )
{
m_type = PROP_STRING;
m_string = new CStr( value );
}
CGenericProperty::CGenericProperty( CVector3D& value )
{
m_type = PROP_VECTOR;
m_vector = new CVector3D( value );
}
CGenericProperty::CGenericProperty( void* value )
{
m_type = PROP_PTR;
m_ptr = value;
}
CGenericProperty::CGenericProperty( i32* value )
{
m_type = PROP_INTEGER_INTRINSIC;
m_integerptr = value;
}
CGenericProperty::CGenericProperty( float* value )
{
m_type = PROP_FLOAT_INTRINSIC;
m_floatptr = value;
}
CGenericProperty::CGenericProperty( CStr* value )
{
m_type = PROP_STRING_INTRINSIC;
m_string = value;
}
CGenericProperty::CGenericProperty( CVector3D* value )
{
m_type = PROP_VECTOR_INTRINSIC;
m_vector = value;
}
CGenericProperty::~CGenericProperty()
{
switch( m_type )
{
case PROP_STRING:
delete( m_string ); break;
case PROP_VECTOR:
delete( m_vector ); break;
default:
break;
}
}
CGenericProperty::operator CStr&()
{
char working[64];
switch( m_type )
{
case PROP_STRING:
case PROP_STRING_INTRINSIC:
return( *m_string );
case PROP_VECTOR:
case PROP_VECTOR_INTRINSIC:
snprintf( working, 63, "{ %f, %f, %f }", m_vector->X, m_vector->Y, m_vector->Z );
working[63] = 0;
return( CStr( working ) );
case PROP_INTEGER:
return( CStr( m_integer ) );
case PROP_INTEGER_INTRINSIC:
return( CStr( *m_integerptr ) );
case PROP_FLOAT:
return( CStr( m_float ) );
case PROP_FLOAT_INTRINSIC:
return( CStr( *m_floatptr ) );
default:
return CStr();
}
}
CGenericProperty::operator CVector3D()
{
switch( m_type )
{
case PROP_VECTOR:
return( *m_vector );
default:
return CVector3D();
}
}
CGenericProperty::operator i32()
{
switch( m_type )
{
case PROP_INTEGER:
return( m_integer );
case PROP_INTEGER_INTRINSIC:
return( *m_integerptr );
case PROP_FLOAT:
return( (i32)m_float );
case PROP_FLOAT_INTRINSIC:
return( (i32)*m_floatptr );
case PROP_STRING:
return( m_string->ToInt() );
default:
return( 0 );
}
}
CGenericProperty::operator float()
{
switch( m_type )
{
case PROP_INTEGER:
return( (float)m_integer );
case PROP_INTEGER_INTRINSIC:
return( (float)*m_integerptr );
case PROP_FLOAT:
return( m_float );
case PROP_FLOAT_INTRINSIC:
return( *m_floatptr );
case PROP_STRING:
return( m_string->ToFloat() );
default:
return( 0.0f );
}
}
CGenericProperty::operator void*()
{
switch( m_type )
{
case PROP_PTR:
return( m_ptr );
default:
return( NULL );
}
}
*/

View file

@ -17,6 +17,9 @@
#include "CStr.h" #include "CStr.h"
#include "Vector3D.h" #include "Vector3D.h"
#include "scripting/ScriptingHost.h"
#include "scripting/JSInterface_Entity.h"
#include "scripting/JSInterface_Vector3D.h"
#ifndef __GNUC__ #ifndef __GNUC__
@ -35,89 +38,126 @@
#endif #endif
class CGenericProperty class IPropertyOwner;
class CBaseEntity;
class CProperty;
struct SProperty_NumericModifier;
struct SProperty_StringModifier;
class CProperty
{
protected:
IPropertyOwner* m_owner;
void (IPropertyOwner::*m_updateFn)();
virtual void set( const jsval value ) = 0;
public:
CProperty& operator=( const jsval value );
virtual operator jsval() = 0;
virtual bool rebuild( CProperty* parent, bool triggerFn = true ) = 0; // Returns true if the rebuild changed the value of this property.
void associate( IPropertyOwner* owner, const CStr& name );
void associate( IPropertyOwner* owner, const CStr& name, void (IPropertyOwner::*updateFn)() );
};
class CProperty_i32 : public CProperty
{
i32 data;
SProperty_NumericModifier* modifier;
public:
CProperty_i32();
~CProperty_i32();
void set( const jsval value );
operator jsval();
bool rebuild( CProperty* parent, bool triggerFn = true );
CProperty_i32& operator=( const i32 value );
operator i32();
};
class CProperty_float : public CProperty
{
float data;
SProperty_NumericModifier* modifier;
public:
CProperty_float();
~CProperty_float();
void set( const jsval value );
operator jsval();
bool rebuild( CProperty* parent, bool triggerFn = true );
CProperty_float& operator=( const float& value );
operator float();
operator bool();
float operator+( float value );
float operator-( float value );
float operator*( float value );
float operator/( float value );
bool operator<( float value );
bool operator>( float value );
bool operator==( float value );
};
class CProperty_CStr : public CProperty, public CStr
{
SProperty_StringModifier* modifier;
public:
CProperty_CStr();
~CProperty_CStr();
void set( const jsval value );
operator jsval();
bool rebuild( CProperty* parent, bool triggerFn = true );
CProperty_CStr& operator=( const CStr& value );
};
class CProperty_CVector3D : public CProperty, public CVector3D
{ {
public: public:
enum EPropTypes void set( const jsval value );
{ operator jsval();
PROP_INTRINSIC = 256, bool rebuild( CProperty* parent, bool triggerFn = true );
PROP_TYPELOCKED = 512, CProperty_CVector3D& operator=( const CVector3D& value );
PROP_STRIPFLAGS = 255, };
PROP_INTEGER = 0,
PROP_FLOAT, class CProperty_CBaseEntityPtr : public CProperty
PROP_STRING, {
PROP_VECTOR, CBaseEntity* data;
PROP_PTR,
PROP_INTEGER_INTRINSIC = PROP_INTEGER | PROP_INTRINSIC,
PROP_FLOAT_INTRINSIC = PROP_FLOAT | PROP_INTRINSIC,
PROP_STRING_INTRINSIC = PROP_STRING | PROP_INTRINSIC,
PROP_VECTOR_INTRINSIC = PROP_VECTOR | PROP_INTRINSIC
};
EPropTypes m_type;
private:
union
{
i32 m_integer;
i32* m_integerptr;
float m_float;
float* m_floatptr;
CStr* m_string;
CVector3D* m_vector;
void* m_ptr;
};
public: public:
CGenericProperty(); // Create an integer property containing 0. void set( const jsval value );
~CGenericProperty(); operator jsval();
void releaseData(); bool rebuild( CProperty* parent, bool triggerFn = true );
operator CBaseEntity*();
operator bool();
CBaseEntity& operator*() const;
CBaseEntity* operator->() const;
CProperty_CBaseEntityPtr& operator=( CBaseEntity* value );
};
// Associator functions: Links the property with the specified engine variable. // e.g. Entities and their templates.
void associate( i32* value ); class IPropertyOwner
void associate( float* value ); {
void associate( CStr* value ); public:
void associate( CVector3D* value ); CProperty_CBaseEntityPtr m_base;
STL_HASH_MAP<CStr,CProperty*,CStr_hash_compare> m_properties;
// Getter functions: Attempts to convert the property to the given type. std::vector<IPropertyOwner*> m_inheritors;
operator i32(); // Convert to an integer if possible (integer, float, some strings), otherwise returns 0. void rebuild( CStr propName ); // Recursively rebuild just the named property over the inheritance tree.
operator float(); // Convert to a float if possible (integer, float, some strings), otherwise returns 0.0f. void rebuild(); // Recursively rebuild everything over the inheritance tree.
operator CStr(); // Convert to a string if possible (all except generic pointer), otherwise returns CStr(). };
operator CVector3D(); // If this property is a vector, returns that vector, otherwise returns CVector3D().
operator void*(); // If this property is a generic pointer, returns that pointer, otherwise returns NULL.
// Setter functions: If this is a typelocked property, attempts to convert the given data struct SProperty_NumericModifier
// into the appropriate type, otherwise setting the associated value to 0, 0.0f, CStr() or CVector3D(). {
// If this property is typeloose, converts this property into one of the same type float multiplicative;
// as the given value, then stores that value in this property. float additive;
CGenericProperty& operator=( i32 value ); void operator=( float value )
CGenericProperty& operator=( float value ); {
CGenericProperty& operator=( CStr& value ); multiplicative = 0.0f;
CGenericProperty& operator=( CVector3D& value ); additive = value;
CGenericProperty& operator=( void* value ); // Be careful with this one. A lot of things will cast to void*. }
// Especially pointers you meant to associate(). };
// Typelock functions. Use these when you want to make sure the property has the given type. struct SProperty_StringModifier
void typelock( EPropTypes type ); {
void typeloose(); CStr replacement;
void operator=( const CStr& value )
private: {
// resolve-as functions. References the data, whereever it is. replacement = value;
i32& asInteger(); }
float& asFloat();
CStr& asString();
CVector3D& asVector();
// to functions. Convert whatever this is now to the chosen type.
i32 toInteger();
float toFloat();
CStr toString();
CVector3D toVector();
void* toVoid();
// from functions. Convert the given value to whatever type this is now.
void fromInteger( i32 value );
void fromFloat( float value );
void fromString( CStr& value );
void fromVector( CVector3D& value );
void fromVoid( void* value );
}; };
#endif #endif

View file

@ -16,12 +16,18 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
float len = delta.length(); float len = delta.length();
// janwas added EVIL HACK: BoundsChecker complains about NaNs // ... 'Are we there yet?' ...
// in atan2 and fabs => delta must be 0 somewhere.
// currently skip over all math code that would break. if( len < 0.1f )
// what's the real solution? {
if(len == 0.0f) if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
goto small_delta; {
repath();
}
else
m_orderQueue.pop_front();
return( false );
}
// Curve smoothing. // Curve smoothing.
// Here there be trig. // Here there be trig.
@ -44,7 +50,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
{ {
m_targetorientation = atan2( delta.x, delta.y ); m_targetorientation = atan2( delta.x, delta.y );
float deltatheta = m_targetorientation - m_orientation; float deltatheta = m_targetorientation - (float)m_orientation;
while( deltatheta > PI ) deltatheta -= 2 * PI; while( deltatheta > PI ) deltatheta -= 2 * PI;
while( deltatheta < -PI ) deltatheta += 2 * PI; while( deltatheta < -PI ) deltatheta += 2 * PI;
@ -53,10 +59,10 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
float maxTurningSpeed = ( m_speed / m_turningRadius ) * timestep; float maxTurningSpeed = ( m_speed / m_turningRadius ) * timestep;
if( deltatheta > 0 ) if( deltatheta > 0 )
{ {
m_orientation += MIN( deltatheta, maxTurningSpeed ); m_orientation = m_orientation + MIN( deltatheta, maxTurningSpeed );
} }
else else
m_orientation += MAX( deltatheta, -maxTurningSpeed ); m_orientation = m_orientation + MAX( deltatheta, -maxTurningSpeed );
m_ahead.x = sin( m_orientation ); m_ahead.x = sin( m_orientation );
m_ahead.y = cos( m_orientation ); m_ahead.y = cos( m_orientation );
@ -68,33 +74,11 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
} }
} }
if( len < 0.1f )
{
small_delta:
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
{
// Repath.
CVector2D destination;
while( !m_orderQueue.empty() &&
( ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_COLLISION )
|| ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_NOPATHING )
|| ( m_orderQueue.front().m_type == CEntityOrder::ORDER_GOTO_SMOOTHED ) ) )
{
destination = m_orderQueue.front().m_data[0].location;
m_orderQueue.pop_front();
}
g_Pathfinder.requestPath( me, destination );
}
else
m_orderQueue.pop_front();
return( false );
}
if( m_bounds->m_type == CBoundingObject::BOUND_OABB ) if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
((CBoundingBox*)m_bounds)->setOrientation( m_ahead ); ((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
float scale = timestep * m_speed; float scale = m_speed * timestep;
if( scale > len ) if( scale > len )
scale = len; scale = len;

View file

@ -5,8 +5,6 @@
sparsePathTree::sparsePathTree( const CVector2D& _from, const CVector2D& _to, HEntity _entity, CBoundingObject* _destinationCollisionObject ) sparsePathTree::sparsePathTree( const CVector2D& _from, const CVector2D& _to, HEntity _entity, CBoundingObject* _destinationCollisionObject )
{ {
from = _from; to = _to; from = _from; to = _to;
assert( from.length() > 0.01f );
assert( to.length() > 0.01f );
entity = _entity; destinationCollisionObject = _destinationCollisionObject; entity = _entity; destinationCollisionObject = _destinationCollisionObject;
leftPre = NULL; leftPost = NULL; leftPre = NULL; leftPost = NULL;
@ -46,7 +44,7 @@ bool sparsePathTree::slice()
float turningRadius = ( entity->m_bounds->m_radius + r.boundingObject->m_radius ) * 1.1f; float turningRadius = ( entity->m_bounds->m_radius + r.boundingObject->m_radius ) * 1.1f;
if( turningRadius < entity->m_turningRadius ) turningRadius = entity->m_turningRadius; if( entity->m_turningRadius > turningRadius ) turningRadius = entity->m_turningRadius;
// Too close, an impossible turn // Too close, an impossible turn
if( r.distance < turningRadius ) if( r.distance < turningRadius )

View file

@ -0,0 +1,68 @@
#include "precompiled.h"
#include "JSInterface_BaseEntity.h"
#include "BaseEntity.h"
#include "EntityHandles.h"
JSClass JSI_BaseEntity::JSI_class = {
"EntityTemplate", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
JSI_BaseEntity::getProperty, JSI_BaseEntity::setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, NULL,
NULL, NULL, NULL, NULL
};
JSPropertySpec JSI_BaseEntity::JSI_props[] =
{
{ 0 }
};
JSFunctionSpec JSI_BaseEntity::JSI_methods[] =
{
{ "toString", JSI_BaseEntity::toString, 0, 0, 0 },
{ 0 }
};
JSBool JSI_BaseEntity::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
CStr propName = g_ScriptingHost.ValueToString( id );
if( e->m_properties.find( propName ) != e->m_properties.end() )
{
*vp = *(e->m_properties[propName]);
return( JS_TRUE );
}
return( JS_TRUE );
}
JSBool JSI_BaseEntity::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
CStr propName = g_ScriptingHost.ValueToString( id );
if( e->m_properties.find( propName ) != e->m_properties.end() )
{
*(e->m_properties[propName]) = *vp;
e->rebuild( propName );
return( JS_TRUE );
}
return( JS_TRUE );
}
void JSI_BaseEntity::init()
{
g_ScriptingHost.DefineCustomObjectType( &JSI_class, NULL, 0, JSI_props, JSI_methods, NULL, NULL );
}
JSBool JSI_BaseEntity::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
{
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
char buffer[256];
snprintf( buffer, 256, "[object EntityTemplate: %s]", (const TCHAR*)e->m_name );
buffer[255] = 0;
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
return( JS_TRUE );
}

View file

@ -0,0 +1,30 @@
// JSInterface_BaseEntity.h
//
// Last modified: 08 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
//
// An interface between CBaseEntity and the JavaScript class EntityTemplate
//
// Usage: Used when manipulating objects of class 'EntityTemplate' in JavaScript.
//
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
#include "scripting/ScriptingHost.h"
#ifndef JSI_BASEENTITY_INCLUDED
#define JSI_BASEENTITY_INCLUDED
namespace JSI_BaseEntity
{
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
extern JSClass JSI_class;
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
JSBool addProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool delProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
void finalize( JSContext* cx, JSObject* obj );
void init();
};
#endif

View file

@ -0,0 +1,136 @@
#include "precompiled.h"
#include "JSInterface_Entity.h"
#include "scripting/JSInterface_BaseEntity.h"
#include "scripting/JSInterface_Vector3D.h"
#include "EntityHandles.h"
#include "Entity.h"
#include "EntityManager.h"
#include "BaseEntityCollection.h"
#include "CConsole.h"
JSClass JSI_Entity::JSI_class = {
"Entity", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub,
JSI_Entity::getProperty, JSI_Entity::setProperty,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, JSI_Entity::finalize,
NULL, NULL, NULL, NULL
};
JSPropertySpec JSI_Entity::JSI_props[] =
{
{ 0 }
};
JSFunctionSpec JSI_Entity::JSI_methods[] =
{
{ "toString", JSI_Entity::toString, 0, 0, 0 },
{ 0 }
};
JSBool JSI_Entity::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
if( !e )
{
*vp = JSVAL_NULL;
return( JS_TRUE );
}
CStr propName = g_ScriptingHost.ValueToString( id );
if( (*e)->m_properties.find( propName ) != (*e)->m_properties.end() )
{
*vp = *((*e)->m_properties[propName]);
return( JS_TRUE );
}
return( JS_TRUE );
}
JSBool JSI_Entity::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
{
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
CStr propName = g_ScriptingHost.ValueToString( id );
if( (*e)->m_properties.find( propName ) != (*e)->m_properties.end() )
{
*((*e)->m_properties[propName]) = *vp;
(*e)->rebuild( propName );
return( JS_TRUE );
}
return( JS_TRUE );
}
JSBool JSI_Entity::construct( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval )
{
assert( argc >= 2 );
CBaseEntity* baseEntity;
CVector3D position;
float orientation = 0.0f;
JSObject* jsBaseEntity = JSVAL_TO_OBJECT( argv[0] );
if( JSVAL_IS_OBJECT( argv[0] ) && ( JS_GetClass( jsBaseEntity ) == &JSI_BaseEntity::JSI_class ) )
{
baseEntity = (CBaseEntity*)JS_GetPrivate( cx, jsBaseEntity );
}
else
{
CStr templateName;
try
{
templateName = g_ScriptingHost.ValueToString( argv[0] );
}
catch( ... )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
baseEntity = g_EntityTemplateCollection.getTemplate( templateName );
}
if( !baseEntity )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
}
JSObject* jsVector3D = JSVAL_TO_OBJECT( argv[1] );
if( JSVAL_IS_OBJECT( argv[1] ) && ( JS_GetClass( jsVector3D ) == &JSI_Vector3D::JSI_class ) )
position = *( ( (JSI_Vector3D::Vector3D_Info*)JS_GetPrivate( cx, jsVector3D ) )->vector );
if( argc >= 3 )
{
try
{
orientation = (float)g_ScriptingHost.ValueToDouble( argv[2] );
}
catch( ... )
{
orientation = 0.0f;
}
}
HEntity* handle = new HEntity( g_EntityManager.create( baseEntity, position, orientation ) );
(*handle)->dispatch( &CMessage( CMessage::EMSG_INIT ) );
JSObject* entity = JS_NewObject( cx, &JSI_Entity::JSI_class, NULL, NULL );
JS_SetPrivate( cx, entity, handle );
*rval = OBJECT_TO_JSVAL( entity );
return( JS_TRUE );
}
void JSI_Entity::finalize( JSContext* cx, JSObject* obj )
{
delete( JS_GetPrivate( cx, obj ) );
}
void JSI_Entity::init()
{
g_ScriptingHost.DefineCustomObjectType( &JSI_class, construct, 2, JSI_props, JSI_methods, NULL, NULL );
}
JSBool JSI_Entity::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
{
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
char buffer[256];
snprintf( buffer, 256, "[object Entity: \"%s\" (%s)]", (const TCHAR*)(*e)->m_name, (const TCHAR*)(*e)->m_base->m_name );
buffer[255] = 0;
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
return( JS_TRUE );
}

View file

@ -0,0 +1,31 @@
// JSInterface_Entity.h
//
// Last modified: 03 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
//
// The interface layer between JavaScript code and the actual CEntity object.
//
// Usage: Used when manipulating objects of class 'Entity' in JavaScript.
//
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
#include "scripting/ScriptingHost.h"
#ifndef JSI_ENTITY_INCLUDED
#define JSI_ENTITY_INCLUDED
namespace JSI_Entity
{
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
extern JSClass JSI_class;
extern JSPropertySpec JSI_props[];
extern JSFunctionSpec JSI_methods[];
JSBool addProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool delProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
JSBool construct( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval );
void finalize( JSContext* cx, JSObject* obj );
void init();
};
#endif

View file

@ -23,6 +23,7 @@ package.files = {
{ sourcesfromdirs("../../ps") }, { sourcesfromdirs("../../ps") },
-- simulation/ -- simulation/
{ sourcesfromdirs("../../simulation") }, { sourcesfromdirs("../../simulation") },
{ sourcesfromdirs("../../simulation/scripting") },
-- lib/ -- lib/
{ sourcesfromdirs( { sourcesfromdirs(
"../../lib", "../../lib",
@ -34,6 +35,7 @@ package.files = {
-- maths/ -- maths/
{ sourcesfromdirs( { sourcesfromdirs(
"../../maths") }, "../../maths") },
{ sourcesfromdirs( "../../maths/scripting" ) },
-- renderer/ -- renderer/
{ sourcesfromdirs( { sourcesfromdirs(
"../../renderer") }, "../../renderer") },