diff --git a/source/graphics/TextureEntry.cpp b/source/graphics/TextureEntry.cpp index decc62ea7f..9374e12183 100755 --- a/source/graphics/TextureEntry.cpp +++ b/source/graphics/TextureEntry.cpp @@ -1,5 +1,4 @@ #include "precompiled.h" - #include "ogl.h" #include "res/tex.h" #include "TextureEntry.h" diff --git a/source/lib/res/file.cpp b/source/lib/res/file.cpp index 560bcf5555..a8729b7da4 100755 --- a/source/lib/res/file.cpp +++ b/source/lib/res/file.cpp @@ -28,6 +28,7 @@ #include #include + #include // block := power-of-two sized chunk of a file. diff --git a/source/main.cpp b/source/main.cpp index 340813c72f..f7379c39d6 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -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. diff --git a/source/maths/Vector3D.h b/source/maths/Vector3D.h index 8a68a1f6bd..6d02761427 100755 --- a/source/maths/Vector3D.h +++ b/source/maths/Vector3D.h @@ -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 ; diff --git a/source/maths/scripting/JSInterface_Vector3D.cpp b/source/maths/scripting/JSInterface_Vector3D.cpp new file mode 100755 index 0000000000..3dc115283b --- /dev/null +++ b/source/maths/scripting/JSInterface_Vector3D.cpp @@ -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 ); +} \ No newline at end of file diff --git a/source/maths/scripting/JSInterface_Vector3D.h b/source/maths/scripting/JSInterface_Vector3D.h new file mode 100755 index 0000000000..68b85791ed --- /dev/null +++ b/source/maths/scripting/JSInterface_Vector3D.h @@ -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 \ No newline at end of file diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index 4eb42eb134..1ab4adad0c 100755 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -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(": %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(); } diff --git a/source/ps/CConsole.h b/source/ps/CConsole.h index f098c9f1eb..ab4079608b 100755 --- a/source/ps/CConsole.h +++ b/source/ps/CConsole.h @@ -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 + diff --git a/source/ps/CStr.h b/source/ps/CStr.h index 343bc17966..36586c63a1 100755 --- a/source/ps/CStr.h +++ b/source/ps/CStr.h @@ -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]; }; diff --git a/source/renderer/ModelRData.cpp b/source/renderer/ModelRData.cpp index ec99417de8..429dc08f66 100755 --- a/source/renderer/ModelRData.cpp +++ b/source/renderer/ModelRData.cpp @@ -8,12 +8,12 @@ #include "ModelRData.h" #include "Model.h" -/////////////////////////////////////////////////////////////////// -// shared list of all submitted models this frame -std::vector CModelRData::m_Models; +/////////////////////////////////////////////////////////////////// +// shared list of all submitted models this frame +std::vector 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; jGetNumFaces(); 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 && iGetNumVertices(); 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; jGetTransform(); + const CMatrix3D& transform=m_Model->GetTransform(); const CMatrix3D& invtransform=m_Model->GetInvTransform(); for (uint j=0; jGetNumVertices(),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;iGetRenderData(); - modeldata->SubmitBatches(); - } - - // step through all accumulated batches - const std::list& buffers=g_VBMan.GetBufferList(); - std::list::const_iterator iter; - for (iter=buffers.begin();iter!=buffers.end();++iter) { - CVertexBuffer* buffer=*iter; - - // any batches in this VB? - const std::vector& 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;im_IndexData.size()>0) { - if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); - for (uint j=0;jm_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;iGetRenderData(); - 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;iGetRenderData(); + modeldata->SubmitBatches(); + } + + // step through all accumulated batches + const std::list& buffers=g_VBMan.GetBufferList(); + std::list::const_iterator iter; + for (iter=buffers.begin();iter!=buffers.end();++iter) { + CVertexBuffer* buffer=*iter; + + // any batches in this VB? + const std::vector& 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;im_IndexData.size()>0) { + if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); + for (uint j=0;jm_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;iGetRenderData(); + 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); + } +} diff --git a/source/renderer/ModelRData.h b/source/renderer/ModelRData.h index afb04b0de8..0a01357a16 100755 --- a/source/renderer/ModelRData.h +++ b/source/renderer/ModelRData.h @@ -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 m_Models; + // list of all submitted models + static std::vector m_Models; }; diff --git a/source/renderer/PatchRData.cpp b/source/renderer/PatchRData.cpp index 791b77b38e..7c12a3b443 100755 --- a/source/renderer/PatchRData.cpp +++ b/source/renderer/PatchRData.cpp @@ -7,11 +7,11 @@ #include "Renderer.h" #include "PatchRData.h" #include "AlphaMapCalculator.h" - -/////////////////////////////////////////////////////////////////// -// shared list of all submitted patches this frame -std::vector CPatchRData::m_Patches; - + +/////////////////////////////////////////////////////////////////// +// shared list of all submitted patches this frame +std::vector 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 (xmax) 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 (xmax) 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::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;km_Index; + std::set::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;km_Index; + u32 base=m_VBBase->m_Index; for (uint i=0;im_Parent; u32 mapSize=terrain->GetVerticesPerSide(); - // build vertices + // build vertices for (int j=0;jCalcPosition(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;im_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_NextBlendSplatm_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;iGetRenderData(); - patchdata->SubmitBaseBatches(); - } - - // render base passes for each patch - const std::list& buffers=g_VBMan.GetBufferList(); - std::list::const_iterator iter; - for (iter=buffers.begin();iter!=buffers.end();++iter) { - CVertexBuffer* buffer=*iter; - - // any batches in this VB? - const std::vector& 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;im_IndexData.size()>0) { - g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); - for (uint j=0;jm_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;iGetRenderData(); - 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;iGetRenderData(); - patchdata->SetupBlendBatches(); - } - - bool finished=true; - do - { - for (i=0;iGetRenderData(); - if (!patchdata->SubmitBlendBatches()) finished=false; - } - } while (!finished); - - // render blend passes for each patch - const std::list& buffers=g_VBMan.GetBufferList(); - std::list::const_iterator iter; - for (iter=buffers.begin();iter!=buffers.end();++iter) { - CVertexBuffer* buffer=*iter; - - // any batches in this VB? - const std::vector& 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;im_IndexData.size()>0) { - g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); - for (uint j=0;jm_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;iGetRenderData(); - 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;iGetRenderData(); - 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& buffers=g_VBMan.GetBufferList(); - std::list::const_iterator iter; - for (iter=buffers.begin();iter!=buffers.end();++iter) { - CVertexBuffer* buffer=*iter; - - // any batches in this VB? - const std::vector& 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;jm_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;iGetRenderData();; - 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;im_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_NextBlendSplatm_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;iGetRenderData(); + patchdata->SubmitBaseBatches(); + } + + // render base passes for each patch + const std::list& buffers=g_VBMan.GetBufferList(); + std::list::const_iterator iter; + for (iter=buffers.begin();iter!=buffers.end();++iter) { + CVertexBuffer* buffer=*iter; + + // any batches in this VB? + const std::vector& 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;im_IndexData.size()>0) { + g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); + for (uint j=0;jm_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;iGetRenderData(); + 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;iGetRenderData(); + patchdata->SetupBlendBatches(); + } + + bool finished=true; + do + { + for (i=0;iGetRenderData(); + if (!patchdata->SubmitBlendBatches()) finished=false; + } + } while (!finished); + + // render blend passes for each patch + const std::list& buffers=g_VBMan.GetBufferList(); + std::list::const_iterator iter; + for (iter=buffers.begin();iter!=buffers.end();++iter) { + CVertexBuffer* buffer=*iter; + + // any batches in this VB? + const std::vector& 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;im_IndexData.size()>0) { + g_Renderer.BindTexture(0,tex_id(batch->m_Texture)); + for (uint j=0;jm_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;iGetRenderData(); + 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;iGetRenderData(); + 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& buffers=g_VBMan.GetBufferList(); + std::list::const_iterator iter; + for (iter=buffers.begin();iter!=buffers.end();++iter) { + CVertexBuffer* buffer=*iter; + + // any batches in this VB? + const std::vector& 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;jm_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;iGetRenderData();; + patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0); + } +#endif + + glDisable(GL_ALPHA_TEST); + + glDisable(GL_BLEND); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } \ No newline at end of file diff --git a/source/renderer/PatchRData.h b/source/renderer/PatchRData.h index 051ddaab52..ec5d91466a 100755 --- a/source/renderer/PatchRData.h +++ b/source/renderer/PatchRData.h @@ -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 m_Indices; - // indices into base vertices for the shadow map pass - std::vector m_ShadowMapIndices; + // indices into base vertices for the shadow map pass + std::vector m_ShadowMapIndices; // list of base splats to apply to this patch std::vector 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 m_BlendIndices; // splats used in blend pass - std::vector m_BlendSplats; - // index of the next blend splat to render - u32 m_NextBlendSplat; - // list of all submitted patches + std::vector m_BlendSplats; + // index of the next blend splat to render + u32 m_NextBlendSplat; + // list of all submitted patches static std::vector m_Patches; }; diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index 692f88cf40..44fd4133e3 100755 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -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;iLog(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 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)); diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h index d91fabe806..1d403f7096 100755 --- a/source/renderer/Renderer.h +++ b/source/renderer/Renderer.h @@ -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]; }; diff --git a/source/renderer/TransparencyRenderer.cpp b/source/renderer/TransparencyRenderer.cpp index 436b35e03d..68b2bcfdd7 100755 --- a/source/renderer/TransparencyRenderer.cpp +++ b/source/renderer/TransparencyRenderer.cpp @@ -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 @@ -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); diff --git a/source/renderer/TransparencyRenderer.h b/source/renderer/TransparencyRenderer.h index 87b7ce906a..3f6635c1c3 100755 --- a/source/renderer/TransparencyRenderer.h +++ b/source/renderer/TransparencyRenderer.h @@ -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 diff --git a/source/renderer/VertexBuffer.cpp b/source/renderer/VertexBuffer.cpp index 4d84a218cb..e05ce2629a 100755 --- a/source/renderer/VertexBuffer.cpp +++ b/source/renderer/VertexBuffer.cpp @@ -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::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::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;im_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;im_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(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::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::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;im_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;im_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(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; } \ No newline at end of file diff --git a/source/renderer/VertexBuffer.h b/source/renderer/VertexBuffer.h index 314c08c6a8..b9dbd1e2e9 100755 --- a/source/renderer/VertexBuffer.h +++ b/source/renderer/VertexBuffer.h @@ -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 -#include - -// 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 > 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& 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 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 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 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 +#include + +// 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 > 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& 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 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 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 m_FreeBatches; +}; + #endif \ No newline at end of file diff --git a/source/renderer/VertexBufferManager.cpp b/source/renderer/VertexBufferManager.cpp index 4d67593ca1..1e678cf759 100755 --- a/source/renderer/VertexBufferManager.cpp +++ b/source/renderer/VertexBufferManager.cpp @@ -1,64 +1,65 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Name: VertexBufferManager.cpp -// Author: Rich Cross -// Contact: rich@wildfiregames.com -// -/////////////////////////////////////////////////////////////////////////////// -#include "precompiled.h" -#include -#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::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::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 +#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::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::iterator Iter; + for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) { + CVertexBuffer* buffer=*iter; + buffer->ClearBatchIndices(); + } } \ No newline at end of file diff --git a/source/renderer/VertexBufferManager.h b/source/renderer/VertexBufferManager.h index 28cb59d91a..914c5bdfea 100755 --- a/source/renderer/VertexBufferManager.h +++ b/source/renderer/VertexBufferManager.h @@ -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& GetBufferList() const { return m_Buffers; } - -private: - // list of all known vertex buffers - std::list 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& GetBufferList() const { return m_Buffers; } + +private: + // list of all known vertex buffers + std::list m_Buffers; +}; + +extern CVertexBufferManager g_VBMan; + + #endif \ No newline at end of file diff --git a/source/sced/BrushShapeEditorTool.cpp b/source/sced/BrushShapeEditorTool.cpp index e9c5d2a54c..3af169f1fb 100755 --- a/source/sced/BrushShapeEditorTool.cpp +++ b/source/sced/BrushShapeEditorTool.cpp @@ -1,9 +1,9 @@ #include #include -#include "ogl.h" +#include "ogl.h" #include "Renderer.h" -#include "BrushShapeEditorTool.h" - +#include "BrushShapeEditorTool.h" + // default tool instance CBrushShapeEditorTool CBrushShapeEditorTool::m_BrushShapeEditorTool; diff --git a/source/sced/BrushTool.cpp b/source/sced/BrushTool.cpp index 44a9eadc77..3ce0b6602f 100755 --- a/source/sced/BrushTool.cpp +++ b/source/sced/BrushTool.cpp @@ -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); diff --git a/source/sced/EditorData.cpp b/source/sced/EditorData.cpp index 322489b67d..fede4660d6 100755 --- a/source/sced/EditorData.cpp +++ b/source/sced/EditorData.cpp @@ -1,664 +1,664 @@ -#include "EditorData.h" -#include "UIGlobals.h" -#include "ToolManager.h" -#include "ObjectManager.h" -#include "UnitManager.h" -#include "TextureManager.h" -#include "Model.h" -#include "SkeletonAnimManager.h" - -#include "ogl.h" -#include "res/tex.h" -#include "time.h" - -#include "BaseEntityCollection.h" -#include "Entity.h" -#include "EntityHandles.h" -#include "EntityManager.h" - -#include "XML.h" - -const int NUM_ALPHA_MAPS = 14; -Handle AlphaMaps[NUM_ALPHA_MAPS]; - -CTerrain g_Terrain; -CLightEnv g_LightEnv; -CMiniMap g_MiniMap; -CEditorData g_EditorData; - -CEditorData::CEditorData() -{ - m_ModelMatrix.SetIdentity(); - m_ScenarioName="Scenario01"; -} - -void CEditorData::SetMode(EditMode mode) -{ - if (m_Mode==TEST_MODE && mode!=TEST_MODE) StopTestMode(); - m_Mode=mode; - if (m_Mode==TEST_MODE) StartTestMode(); -} - -bool CEditorData::InitScene() -{ - // setup default lighting environment - g_LightEnv.m_SunColor=RGBColor(1,1,1); - g_LightEnv.m_Rotation=DEGTORAD(270); - g_LightEnv.m_Elevation=DEGTORAD(45); - g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0); - g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f); - g_Renderer.SetLightEnv(&g_LightEnv); - - // load the default - if (!LoadTerrain("terrain.raw")) return false; - - // get default texture to apply to terrain - CTextureEntry* texture=0; - for (uint i=0;im_MiniPatches[j][i].Tex1=texture ? texture->GetHandle() : 0; - } - } - } - } - - // setup camera - InitCamera(); - - // build the terrain plane - float h=128*HEIGHT_SCALE; - u32 mapSize=g_Terrain.GetVerticesPerSide(); - CVector3D pt0(0,h,0),pt1(float(CELL_SIZE*mapSize),h,0),pt2(0,h,float(CELL_SIZE*mapSize)); - m_TerrainPlane.Set(pt0,pt1,pt2); - m_TerrainPlane.Normalize(); - - 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,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=24; - header.image_descriptor=0; - - if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) { - fclose(fp); - return false; - } - - // write data - if (fwrite(data,width*height*3,1,fp)!=1) { - fclose(fp); - return false; - } - - // return success .. - fclose(fp); - return true; -} - -void CEditorData::LoadAlphaMaps() -{ - const char* fns[CRenderer::NumAlphaMaps] = { - "art/textures/terrain/alphamaps/special/blendcircle.png", - "art/textures/terrain/alphamaps/special/blendlshape.png", - "art/textures/terrain/alphamaps/special/blendedge.png", - "art/textures/terrain/alphamaps/special/blendedgecorner.png", - "art/textures/terrain/alphamaps/special/blendedgetwocorners.png", - "art/textures/terrain/alphamaps/special/blendfourcorners.png", - "art/textures/terrain/alphamaps/special/blendtwooppositecorners.png", - "art/textures/terrain/alphamaps/special/blendlshapecorner.png", - "art/textures/terrain/alphamaps/special/blendtwocorners.png", - "art/textures/terrain/alphamaps/special/blendcorner.png", - "art/textures/terrain/alphamaps/special/blendtwoedges.png", - "art/textures/terrain/alphamaps/special/blendthreecorners.png", - "art/textures/terrain/alphamaps/special/blendushape.png", - "art/textures/terrain/alphamaps/special/blendbad.png" - }; - - g_Renderer.LoadAlphaMaps(fns); -} - -void CEditorData::InitResources() -{ - g_TexMan.LoadTerrainTextures(); - LoadAlphaMaps(); - g_ObjMan.LoadObjects(); -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// InitSingletons: create and initialise required singletons -void CEditorData::InitSingletons() -{ - // create terrain related stuff - new CTextureManager; - - // create actor related stuff - new CSkeletonAnimManager; - new CObjectManager; - new CUnitManager; - - // create entity related stuff - new CBaseEntityCollection; - new CEntityManager; - g_EntityTemplateCollection.loadTemplates(); -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// Init: perform one time initialisation of the editor -bool CEditorData::Init() -{ - // start up Xerces - XMLPlatformUtils::Initialize(); - - // create and initialise singletons - InitSingletons(); - - // load default textures - InitResources(); - - // create the scene - terrain, camera, light environment etc - if (!InitScene()) return false; - - // set up an empty minimap - g_MiniMap.Initialise(); - - // set up the info box - m_InfoBox.Initialise(); - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -// Terminate: close down the editor (destroy singletons in reverse order to construction) -void CEditorData::Terminate() -{ - // destroy entity related stuff - delete CEntityManager::GetSingletonPtr(); - delete CBaseEntityCollection::GetSingletonPtr(); - - // destroy actor related stuff - delete CUnitManager::GetSingletonPtr(); - delete CObjectManager::GetSingletonPtr(); - delete CSkeletonAnimManager::GetSingletonPtr(); - - // destroy terrain related stuff - delete CTextureManager::GetSingletonPtr(); - - // close down Xerces - XMLPlatformUtils::Terminate(); -} - -void CEditorData::InitCamera() -{ - g_NaviCam.GetCamera().SetProjection(1.0f,10000.0f,DEGTORAD(90)); - g_NaviCam.GetCamera().m_Orientation.SetIdentity(); -#ifdef TOPDOWNVIEW - g_NaviCam.GetCamera().m_Orientation.RotateX(DEGTORAD(90)); - g_NaviCam.GetCamera().m_Orientation.Translate(CELL_SIZE*250*0.5, 80, CELL_SIZE*250*0.5); -#else - g_NaviCam.GetCamera().m_Orientation.RotateX(DEGTORAD(40)); - g_NaviCam.GetCamera().m_Orientation.RotateY(DEGTORAD(-45)); - g_NaviCam.GetCamera().m_Orientation.Translate(600, 200, 125); -#endif - - OnCameraChanged(); -} - -void CEditorData::OnCameraChanged() -{ - int width=g_Renderer.GetWidth(); - int height=g_Renderer.GetHeight(); - - // resize viewport - SViewPort viewport; - viewport.m_X=0; - viewport.m_Y=0; - viewport.m_Width=width; - viewport.m_Height=height; - g_NaviCam.GetCamera().SetViewPort(&viewport); - - // rebuild object camera - m_ObjectCamera.SetViewPort(&viewport); - m_ObjectCamera.SetProjection(1.0f,10000.0f,DEGTORAD(90)); - - - // recalculate projection matrix - g_NaviCam.GetCamera().SetProjection(1.0f,10000.0f,DEGTORAD(20)); - - // update viewing frustum - g_NaviCam.GetCamera().UpdateFrustum(); - - // calculate intersection of camera stabbing lines with terrain plane - - // get points of back plane of frustum in camera space - float aspect=height>0 ? float(width)/float(height) : 1.0f; - float zfar=g_NaviCam.GetCamera().GetFarPlane(); - CVector3D cPts[4]; - float x=zfar*float(tan(g_NaviCam.GetCamera().GetFOV()*aspect*0.5)); - float y=zfar*float(tan(g_NaviCam.GetCamera().GetFOV()*0.5)); - cPts[0].X=-x; - cPts[0].Y=-y; - cPts[0].Z=zfar; - cPts[1].X=x; - cPts[1].Y=-y; - cPts[1].Z=zfar; - cPts[2].X=x; - cPts[2].Y=y; - cPts[2].Z=zfar; - cPts[3].X=-x; - cPts[3].Y=y; - cPts[3].Z=zfar; - - // transform to world space - CVector3D wPts[4]; - for (int i=0;i<4;i++) { - wPts[i]=g_NaviCam.GetCamera().m_Orientation.Transform(cPts[i]); - } - - // now intersect a ray from the camera through each point - CVector3D rayOrigin=g_NaviCam.GetCamera().m_Orientation.GetTranslation(); - CVector3D rayDir=g_NaviCam.GetCamera().m_Orientation.GetIn(); - - CVector3D hitPt[4]; - for (i=0;i<4;i++) { - CVector3D rayDir=wPts[i]-rayOrigin; - rayDir.Normalize(); - - // get intersection point - m_TerrainPlane.FindRayIntersection(rayOrigin,rayDir,&hitPt[i]); - } - - for (i=0;i<4;i++) { - // convert to minimap space - float px=hitPt[i].X; - float pz=hitPt[i].Z; - g_MiniMap.m_ViewRect[i][0]=(197*px/float(CELL_SIZE*g_Terrain.GetVerticesPerSide())); - g_MiniMap.m_ViewRect[i][1]=197*pz/float(CELL_SIZE*g_Terrain.GetVerticesPerSide()); - } -} - -void CEditorData::RenderTerrain() -{ - CFrustum frustum=g_NaviCam.GetCamera().GetFustum(); - u32 patchesPerSide=g_Terrain.GetPatchesPerSide(); - for (uint j=0; jGetBounds())) { - g_Renderer.Submit(patch); - } - } - } -} - -void CEditorData::OnScreenShot(const char* filename) -{ - g_Renderer.SetClearColor(0); - g_Renderer.BeginFrame(); - g_Renderer.SetCamera(g_NaviCam.GetCamera()); - - RenderWorld(); - - g_Renderer.EndFrame(); - - int width=g_Renderer.GetWidth(); - int height=g_Renderer.GetHeight(); - unsigned char* data=new unsigned char[width*height*3]; - - glReadBuffer(GL_BACK); - glReadPixels(0,0,width,height,GL_BGR_EXT,GL_UNSIGNED_BYTE,data); - - saveTGA(filename,width,height,data); - - delete[] data; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// SubmitModelRecursive: recurse down given model, submitting it and all it's descendents to the -// renderer -void SubmitModelRecursive(CModel* model) -{ - g_Renderer.Submit(model); - - const std::vector& props=model->GetProps(); - for (uint i=0;i& units=g_UnitMan.GetUnits(); - for (i=0;iGetModel()); - } - - u32 patchesPerSide=g_Terrain.GetPatchesPerSide(); - for (j=0; j& units=g_UnitMan.GetUnits(); - uint i; - for (i=0;iGetModel()->GetBounds())) { - SubmitModelRecursive(units[i]->GetModel()); - } - } -} - -void CEditorData::RenderWorld() -{ - // render terrain - RenderTerrain(); - - // render all the units - RenderModels(); - - // flush prior to rendering overlays etc - g_Renderer.FlushFrame(); -} - -void CEditorData::RenderObEdGrid() -{ - int i; - const int numSteps=32; - const CVector3D start(-numSteps*CELL_SIZE/2,0,-numSteps*CELL_SIZE/2); - const CVector3D end(numSteps*CELL_SIZE/2,0,numSteps*CELL_SIZE/2); - - glDisable(GL_TEXTURE_2D); - - glDepthMask(0); - glColor4f(0.5f,0.5f,0.5f,0.35f); - glLineWidth(1.0f); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - - glBegin(GL_LINES); - for (i=0;i<=numSteps;i++) { - if (i%8==0) continue; - CVector3D v0(start.X+(i*(end.X-start.X))/float(numSteps),start.Y,start.Z); - glVertex3fv(&v0.X); - - CVector3D v1(v0.X,end.Y,end.Z); - glVertex3fv(&v1.X); - } - - for (i=0;i<=numSteps;i++) { - if (i%8==0) continue; - CVector3D v0(start.X,start.Y,start.Z+(i*(end.Z-start.Z))/float(numSteps)); - glVertex3fv(&v0.X); - - CVector3D v1(end.X,end.Y,v0.Z); - glVertex3fv(&v1.X); - } - glEnd(); - - glDisable(GL_BLEND); - - glColor3f(0,0,0.5); - glLineWidth(2.0f); - - glBegin(GL_LINES); - for (i=0;i<=numSteps;i+=8) { - CVector3D v0(start.X+(i*(end.X-start.X))/float(numSteps),start.Y,start.Z); - glVertex3fv(&v0.X); - - CVector3D v1(v0.X,end.Y,end.Z); - glVertex3fv(&v1.X); - } - - for (i=0;i<=numSteps;i+=8) { - CVector3D v0(start.X,start.Y,start.Z+(i*(end.Z-start.Z))/float(numSteps)); - glVertex3fv(&v0.X); - - CVector3D v1(end.X,end.Y,v0.Z); - glVertex3fv(&v1.X); - } - glEnd(); - glDepthMask(1); -} - -void CEditorData::OnDraw() -{ - if (m_Mode==SCENARIO_EDIT || m_Mode==TEST_MODE) { - g_Renderer.SetClearColor(0); - g_Renderer.BeginFrame(); - - // setup camera - g_Renderer.SetCamera(g_NaviCam.GetCamera()); - - // render base terrain plus models - RenderWorld(); - - if (m_Mode!=TEST_MODE) { - // render the active tool - g_ToolMan.OnDraw(); - } - - // flush prior to rendering overlays .. - g_Renderer.FlushFrame(); - - // .. and here's the overlays - g_MiniMap.Render(); - m_InfoBox.Render(); - } else { - g_Renderer.SetClearColor(0x00453015); - g_Renderer.BeginFrame(); - - CObjectEntry* selobject=g_ObjMan.GetSelectedObject(); - if (selobject && selobject->m_Model) { - // setup camera such that object is in the centre of the viewport - m_ModelMatrix.SetIdentity(); - selobject->m_Model->SetTransform(m_ModelMatrix); - - const CBound& bound=selobject->m_Model->GetBounds(); - CVector3D pt((bound[0].X+bound[1].X)*0.5f,(bound[0].Y+bound[1].Y)*0.5f,bound[0].Z); - - float hfov=tan(DEGTORAD(45)); - float vfov=hfov/g_Renderer.GetAspect(); - float zx=(bound[1].X-bound[0].X)*0.5f/hfov; - float zy=(bound[1].Y-bound[0].Y)*0.5f/vfov; - float z=zx>zy ? zx : zy; - z=(z+1)*2; - - m_ObjectCamera.m_Orientation.SetIdentity(); - m_ObjectCamera.m_Orientation.Translate(pt.X,pt.Y,-z); - - g_Renderer.SetCamera(m_ObjectCamera); - - RenderObEdGrid(); - - g_Renderer.Submit(selobject->m_Model); - } - - // flush prior to rendering overlays .. - g_Renderer.FlushFrame(); - - // .. and here's the overlays - m_InfoBox.Render(); - } - - g_Renderer.EndFrame(); - - // notify info box frame is complete; gives it chance to accumulate stats, check - // fps, etc - m_InfoBox.OnFrameComplete(); -} - - -bool CEditorData::LoadTerrain(const char* filename) -{ - Handle h = tex_load(filename); - if(h<=0) { - char buf[1024]; - sprintf(buf,"Failed to load \"%s\"",filename); - ErrorBox(buf); - return false; - } else { - - int width=0; - int height=0; - int bpp=0; - void *ptr=0; - - int i=tex_info(h, &width, &height, NULL, &bpp, &ptr); - if (i) - { - printf("tex_info error: %d\n",i); - fflush(stdout); - } - - // rescale the texture to fit to the nearest of the 4 possible map sizes - u32 mapsize=9; // assume smallest map - if (width>11*PATCH_SIZE+1) mapsize=11; - if (width>13*PATCH_SIZE+1) mapsize=13; - if (width>17*PATCH_SIZE+1) mapsize=17; - - u32 targetsize=mapsize*PATCH_SIZE+1; - unsigned char* data=new unsigned char[targetsize*targetsize*bpp/8]; - u32 fmt=(bpp==8) ? GL_RED : ((bpp==24) ? GL_RGB : GL_RGBA); - gluScaleImage(fmt,width,height,GL_UNSIGNED_BYTE,ptr, - targetsize,targetsize,GL_UNSIGNED_BYTE,data); - - // build 16 bit heightmap from red channel of texture - u16* heightmap=new u16[targetsize*targetsize]; - int stride=bpp/8; - u16* hmptr=heightmap; - - // get src of copy - const u8* dataptr = (bpp==8) ? data : ((bpp==24) ? data+2 : data+3); - - // build heightmap - for (uint j=0;j& units=g_UnitMan.GetUnits(); - for (uint i=0;iGetModel()->Update(time); - } - if (m_Mode==TEST_MODE) { - g_EntityManager.updateAll( time ); - } - } else { - CObjectEntry* selobject=g_ObjMan.GetSelectedObject(); - if (selobject && selobject->m_Model) { - selobject->m_Model->Update(time); - } - } -} - -void CEditorData::StartTestMode() -{ - // initialise entities - g_EntityManager.dispatchAll( &CMessage( CMessage::EMSG_INIT ) ); -} - -void CEditorData::StopTestMode() -{ - // make all units idle again - const std::vector& units=g_UnitMan.GetUnits(); - for (uint i=0;iGetObject()->m_IdleAnim) { - units[i]->GetModel()->SetAnimation(units[i]->GetObject()->m_IdleAnim); - } - } +#include "EditorData.h" +#include "UIGlobals.h" +#include "ToolManager.h" +#include "ObjectManager.h" +#include "UnitManager.h" +#include "TextureManager.h" +#include "Model.h" +#include "SkeletonAnimManager.h" + +#include "ogl.h" +#include "res/tex.h" +#include "time.h" + +#include "BaseEntityCollection.h" +#include "Entity.h" +#include "EntityHandles.h" +#include "EntityManager.h" + +#include "XML.h" + +const int NUM_ALPHA_MAPS = 14; +Handle AlphaMaps[NUM_ALPHA_MAPS]; + +CTerrain g_Terrain; +CLightEnv g_LightEnv; +CMiniMap g_MiniMap; +CEditorData g_EditorData; + +CEditorData::CEditorData() +{ + m_ModelMatrix.SetIdentity(); + m_ScenarioName="Scenario01"; +} + +void CEditorData::SetMode(EditMode mode) +{ + if (m_Mode==TEST_MODE && mode!=TEST_MODE) StopTestMode(); + m_Mode=mode; + if (m_Mode==TEST_MODE) StartTestMode(); +} + +bool CEditorData::InitScene() +{ + // setup default lighting environment + g_LightEnv.m_SunColor=RGBColor(1,1,1); + g_LightEnv.m_Rotation=DEGTORAD(270); + g_LightEnv.m_Elevation=DEGTORAD(45); + g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0); + g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f); + g_Renderer.SetLightEnv(&g_LightEnv); + + // load the default + if (!LoadTerrain("terrain.raw")) return false; + + // get default texture to apply to terrain + CTextureEntry* texture=0; + for (uint i=0;im_MiniPatches[j][i].Tex1=texture ? texture->GetHandle() : 0; + } + } + } + } + + // setup camera + InitCamera(); + + // build the terrain plane + float h=128*HEIGHT_SCALE; + u32 mapSize=g_Terrain.GetVerticesPerSide(); + CVector3D pt0(0,h,0),pt1(float(CELL_SIZE*mapSize),h,0),pt2(0,h,float(CELL_SIZE*mapSize)); + m_TerrainPlane.Set(pt0,pt1,pt2); + m_TerrainPlane.Normalize(); + + 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,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=24; + header.image_descriptor=0; + + if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) { + fclose(fp); + return false; + } + + // write data + if (fwrite(data,width*height*3,1,fp)!=1) { + fclose(fp); + return false; + } + + // return success .. + fclose(fp); + return true; +} + +void CEditorData::LoadAlphaMaps() +{ + const char* fns[CRenderer::NumAlphaMaps] = { + "art/textures/terrain/alphamaps/special/blendcircle.png", + "art/textures/terrain/alphamaps/special/blendlshape.png", + "art/textures/terrain/alphamaps/special/blendedge.png", + "art/textures/terrain/alphamaps/special/blendedgecorner.png", + "art/textures/terrain/alphamaps/special/blendedgetwocorners.png", + "art/textures/terrain/alphamaps/special/blendfourcorners.png", + "art/textures/terrain/alphamaps/special/blendtwooppositecorners.png", + "art/textures/terrain/alphamaps/special/blendlshapecorner.png", + "art/textures/terrain/alphamaps/special/blendtwocorners.png", + "art/textures/terrain/alphamaps/special/blendcorner.png", + "art/textures/terrain/alphamaps/special/blendtwoedges.png", + "art/textures/terrain/alphamaps/special/blendthreecorners.png", + "art/textures/terrain/alphamaps/special/blendushape.png", + "art/textures/terrain/alphamaps/special/blendbad.png" + }; + + g_Renderer.LoadAlphaMaps(fns); +} + +void CEditorData::InitResources() +{ + g_TexMan.LoadTerrainTextures(); + LoadAlphaMaps(); + g_ObjMan.LoadObjects(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// InitSingletons: create and initialise required singletons +void CEditorData::InitSingletons() +{ + // create terrain related stuff + new CTextureManager; + + // create actor related stuff + new CSkeletonAnimManager; + new CObjectManager; + new CUnitManager; + + // create entity related stuff + new CBaseEntityCollection; + new CEntityManager; + g_EntityTemplateCollection.loadTemplates(); +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Init: perform one time initialisation of the editor +bool CEditorData::Init() +{ + // start up Xerces + XMLPlatformUtils::Initialize(); + + // create and initialise singletons + InitSingletons(); + + // load default textures + InitResources(); + + // create the scene - terrain, camera, light environment etc + if (!InitScene()) return false; + + // set up an empty minimap + g_MiniMap.Initialise(); + + // set up the info box + m_InfoBox.Initialise(); + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Terminate: close down the editor (destroy singletons in reverse order to construction) +void CEditorData::Terminate() +{ + // destroy entity related stuff + delete CEntityManager::GetSingletonPtr(); + delete CBaseEntityCollection::GetSingletonPtr(); + + // destroy actor related stuff + delete CUnitManager::GetSingletonPtr(); + delete CObjectManager::GetSingletonPtr(); + delete CSkeletonAnimManager::GetSingletonPtr(); + + // destroy terrain related stuff + delete CTextureManager::GetSingletonPtr(); + + // close down Xerces + XMLPlatformUtils::Terminate(); +} + +void CEditorData::InitCamera() +{ + g_NaviCam.GetCamera().SetProjection(1.0f,10000.0f,DEGTORAD(90)); + g_NaviCam.GetCamera().m_Orientation.SetIdentity(); +#ifdef TOPDOWNVIEW + g_NaviCam.GetCamera().m_Orientation.RotateX(DEGTORAD(90)); + g_NaviCam.GetCamera().m_Orientation.Translate(CELL_SIZE*250*0.5, 80, CELL_SIZE*250*0.5); +#else + g_NaviCam.GetCamera().m_Orientation.RotateX(DEGTORAD(40)); + g_NaviCam.GetCamera().m_Orientation.RotateY(DEGTORAD(-45)); + g_NaviCam.GetCamera().m_Orientation.Translate(600, 200, 125); +#endif + + OnCameraChanged(); +} + +void CEditorData::OnCameraChanged() +{ + int width=g_Renderer.GetWidth(); + int height=g_Renderer.GetHeight(); + + // resize viewport + SViewPort viewport; + viewport.m_X=0; + viewport.m_Y=0; + viewport.m_Width=width; + viewport.m_Height=height; + g_NaviCam.GetCamera().SetViewPort(&viewport); + + // rebuild object camera + m_ObjectCamera.SetViewPort(&viewport); + m_ObjectCamera.SetProjection(1.0f,10000.0f,DEGTORAD(90)); + + + // recalculate projection matrix + g_NaviCam.GetCamera().SetProjection(1.0f,10000.0f,DEGTORAD(20)); + + // update viewing frustum + g_NaviCam.GetCamera().UpdateFrustum(); + + // calculate intersection of camera stabbing lines with terrain plane + + // get points of back plane of frustum in camera space + float aspect=height>0 ? float(width)/float(height) : 1.0f; + float zfar=g_NaviCam.GetCamera().GetFarPlane(); + CVector3D cPts[4]; + float x=zfar*float(tan(g_NaviCam.GetCamera().GetFOV()*aspect*0.5)); + float y=zfar*float(tan(g_NaviCam.GetCamera().GetFOV()*0.5)); + cPts[0].X=-x; + cPts[0].Y=-y; + cPts[0].Z=zfar; + cPts[1].X=x; + cPts[1].Y=-y; + cPts[1].Z=zfar; + cPts[2].X=x; + cPts[2].Y=y; + cPts[2].Z=zfar; + cPts[3].X=-x; + cPts[3].Y=y; + cPts[3].Z=zfar; + + // transform to world space + CVector3D wPts[4]; + for (int i=0;i<4;i++) { + wPts[i]=g_NaviCam.GetCamera().m_Orientation.Transform(cPts[i]); + } + + // now intersect a ray from the camera through each point + CVector3D rayOrigin=g_NaviCam.GetCamera().m_Orientation.GetTranslation(); + CVector3D rayDir=g_NaviCam.GetCamera().m_Orientation.GetIn(); + + CVector3D hitPt[4]; + for (i=0;i<4;i++) { + CVector3D rayDir=wPts[i]-rayOrigin; + rayDir.Normalize(); + + // get intersection point + m_TerrainPlane.FindRayIntersection(rayOrigin,rayDir,&hitPt[i]); + } + + for (i=0;i<4;i++) { + // convert to minimap space + float px=hitPt[i].X; + float pz=hitPt[i].Z; + g_MiniMap.m_ViewRect[i][0]=(197*px/float(CELL_SIZE*g_Terrain.GetVerticesPerSide())); + g_MiniMap.m_ViewRect[i][1]=197*pz/float(CELL_SIZE*g_Terrain.GetVerticesPerSide()); + } +} + +void CEditorData::RenderTerrain() +{ + CFrustum frustum=g_NaviCam.GetCamera().GetFustum(); + u32 patchesPerSide=g_Terrain.GetPatchesPerSide(); + for (uint j=0; jGetBounds())) { + g_Renderer.Submit(patch); + } + } + } +} + +void CEditorData::OnScreenShot(const char* filename) +{ + g_Renderer.SetClearColor(0); + g_Renderer.BeginFrame(); + g_Renderer.SetCamera(g_NaviCam.GetCamera()); + + RenderWorld(); + + g_Renderer.EndFrame(); + + int width=g_Renderer.GetWidth(); + int height=g_Renderer.GetHeight(); + unsigned char* data=new unsigned char[width*height*3]; + + glReadBuffer(GL_BACK); + glReadPixels(0,0,width,height,GL_BGR_EXT,GL_UNSIGNED_BYTE,data); + + saveTGA(filename,width,height,data); + + delete[] data; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// SubmitModelRecursive: recurse down given model, submitting it and all it's descendents to the +// renderer +void SubmitModelRecursive(CModel* model) +{ + g_Renderer.Submit(model); + + const std::vector& props=model->GetProps(); + for (uint i=0;i& units=g_UnitMan.GetUnits(); + for (i=0;iGetModel()); + } + + u32 patchesPerSide=g_Terrain.GetPatchesPerSide(); + for (j=0; j& units=g_UnitMan.GetUnits(); + uint i; + for (i=0;iGetModel()->GetBounds())) { + SubmitModelRecursive(units[i]->GetModel()); + } + } +} + +void CEditorData::RenderWorld() +{ + // render terrain + RenderTerrain(); + + // render all the units + RenderModels(); + + // flush prior to rendering overlays etc + g_Renderer.FlushFrame(); +} + +void CEditorData::RenderObEdGrid() +{ + int i; + const int numSteps=32; + const CVector3D start(-numSteps*CELL_SIZE/2,0,-numSteps*CELL_SIZE/2); + const CVector3D end(numSteps*CELL_SIZE/2,0,numSteps*CELL_SIZE/2); + + glDisable(GL_TEXTURE_2D); + + glDepthMask(0); + glColor4f(0.5f,0.5f,0.5f,0.35f); + glLineWidth(1.0f); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + glBegin(GL_LINES); + for (i=0;i<=numSteps;i++) { + if (i%8==0) continue; + CVector3D v0(start.X+(i*(end.X-start.X))/float(numSteps),start.Y,start.Z); + glVertex3fv(&v0.X); + + CVector3D v1(v0.X,end.Y,end.Z); + glVertex3fv(&v1.X); + } + + for (i=0;i<=numSteps;i++) { + if (i%8==0) continue; + CVector3D v0(start.X,start.Y,start.Z+(i*(end.Z-start.Z))/float(numSteps)); + glVertex3fv(&v0.X); + + CVector3D v1(end.X,end.Y,v0.Z); + glVertex3fv(&v1.X); + } + glEnd(); + + glDisable(GL_BLEND); + + glColor3f(0,0,0.5); + glLineWidth(2.0f); + + glBegin(GL_LINES); + for (i=0;i<=numSteps;i+=8) { + CVector3D v0(start.X+(i*(end.X-start.X))/float(numSteps),start.Y,start.Z); + glVertex3fv(&v0.X); + + CVector3D v1(v0.X,end.Y,end.Z); + glVertex3fv(&v1.X); + } + + for (i=0;i<=numSteps;i+=8) { + CVector3D v0(start.X,start.Y,start.Z+(i*(end.Z-start.Z))/float(numSteps)); + glVertex3fv(&v0.X); + + CVector3D v1(end.X,end.Y,v0.Z); + glVertex3fv(&v1.X); + } + glEnd(); + glDepthMask(1); +} + +void CEditorData::OnDraw() +{ + if (m_Mode==SCENARIO_EDIT || m_Mode==TEST_MODE) { + g_Renderer.SetClearColor(0); + g_Renderer.BeginFrame(); + + // setup camera + g_Renderer.SetCamera(g_NaviCam.GetCamera()); + + // render base terrain plus models + RenderWorld(); + + if (m_Mode!=TEST_MODE) { + // render the active tool + g_ToolMan.OnDraw(); + } + + // flush prior to rendering overlays .. + g_Renderer.FlushFrame(); + + // .. and here's the overlays + g_MiniMap.Render(); + m_InfoBox.Render(); + } else { + g_Renderer.SetClearColor(0x00453015); + g_Renderer.BeginFrame(); + + CObjectEntry* selobject=g_ObjMan.GetSelectedObject(); + if (selobject && selobject->m_Model) { + // setup camera such that object is in the centre of the viewport + m_ModelMatrix.SetIdentity(); + selobject->m_Model->SetTransform(m_ModelMatrix); + + const CBound& bound=selobject->m_Model->GetBounds(); + CVector3D pt((bound[0].X+bound[1].X)*0.5f,(bound[0].Y+bound[1].Y)*0.5f,bound[0].Z); + + float hfov=tan(DEGTORAD(45)); + float vfov=hfov/g_Renderer.GetAspect(); + float zx=(bound[1].X-bound[0].X)*0.5f/hfov; + float zy=(bound[1].Y-bound[0].Y)*0.5f/vfov; + float z=zx>zy ? zx : zy; + z=(z+1)*2; + + m_ObjectCamera.m_Orientation.SetIdentity(); + m_ObjectCamera.m_Orientation.Translate(pt.X,pt.Y,-z); + + g_Renderer.SetCamera(m_ObjectCamera); + + RenderObEdGrid(); + + g_Renderer.Submit(selobject->m_Model); + } + + // flush prior to rendering overlays .. + g_Renderer.FlushFrame(); + + // .. and here's the overlays + m_InfoBox.Render(); + } + + g_Renderer.EndFrame(); + + // notify info box frame is complete; gives it chance to accumulate stats, check + // fps, etc + m_InfoBox.OnFrameComplete(); +} + + +bool CEditorData::LoadTerrain(const char* filename) +{ + Handle h = tex_load(filename); + if(h<=0) { + char buf[1024]; + sprintf(buf,"Failed to load \"%s\"",filename); + ErrorBox(buf); + return false; + } else { + + int width=0; + int height=0; + int bpp=0; + void *ptr=0; + + int i=tex_info(h, &width, &height, NULL, &bpp, &ptr); + if (i) + { + printf("tex_info error: %d\n",i); + fflush(stdout); + } + + // rescale the texture to fit to the nearest of the 4 possible map sizes + u32 mapsize=9; // assume smallest map + if (width>11*PATCH_SIZE+1) mapsize=11; + if (width>13*PATCH_SIZE+1) mapsize=13; + if (width>17*PATCH_SIZE+1) mapsize=17; + + u32 targetsize=mapsize*PATCH_SIZE+1; + unsigned char* data=new unsigned char[targetsize*targetsize*bpp/8]; + u32 fmt=(bpp==8) ? GL_RED : ((bpp==24) ? GL_RGB : GL_RGBA); + gluScaleImage(fmt,width,height,GL_UNSIGNED_BYTE,ptr, + targetsize,targetsize,GL_UNSIGNED_BYTE,data); + + // build 16 bit heightmap from red channel of texture + u16* heightmap=new u16[targetsize*targetsize]; + int stride=bpp/8; + u16* hmptr=heightmap; + + // get src of copy + const u8* dataptr = (bpp==8) ? data : ((bpp==24) ? data+2 : data+3); + + // build heightmap + for (uint j=0;j& units=g_UnitMan.GetUnits(); + for (uint i=0;iGetModel()->Update(time); + } + if (m_Mode==TEST_MODE) { + g_EntityManager.updateAll( time ); + } + } else { + CObjectEntry* selobject=g_ObjMan.GetSelectedObject(); + if (selobject && selobject->m_Model) { + selobject->m_Model->Update(time); + } + } +} + +void CEditorData::StartTestMode() +{ + // initialise entities + g_EntityManager.dispatchAll( &CMessage( CMessage::EMSG_INIT ) ); +} + +void CEditorData::StopTestMode() +{ + // make all units idle again + const std::vector& units=g_UnitMan.GetUnits(); + for (uint i=0;iGetObject()->m_IdleAnim) { + units[i]->GetModel()->SetAnimation(units[i]->GetObject()->m_IdleAnim); + } + } } \ No newline at end of file diff --git a/source/sced/MiniMap.cpp b/source/sced/MiniMap.cpp index c3ea7838cf..5213d355c8 100755 --- a/source/sced/MiniMap.cpp +++ b/source/sced/MiniMap.cpp @@ -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>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>8; @@ -276,6 +276,6 @@ void CMiniMap::Rebuild(int x,int y,int w,int h) *dataptr++=ScaleColor(color,float(val)/255.0f); } } - + UpdateTexture(); } diff --git a/source/sced/MiniMap.h b/source/sced/MiniMap.h index 740f4f05f7..83b7fd4b23 100755 --- a/source/sced/MiniMap.h +++ b/source/sced/MiniMap.h @@ -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; }; diff --git a/source/sced/RaiseElevationTool.h b/source/sced/RaiseElevationTool.h index 25c4e6556f..a73ae8ec61 100755 --- a/source/sced/RaiseElevationTool.h +++ b/source/sced/RaiseElevationTool.h @@ -1,7 +1,7 @@ #ifndef _RAISEELEVATIONTOOL_H #define _RAISEELEVATIONTOOL_H -#include +#include #include "lib.h" #include "res/res.h" #include "BrushTool.h" diff --git a/source/sced/ui/BrushShapeEditorDlgBar.cpp b/source/sced/ui/BrushShapeEditorDlgBar.cpp index f4a6755422..0d86e93dc7 100755 --- a/source/sced/ui/BrushShapeEditorDlgBar.cpp +++ b/source/sced/ui/BrushShapeEditorDlgBar.cpp @@ -1,5 +1,5 @@ #include "stdafx.h" -#define _IGNORE_WGL_H_ +#define _IGNORE_WGL_H_ #include "MainFrm.h" #include "EditorData.h" #include "BrushShapeEditorTool.h" diff --git a/source/sced/ui/ColorButton.h b/source/sced/ui/ColorButton.h index 027212fe4f..ea23059add 100755 --- a/source/sced/ui/ColorButton.h +++ b/source/sced/ui/ColorButton.h @@ -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 diff --git a/source/sced/ui/ElevToolsDlgBar.cpp b/source/sced/ui/ElevToolsDlgBar.cpp index 4d3d53843a..9ee9c88944 100755 --- a/source/sced/ui/ElevToolsDlgBar.cpp +++ b/source/sced/ui/ElevToolsDlgBar.cpp @@ -1,4 +1,4 @@ -#include +#include #include "stdafx.h" #include "ToolManager.h" #include "ElevToolsDlgBar.h" diff --git a/source/sced/ui/MainFrm.cpp b/source/sced/ui/MainFrm.cpp index 755297b6dc..3e919761e8 100755 --- a/source/sced/ui/MainFrm.cpp +++ b/source/sced/ui/MainFrm.cpp @@ -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;im_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;iTex1=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;im_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;iTex1=tex->GetHandle(); + mp->Tex1Priority=tex->GetType(); + mp->m_Parent->SetDirty(RENDERDATA_UPDATE_VERTICES | RENDERDATA_UPDATE_INDICES); + } + } + g_MiniMap.Rebuild(); +*/ +} diff --git a/source/sced/ui/MainFrm.h b/source/sced/ui/MainFrm.h index 6dfa67049a..fa869eade8 100755 --- a/source/sced/ui/MainFrm.h +++ b/source/sced/ui/MainFrm.h @@ -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() }; diff --git a/source/sced/ui/ScEd.cpp b/source/sced/ui/ScEd.cpp index 49e80f1b9f..7b5df6ee9e 100755 --- a/source/sced/ui/ScEd.cpp +++ b/source/sced/ui/ScEd.cpp @@ -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 diff --git a/source/sced/ui/ScEdView.cpp b/source/sced/ui/ScEdView.cpp index 8da95fc285..f42c1a355a 100755 --- a/source/sced/ui/ScEdView.cpp +++ b/source/sced/ui/ScEdView.cpp @@ -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; diff --git a/source/sced/ui/TexToolsDlgBar.cpp b/source/sced/ui/TexToolsDlgBar.cpp index 930549d124..411a4e4711 100755 --- a/source/sced/ui/TexToolsDlgBar.cpp +++ b/source/sced/ui/TexToolsDlgBar.cpp @@ -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) diff --git a/source/sced/ui/UnitPropertiesDlgBar.cpp b/source/sced/ui/UnitPropertiesDlgBar.cpp index aa31c24935..1dbf9d8012 100755 --- a/source/sced/ui/UnitPropertiesDlgBar.cpp +++ b/source/sced/ui/UnitPropertiesDlgBar.cpp @@ -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) diff --git a/source/sced/ui/resource.h b/source/sced/ui/resource.h index 4a3a65317a..3030fbb2b7 100755 --- a/source/sced/ui/resource.h +++ b/source/sced/ui/resource.h @@ -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 diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index 44400252ef..1dd9c94165 100755 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -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 ); +} + diff --git a/source/scripting/ScriptGlue.h b/source/scripting/ScriptGlue.h index 1cd25886a5..22b4ef8ea8 100755 --- a/source/scripting/ScriptGlue.h +++ b/source/scripting/ScriptGlue.h @@ -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 diff --git a/source/scripting/ScriptingHost.cpp b/source/scripting/ScriptingHost.cpp index 6526ac65f9..3b8e47c470 100755 --- a/source/scripting/ScriptingHost.cpp +++ b/source/scripting/ScriptingHost.cpp @@ -2,12 +2,16 @@ #include "ScriptingHost.h" #include "ScriptGlue.h" +#include "CConsole.h" #include #include #include +#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 << ") "; diff --git a/source/scripting/ScriptingHost.h b/source/scripting/ScriptingHost.h index d54b8a8bbe..4f923dfc4b 100755 --- a/source/scripting/ScriptingHost.h +++ b/source/scripting/ScriptingHost.h @@ -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); diff --git a/source/simulation/BaseEntity.cpp b/source/simulation/BaseEntity.cpp index 621b5c4cab..f01070cc60 100755 --- a/source/simulation/BaseEntity.cpp +++ b/source/simulation/BaseEntity.cpp @@ -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; diff --git a/source/simulation/BaseEntity.h b/source/simulation/BaseEntity.h index 0696e3ebc0..7dd268c8a9 100755 --- a/source/simulation/BaseEntity.h +++ b/source/simulation/BaseEntity.h @@ -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 m_properties; + CProperty_float m_speed; + CProperty_float m_turningRadius; }; #endif diff --git a/source/simulation/BaseEntityCollection.cpp b/source/simulation/BaseEntityCollection.cpp index e7f7e4610c..edfcbeadd8 100755 --- a/source/simulation/BaseEntityCollection.cpp +++ b/source/simulation/BaseEntityCollection.cpp @@ -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] ); +} diff --git a/source/simulation/BaseEntityCollection.h b/source/simulation/BaseEntityCollection.h index 05f685be06..bc258b920b 100755 --- a/source/simulation/BaseEntityCollection.h +++ b/source/simulation/BaseEntityCollection.h @@ -28,11 +28,12 @@ class CBaseEntityCollection : public Singleton { - std::vector m_templates; + std::vector m_templates; public: + ~CBaseEntityCollection(); CBaseEntity* getTemplate( CStr entityType ); void loadTemplates(); - void addTemplate( CBaseEntity& temp ); + void addTemplate( CBaseEntity* temp ); CBaseEntity* getTemplateByActor( CObjectEntry* actor ); }; diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index f192225b09..8b80b62b04 100755 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -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! ;) diff --git a/source/simulation/Entity.h b/source/simulation/Entity.h index 473d9dc157..41becacc19 100755 --- a/source/simulation/Entity.h +++ b/source/simulation/Entity.h @@ -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 m_orderQueue; - // Extended properties table - - STL_HASH_MAP 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 ); }; diff --git a/source/simulation/EntityManager.cpp b/source/simulation/EntityManager.cpp index e7baed6e9f..6aa91bc3a1 100755 --- a/source/simulation/EntityManager.cpp +++ b/source/simulation/EntityManager.cpp @@ -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* CEntityManager::matches( EntityPredicate predicate ) { std::vector* matchlist = new std::vector; diff --git a/source/simulation/EntityManager.h b/source/simulation/EntityManager.h index e3bf27415b..a265955bf8 100755 --- a/source/simulation/EntityManager.h +++ b/source/simulation/EntityManager.h @@ -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* matches( EntityPredicate predicate ); std::vector* getActive(); static inline bool extant() // True if the singleton is actively maintaining handles. When false, system is shutting down, handles are quietly dumped. diff --git a/source/simulation/EntityProperties.cpp b/source/simulation/EntityProperties.cpp index 6bc2b768a2..42d17fce26 100755 --- a/source/simulation/EntityProperties.cpp +++ b/source/simulation/EntityProperties.cpp @@ -1,621 +1,368 @@ #include "precompiled.h" #include "EntityProperties.h" +#include "BaseEntityCollection.h" +#include "scripting/JSInterface_BaseEntity.h" -#include - -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::iterator it; + for( it = m_inheritors.begin(); it != m_inheritors.end(); it++ ) + (*it)->rebuild( propertyName ); + } +} + +void IPropertyOwner::rebuild() +{ + STL_HASH_MAP::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::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 ); - } -} -*/ diff --git a/source/simulation/EntityProperties.h b/source/simulation/EntityProperties.h index 0876b28526..08e51ae43d 100755 --- a/source/simulation/EntityProperties.h +++ b/source/simulation/EntityProperties.h @@ -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 m_properties; + std::vector 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 diff --git a/source/simulation/EntityStateProcessing.cpp b/source/simulation/EntityStateProcessing.cpp index cee39d3fd9..9600524076 100755 --- a/source/simulation/EntityStateProcessing.cpp +++ b/source/simulation/EntityStateProcessing.cpp @@ -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; diff --git a/source/simulation/PathfindSparse.cpp b/source/simulation/PathfindSparse.cpp index 21750ac8b3..9c927c6fc0 100755 --- a/source/simulation/PathfindSparse.cpp +++ b/source/simulation/PathfindSparse.cpp @@ -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 ) diff --git a/source/simulation/scripting/JSInterface_BaseEntity.cpp b/source/simulation/scripting/JSInterface_BaseEntity.cpp new file mode 100755 index 0000000000..6b0cdd8490 --- /dev/null +++ b/source/simulation/scripting/JSInterface_BaseEntity.cpp @@ -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 ); +} \ No newline at end of file diff --git a/source/simulation/scripting/JSInterface_BaseEntity.h b/source/simulation/scripting/JSInterface_BaseEntity.h new file mode 100755 index 0000000000..943dde1896 --- /dev/null +++ b/source/simulation/scripting/JSInterface_BaseEntity.h @@ -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 \ No newline at end of file diff --git a/source/simulation/scripting/JSInterface_Entity.cpp b/source/simulation/scripting/JSInterface_Entity.cpp new file mode 100755 index 0000000000..7dbce7f7e1 --- /dev/null +++ b/source/simulation/scripting/JSInterface_Entity.cpp @@ -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 ); +} \ No newline at end of file diff --git a/source/simulation/scripting/JSInterface_Entity.h b/source/simulation/scripting/JSInterface_Entity.h new file mode 100755 index 0000000000..91671e6059 --- /dev/null +++ b/source/simulation/scripting/JSInterface_Entity.h @@ -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 \ No newline at end of file diff --git a/source/workspaces/premake/premake.lua b/source/workspaces/premake/premake.lua index fe0bda22c7..2e2484e878 100755 --- a/source/workspaces/premake/premake.lua +++ b/source/workspaces/premake/premake.lua @@ -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") },