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 "ogl.h"
#include "res/tex.h"
#include "TextureEntry.h"

View File

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

View File

@ -42,10 +42,14 @@
#include "PathfindEngine.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"
#ifndef NO_GUI
#include "gui/GUI.h"
#endif
@ -431,7 +435,7 @@ void ParseArgs(int argc, char* argv[])
}
break;
case 'e':
g_EntGraph = true;
g_EntGraph = true; break;
case 'v':
g_VSync = true;
break;
@ -622,7 +626,7 @@ PREVTSC=TSC;
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
new CRenderer;
@ -653,6 +657,10 @@ PREVTSC=TSC;
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
// development. that means loading no map at all is currently impossible.

View File

@ -22,7 +22,7 @@ class CVector3D
float X, Y, Z;
public:
CVector3D () { }
CVector3D () { X = 0.0f; Y = 0.0f; Z = 0.0f; }
CVector3D (float x, float y, float z);
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 "sysdep/sysdep.h"
#include "scripting/ScriptingHost.h"
CConsole::CConsole(float X, float Y, float W, float 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.
void CConsole::InsertChar(const int szChar)
void CConsole::InsertChar(const int szChar, const int cooked )
{
static int iHistoryPos = -1;
@ -321,15 +323,16 @@ void CConsole::InsertChar(const int szChar)
default: //Insert a character
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?
m_szBuffer[m_iBufferPos] = szChar; //cat char onto end
m_szBuffer[m_iBufferPos] = cooked; //cat char onto end
else{ //we need to insert
int i;
for(i=m_iBufferLength; i>m_iBufferPos; i--)
m_szBuffer[i] = m_szBuffer[i-1]; // move chars to right
m_szBuffer[i] = szChar;
m_szBuffer[i] = cooked;
}
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);
delete[] szCommand;
@ -425,6 +440,6 @@ bool conInputHandler(const SDL_Event& ev)
if(ev.type != SDL_KEYDOWN)
return false;
g_Console->InsertChar(ev.key.keysym.sym);
g_Console->InsertChar(ev.key.keysym.sym, ev.key.keysym.unicode );
return g_Console->IsActive();
}

View File

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

View File

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

View File

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

View File

@ -26,14 +26,14 @@ public:
// 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
float BackToFrontIndexSort(CMatrix3D& objToCam);
// submit a model to render this frame
static void Submit(CModel* model);
// clear per frame patch list
static void ClearSubmissions() { m_Models.clear(); }
// render all submitted models
static void RenderModels(u32 streamflags);
// submit a model to render this frame
static void Submit(CModel* model);
// clear per frame patch list
static void ClearSubmissions() { m_Models.clear(); }
// render all submitted models
static void RenderModels(u32 streamflags);
private:
// build this renderdata object
@ -42,8 +42,8 @@ private:
void BuildVertices();
void BuildIndices();
// submit batches for this model to the vertex buffer
void SubmitBatches();
// submit batches for this model to the vertex buffer
void SubmitBatches();
struct SVertex {
// vertex position
@ -66,8 +66,8 @@ private:
u16* m_Indices;
// model render flags
u32 m_Flags;
// list of all submitted models
static std::vector<CModel*> m_Models;
// list of all submitted models
static std::vector<CModel*> m_Models;
};

View File

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

View File

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

View File

@ -25,7 +25,7 @@
#include "PatchRData.h"
#include "Texture.h"
#include "LightEnv.h"
#include "CLogger.h"
#include "CLogger.h"
#include "Model.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.width=width;
header.height=height;
header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0;
header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0;
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
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()
{
m_Width=0;
@ -106,18 +106,18 @@ CRenderer::CRenderer()
m_ModelRenderMode=SOLID;
m_ClearColor[0]=m_ClearColor[1]=m_ClearColor[2]=m_ClearColor[3]=0;
m_ShadowMap=0;
m_Options.m_NoVBO=false;
m_Options.m_Shadows=true;
m_Options.m_ShadowColor=RGBAColor(0.4f,0.4f,0.4f,1.0f);
for (uint i=0;i<MaxTextureUnits;i++) {
m_ActiveTextures[i]=0;
}
for (uint i=0;i<MaxTextureUnits;i++) {
m_ActiveTextures[i]=0;
}
}
///////////////////////////////////////////////////////////////////////////////////
// CRenderer destructor
///////////////////////////////////////////////////////////////////////////////////
// CRenderer destructor
CRenderer::~CRenderer()
{
}
@ -166,13 +166,13 @@ bool CRenderer::Open(int width, int height, int depth)
// query card capabilities
EnumCaps();
GLint bits;
glGetIntegerv(GL_DEPTH_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits);
glGetIntegerv(GL_STENCIL_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits);
glGetIntegerv(GL_ALPHA_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits);
GLint bits;
glGetIntegerv(GL_DEPTH_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits);
glGetIntegerv(GL_STENCIL_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits);
glGetIntegerv(GL_ALPHA_BITS,&bits);
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits);
return true;
}
@ -184,10 +184,10 @@ void CRenderer::Close()
// resize renderer view
void CRenderer::Resize(int width,int height)
{
if (m_ShadowMap && (width>m_Width || height>m_Height)) {
glDeleteTextures(1,(GLuint*) &m_ShadowMap);
m_ShadowMap=0;
}
if (m_ShadowMap && (width>m_Width || height>m_Height)) {
glDeleteTextures(1,(GLuint*) &m_ShadowMap);
m_ShadowMap=0;
}
m_Width=width;
m_Height=height;
}
@ -270,7 +270,7 @@ void CRenderer::BeginFrame()
}
// init per frame stuff
m_ShadowRendered=false;
m_ShadowRendered=false;
m_ShadowBound.SetEmpty();
}
@ -400,7 +400,7 @@ void CRenderer::CalcShadowMatrices()
// shift near and far clip planes slightly to avoid artifacts with points
// 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;
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
m_ShadowMapWidth=m_Width;
m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth);
m_ShadowMapHeight=m_Height;
m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight);
m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth);
m_ShadowMapHeight=m_Height;
m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight);
// create texture object - initially filled with white, so clamp to edge clamps to correct color
glGenTextures(1,(GLuint*) &m_ShadowMap);
BindTexture(0,(GLuint) m_ShadowMap);
u32 size=m_ShadowMapWidth*m_ShadowMapHeight;
u32* buf=new u32[size];
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);
delete[] buf;
BindTexture(0,(GLuint) m_ShadowMap);
u32 size=m_ShadowMapWidth*m_ShadowMapHeight;
u32* buf=new u32[size];
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);
delete[] buf;
// set texture parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -578,7 +578,7 @@ void CRenderer::RenderShadowMap()
if (!m_ShadowMap) CreateShadowMap();
// 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);
// build required matrices
@ -636,27 +636,27 @@ void CRenderer::RenderShadowMap()
glEnable(GL_SCISSOR_TEST);
glScissor(1,1,m_Width-2,m_Height-2);
glActiveTexture(GL_TEXTURE0);
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_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
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_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);
glColor4fv(m_Options.m_ShadowColor);
glDisable(GL_CULL_FACE);
glColor4fv(m_Options.m_ShadowColor);
glDisable(GL_CULL_FACE);
// render models
CModelRData::RenderModels(STREAM_POS);
// call on the transparency renderer to render all the transparent stuff
g_TransparencyRenderer.RenderShadows();
glEnable(GL_CULL_FACE);
glEnable(GL_CULL_FACE);
glColor3f(1.0f,1.0f,1.0f);
@ -675,46 +675,46 @@ void CRenderer::RenderShadowMap()
if (0)
{
#if 1
#if 1
// 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))
unsigned char* data=new unsigned char[m_ShadowMapWidth*m_ShadowMapHeight*3];
glGetTexImage(GL_TEXTURE_2D,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,data);
saveTGA("d:\\test4.tga",m_ShadowMapWidth,m_ShadowMapHeight,24,data);
delete[] data;
#else
unsigned char* data=new unsigned char[m_Width*m_Height*4];
glReadBuffer(GL_BACK);
glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data);
saveTGA("d:\\test3.tga",m_Width,m_Height,32,data);
delete[] data;
#endif
#else
unsigned char* data=new unsigned char[m_Width*m_Height*4];
glReadBuffer(GL_BACK);
glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data);
saveTGA("d:\\test3.tga",m_Width,m_Height,32,data);
delete[] data;
#endif
}
}
void CRenderer::ApplyShadowMap()
{
CMatrix3D tmp2;
CMatrix3D texturematrix;
float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth);
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
tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5)
texturematrix=texturematrix*tmp2;
texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1)
texturematrix=texturematrix*m_LightTransform; // transform world -> light space
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(&texturematrix._11);
glMatrixMode(GL_MODELVIEW);
CMatrix3D tmp2;
CMatrix3D texturematrix;
float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth);
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
tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5)
texturematrix=texturematrix*tmp2;
texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1)
texturematrix=texturematrix*m_LightTransform; // transform world -> light space
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(&texturematrix._11);
glMatrixMode(GL_MODELVIEW);
CPatchRData::ApplyShadowMap(m_ShadowMap);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void CRenderer::RenderPatches()
@ -731,8 +731,8 @@ void CRenderer::RenderPatches()
// switch wireframe off again
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
} 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:
// first switch on wireframe
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
@ -778,42 +778,42 @@ void CRenderer::RenderPatches()
// restore fill mode, and we're done
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
*/
}
*/
}
}
void CRenderer::RenderModelSubmissions()
{
// set up texture environment for base pass - modulate texture and primary color
glActiveTexture(GL_TEXTURE0);
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_SOURCE0_RGB_ARB, GL_TEXTURE);
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_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// 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_SOURCE0_ALPHA_ARB, GL_ONE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
// set up texture environment for base pass - modulate texture and primary color
glActiveTexture(GL_TEXTURE0);
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_SOURCE0_RGB_ARB, GL_TEXTURE);
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_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// 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_SOURCE0_ALPHA_ARB, GL_ONE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
// setup client states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render models
// render models
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
// switch off client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
void CRenderer::RenderModels()
{
{
// switch on wireframe if we need it
if (m_ModelRenderMode==WIREFRAME) {
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
@ -887,11 +887,11 @@ void CRenderer::FlushFrame()
// render submitted patches and models
RenderPatches();
RenderModels();
if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap();
m_ShadowRendered=true;
// call on the transparency renderer to render all the transparent stuff
g_TransparencyRenderer.Render();
if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap();
m_ShadowRendered=true;
// call on the transparency renderer to render all the transparent stuff
g_TransparencyRenderer.Render();
// empty lists
g_TransparencyRenderer.Clear();
@ -899,22 +899,22 @@ void CRenderer::FlushFrame()
CModelRData::ClearSubmissions();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// EndFrame: signal frame end; implicitly flushes batched objects
void CRenderer::EndFrame()
{
FlushFrame();
g_Renderer.SetTexture(0,0);
static bool once=false;
if (!once && glGetError()) {
CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n");
once=true;
g_Renderer.SetTexture(0,0);
static bool once=false;
if (!once && glGetError()) {
CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n");
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)
{
CMatrix3D view;
@ -935,16 +935,16 @@ void CRenderer::SetCamera(CCamera& camera)
void CRenderer::Submit(CPatch* patch)
{
CPatchRData::Submit(patch);
CPatchRData::Submit(patch);
}
void CRenderer::Submit(CModel* model)
{
if (1 /*ThisModelCastsShadows*/) {
m_ShadowBound+=model->GetBounds();
}
CModelRData::Submit(model);
{
if (1 /*ThisModelCastsShadows*/) {
m_ShadowBound+=model->GetBounds();
}
CModelRData::Submit(model);
}
void CRenderer::Submit(CSprite* sprite)
@ -966,14 +966,14 @@ void CRenderer::RenderPatchSubmissions()
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render everything
CPatchRData::RenderBaseSplats();
// render everything
CPatchRData::RenderBaseSplats();
CPatchRData::RenderBlendSplats();
// switch off all client states
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_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 {
h=tex_load(texture->GetName());
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);
return false;
} else {
int tw,th;
tex_info(h, &tw, &th, NULL, NULL, NULL);
tw&=(tw-1);
th&=(th-1);
if (tw || th) {
texture->SetHandle(0xffffffff);
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
return false;
} else {
BindTexture(0,tex_id(h));
int tw,th;
tex_info(h, &tw, &th, NULL, NULL, NULL);
tw&=(tw-1);
th&=(th-1);
if (tw || th) {
texture->SetHandle(0xffffffff);
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
return false;
} else {
BindTexture(0,tex_id(h));
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
if (wrapflags) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
} else {
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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
texture->SetHandle(h);
return true;
return true;
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BindTexture: bind a GL texture object to current active unit
void CRenderer::BindTexture(int unit,GLuint tex)
{
#if 0
{
#if 0
glActiveTexture(GL_TEXTURE0+unit);
if (tex==m_ActiveTextures[unit]) return;
if (tex) {
glBindTexture(GL_TEXTURE_2D,tex);
if (tex) {
glBindTexture(GL_TEXTURE_2D,tex);
if (!m_ActiveTextures[unit]) {
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
}
} else if (m_ActiveTextures[unit]) {
glDisable(GL_TEXTURE_2D);
}
m_ActiveTextures[unit]=tex;
#endif
glActiveTexture(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D,tex);
if (tex) {
glEnable(GL_TEXTURE_2D);
} else {
glDisable(GL_TEXTURE_2D);
}
m_ActiveTextures[unit]=tex;
m_ActiveTextures[unit]=tex;
#endif
glActiveTexture(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D,tex);
if (tex) {
glEnable(GL_TEXTURE_2D);
} else {
glDisable(GL_TEXTURE_2D);
}
m_ActiveTextures[unit]=tex;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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)
{
{
if (texture) {
Handle h=texture->GetHandle();
BindTexture(unit,tex_id(h));

View File

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

View File

@ -1,11 +1,11 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: TransparencyRenderer.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// Name: TransparencyRenderer.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include <algorithm>
@ -38,8 +38,8 @@ void CTransparencyRenderer::Sort()
// Render: render all deferred passes; call Sort before using to ensure passes
// are drawn in correct order
void CTransparencyRenderer::Render()
{
if (m_Objects.size()==0) return;
{
if (m_Objects.size()==0) return;
// switch on wireframe if we need it
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
@ -63,24 +63,24 @@ void CTransparencyRenderer::Render()
glEnable(GL_ALPHA_TEST);
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);
RenderObjectsStreams(STREAM_POS|STREAM_UV0);
glColorMask(1,1,1,1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glColorMask(1,1,1,1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(0);
glAlphaFunc(GL_GREATER,0);
// 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_SOURCE0_RGB_ARB, GL_TEXTURE);
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_OPERAND1_RGB_ARB, GL_SRC_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_SOURCE0_RGB_ARB, GL_TEXTURE);
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_OPERAND1_RGB_ARB, GL_SRC_COLOR);
RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0);
@ -155,8 +155,8 @@ void CTransparencyRenderer::Add(CModel* model)
void CTransparencyRenderer::RenderShadows()
{
if (m_Objects.size()==0) return;
if (m_Objects.size()==0) return;
// switch on client states
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -174,7 +174,7 @@ void CTransparencyRenderer::RenderShadows()
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
RenderObjectsStreams(STREAM_POS|STREAM_UV0);
glDepthMask(1);
glDisable(GL_BLEND);

View File

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

View File

@ -1,184 +1,185 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: VertexBuffer.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include "ogl.h"
#include "Renderer.h"
#include "VertexBuffer.h"
///////////////////////////////////////////////////////////////////////////////
// shared list of all free batch objects
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches;
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer constructor
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;
// allocate raw buffer
if (g_Renderer.m_Caps.m_VBO) {
glGenBuffersARB(1,&m_Handle);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
} else {
m_SysMem=new u8[MAX_VB_SIZE_BYTES];
}
// create sole free chunk
VBChunk* chunk=new VBChunk;
chunk->m_Owner=this;
chunk->m_Count=m_FreeVertices;
chunk->m_Index=0;
m_FreeList.push_front(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer destructor
CVertexBuffer::~CVertexBuffer()
{
if (m_Handle) {
glDeleteBuffersARB(1,&m_Handle);
} 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
// 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;
// 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;
typedef std::list<VBChunk*>::iterator Iter;
for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) {
chunk=*iter;
if (numVertices<=chunk->m_Count) {
// remove this chunk from the free list
size_t size1=m_FreeList.size();
m_FreeList.erase(iter);
size_t size2=m_FreeList.size();
// no need to search further ..
break;
}
}
if (!chunk) {
// 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
VBChunk* newchunk=new VBChunk;
newchunk->m_Owner=this;
newchunk->m_Count=chunk->m_Count-numVertices;
newchunk->m_Index=chunk->m_Index+numVertices;
m_FreeList.push_front(newchunk);
// resize given chunk, resize total available free vertices
chunk->m_Count=numVertices;
m_FreeVertices-=numVertices;
// return found chunk
return 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
// excessive fragmentation of vertex buffer space
m_FreeList.push_front(chunk);
m_FreeVertices+=chunk->m_Count;
}
///////////////////////////////////////////////////////////////////////////////
// ClearBatchIndices: clear lists of all batches
void CVertexBuffer::ClearBatchIndices()
{
for (uint i=0;i<m_Batches.size();i++) {
m_Batches[i]->m_IndexData.clear();
m_FreeBatches.push_back(m_Batches[i]);
}
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)
{
// try and find a batch using this texture
size_t i;
Batch* batch=0;
for (i=0;i<m_Batches.size();++i) {
if (m_Batches[i]->m_Texture==texture) {
batch=m_Batches[i];
break;
}
}
if (!batch) {
if (m_FreeBatches.size()) {
batch=m_FreeBatches.back();
m_FreeBatches.pop_back();
} else {
batch=new Batch;
}
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();
batch->m_IndexData.resize(cursize+1);
// store batch
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)
{
if (g_Renderer.m_Caps.m_VBO) {
assert(m_Handle);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data);
} else {
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
u8* CVertexBuffer::Bind()
{
u8* base;
if (g_Renderer.m_Caps.m_VBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
base=(u8*) 0;
} else {
base=(u8*) m_SysMem;
}
return base;
///////////////////////////////////////////////////////////////////////////////
//
// Name: VertexBuffer.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include "ogl.h"
#include "Renderer.h"
#include "VertexBuffer.h"
///////////////////////////////////////////////////////////////////////////////
// shared list of all free batch objects
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches;
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer constructor
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;
// allocate raw buffer
if (g_Renderer.m_Caps.m_VBO) {
glGenBuffersARB(1,&m_Handle);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
} else {
m_SysMem=new u8[MAX_VB_SIZE_BYTES];
}
// create sole free chunk
VBChunk* chunk=new VBChunk;
chunk->m_Owner=this;
chunk->m_Count=m_FreeVertices;
chunk->m_Index=0;
m_FreeList.push_front(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// CVertexBuffer destructor
CVertexBuffer::~CVertexBuffer()
{
if (m_Handle) {
glDeleteBuffersARB(1,&m_Handle);
} 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
// 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;
// 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;
typedef std::list<VBChunk*>::iterator Iter;
for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) {
chunk=*iter;
if (numVertices<=chunk->m_Count) {
// remove this chunk from the free list
size_t size1=m_FreeList.size();
m_FreeList.erase(iter);
size_t size2=m_FreeList.size();
// no need to search further ..
break;
}
}
if (!chunk) {
// 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
VBChunk* newchunk=new VBChunk;
newchunk->m_Owner=this;
newchunk->m_Count=chunk->m_Count-numVertices;
newchunk->m_Index=chunk->m_Index+numVertices;
m_FreeList.push_front(newchunk);
// resize given chunk, resize total available free vertices
chunk->m_Count=numVertices;
m_FreeVertices-=numVertices;
// return found chunk
return 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
// excessive fragmentation of vertex buffer space
m_FreeList.push_front(chunk);
m_FreeVertices+=chunk->m_Count;
}
///////////////////////////////////////////////////////////////////////////////
// ClearBatchIndices: clear lists of all batches
void CVertexBuffer::ClearBatchIndices()
{
for (uint i=0;i<m_Batches.size();i++) {
m_Batches[i]->m_IndexData.clear();
m_FreeBatches.push_back(m_Batches[i]);
}
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)
{
// try and find a batch using this texture
size_t i;
Batch* batch=0;
for (i=0;i<m_Batches.size();++i) {
if (m_Batches[i]->m_Texture==texture) {
batch=m_Batches[i];
break;
}
}
if (!batch) {
if (m_FreeBatches.size()) {
batch=m_FreeBatches.back();
m_FreeBatches.pop_back();
} else {
batch=new Batch;
}
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();
batch->m_IndexData.resize(cursize+1);
// store batch
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)
{
if (g_Renderer.m_Caps.m_VBO) {
assert(m_Handle);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data);
} else {
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
u8* CVertexBuffer::Bind()
{
u8* base;
if (g_Renderer.m_Caps.m_VBO) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
base=(u8*) 0;
} else {
base=(u8*) m_SysMem;
}
return base;
}

View File

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

View File

@ -1,64 +1,65 @@
///////////////////////////////////////////////////////////////////////////////
//
// Name: VertexBufferManager.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include <assert.h>
#include "ogl.h"
#include "VertexBufferManager.h"
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
// if no free chunks available
CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
{
CVertexBuffer::VBChunk* result=0;
// TODO, RC - run some sanity checks on allocation request
// iterate through all existing buffers testing for one that'll
// satisfy the allocation
typedef std::list<CVertexBuffer*>::iterator Iter;
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
CVertexBuffer* buffer=*iter;
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);
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
assert(result);
return result;
}
///////////////////////////////////////////////////////////////////////////////
// Release: return given chunk to it's owner
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
{
assert(chunk);
chunk->m_Owner->Release(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// 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) {
CVertexBuffer* buffer=*iter;
buffer->ClearBatchIndices();
}
///////////////////////////////////////////////////////////////////////////////
//
// Name: VertexBufferManager.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include <assert.h>
#include "ogl.h"
#include "VertexBufferManager.h"
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
// if no free chunks available
CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
{
CVertexBuffer::VBChunk* result=0;
// TODO, RC - run some sanity checks on allocation request
// iterate through all existing buffers testing for one that'll
// satisfy the allocation
typedef std::list<CVertexBuffer*>::iterator Iter;
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
CVertexBuffer* buffer=*iter;
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);
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
assert(result);
return result;
}
///////////////////////////////////////////////////////////////////////////////
// Release: return given chunk to it's owner
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
{
assert(chunk);
chunk->m_Owner->Release(chunk);
}
///////////////////////////////////////////////////////////////////////////////
// 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) {
CVertexBuffer* buffer=*iter;
buffer->ClearBatchIndices();
}
}

View File

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

View File

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

View File

@ -53,7 +53,7 @@ static void RenderTileOutline(int gx,int gz)
void CBrushTool::OnDraw()
{
g_Renderer.SetTexture(0,0);
g_Renderer.SetTexture(0,0);
glEnable(GL_BLEND);
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"
extern CTerrain g_Terrain;
struct TGAHeader {
// header stuff
unsigned char iif_size;
unsigned char cmap_type;
unsigned char image_type;
unsigned char pad[5];
// origin : unused
unsigned short d_x_origin;
unsigned short d_y_origin;
// dimensions
unsigned short width;
unsigned short height;
// bits per pixel : 16, 24 or 32
unsigned char bpp;
// image descriptor : Bits 3-0: size of alpha channel
// Bit 4: must be 0 (reserved)
// Bit 5: should be 0 (origin)
// Bits 6-7: should be 0 (interleaving)
unsigned char image_descriptor;
};
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
{
FILE* fp=fopen(filename,"wb");
if (!fp) return false;
// fill file header
TGAHeader header;
header.iif_size=0;
header.cmap_type=0;
header.image_type=2;
memset(header.pad,0,sizeof(header.pad));
header.d_x_origin=0;
header.d_y_origin=0;
header.width=width;
header.height=height;
header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0;
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
fclose(fp);
return false;
}
// write data
if (fwrite(data,width*height*bpp/8,1,fp)!=1) {
fclose(fp);
return false;
}
// return success ..
fclose(fp);
return true;
}
struct TGAHeader {
// header stuff
unsigned char iif_size;
unsigned char cmap_type;
unsigned char image_type;
unsigned char pad[5];
// origin : unused
unsigned short d_x_origin;
unsigned short d_y_origin;
// dimensions
unsigned short width;
unsigned short height;
// bits per pixel : 16, 24 or 32
unsigned char bpp;
// image descriptor : Bits 3-0: size of alpha channel
// Bit 4: must be 0 (reserved)
// Bit 5: should be 0 (origin)
// Bits 6-7: should be 0 (interleaving)
unsigned char image_descriptor;
};
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
{
FILE* fp=fopen(filename,"wb");
if (!fp) return false;
// fill file header
TGAHeader header;
header.iif_size=0;
header.cmap_type=0;
header.image_type=2;
memset(header.pad,0,sizeof(header.pad));
header.d_x_origin=0;
header.d_y_origin=0;
header.width=width;
header.height=height;
header.bpp=bpp;
header.image_descriptor=(bpp==32) ? 8 : 0;
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
fclose(fp);
return false;
}
// write data
if (fwrite(data,width*height*bpp/8,1,fp)!=1) {
fclose(fp);
return false;
}
// return success ..
fclose(fp);
return true;
}
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
if (m_Handle) {
glDeleteTextures(1,(GLuint*) &m_Handle);
glDeleteTextures(1,(GLuint*) &m_Handle);
delete[] m_Data;
}
@ -103,12 +103,12 @@ void CMiniMap::Initialise()
g_Renderer.BindTexture(0,m_Handle);
// allocate an image big enough to fit the entire map into
m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide());
u32 mapSize=g_Terrain.GetVerticesPerSide();
m_Size=RoundUpToPowerOf2(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);
// allocate local copy
m_Data=new u32[(mapSize-1)*(mapSize-1)];
// allocate local copy
m_Data=new u32[(mapSize-1)*(mapSize-1)];
// set texture parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
@ -139,7 +139,7 @@ void CMiniMap::Render()
int h=g_Renderer.GetHeight();
glOrtho(0,w,0,h,-1,1);
// bind to the minimap
// bind to the minimap
g_Renderer.BindTexture(0,m_Handle);
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;
// 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);
UpdateTexture();
}
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++) {
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++) {
// get height at this pixel
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);
}
}
UpdateTexture();
}
void CMiniMap::Rebuild()
{
u32 mapSize=g_Terrain.GetVerticesPerSide();
{
u32 mapSize=g_Terrain.GetVerticesPerSide();
Rebuild(0,0,mapSize-1,mapSize-1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UpdateTexture: send data to GL; update stored texture data
void CMiniMap::UpdateTexture()
{
// bind to the minimap
g_Renderer.BindTexture(0,m_Handle);
// subimage to update pixels
u32 mapSize=g_Terrain.GetVerticesPerSide();
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UpdateTexture: send data to GL; update stored texture data
void CMiniMap::UpdateTexture()
{
// bind to the minimap
g_Renderer.BindTexture(0,m_Handle);
// subimage to update pixels
u32 mapSize=g_Terrain.GetVerticesPerSide();
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)
{
u32 mapSize=g_Terrain.GetVerticesPerSide();
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++) {
// get height at this pixel
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);
}
}
UpdateTexture();
}

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#include "stdafx.h"
#define _IGNORE_WGL_H_
#define _IGNORE_WGL_H_
#include "MainFrm.h"
#include "EditorData.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.Z=((c>>16) & 0xff)/255.0f;
}
inline void ColorRefToRGBAColor(COLORREF c,BYTE alpha,RGBAColor& result)
{
result[0]=(c & 0xff)/255.0f;
result[1]=((c>>8) & 0xff)/255.0f;
result[2]=((c>>16) & 0xff)/255.0f;
result[3]=alpha/255.0f;
}
inline void ColorRefToRGBAColor(COLORREF c,BYTE alpha,RGBAColor& result)
{
result[0]=(c & 0xff)/255.0f;
result[1]=((c>>8) & 0xff)/255.0f;
result[2]=((c>>16) & 0xff)/255.0f;
result[3]=alpha/255.0f;
}
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);
}
inline void RGBAColorToColorRef(const RGBAColor& c,COLORREF& result)
{
int r=int(c[0]*255);
if (r<0) r=0;
if (r>255) r=255;
int g=int(c[1]*255);
if (g<0) g=0;
if (g>255) g=255;
int b=int(c[2]*255);
if (b<0) b=0;
if (b>255) b=255;
int a=int(c[3]*255);
if (a<0) a=0;
if (a>255) a=255;
result=r | (g<<8) | (b<<16) | (a<<24);
}
inline void RGBAColorToColorRef(const RGBAColor& c,COLORREF& result)
{
int r=int(c[0]*255);
if (r<0) r=0;
if (r>255) r=255;
int g=int(c[1]*255);
if (g<0) g=0;
if (g>255) g=255;
int b=int(c[2]*255);
if (b<0) b=0;
if (b>255) b=255;
int a=int(c[3]*255);
if (a<0) a=0;
if (a>255) a=255;
result=r | (g<<8) | (b<<16) | (a<<24);
}
/////////////////////////////////////////////////////////////////////////////
// CColorButton window

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,17 @@
#include "precompiled.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:
@ -12,7 +23,9 @@
JSFunctionSpec ScriptFunctionTable[] =
{
{"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},
};
@ -47,3 +60,62 @@ JSBool WriteLog(JSContext * context, JSObject * globalObject, unsigned int argc,
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 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[];
#endif

View File

@ -2,12 +2,16 @@
#include "ScriptingHost.h"
#include "ScriptGlue.h"
#include "CConsole.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include "float.h" // <- MT: Just for _finite(), converting certain strings was causing wierd bugs.
#pragma comment (lib, "js32.lib")
extern CConsole* g_Console;
namespace
{
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)
{
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);
if( !ok ) return( NULL );
return rval;
}
@ -223,6 +234,13 @@ void ScriptingHost::SetObjectProperty(JSObject * object, const std::string & pro
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)
{
int32 i = 0;
@ -264,7 +282,7 @@ double ScriptingHost::ValueToDouble(const jsval value)
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"));
}
@ -274,6 +292,14 @@ double ScriptingHost::ValueToDouble(const jsval value)
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)
{
std::cout << report->filename << " (" << report->lineno << ") ";

View File

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

View File

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

View File

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

View File

@ -18,8 +18,8 @@ void CBaseEntityCollection::loadTemplates()
{
while (vfs_next_dirent(handle, &dent, ".xml") == 0)
{
CBaseEntity newTemplate;
if( newTemplate.loadXML( pathname + dent.name ) )
CBaseEntity* newTemplate = new CBaseEntity();
if( newTemplate->loadXML( pathname + dent.name ) )
{
addTemplate( newTemplate );
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");
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 );
}
@ -49,7 +45,7 @@ void CBaseEntityCollection::addTemplate( CBaseEntity& temp )
CBaseEntity* CBaseEntityCollection::getTemplate( CStr name )
{
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 );
}
@ -57,7 +53,13 @@ CBaseEntity* CBaseEntityCollection::getTemplate( CStr name )
CBaseEntity* CBaseEntityCollection::getTemplateByActor( CObjectEntry* actor )
{
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 );
}
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>
{
std::vector<CBaseEntity> m_templates;
std::vector<CBaseEntity*> m_templates;
public:
~CBaseEntityCollection();
CBaseEntity* getTemplate( CStr entityType );
void loadTemplates();
void addTemplate( CBaseEntity& temp );
void addTemplate( CBaseEntity* temp );
CBaseEntity* getTemplateByActor( CObjectEntry* actor );
};

View File

@ -11,17 +11,63 @@
#include "Terrain.h"
#include "Collision.h"
#include "PathfindEngine.h"
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.
m_actor = NULL;
m_bounds = NULL;
m_base = base;
m_actor = new CUnit(m_base->m_actorObject,m_base->m_actorObject->m_Model->Clone());
loadBase();
// HACK: Debugging
// assert( m_base->m_name != CStr( "Waypoint" ) );
snapToGround();
updateActorTransforms();
}
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.
@ -29,13 +75,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
// Set up our instance data
m_speed = m_base->m_speed;
m_turningRadius = m_base->m_turningRadius;
m_position = position;
m_orientation = orientation;
m_ahead.x = sin( orientation );
m_ahead.y = cos( orientation );
m_base->m_inheritors.push_back( this );
rebuild();
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 );
}
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 )
{
return( e->m_base->m_name == CStr( "Waypoint" ) );
@ -105,6 +126,8 @@ float CEntity::getExactGroundLevel( float x, float y )
u16* heightmap = g_Terrain.GetHeightMap();
unsigned long mapsize = g_Terrain.GetVerticesPerSide();
assert( ( xi >= 0 ) && ( xi < mapsize ) && ( yi >= 0 ) && ( yi < mapsize ) );
float h00 = heightmap[yi*mapsize + xi];
float h01 = heightmap[yi*mapsize + xi + mapsize];
float h10 = heightmap[yi*mapsize + xi + 1];
@ -204,6 +227,39 @@ void CEntity::pushOrder( CEntityOrder& 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()
{
// Rich! Help! ;)

View File

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

View File

@ -34,6 +34,12 @@ HEntity CEntityManager::create( CStr templatename, CVector3D position, float ori
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>* matchlist = new std::vector<HEntity>;

View File

@ -42,10 +42,11 @@ public:
~CEntityManager();
HEntity create( CBaseEntity* base, CVector3D position, float orientation );
HEntity create( CStr templatename, CVector3D position, float orientation );
HEntity* getByHandle( u16 index );
void kill( HEntity ent );
void updateAll( float timestep );
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>* getActive();
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 "EntityProperties.h"
#include "BaseEntityCollection.h"
#include "scripting/JSInterface_BaseEntity.h"
#include <cassert>
CGenericProperty::CGenericProperty()
void CProperty::associate( IPropertyOwner* owner, const CStr& name )
{
m_type = PROP_INTEGER;
m_integer = 0;
m_owner = owner;
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 )
{
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;
}
set( value );
return( *this );
}
CGenericProperty& CGenericProperty::operator=( float value )
CProperty_i32::CProperty_i32()
{
if( m_type & PROP_TYPELOCKED )
{
fromFloat( value );
}
else
{
releaseData();
m_type = PROP_FLOAT;
m_float = value;
}
modifier = NULL;
}
CProperty_i32::~CProperty_i32()
{
if( modifier )
delete( modifier );
}
inline CProperty_i32& CProperty_i32::operator =( i32 value )
{
if( !modifier )
modifier = new SProperty_NumericModifier();
*modifier = (float)value;
data = value;
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();
m_type = PROP_STRING;
m_string = new CStr( value );
*modifier = 0;
}
}
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 );
}
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();
m_type = PROP_VECTOR;
m_vector = new CVector3D( value );
*modifier = 0.0f;
}
}
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 );
}
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();
m_type = PROP_PTR;
m_ptr = value;
*modifier = CStr();
m_String.clear();
}
}
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 );
}
void CGenericProperty::associate( i32* value )
void CProperty_CVector3D::set( jsval value )
{
i32 current = toInteger();
releaseData();
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 )
JSObject* vector3d = JSVAL_TO_OBJECT( value );
if( !JSVAL_IS_OBJECT( value ) || ( JS_GetClass( vector3d ) != &JSI_Vector3D::JSI_class ) )
{
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();
releaseData();
m_integer = current;
CProperty* baseProperty = NULL;
if( m_base->m_properties.find( property->first ) != m_base->m_properties.end() )
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 );
}
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 )
else
{
case PROP_INTEGER:
return( asInteger() );
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" );
for( property = m_properties.begin(); property != m_properties.end(); property++ )
(property->second)->rebuild( NULL, false );
}
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 "Vector3D.h"
#include "scripting/ScriptingHost.h"
#include "scripting/JSInterface_Entity.h"
#include "scripting/JSInterface_Vector3D.h"
#ifndef __GNUC__
@ -35,89 +38,126 @@
#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:
enum EPropTypes
{
PROP_INTRINSIC = 256,
PROP_TYPELOCKED = 512,
PROP_STRIPFLAGS = 255,
PROP_INTEGER = 0,
PROP_FLOAT,
PROP_STRING,
PROP_VECTOR,
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;
};
void set( const jsval value );
operator jsval();
bool rebuild( CProperty* parent, bool triggerFn = true );
CProperty_CVector3D& operator=( const CVector3D& value );
};
class CProperty_CBaseEntityPtr : public CProperty
{
CBaseEntity* data;
public:
CGenericProperty(); // Create an integer property containing 0.
~CGenericProperty();
void releaseData();
void set( const jsval value );
operator jsval();
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.
void associate( i32* value );
void associate( float* value );
void associate( CStr* value );
void associate( CVector3D* value );
// Getter functions: Attempts to convert the property to the given type.
operator i32(); // Convert to an integer if possible (integer, float, some strings), otherwise returns 0.
operator float(); // Convert to a float if possible (integer, float, some strings), otherwise returns 0.0f.
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.
// e.g. Entities and their templates.
class IPropertyOwner
{
public:
CProperty_CBaseEntityPtr m_base;
STL_HASH_MAP<CStr,CProperty*,CStr_hash_compare> m_properties;
std::vector<IPropertyOwner*> m_inheritors;
void rebuild( CStr propName ); // Recursively rebuild just the named property over the inheritance tree.
void rebuild(); // Recursively rebuild everything over the inheritance tree.
};
// Setter functions: If this is a typelocked property, attempts to convert the given data
// 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
// as the given value, then stores that value in this property.
CGenericProperty& operator=( i32 value );
CGenericProperty& operator=( float value );
CGenericProperty& operator=( CStr& value );
CGenericProperty& operator=( CVector3D& value );
CGenericProperty& operator=( void* value ); // Be careful with this one. A lot of things will cast to void*.
// Especially pointers you meant to associate().
struct SProperty_NumericModifier
{
float multiplicative;
float additive;
void operator=( float value )
{
multiplicative = 0.0f;
additive = value;
}
};
// Typelock functions. Use these when you want to make sure the property has the given type.
void typelock( EPropTypes type );
void typeloose();
private:
// resolve-as functions. References the data, whereever it is.
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 );
struct SProperty_StringModifier
{
CStr replacement;
void operator=( const CStr& value )
{
replacement = value;
}
};
#endif

View File

@ -16,12 +16,18 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
float len = delta.length();
// janwas added EVIL HACK: BoundsChecker complains about NaNs
// in atan2 and fabs => delta must be 0 somewhere.
// currently skip over all math code that would break.
// what's the real solution?
if(len == 0.0f)
goto small_delta;
// ... 'Are we there yet?' ...
if( len < 0.1f )
{
if( current->m_type == CEntityOrder::ORDER_GOTO_COLLISION )
{
repath();
}
else
m_orderQueue.pop_front();
return( false );
}
// Curve smoothing.
// Here there be trig.
@ -44,7 +50,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
{
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;
@ -53,10 +59,10 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, float timestep )
float maxTurningSpeed = ( m_speed / m_turningRadius ) * timestep;
if( deltatheta > 0 )
{
m_orientation += MIN( deltatheta, maxTurningSpeed );
m_orientation = m_orientation + MIN( deltatheta, maxTurningSpeed );
}
else
m_orientation += MAX( deltatheta, -maxTurningSpeed );
m_orientation = m_orientation + MAX( deltatheta, -maxTurningSpeed );
m_ahead.x = sin( 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 )
((CBoundingBox*)m_bounds)->setOrientation( m_ahead );
float scale = timestep * m_speed;
float scale = m_speed * timestep;
if( scale > len )
scale = len;

View File

@ -5,8 +5,6 @@
sparsePathTree::sparsePathTree( const CVector2D& _from, const CVector2D& _to, HEntity _entity, CBoundingObject* _destinationCollisionObject )
{
from = _from; to = _to;
assert( from.length() > 0.01f );
assert( to.length() > 0.01f );
entity = _entity; destinationCollisionObject = _destinationCollisionObject;
leftPre = NULL; leftPost = NULL;
@ -46,7 +44,7 @@ bool sparsePathTree::slice()
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
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") },
-- simulation/
{ sourcesfromdirs("../../simulation") },
{ sourcesfromdirs("../../simulation/scripting") },
-- lib/
{ sourcesfromdirs(
"../../lib",
@ -34,6 +35,7 @@ package.files = {
-- maths/
{ sourcesfromdirs(
"../../maths") },
{ sourcesfromdirs( "../../maths/scripting" ) },
-- renderer/
{ sourcesfromdirs(
"../../renderer") },