JS Interface to entities. It even partially works now.
This was SVN commit r469.
This commit is contained in:
parent
663f25f6b6
commit
e4fe4ed602
@ -1,5 +1,4 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "ogl.h"
|
||||
#include "res/tex.h"
|
||||
#include "TextureEntry.h"
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <string>
|
||||
|
||||
// block := power-of-two sized chunk of a file.
|
||||
|
@ -42,10 +42,14 @@
|
||||
#include "PathfindEngine.h"
|
||||
#include "XML.h"
|
||||
|
||||
#include "ConfigDB.h"
|
||||
#include "scripting/JSInterface_Entity.h"
|
||||
#include "scripting/JSInterface_BaseEntity.h"
|
||||
#include "scripting/JSInterface_Vector3D.h"
|
||||
|
||||
#include "ConfigDB.h"
|
||||
#include "CLogger.h"
|
||||
|
||||
|
||||
#ifndef NO_GUI
|
||||
#include "gui/GUI.h"
|
||||
#endif
|
||||
@ -431,7 +435,7 @@ void ParseArgs(int argc, char* argv[])
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
g_EntGraph = true;
|
||||
g_EntGraph = true; break;
|
||||
case 'v':
|
||||
g_VSync = true;
|
||||
break;
|
||||
@ -622,7 +626,7 @@ PREVTSC=TSC;
|
||||
|
||||
font = font_load("fonts/verdana.fnt");
|
||||
|
||||
g_Console = new CConsole(0, g_yres-600.f, 800.f, 600.f);
|
||||
g_Console = new CConsole(0, g_yres-600.f, g_xres, 600.f);
|
||||
|
||||
// create renderer
|
||||
new CRenderer;
|
||||
@ -653,6 +657,10 @@ PREVTSC=TSC;
|
||||
|
||||
g_EntityTemplateCollection.loadTemplates();
|
||||
|
||||
// Register the JavaScript interfaces with the runtime
|
||||
JSI_Entity::init();
|
||||
JSI_BaseEntity::init();
|
||||
JSI_Vector3D::init();
|
||||
|
||||
// if no map name specified, load test01.pmp (for convenience during
|
||||
// development. that means loading no map at all is currently impossible.
|
||||
|
@ -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 ;
|
||||
|
138
source/maths/scripting/JSInterface_Vector3D.cpp
Executable file
138
source/maths/scripting/JSInterface_Vector3D.cpp
Executable file
@ -0,0 +1,138 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "JSInterface_Vector3D.h"
|
||||
|
||||
JSClass JSI_Vector3D::JSI_class = {
|
||||
"Vector3D", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JSI_Vector3D::getProperty, JSI_Vector3D::setProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub, JSI_Vector3D::finalize,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
JSPropertySpec JSI_Vector3D::JSI_props[] =
|
||||
{
|
||||
{ "x", JSI_Vector3D::component_x, JSPROP_ENUMERATE },
|
||||
{ "y", JSI_Vector3D::component_y, JSPROP_ENUMERATE },
|
||||
{ "z", JSI_Vector3D::component_z, JSPROP_ENUMERATE },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSFunctionSpec JSI_Vector3D::JSI_methods[] =
|
||||
{
|
||||
{ "toString", JSI_Vector3D::toString, 0, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void JSI_Vector3D::init()
|
||||
{
|
||||
g_ScriptingHost.DefineCustomObjectType( &JSI_class, JSI_Vector3D::construct, 0, JSI_props, JSI_methods, NULL, NULL );
|
||||
}
|
||||
|
||||
JSI_Vector3D::Vector3D_Info::Vector3D_Info()
|
||||
{
|
||||
owner = NULL;
|
||||
vector = new CVector3D();
|
||||
}
|
||||
|
||||
JSI_Vector3D::Vector3D_Info::Vector3D_Info( float x, float y, float z )
|
||||
{
|
||||
owner = NULL;
|
||||
vector = new CVector3D( x, y, z );
|
||||
}
|
||||
|
||||
JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner )
|
||||
{
|
||||
owner = _owner;
|
||||
updateFn = NULL;
|
||||
vector = copy;
|
||||
}
|
||||
|
||||
JSI_Vector3D::Vector3D_Info::Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner, void( IPropertyOwner::*_updateFn )(void) )
|
||||
{
|
||||
owner = _owner;
|
||||
updateFn = _updateFn;
|
||||
vector = copy;
|
||||
}
|
||||
|
||||
JSI_Vector3D::Vector3D_Info::~Vector3D_Info()
|
||||
{
|
||||
if( !owner ) delete( vector );
|
||||
}
|
||||
|
||||
JSBool JSI_Vector3D::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
if( !JSVAL_IS_INT( id ) )
|
||||
return( JS_TRUE );
|
||||
|
||||
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
|
||||
if( !vectorInfo ) return( JS_TRUE );
|
||||
CVector3D* vectorData = vectorInfo->vector;
|
||||
|
||||
switch( g_ScriptingHost.ValueToInt( id ) )
|
||||
{
|
||||
case component_x: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->X ) ); return( JS_TRUE );
|
||||
case component_y: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Y ) ); return( JS_TRUE );
|
||||
case component_z: *vp = DOUBLE_TO_JSVAL( JS_NewDouble( cx, vectorData->Z ) ); return( JS_TRUE );
|
||||
}
|
||||
|
||||
return( JS_FALSE );
|
||||
}
|
||||
|
||||
JSBool JSI_Vector3D::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
if( !JSVAL_IS_INT( id ) )
|
||||
return( JS_TRUE );
|
||||
|
||||
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
|
||||
if( !vectorInfo ) return( JS_TRUE );
|
||||
CVector3D* vectorData = vectorInfo->vector;
|
||||
|
||||
switch( g_ScriptingHost.ValueToInt( id ) )
|
||||
{
|
||||
case component_x: vectorData->X = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
|
||||
case component_y: vectorData->Y = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
|
||||
case component_z: vectorData->Z = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
|
||||
}
|
||||
|
||||
if( vectorInfo->owner && vectorInfo->updateFn ) ( (vectorInfo->owner)->*(vectorInfo->updateFn) )();
|
||||
|
||||
return( JS_TRUE );
|
||||
return( JS_FALSE );
|
||||
}
|
||||
|
||||
JSBool JSI_Vector3D::construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
if( ( argc != 0 ) && ( argc != 3 ) ) return( JS_FALSE );
|
||||
if( argc == 0 )
|
||||
{
|
||||
JS_SetPrivate( cx, obj, new Vector3D_Info() );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
else if( argc == 3 )
|
||||
{
|
||||
float x = (float)g_ScriptingHost.ValueToDouble( argv[0] );
|
||||
float y = (float)g_ScriptingHost.ValueToDouble( argv[1] );
|
||||
float z = (float)g_ScriptingHost.ValueToDouble( argv[2] );
|
||||
JS_SetPrivate( cx, obj, new Vector3D_Info( x, y, z ) );
|
||||
}
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
void JSI_Vector3D::finalize( JSContext* cx, JSObject* obj )
|
||||
{
|
||||
delete( JS_GetPrivate( cx, obj ) );
|
||||
}
|
||||
|
||||
JSBool JSI_Vector3D::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
char buffer[256];
|
||||
Vector3D_Info* vectorInfo = (Vector3D_Info*)JS_GetPrivate( cx, obj );
|
||||
if( !vectorInfo ) return( JS_TRUE );
|
||||
CVector3D* vectorData = vectorInfo->vector;
|
||||
snprintf( buffer, 256, "[object Vector3D: ( %f, %f, %f )]", vectorData->X, vectorData->Y, vectorData->Z );
|
||||
buffer[255] = 0;
|
||||
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
|
||||
return( JS_TRUE );
|
||||
}
|
49
source/maths/scripting/JSInterface_Vector3D.h
Executable file
49
source/maths/scripting/JSInterface_Vector3D.h
Executable file
@ -0,0 +1,49 @@
|
||||
// JSInterface_Entity.h
|
||||
//
|
||||
// Last modified: 03 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
//
|
||||
// A JavaScript class representing a Prometheus CVector3D object.
|
||||
//
|
||||
// Usage: Used when manipulating objects of class 'Vector3D' in JavaScript.
|
||||
//
|
||||
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
|
||||
#include "scripting/ScriptingHost.h"
|
||||
#include "Vector3D.h"
|
||||
|
||||
#ifndef JSI_VECTOR3_INCLUDED
|
||||
#define JSI_VECTOR3_INCLUDED
|
||||
|
||||
class IPropertyOwner;
|
||||
|
||||
namespace JSI_Vector3D
|
||||
{
|
||||
enum
|
||||
{
|
||||
component_x,
|
||||
component_y,
|
||||
component_z
|
||||
};
|
||||
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
|
||||
struct Vector3D_Info
|
||||
{
|
||||
IPropertyOwner* owner;
|
||||
void ( IPropertyOwner::*updateFn )();
|
||||
CVector3D* vector;
|
||||
Vector3D_Info();
|
||||
Vector3D_Info( float x, float y, float z );
|
||||
Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner );
|
||||
Vector3D_Info( CVector3D* copy, IPropertyOwner* _owner, void (IPropertyOwner::*_updateFn)() );
|
||||
~Vector3D_Info();
|
||||
};
|
||||
extern JSClass JSI_class;
|
||||
extern JSPropertySpec JSI_props[];
|
||||
extern JSFunctionSpec JSI_methods[];
|
||||
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
void finalize( JSContext* cx, JSObject* obj );
|
||||
JSBool construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
|
||||
void init();
|
||||
};
|
||||
|
||||
#endif
|
@ -5,6 +5,8 @@
|
||||
#include "Prometheus.h"
|
||||
#include "sysdep/sysdep.h"
|
||||
|
||||
#include "scripting/ScriptingHost.h"
|
||||
|
||||
CConsole::CConsole(float X, float Y, float W, float H)
|
||||
: m_fX(X), m_fY(Y), m_fWidth(W), m_fHeight(H)
|
||||
{
|
||||
@ -242,7 +244,7 @@ void CConsole::DrawCursor(void)
|
||||
|
||||
|
||||
//Inserts a character into the buffer.
|
||||
void CConsole::InsertChar(const int szChar)
|
||||
void CConsole::InsertChar(const int szChar, const int cooked )
|
||||
{
|
||||
static int iHistoryPos = -1;
|
||||
|
||||
@ -321,15 +323,16 @@ void CConsole::InsertChar(const int szChar)
|
||||
|
||||
default: //Insert a character
|
||||
if (IsFull()) return;
|
||||
if (!isprint(szChar)) return;
|
||||
if( cooked >= 255 ) return;
|
||||
if (!isprint( cooked )) return;
|
||||
|
||||
if (IsEOB()) //are we at the end of the buffer?
|
||||
m_szBuffer[m_iBufferPos] = szChar; //cat char onto end
|
||||
m_szBuffer[m_iBufferPos] = cooked; //cat char onto end
|
||||
else{ //we need to insert
|
||||
int i;
|
||||
for(i=m_iBufferLength; i>m_iBufferPos; i--)
|
||||
m_szBuffer[i] = m_szBuffer[i-1]; // move chars to right
|
||||
m_szBuffer[i] = szChar;
|
||||
m_szBuffer[i] = cooked;
|
||||
}
|
||||
|
||||
m_iBufferPos++;
|
||||
@ -410,6 +413,18 @@ void CConsole::ProcessBuffer(const char* szLine){
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( szLine[0] == ':' )
|
||||
{
|
||||
// Process it as JavaScript
|
||||
g_ScriptingHost.ExecuteScript( szLine + 1 );
|
||||
}
|
||||
else if( szLine[0] == '?' )
|
||||
{
|
||||
// Process it as JavaScript and display the result
|
||||
jsval rval = g_ScriptingHost.ExecuteScript( szLine + 1 );
|
||||
if( rval )
|
||||
InsertMessage( g_ScriptingHost.ValueToString( rval ).c_str() );
|
||||
}
|
||||
else InsertMessage("<say>: %s", szLine);
|
||||
|
||||
delete[] szCommand;
|
||||
@ -425,6 +440,6 @@ bool conInputHandler(const SDL_Event& ev)
|
||||
if(ev.type != SDL_KEYDOWN)
|
||||
return false;
|
||||
|
||||
g_Console->InsertChar(ev.key.keysym.sym);
|
||||
g_Console->InsertChar(ev.key.keysym.sym, ev.key.keysym.unicode );
|
||||
return g_Console->IsActive();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -8,12 +8,12 @@
|
||||
#include "ModelRData.h"
|
||||
#include "Model.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// shared list of all submitted models this frame
|
||||
std::vector<CModel*> CModelRData::m_Models;
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// shared list of all submitted models this frame
|
||||
std::vector<CModel*> CModelRData::m_Models;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CModelRData constructor
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CModelRData constructor
|
||||
CModelRData::CModelRData(CModel* model)
|
||||
: m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0), m_Flags(0)
|
||||
{
|
||||
@ -22,16 +22,16 @@ CModelRData::CModelRData(CModel* model)
|
||||
Build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CModelRData destructor
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CModelRData destructor
|
||||
CModelRData::~CModelRData()
|
||||
{
|
||||
{
|
||||
// clean up system copies of data
|
||||
delete[] m_Indices;
|
||||
delete[] m_Vertices;
|
||||
delete[] m_Normals;
|
||||
if (m_VB) {
|
||||
// release vertex buffer chunks
|
||||
if (m_VB) {
|
||||
// release vertex buffer chunks
|
||||
g_VBMan.Release(m_VB);
|
||||
}
|
||||
}
|
||||
@ -51,19 +51,19 @@ void CModelRData::Build()
|
||||
|
||||
void CModelRData::BuildIndices()
|
||||
{
|
||||
CModelDef* mdef=m_Model->GetModelDef();
|
||||
assert(mdef);
|
||||
|
||||
// must have a valid vertex buffer by this point so we know where indices are supposed to start
|
||||
CModelDef* mdef=m_Model->GetModelDef();
|
||||
assert(mdef);
|
||||
|
||||
// must have a valid vertex buffer by this point so we know where indices are supposed to start
|
||||
assert(m_VB);
|
||||
|
||||
|
||||
// allocate indices if we haven't got any already
|
||||
if (!m_Indices) {
|
||||
m_Indices=new u16[mdef->GetNumFaces()*3];
|
||||
}
|
||||
|
||||
// build indices
|
||||
u32 base=m_VB->m_Index;
|
||||
u32 base=m_VB->m_Index;
|
||||
u32 indices=0;
|
||||
SModelFace* faces=mdef->GetFaces();
|
||||
for (int j=0; j<mdef->GetNumFaces(); j++) {
|
||||
@ -91,40 +91,40 @@ static SColor4ub ConvertColor(const RGBColor& src)
|
||||
return result;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the vertex position using it's blend data and given bone matrices
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the vertex position using it's blend data and given bone matrices
|
||||
static void SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices,CVector3D& result)
|
||||
{
|
||||
CVector3D tmp;
|
||||
const SVertexBlend& blend=vertex.m_Blend;
|
||||
|
||||
// must have at least one valid bone if we're using SkinPoint
|
||||
assert(blend.m_Bone[0]!=0xff);
|
||||
|
||||
const CMatrix3D& m=matrices[blend.m_Bone[0]];
|
||||
m.Transform(vertex.m_Coords,result);
|
||||
result*=blend.m_Weight[0];
|
||||
|
||||
for (u32 i=1;blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
||||
const CMatrix3D& m=matrices[blend.m_Bone[i]];
|
||||
m.Transform(vertex.m_Coords,tmp);
|
||||
result+=tmp*blend.m_Weight[i];
|
||||
}
|
||||
CVector3D tmp;
|
||||
const SVertexBlend& blend=vertex.m_Blend;
|
||||
|
||||
// must have at least one valid bone if we're using SkinPoint
|
||||
assert(blend.m_Bone[0]!=0xff);
|
||||
|
||||
const CMatrix3D& m=matrices[blend.m_Bone[0]];
|
||||
m.Transform(vertex.m_Coords,result);
|
||||
result*=blend.m_Weight[0];
|
||||
|
||||
for (u32 i=1;blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
||||
const CMatrix3D& m=matrices[blend.m_Bone[i]];
|
||||
m.Transform(vertex.m_Coords,tmp);
|
||||
result+=tmp*blend.m_Weight[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the vertex normal using it's blend data and given bone matrices
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the vertex normal using it's blend data and given bone matrices
|
||||
static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,CVector3D& result)
|
||||
{
|
||||
CVector3D tmp;
|
||||
const SVertexBlend& blend=vertex.m_Blend;
|
||||
|
||||
// must have at least one valid bone if we're using SkinNormal
|
||||
assert(blend.m_Bone[0]!=0xff);
|
||||
|
||||
const CMatrix3D& m=invmatrices[blend.m_Bone[0]];
|
||||
m.RotateTransposed(vertex.m_Norm,result);
|
||||
result*=blend.m_Weight[0];
|
||||
const SVertexBlend& blend=vertex.m_Blend;
|
||||
|
||||
// must have at least one valid bone if we're using SkinNormal
|
||||
assert(blend.m_Bone[0]!=0xff);
|
||||
|
||||
const CMatrix3D& m=invmatrices[blend.m_Bone[0]];
|
||||
m.RotateTransposed(vertex.m_Norm,result);
|
||||
result*=blend.m_Weight[0];
|
||||
|
||||
for (u32 i=1;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
||||
const CMatrix3D& m=invmatrices[blend.m_Bone[i]];
|
||||
@ -146,9 +146,9 @@ void CModelRData::BuildVertices()
|
||||
// build vertices
|
||||
u32 numVertices=mdef->GetNumVertices();
|
||||
SModelVertex* vertices=mdef->GetVertices();
|
||||
const CMatrix3D* bonematrices=m_Model->GetBoneMatrices();
|
||||
const CMatrix3D* bonematrices=m_Model->GetBoneMatrices();
|
||||
if (bonematrices) {
|
||||
// boned model - calculate skinned vertex positions/normals
|
||||
// boned model - calculate skinned vertex positions/normals
|
||||
const CMatrix3D* invbonematrices=m_Model->GetInvBoneMatrices();
|
||||
for (uint j=0; j<numVertices; j++) {
|
||||
SkinPoint(vertices[j],bonematrices,m_Vertices[j].m_Position);
|
||||
@ -156,7 +156,7 @@ void CModelRData::BuildVertices()
|
||||
}
|
||||
} else {
|
||||
// just copy regular positions, transform normals to world space
|
||||
const CMatrix3D& transform=m_Model->GetTransform();
|
||||
const CMatrix3D& transform=m_Model->GetTransform();
|
||||
const CMatrix3D& invtransform=m_Model->GetInvTransform();
|
||||
for (uint j=0; j<numVertices; j++) {
|
||||
transform.Transform(vertices[j].m_Coords,m_Vertices[j].m_Position);
|
||||
@ -170,11 +170,11 @@ void CModelRData::BuildVertices()
|
||||
m_Vertices[j].m_UVs[1]=1-vertices[j].m_V;
|
||||
g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j],m_Vertices[j].m_Color);
|
||||
}
|
||||
|
||||
|
||||
// upload everything to vertex buffer - create one if necessary
|
||||
if (!m_VB) {
|
||||
m_VB=g_VBMan.Allocate(sizeof(SVertex),mdef->GetNumVertices(),mdef->GetNumBones() ? true : false);
|
||||
}
|
||||
if (!m_VB) {
|
||||
m_VB=g_VBMan.Allocate(sizeof(SVertex),mdef->GetNumVertices(),mdef->GetNumBones() ? true : false);
|
||||
}
|
||||
m_VB->m_Owner->UpdateChunkVertices(m_VB,m_Vertices);
|
||||
}
|
||||
|
||||
@ -275,88 +275,88 @@ float CModelRData::BackToFrontIndexSort(CMatrix3D& objToCam)
|
||||
|
||||
return mindist;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBatches: submit batches for this model to the vertex buffer
|
||||
void CModelRData::SubmitBatches()
|
||||
{
|
||||
assert(m_VB);
|
||||
m_VB->m_Owner->AppendBatch(m_VB,m_Model->GetTexture()->GetHandle(),m_Model->GetModelDef()->GetNumFaces()*3,m_Indices);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderModels: render all submitted models; assumes necessary client states already enabled,
|
||||
// and texture environment already setup as required
|
||||
void CModelRData::RenderModels(u32 streamflags)
|
||||
{
|
||||
uint i;
|
||||
#if 1
|
||||
// submit batches for each model to the vertex buffer
|
||||
for (i=0;i<m_Models.size();++i) {
|
||||
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
|
||||
modeldata->SubmitBatches();
|
||||
}
|
||||
|
||||
// step through all accumulated batches
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position));
|
||||
if (streamflags & STREAM_COLOR) glColorPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Color));
|
||||
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_TRIANGLES,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_ModelTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (i=0;i<m_Models.size();++i) {
|
||||
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
|
||||
modeldata->RenderStreams(streamflags);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Submit: submit a model to render this frame
|
||||
void CModelRData::Submit(CModel* model)
|
||||
{
|
||||
CModelRData* data=(CModelRData*) model->GetRenderData();
|
||||
if (data==0) {
|
||||
// no renderdata for model, create it now
|
||||
data=new CModelRData(model);
|
||||
model->SetRenderData(data);
|
||||
} else {
|
||||
data->Update();
|
||||
}
|
||||
|
||||
if (data->GetFlags() & MODELRDATA_FLAG_TRANSPARENT) {
|
||||
// add this mode to the transparency renderer for later processing - calculate
|
||||
// transform matrix
|
||||
g_TransparencyRenderer.Add(model);
|
||||
} else {
|
||||
// add to regular model list
|
||||
m_Models.push_back(model);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBatches: submit batches for this model to the vertex buffer
|
||||
void CModelRData::SubmitBatches()
|
||||
{
|
||||
assert(m_VB);
|
||||
m_VB->m_Owner->AppendBatch(m_VB,m_Model->GetTexture()->GetHandle(),m_Model->GetModelDef()->GetNumFaces()*3,m_Indices);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderModels: render all submitted models; assumes necessary client states already enabled,
|
||||
// and texture environment already setup as required
|
||||
void CModelRData::RenderModels(u32 streamflags)
|
||||
{
|
||||
uint i;
|
||||
#if 1
|
||||
// submit batches for each model to the vertex buffer
|
||||
for (i=0;i<m_Models.size();++i) {
|
||||
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
|
||||
modeldata->SubmitBatches();
|
||||
}
|
||||
|
||||
// step through all accumulated batches
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position));
|
||||
if (streamflags & STREAM_COLOR) glColorPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Color));
|
||||
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
if (streamflags & STREAM_UV0) g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_TRIANGLES,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_ModelTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (i=0;i<m_Models.size();++i) {
|
||||
CModelRData* modeldata=(CModelRData*) m_Models[i]->GetRenderData();
|
||||
modeldata->RenderStreams(streamflags);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Submit: submit a model to render this frame
|
||||
void CModelRData::Submit(CModel* model)
|
||||
{
|
||||
CModelRData* data=(CModelRData*) model->GetRenderData();
|
||||
if (data==0) {
|
||||
// no renderdata for model, create it now
|
||||
data=new CModelRData(model);
|
||||
model->SetRenderData(data);
|
||||
} else {
|
||||
data->Update();
|
||||
}
|
||||
|
||||
if (data->GetFlags() & MODELRDATA_FLAG_TRANSPARENT) {
|
||||
// add this mode to the transparency renderer for later processing - calculate
|
||||
// transform matrix
|
||||
g_TransparencyRenderer.Add(model);
|
||||
} else {
|
||||
// add to regular model list
|
||||
m_Models.push_back(model);
|
||||
}
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ public:
|
||||
// sort indices of this object from back to front according to given
|
||||
// object to camera space transform; return sqrd distance to centre of nearest triangle
|
||||
float BackToFrontIndexSort(CMatrix3D& objToCam);
|
||||
|
||||
// submit a model to render this frame
|
||||
static void Submit(CModel* model);
|
||||
// clear per frame patch list
|
||||
static void ClearSubmissions() { m_Models.clear(); }
|
||||
|
||||
// render all submitted models
|
||||
static void RenderModels(u32 streamflags);
|
||||
|
||||
// submit a model to render this frame
|
||||
static void Submit(CModel* model);
|
||||
// clear per frame patch list
|
||||
static void ClearSubmissions() { m_Models.clear(); }
|
||||
|
||||
// render all submitted models
|
||||
static void RenderModels(u32 streamflags);
|
||||
|
||||
private:
|
||||
// build this renderdata object
|
||||
@ -42,8 +42,8 @@ private:
|
||||
void BuildVertices();
|
||||
void BuildIndices();
|
||||
|
||||
// submit batches for this model to the vertex buffer
|
||||
void SubmitBatches();
|
||||
// submit batches for this model to the vertex buffer
|
||||
void SubmitBatches();
|
||||
|
||||
struct SVertex {
|
||||
// vertex position
|
||||
@ -66,8 +66,8 @@ private:
|
||||
u16* m_Indices;
|
||||
// model render flags
|
||||
u32 m_Flags;
|
||||
// list of all submitted models
|
||||
static std::vector<CModel*> m_Models;
|
||||
// list of all submitted models
|
||||
static std::vector<CModel*> m_Models;
|
||||
};
|
||||
|
||||
|
||||
|
@ -7,11 +7,11 @@
|
||||
#include "Renderer.h"
|
||||
#include "PatchRData.h"
|
||||
#include "AlphaMapCalculator.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// shared list of all submitted patches this frame
|
||||
std::vector<CPatch*> CPatchRData::m_Patches;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// shared list of all submitted patches this frame
|
||||
std::vector<CPatch*> CPatchRData::m_Patches;
|
||||
|
||||
|
||||
const int BlendOffsets[8][2] = {
|
||||
{ 0, -1 },
|
||||
@ -24,40 +24,40 @@ const int BlendOffsets[8][2] = {
|
||||
{ 1, -1 }
|
||||
};
|
||||
|
||||
inline int clamp(int x,int min,int max)
|
||||
{
|
||||
if (x<min) return min;
|
||||
else if (x>max) return max;
|
||||
else return x;
|
||||
}
|
||||
|
||||
static SColor4ub ConvertColor(const RGBColor& src)
|
||||
{
|
||||
SColor4ub result;
|
||||
result.R=clamp(int(src.X*255),0,255);
|
||||
result.G=clamp(int(src.Y*255),0,255);
|
||||
result.B=clamp(int(src.Z*255),0,255);
|
||||
result.A=0xff;
|
||||
return result;
|
||||
}
|
||||
inline int clamp(int x,int min,int max)
|
||||
{
|
||||
if (x<min) return min;
|
||||
else if (x>max) return max;
|
||||
else return x;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData constructor
|
||||
static SColor4ub ConvertColor(const RGBColor& src)
|
||||
{
|
||||
SColor4ub result;
|
||||
result.R=clamp(int(src.X*255),0,255);
|
||||
result.G=clamp(int(src.Y*255),0,255);
|
||||
result.B=clamp(int(src.Z*255),0,255);
|
||||
result.A=0xff;
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData constructor
|
||||
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_Vertices(0), m_VBBase(0), m_VBBlends(0)
|
||||
{
|
||||
assert(patch);
|
||||
Build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData destructor
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData destructor
|
||||
CPatchRData::~CPatchRData()
|
||||
{
|
||||
// delete copy of vertex data
|
||||
delete[] m_Vertices;
|
||||
// delete copy of vertex data
|
||||
delete[] m_Vertices;
|
||||
// release vertex buffer chunks
|
||||
if (m_VBBase) g_VBMan.Release(m_VBBase);
|
||||
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
|
||||
if (m_VBBase) g_VBMan.Release(m_VBBase);
|
||||
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
|
||||
}
|
||||
|
||||
|
||||
@ -253,47 +253,47 @@ void CPatchRData::BuildBlends()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// build vertex data
|
||||
if (m_VBBlends) {
|
||||
// release existing vertex buffer chunk
|
||||
if (m_VBBlends) {
|
||||
// release existing vertex buffer chunk
|
||||
g_VBMan.Release(m_VBBlends);
|
||||
}
|
||||
m_VBBlends=g_VBMan.Allocate(sizeof(SBlendVertex),m_BlendVertices.size(),false);
|
||||
}
|
||||
m_VBBlends=g_VBMan.Allocate(sizeof(SBlendVertex),m_BlendVertices.size(),false);
|
||||
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]);
|
||||
|
||||
|
||||
// now build outgoing splats
|
||||
m_BlendSplats.resize(splatTextures.size());
|
||||
int splatCount=0;
|
||||
|
||||
u32 base=m_VBBlends->m_Index;
|
||||
std::set<Handle>::iterator iter=splatTextures.begin();
|
||||
for (;iter!=splatTextures.end();++iter) {
|
||||
Handle tex=*iter;
|
||||
|
||||
SSplat& splat=m_BlendSplats[splatCount];
|
||||
splat.m_IndexStart=m_BlendIndices.size();
|
||||
splat.m_Texture=tex;
|
||||
|
||||
for (uint k=0;k<splats.size();k++) {
|
||||
if (splats[k].m_Texture==tex) {
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[0]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[1]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[2]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[3]+base);
|
||||
splat.m_IndexCount+=4;
|
||||
}
|
||||
}
|
||||
splatCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// now build outgoing splats
|
||||
m_BlendSplats.resize(splatTextures.size());
|
||||
int splatCount=0;
|
||||
|
||||
u32 base=m_VBBlends->m_Index;
|
||||
std::set<Handle>::iterator iter=splatTextures.begin();
|
||||
for (;iter!=splatTextures.end();++iter) {
|
||||
Handle tex=*iter;
|
||||
|
||||
SSplat& splat=m_BlendSplats[splatCount];
|
||||
splat.m_IndexStart=m_BlendIndices.size();
|
||||
splat.m_Texture=tex;
|
||||
|
||||
for (uint k=0;k<splats.size();k++) {
|
||||
if (splats[k].m_Texture==tex) {
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[0]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[1]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[2]+base);
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[3]+base);
|
||||
splat.m_IndexCount+=4;
|
||||
}
|
||||
}
|
||||
splatCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CPatchRData::BuildIndices()
|
||||
{
|
||||
// must have allocated some vertices before trying to build corresponding indices
|
||||
assert(m_VBBase);
|
||||
{
|
||||
// must have allocated some vertices before trying to build corresponding indices
|
||||
assert(m_VBBase);
|
||||
|
||||
// number of vertices in each direction in each patch
|
||||
int vsize=PATCH_SIZE+1;
|
||||
@ -318,7 +318,7 @@ void CPatchRData::BuildIndices()
|
||||
// now build base splats from interior textures
|
||||
m_Splats.resize(textures.size());
|
||||
// build indices for base splats
|
||||
u32 base=m_VBBase->m_Index;
|
||||
u32 base=m_VBBase->m_Index;
|
||||
for (uint i=0;i<m_Splats.size();i++) {
|
||||
Handle h=textures[i];
|
||||
|
||||
@ -337,25 +337,25 @@ void CPatchRData::BuildIndices()
|
||||
}
|
||||
}
|
||||
splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart;
|
||||
}
|
||||
|
||||
// build indices for the shadow map pass
|
||||
for (int j=0;j<PATCH_SIZE;j++) {
|
||||
for (int i=0;i<PATCH_SIZE;i++) {
|
||||
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+0))+base);
|
||||
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+1))+base);
|
||||
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+1))+base);
|
||||
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+0))+base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build indices for the shadow map pass
|
||||
for (int j=0;j<PATCH_SIZE;j++) {
|
||||
for (int i=0;i<PATCH_SIZE;i++) {
|
||||
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+0))+base);
|
||||
m_ShadowMapIndices.push_back(((j+0)*vsize+(i+1))+base);
|
||||
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+1))+base);
|
||||
m_ShadowMapIndices.push_back(((j+1)*vsize+(i+0))+base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPatchRData::BuildVertices()
|
||||
{
|
||||
CVector3D normal;
|
||||
RGBColor c;
|
||||
|
||||
CVector3D normal;
|
||||
RGBColor c;
|
||||
|
||||
// number of vertices in each direction in each patch
|
||||
int vsize=PATCH_SIZE+1;
|
||||
|
||||
@ -372,25 +372,25 @@ void CPatchRData::BuildVertices()
|
||||
CTerrain* terrain=m_Patch->m_Parent;
|
||||
u32 mapSize=terrain->GetVerticesPerSide();
|
||||
|
||||
// build vertices
|
||||
// build vertices
|
||||
for (int j=0;j<vsize;j++) {
|
||||
for (int i=0;i<vsize;i++) {
|
||||
int ix=px*PATCH_SIZE+i;
|
||||
int iz=pz*PATCH_SIZE+j;
|
||||
int v=(j*vsize)+i;
|
||||
int v=(j*vsize)+i;
|
||||
|
||||
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
|
||||
terrain->CalcNormal(ix,iz,normal);
|
||||
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal,c);
|
||||
vertices[v].m_Color=ConvertColor(c);
|
||||
terrain->CalcNormal(ix,iz,normal);
|
||||
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal,c);
|
||||
vertices[v].m_Color=ConvertColor(c);
|
||||
vertices[v].m_UVs[0]=i*0.125f;
|
||||
vertices[v].m_UVs[1]=j*0.125f;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_VBBase) {
|
||||
if (!m_VBBase) {
|
||||
m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,false);
|
||||
}
|
||||
}
|
||||
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
|
||||
}
|
||||
|
||||
@ -464,7 +464,7 @@ void CPatchRData::RenderBlends()
|
||||
|
||||
if (m_BlendVertices.size()==0) return;
|
||||
|
||||
u8* base=m_VBBlends->m_Owner->Bind();
|
||||
u8* base=m_VBBlends->m_Owner->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBlendVertex);
|
||||
@ -491,7 +491,7 @@ void CPatchRData::RenderBlends()
|
||||
|
||||
void CPatchRData::RenderOutline()
|
||||
{
|
||||
// TODO, RC - fixme, only works for PATCH_SIZE = 16
|
||||
// TODO, RC - fixme, only works for PATCH_SIZE = 16
|
||||
const u16 EdgeIndices[PATCH_SIZE*4] = {
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
33, 50, 67, 84, 101, 118, 135, 152, 169, 186, 203, 220, 237, 254, 271, 288,
|
||||
@ -510,298 +510,298 @@ void CPatchRData::RenderOutline()
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=numIndices/2;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBaseBatches: submit base batches for this patch to the vertex buffer
|
||||
void CPatchRData::SubmitBaseBatches()
|
||||
{
|
||||
assert(m_VBBase);
|
||||
|
||||
for (uint i=0;i<m_Splats.size();i++) {
|
||||
const SSplat& splat=m_Splats[i];
|
||||
m_VBBase->m_Owner->AppendBatch(m_VBBase,splat.m_Texture,splat.m_IndexCount,&m_Indices[splat.m_IndexStart]);
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBlendBatches: submit next set of blend batches for this patch to the vertex buffer;
|
||||
// return true if all blends on this patch have been submitted, else false
|
||||
bool CPatchRData::SubmitBlendBatches()
|
||||
{
|
||||
if (m_NextBlendSplat<m_BlendSplats.size()) {
|
||||
for (uint i=m_NextBlendSplat;i<m_BlendSplats.size();i++) {
|
||||
const SSplat& splat=m_BlendSplats[i];
|
||||
m_VBBlends->m_Owner->AppendBatch(m_VBBlends,splat.m_Texture,splat.m_IndexCount,&m_BlendIndices[splat.m_IndexStart]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderBaseSplats: render all base passes of all patches; assumes vertex, texture and color
|
||||
// client states are enabled
|
||||
void CPatchRData::RenderBaseSplats()
|
||||
{
|
||||
uint i;
|
||||
|
||||
// set up texture environment for base pass
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 1
|
||||
// submit base batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->SubmitBaseBatches();
|
||||
}
|
||||
|
||||
// render base passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBaseVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_UVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->RenderBase();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderBlendSplats: render all blend passes of all patches; assumes vertex, texture and color
|
||||
// client states are enabled
|
||||
void CPatchRData::RenderBlendSplats()
|
||||
{
|
||||
uint i;
|
||||
|
||||
// switch on second uv set
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// switch on the composite alpha map texture
|
||||
g_Renderer.BindTexture(1,g_Renderer.m_CompositeAlphaMap);
|
||||
|
||||
// setup additional texenv required by blend pass
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// switch on blending
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// no need to write to the depth buffer a second time
|
||||
glDepthMask(0);
|
||||
|
||||
#if 1
|
||||
// submit blend batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->SetupBlendBatches();
|
||||
}
|
||||
|
||||
bool finished=true;
|
||||
do
|
||||
{
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
if (!patchdata->SubmitBlendBatches()) finished=false;
|
||||
}
|
||||
} while (!finished);
|
||||
|
||||
// render blend passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBlendVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color));
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
// render blend passes for each patch
|
||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->RenderBlends();
|
||||
}
|
||||
#endif
|
||||
|
||||
// restore depth writes
|
||||
glDepthMask(1);
|
||||
|
||||
// restore default state: switch off blending
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// switch off texture unit 1, make unit 0 active texture
|
||||
g_Renderer.BindTexture(1,0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// tidy up client states
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0_ARB);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Submit: submit a patch to render this frame
|
||||
void CPatchRData::Submit(CPatch* patch)
|
||||
{
|
||||
CPatchRData* data=(CPatchRData*) patch->GetRenderData();
|
||||
if (data==0) {
|
||||
// no renderdata for patch, create it now
|
||||
data=new CPatchRData(patch);
|
||||
patch->SetRenderData(data);
|
||||
} else {
|
||||
data->Update();
|
||||
}
|
||||
|
||||
m_Patches.push_back(patch);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ApplyShadowMap: apply given shadow map to all terrain patches; assume the texture matrix
|
||||
// has been correctly setup on unit 1 to handle the projection
|
||||
void CPatchRData::ApplyShadowMap(GLuint shadowmaphandle)
|
||||
{
|
||||
uint i;
|
||||
|
||||
// glEnable(GL_ALPHA_TEST);
|
||||
// glAlphaFunc(GL_GREATER,0.0f);
|
||||
|
||||
g_Renderer.BindTexture(0,shadowmaphandle);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
glColor3f(1,1,1);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_DST_COLOR,GL_ZERO);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
#if 1
|
||||
// submit base batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->m_VBBase->m_Owner->AppendBatch(patchdata->m_VBBase,0,patchdata->m_ShadowMapIndices.size(),
|
||||
&patchdata->m_ShadowMapIndices[0]);
|
||||
}
|
||||
|
||||
// render base passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBaseVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
|
||||
glTexCoordPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position));
|
||||
|
||||
// render batch (can only be one per buffer, since all batches are flagged as using a null texture)
|
||||
const CVertexBuffer::Batch* batch=batches[0];
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (uint i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();;
|
||||
patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0);
|
||||
}
|
||||
#endif
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBaseBatches: submit base batches for this patch to the vertex buffer
|
||||
void CPatchRData::SubmitBaseBatches()
|
||||
{
|
||||
assert(m_VBBase);
|
||||
|
||||
for (uint i=0;i<m_Splats.size();i++) {
|
||||
const SSplat& splat=m_Splats[i];
|
||||
m_VBBase->m_Owner->AppendBatch(m_VBBase,splat.m_Texture,splat.m_IndexCount,&m_Indices[splat.m_IndexStart]);
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitBlendBatches: submit next set of blend batches for this patch to the vertex buffer;
|
||||
// return true if all blends on this patch have been submitted, else false
|
||||
bool CPatchRData::SubmitBlendBatches()
|
||||
{
|
||||
if (m_NextBlendSplat<m_BlendSplats.size()) {
|
||||
for (uint i=m_NextBlendSplat;i<m_BlendSplats.size();i++) {
|
||||
const SSplat& splat=m_BlendSplats[i];
|
||||
m_VBBlends->m_Owner->AppendBatch(m_VBBlends,splat.m_Texture,splat.m_IndexCount,&m_BlendIndices[splat.m_IndexStart]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderBaseSplats: render all base passes of all patches; assumes vertex, texture and color
|
||||
// client states are enabled
|
||||
void CPatchRData::RenderBaseSplats()
|
||||
{
|
||||
uint i;
|
||||
|
||||
// set up texture environment for base pass
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
#if 1
|
||||
// submit base batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->SubmitBaseBatches();
|
||||
}
|
||||
|
||||
// render base passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBaseVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_UVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->RenderBase();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderBlendSplats: render all blend passes of all patches; assumes vertex, texture and color
|
||||
// client states are enabled
|
||||
void CPatchRData::RenderBlendSplats()
|
||||
{
|
||||
uint i;
|
||||
|
||||
// switch on second uv set
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// switch on the composite alpha map texture
|
||||
g_Renderer.BindTexture(1,g_Renderer.m_CompositeAlphaMap);
|
||||
|
||||
// setup additional texenv required by blend pass
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// switch on blending
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// no need to write to the depth buffer a second time
|
||||
glDepthMask(0);
|
||||
|
||||
#if 1
|
||||
// submit blend batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->SetupBlendBatches();
|
||||
}
|
||||
|
||||
bool finished=true;
|
||||
do
|
||||
{
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
if (!patchdata->SubmitBlendBatches()) finished=false;
|
||||
}
|
||||
} while (!finished);
|
||||
|
||||
// render blend passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBlendVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color));
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0]));
|
||||
|
||||
// render each batch
|
||||
for (i=0;i<batches.size();++i) {
|
||||
const CVertexBuffer::Batch* batch=batches[i];
|
||||
if (batch->m_IndexData.size()>0) {
|
||||
g_Renderer.BindTexture(0,tex_id(batch->m_Texture));
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
// render blend passes for each patch
|
||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->RenderBlends();
|
||||
}
|
||||
#endif
|
||||
|
||||
// restore depth writes
|
||||
glDepthMask(1);
|
||||
|
||||
// restore default state: switch off blending
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// switch off texture unit 1, make unit 0 active texture
|
||||
g_Renderer.BindTexture(1,0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// tidy up client states
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glClientActiveTexture(GL_TEXTURE0_ARB);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Submit: submit a patch to render this frame
|
||||
void CPatchRData::Submit(CPatch* patch)
|
||||
{
|
||||
CPatchRData* data=(CPatchRData*) patch->GetRenderData();
|
||||
if (data==0) {
|
||||
// no renderdata for patch, create it now
|
||||
data=new CPatchRData(patch);
|
||||
patch->SetRenderData(data);
|
||||
} else {
|
||||
data->Update();
|
||||
}
|
||||
|
||||
m_Patches.push_back(patch);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ApplyShadowMap: apply given shadow map to all terrain patches; assume the texture matrix
|
||||
// has been correctly setup on unit 1 to handle the projection
|
||||
void CPatchRData::ApplyShadowMap(GLuint shadowmaphandle)
|
||||
{
|
||||
uint i;
|
||||
|
||||
// glEnable(GL_ALPHA_TEST);
|
||||
// glAlphaFunc(GL_GREATER,0.0f);
|
||||
|
||||
g_Renderer.BindTexture(0,shadowmaphandle);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
glColor3f(1,1,1);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_DST_COLOR,GL_ZERO);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
#if 1
|
||||
// submit base batches for each patch to the vertex buffer
|
||||
for (i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();
|
||||
patchdata->m_VBBase->m_Owner->AppendBatch(patchdata->m_VBBase,0,patchdata->m_ShadowMapIndices.size(),
|
||||
&patchdata->m_ShadowMapIndices[0]);
|
||||
}
|
||||
|
||||
// render base passes for each patch
|
||||
const std::list<CVertexBuffer*>& buffers=g_VBMan.GetBufferList();
|
||||
std::list<CVertexBuffer*>::const_iterator iter;
|
||||
for (iter=buffers.begin();iter!=buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
|
||||
// any batches in this VB?
|
||||
const std::vector<CVertexBuffer::Batch*>& batches=buffer->GetBatches();
|
||||
if (batches.size()>0) {
|
||||
u8* base=buffer->Bind();
|
||||
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBaseVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
|
||||
glTexCoordPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position));
|
||||
|
||||
// render batch (can only be one per buffer, since all batches are flagged as using a null texture)
|
||||
const CVertexBuffer::Batch* batch=batches[0];
|
||||
for (uint j=0;j<batch->m_IndexData.size();j++) {
|
||||
glDrawElements(GL_QUADS,batch->m_IndexData[j].first,GL_UNSIGNED_SHORT,batch->m_IndexData[j].second);
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris+=batch->m_IndexData[j].first/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// everything rendered; empty out batch lists
|
||||
g_VBMan.ClearBatchIndices();
|
||||
#else
|
||||
for (uint i=0;i<m_Patches.size();++i) {
|
||||
CPatchRData* patchdata=(CPatchRData*) m_Patches[i]->GetRenderData();;
|
||||
patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0);
|
||||
}
|
||||
#endif
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
@ -6,12 +6,12 @@
|
||||
#include "Color.h"
|
||||
#include "Vector3D.h"
|
||||
#include "RenderableObject.h"
|
||||
#include "VertexBufferManager.h"
|
||||
#include "VertexBufferManager.h"
|
||||
|
||||
class CPatch;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CPatchRData: class encapsulating logic for rendering terrain patches; holds per
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CPatchRData: class encapsulating logic for rendering terrain patches; holds per
|
||||
// patch data, plus some supporting static functions for batching, etc
|
||||
class CPatchRData : public CRenderData
|
||||
{
|
||||
@ -24,68 +24,68 @@ public:
|
||||
void RenderBlends();
|
||||
void RenderOutline();
|
||||
void RenderStreams(u32 streamflags);
|
||||
|
||||
// submit a patch to render this frame
|
||||
static void Submit(CPatch* patch);
|
||||
// clear per frame patch list
|
||||
static void ClearSubmissions() { m_Patches.clear(); }
|
||||
|
||||
// render the base pass of all patches
|
||||
static void RenderBaseSplats();
|
||||
// render the blend pass of all patches
|
||||
static void RenderBlendSplats();
|
||||
// apply given shadow map to all terrain patches
|
||||
static void ApplyShadowMap(GLuint handle);
|
||||
|
||||
// submit base batches for this patch to the vertex buffer
|
||||
void SubmitBaseBatches();
|
||||
// submit next set of blend batches for this patch to the vertex buffer;
|
||||
// return true if all blends on this patch have been submitted, else false
|
||||
bool SubmitBlendBatches();
|
||||
|
||||
// perform necessary initialisation prior to rendering blend splats
|
||||
void SetupBlendBatches() { m_NextBlendSplat=0; }
|
||||
|
||||
// submit a patch to render this frame
|
||||
static void Submit(CPatch* patch);
|
||||
// clear per frame patch list
|
||||
static void ClearSubmissions() { m_Patches.clear(); }
|
||||
|
||||
// render the base pass of all patches
|
||||
static void RenderBaseSplats();
|
||||
// render the blend pass of all patches
|
||||
static void RenderBlendSplats();
|
||||
// apply given shadow map to all terrain patches
|
||||
static void ApplyShadowMap(GLuint handle);
|
||||
|
||||
// submit base batches for this patch to the vertex buffer
|
||||
void SubmitBaseBatches();
|
||||
// submit next set of blend batches for this patch to the vertex buffer;
|
||||
// return true if all blends on this patch have been submitted, else false
|
||||
bool SubmitBlendBatches();
|
||||
|
||||
// perform necessary initialisation prior to rendering blend splats
|
||||
void SetupBlendBatches() { m_NextBlendSplat=0; }
|
||||
|
||||
private:
|
||||
struct SSplat {
|
||||
SSplat() : m_Texture(0), m_IndexCount(0) {}
|
||||
|
||||
// handle of texture to apply during splat
|
||||
Handle m_Texture;
|
||||
// offset into the index array for this patch where splat starts
|
||||
u32 m_IndexStart;
|
||||
// number of indices used by splat
|
||||
u32 m_IndexCount;
|
||||
};
|
||||
|
||||
struct SBaseVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
};
|
||||
|
||||
struct SBlendVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
// vertex uvs for alpha texture
|
||||
float m_AlphaUVs[2];
|
||||
};
|
||||
|
||||
struct STex {
|
||||
bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; }
|
||||
bool operator<(const STex& rhs) const { return m_Priority<rhs.m_Priority; }
|
||||
Handle m_Handle;
|
||||
int m_Priority;
|
||||
};
|
||||
|
||||
|
||||
struct SSplat {
|
||||
SSplat() : m_Texture(0), m_IndexCount(0) {}
|
||||
|
||||
// handle of texture to apply during splat
|
||||
Handle m_Texture;
|
||||
// offset into the index array for this patch where splat starts
|
||||
u32 m_IndexStart;
|
||||
// number of indices used by splat
|
||||
u32 m_IndexCount;
|
||||
};
|
||||
|
||||
struct SBaseVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
};
|
||||
|
||||
struct SBlendVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
// vertex uvs for alpha texture
|
||||
float m_AlphaUVs[2];
|
||||
};
|
||||
|
||||
struct STex {
|
||||
bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; }
|
||||
bool operator<(const STex& rhs) const { return m_Priority<rhs.m_Priority; }
|
||||
Handle m_Handle;
|
||||
int m_Priority;
|
||||
};
|
||||
|
||||
|
||||
// build this renderdata object
|
||||
void Build();
|
||||
|
||||
@ -103,8 +103,8 @@ private:
|
||||
SBaseVertex* m_Vertices;
|
||||
// indices into base vertices for the base splats
|
||||
std::vector<unsigned short> m_Indices;
|
||||
// indices into base vertices for the shadow map pass
|
||||
std::vector<unsigned short> m_ShadowMapIndices;
|
||||
// indices into base vertices for the shadow map pass
|
||||
std::vector<unsigned short> m_ShadowMapIndices;
|
||||
// list of base splats to apply to this patch
|
||||
std::vector<SSplat> m_Splats;
|
||||
// vertices to use for blending transition texture passes
|
||||
@ -112,10 +112,10 @@ private:
|
||||
// indices into blend vertices for the blend splats
|
||||
std::vector<unsigned short> m_BlendIndices;
|
||||
// splats used in blend pass
|
||||
std::vector<SSplat> m_BlendSplats;
|
||||
// index of the next blend splat to render
|
||||
u32 m_NextBlendSplat;
|
||||
// list of all submitted patches
|
||||
std::vector<SSplat> m_BlendSplats;
|
||||
// index of the next blend splat to render
|
||||
u32 m_NextBlendSplat;
|
||||
// list of all submitted patches
|
||||
static std::vector<CPatch*> m_Patches;
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "PatchRData.h"
|
||||
#include "Texture.h"
|
||||
#include "LightEnv.h"
|
||||
#include "CLogger.h"
|
||||
#include "CLogger.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelDef.h"
|
||||
@ -74,8 +74,8 @@ static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned c
|
||||
header.d_y_origin=0;
|
||||
header.width=width;
|
||||
header.height=height;
|
||||
header.bpp=bpp;
|
||||
header.image_descriptor=(bpp==32) ? 8 : 0;
|
||||
header.bpp=bpp;
|
||||
header.image_descriptor=(bpp==32) ? 8 : 0;
|
||||
|
||||
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
|
||||
fclose(fp);
|
||||
@ -94,8 +94,8 @@ static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned c
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer destructor
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer destructor
|
||||
CRenderer::CRenderer()
|
||||
{
|
||||
m_Width=0;
|
||||
@ -106,18 +106,18 @@ CRenderer::CRenderer()
|
||||
m_ModelRenderMode=SOLID;
|
||||
m_ClearColor[0]=m_ClearColor[1]=m_ClearColor[2]=m_ClearColor[3]=0;
|
||||
m_ShadowMap=0;
|
||||
|
||||
|
||||
m_Options.m_NoVBO=false;
|
||||
m_Options.m_Shadows=true;
|
||||
m_Options.m_ShadowColor=RGBAColor(0.4f,0.4f,0.4f,1.0f);
|
||||
|
||||
for (uint i=0;i<MaxTextureUnits;i++) {
|
||||
m_ActiveTextures[i]=0;
|
||||
}
|
||||
|
||||
for (uint i=0;i<MaxTextureUnits;i++) {
|
||||
m_ActiveTextures[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer destructor
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer destructor
|
||||
CRenderer::~CRenderer()
|
||||
{
|
||||
}
|
||||
@ -166,13 +166,13 @@ bool CRenderer::Open(int width, int height, int depth)
|
||||
// query card capabilities
|
||||
EnumCaps();
|
||||
|
||||
GLint bits;
|
||||
glGetIntegerv(GL_DEPTH_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits);
|
||||
glGetIntegerv(GL_STENCIL_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits);
|
||||
glGetIntegerv(GL_ALPHA_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits);
|
||||
GLint bits;
|
||||
glGetIntegerv(GL_DEPTH_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: depth bits %d",bits);
|
||||
glGetIntegerv(GL_STENCIL_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: stencil bits %d",bits);
|
||||
glGetIntegerv(GL_ALPHA_BITS,&bits);
|
||||
CLogger::GetInstance()->Log(NORMAL,"CRenderer::Open: alpha bits %d",bits);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -184,10 +184,10 @@ void CRenderer::Close()
|
||||
// resize renderer view
|
||||
void CRenderer::Resize(int width,int height)
|
||||
{
|
||||
if (m_ShadowMap && (width>m_Width || height>m_Height)) {
|
||||
glDeleteTextures(1,(GLuint*) &m_ShadowMap);
|
||||
m_ShadowMap=0;
|
||||
}
|
||||
if (m_ShadowMap && (width>m_Width || height>m_Height)) {
|
||||
glDeleteTextures(1,(GLuint*) &m_ShadowMap);
|
||||
m_ShadowMap=0;
|
||||
}
|
||||
m_Width=width;
|
||||
m_Height=height;
|
||||
}
|
||||
@ -270,7 +270,7 @@ void CRenderer::BeginFrame()
|
||||
}
|
||||
|
||||
// init per frame stuff
|
||||
m_ShadowRendered=false;
|
||||
m_ShadowRendered=false;
|
||||
m_ShadowBound.SetEmpty();
|
||||
}
|
||||
|
||||
@ -400,7 +400,7 @@ void CRenderer::CalcShadowMatrices()
|
||||
|
||||
// shift near and far clip planes slightly to avoid artifacts with points
|
||||
// exactly on the clip planes
|
||||
znear=(znear<m_Camera.GetNearPlane()+0.01f) ? m_Camera.GetNearPlane() : znear-0.01f;
|
||||
znear=(znear<m_Camera.GetNearPlane()+0.01f) ? m_Camera.GetNearPlane() : znear-0.01f;
|
||||
zfar+=0.01f;
|
||||
|
||||
m_LightProjection.SetZero();
|
||||
@ -551,19 +551,19 @@ void CRenderer::CreateShadowMap()
|
||||
{
|
||||
// get shadow map size as next power of two up from view width and height
|
||||
m_ShadowMapWidth=m_Width;
|
||||
m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth);
|
||||
m_ShadowMapHeight=m_Height;
|
||||
m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight);
|
||||
m_ShadowMapWidth=RoundUpToPowerOf2(m_ShadowMapWidth);
|
||||
m_ShadowMapHeight=m_Height;
|
||||
m_ShadowMapHeight=RoundUpToPowerOf2(m_ShadowMapHeight);
|
||||
|
||||
// create texture object - initially filled with white, so clamp to edge clamps to correct color
|
||||
glGenTextures(1,(GLuint*) &m_ShadowMap);
|
||||
BindTexture(0,(GLuint) m_ShadowMap);
|
||||
|
||||
u32 size=m_ShadowMapWidth*m_ShadowMapHeight;
|
||||
u32* buf=new u32[size];
|
||||
for (uint i=0;i<size;i++) buf[i]=0x00ffffff;
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_ShadowMapWidth,m_ShadowMapHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
|
||||
delete[] buf;
|
||||
BindTexture(0,(GLuint) m_ShadowMap);
|
||||
|
||||
u32 size=m_ShadowMapWidth*m_ShadowMapHeight;
|
||||
u32* buf=new u32[size];
|
||||
for (uint i=0;i<size;i++) buf[i]=0x00ffffff;
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_ShadowMapWidth,m_ShadowMapHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
|
||||
delete[] buf;
|
||||
|
||||
// set texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
@ -578,7 +578,7 @@ void CRenderer::RenderShadowMap()
|
||||
if (!m_ShadowMap) CreateShadowMap();
|
||||
|
||||
// clear buffers
|
||||
glClearColor(1,1,1,0);
|
||||
glClearColor(1,1,1,0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// build required matrices
|
||||
@ -636,27 +636,27 @@ void CRenderer::RenderShadowMap()
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(1,1,m_Width-2,m_Height-2);
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
glColor4fv(m_Options.m_ShadowColor);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glColor4fv(m_Options.m_ShadowColor);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// render models
|
||||
CModelRData::RenderModels(STREAM_POS);
|
||||
|
||||
// call on the transparency renderer to render all the transparent stuff
|
||||
g_TransparencyRenderer.RenderShadows();
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glColor3f(1.0f,1.0f,1.0f);
|
||||
|
||||
@ -675,46 +675,46 @@ void CRenderer::RenderShadowMap()
|
||||
|
||||
if (0)
|
||||
{
|
||||
#if 1
|
||||
#if 1
|
||||
// debug aid - dump generated shadow map to file; helps verify shadow map
|
||||
// space being well used (not that it is at the minute .. (TODO, RC))
|
||||
unsigned char* data=new unsigned char[m_ShadowMapWidth*m_ShadowMapHeight*3];
|
||||
glGetTexImage(GL_TEXTURE_2D,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,data);
|
||||
saveTGA("d:\\test4.tga",m_ShadowMapWidth,m_ShadowMapHeight,24,data);
|
||||
delete[] data;
|
||||
#else
|
||||
unsigned char* data=new unsigned char[m_Width*m_Height*4];
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data);
|
||||
saveTGA("d:\\test3.tga",m_Width,m_Height,32,data);
|
||||
delete[] data;
|
||||
#endif
|
||||
#else
|
||||
unsigned char* data=new unsigned char[m_Width*m_Height*4];
|
||||
glReadBuffer(GL_BACK);
|
||||
glReadPixels(0,0,m_Width,m_Height,GL_BGRA_EXT,GL_UNSIGNED_BYTE,data);
|
||||
saveTGA("d:\\test3.tga",m_Width,m_Height,32,data);
|
||||
delete[] data;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::ApplyShadowMap()
|
||||
{
|
||||
CMatrix3D tmp2;
|
||||
CMatrix3D texturematrix;
|
||||
|
||||
float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth);
|
||||
float dy=0.5f*float(m_Height)/float(m_ShadowMapHeight);
|
||||
texturematrix.SetTranslation(dx,dy,0); // transform (-0.5, 0.5) to (0,1) - texture space
|
||||
tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5)
|
||||
texturematrix=texturematrix*tmp2;
|
||||
|
||||
texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1)
|
||||
texturematrix=texturematrix*m_LightTransform; // transform world -> light space
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(&texturematrix._11);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
CMatrix3D tmp2;
|
||||
CMatrix3D texturematrix;
|
||||
|
||||
float dx=0.5f*float(m_Width)/float(m_ShadowMapWidth);
|
||||
float dy=0.5f*float(m_Height)/float(m_ShadowMapHeight);
|
||||
texturematrix.SetTranslation(dx,dy,0); // transform (-0.5, 0.5) to (0,1) - texture space
|
||||
tmp2.SetScaling(dx,dy,0); // scale (-1,1) to (-0.5,0.5)
|
||||
texturematrix=texturematrix*tmp2;
|
||||
|
||||
texturematrix=texturematrix*m_LightProjection; // transform light -> projected light space (-1 to 1)
|
||||
texturematrix=texturematrix*m_LightTransform; // transform world -> light space
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(&texturematrix._11);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
CPatchRData::ApplyShadowMap(m_ShadowMap);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void CRenderer::RenderPatches()
|
||||
@ -731,8 +731,8 @@ void CRenderer::RenderPatches()
|
||||
// switch wireframe off again
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
} else if (m_TerrainRenderMode==EDGED_FACES) {
|
||||
/*
|
||||
// TODO, RC - fix this
|
||||
/*
|
||||
// TODO, RC - fix this
|
||||
// edged faces: need to make a second pass over the data:
|
||||
// first switch on wireframe
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
@ -778,42 +778,42 @@ void CRenderer::RenderPatches()
|
||||
|
||||
// restore fill mode, and we're done
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
*/
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CRenderer::RenderModelSubmissions()
|
||||
{
|
||||
// set up texture environment for base pass - modulate texture and primary color
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
// pass one through as alpha; transparent textures handled specially by CTransparencyRenderer
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ONE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
// set up texture environment for base pass - modulate texture and primary color
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
// pass one through as alpha; transparent textures handled specially by CTransparencyRenderer
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ONE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
// setup client states
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// render models
|
||||
// render models
|
||||
CModelRData::RenderModels(STREAM_POS|STREAM_COLOR|STREAM_UV0);
|
||||
|
||||
// switch off client states
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void CRenderer::RenderModels()
|
||||
{
|
||||
{
|
||||
// switch on wireframe if we need it
|
||||
if (m_ModelRenderMode==WIREFRAME) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
@ -887,11 +887,11 @@ void CRenderer::FlushFrame()
|
||||
// render submitted patches and models
|
||||
RenderPatches();
|
||||
RenderModels();
|
||||
if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap();
|
||||
m_ShadowRendered=true;
|
||||
|
||||
// call on the transparency renderer to render all the transparent stuff
|
||||
g_TransparencyRenderer.Render();
|
||||
if (m_Options.m_Shadows && !m_ShadowRendered) ApplyShadowMap();
|
||||
m_ShadowRendered=true;
|
||||
|
||||
// call on the transparency renderer to render all the transparent stuff
|
||||
g_TransparencyRenderer.Render();
|
||||
|
||||
// empty lists
|
||||
g_TransparencyRenderer.Clear();
|
||||
@ -899,22 +899,22 @@ void CRenderer::FlushFrame()
|
||||
CModelRData::ClearSubmissions();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EndFrame: signal frame end; implicitly flushes batched objects
|
||||
void CRenderer::EndFrame()
|
||||
{
|
||||
FlushFrame();
|
||||
g_Renderer.SetTexture(0,0);
|
||||
|
||||
static bool once=false;
|
||||
if (!once && glGetError()) {
|
||||
CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n");
|
||||
once=true;
|
||||
g_Renderer.SetTexture(0,0);
|
||||
|
||||
static bool once=false;
|
||||
if (!once && glGetError()) {
|
||||
CLogger::GetInstance()->Log(ERROR,"CRenderer::EndFrame: GL errors occurred\n");
|
||||
once=true;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCamera: setup projection and transform of camera and adjust viewport to current view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCamera: setup projection and transform of camera and adjust viewport to current view
|
||||
void CRenderer::SetCamera(CCamera& camera)
|
||||
{
|
||||
CMatrix3D view;
|
||||
@ -935,16 +935,16 @@ void CRenderer::SetCamera(CCamera& camera)
|
||||
|
||||
void CRenderer::Submit(CPatch* patch)
|
||||
{
|
||||
CPatchRData::Submit(patch);
|
||||
CPatchRData::Submit(patch);
|
||||
}
|
||||
|
||||
void CRenderer::Submit(CModel* model)
|
||||
{
|
||||
if (1 /*ThisModelCastsShadows*/) {
|
||||
m_ShadowBound+=model->GetBounds();
|
||||
}
|
||||
|
||||
CModelRData::Submit(model);
|
||||
{
|
||||
if (1 /*ThisModelCastsShadows*/) {
|
||||
m_ShadowBound+=model->GetBounds();
|
||||
}
|
||||
|
||||
CModelRData::Submit(model);
|
||||
}
|
||||
|
||||
void CRenderer::Submit(CSprite* sprite)
|
||||
@ -966,14 +966,14 @@ void CRenderer::RenderPatchSubmissions()
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// render everything
|
||||
CPatchRData::RenderBaseSplats();
|
||||
// render everything
|
||||
CPatchRData::RenderBaseSplats();
|
||||
CPatchRData::RenderBlendSplats();
|
||||
|
||||
|
||||
// switch off all client states
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
@ -990,72 +990,72 @@ bool CRenderer::LoadTexture(CTexture* texture,u32 wrapflags)
|
||||
} else {
|
||||
h=tex_load(texture->GetName());
|
||||
if (!h) {
|
||||
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\"",(const char*) texture->GetName());
|
||||
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\"",(const char*) texture->GetName());
|
||||
texture->SetHandle(0xffffffff);
|
||||
return false;
|
||||
} else {
|
||||
int tw,th;
|
||||
tex_info(h, &tw, &th, NULL, NULL, NULL);
|
||||
|
||||
tw&=(tw-1);
|
||||
th&=(th-1);
|
||||
if (tw || th) {
|
||||
texture->SetHandle(0xffffffff);
|
||||
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
|
||||
return false;
|
||||
} else {
|
||||
BindTexture(0,tex_id(h));
|
||||
int tw,th;
|
||||
tex_info(h, &tw, &th, NULL, NULL, NULL);
|
||||
|
||||
tw&=(tw-1);
|
||||
th&=(th-1);
|
||||
if (tw || th) {
|
||||
texture->SetHandle(0xffffffff);
|
||||
CLogger::GetInstance()->Log(ERROR,"LoadTexture failed on \"%s\" : not a power of 2 texture",(const char*) texture->GetName());
|
||||
return false;
|
||||
} else {
|
||||
BindTexture(0,tex_id(h));
|
||||
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
if (wrapflags) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
texture->SetHandle(h);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BindTexture: bind a GL texture object to current active unit
|
||||
void CRenderer::BindTexture(int unit,GLuint tex)
|
||||
{
|
||||
#if 0
|
||||
{
|
||||
#if 0
|
||||
glActiveTexture(GL_TEXTURE0+unit);
|
||||
if (tex==m_ActiveTextures[unit]) return;
|
||||
|
||||
if (tex) {
|
||||
glBindTexture(GL_TEXTURE_2D,tex);
|
||||
if (tex) {
|
||||
glBindTexture(GL_TEXTURE_2D,tex);
|
||||
if (!m_ActiveTextures[unit]) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
} else if (m_ActiveTextures[unit]) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
m_ActiveTextures[unit]=tex;
|
||||
#endif
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+unit);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,tex);
|
||||
if (tex) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
} else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
m_ActiveTextures[unit]=tex;
|
||||
m_ActiveTextures[unit]=tex;
|
||||
#endif
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+unit);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D,tex);
|
||||
if (tex) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
} else {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
m_ActiveTextures[unit]=tex;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetTexture: set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
||||
void CRenderer::SetTexture(int unit,CTexture* texture)
|
||||
{
|
||||
{
|
||||
if (texture) {
|
||||
Handle h=texture->GetHandle();
|
||||
BindTexture(unit,tex_id(h));
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -1,11 +1,11 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: TransparencyRenderer.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: TransparencyRenderer.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -38,8 +38,8 @@ void CTransparencyRenderer::Sort()
|
||||
// Render: render all deferred passes; call Sort before using to ensure passes
|
||||
// are drawn in correct order
|
||||
void CTransparencyRenderer::Render()
|
||||
{
|
||||
if (m_Objects.size()==0) return;
|
||||
{
|
||||
if (m_Objects.size()==0) return;
|
||||
|
||||
// switch on wireframe if we need it
|
||||
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
|
||||
@ -63,24 +63,24 @@ void CTransparencyRenderer::Render()
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER,0.975f);
|
||||
|
||||
// render everything with color writes off to setup depth buffer correctly
|
||||
|
||||
// render everything with color writes off to setup depth buffer correctly
|
||||
glColorMask(0,0,0,0);
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_UV0);
|
||||
glColorMask(1,1,1,1);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColorMask(1,1,1,1);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDepthMask(0);
|
||||
glAlphaFunc(GL_GREATER,0);
|
||||
|
||||
// setup texture environment to modulate diffuse color with texture color
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
// setup texture environment to modulate diffuse color with texture color
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0);
|
||||
|
||||
@ -155,8 +155,8 @@ void CTransparencyRenderer::Add(CModel* model)
|
||||
|
||||
void CTransparencyRenderer::RenderShadows()
|
||||
{
|
||||
if (m_Objects.size()==0) return;
|
||||
|
||||
if (m_Objects.size()==0) return;
|
||||
|
||||
// switch on client states
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
@ -174,7 +174,7 @@ void CTransparencyRenderer::RenderShadows()
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_UV0);
|
||||
|
||||
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,184 +1,185 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBuffer.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "precompiled.h"
|
||||
#include "ogl.h"
|
||||
#include "Renderer.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// shared list of all free batch objects
|
||||
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer constructor
|
||||
CVertexBuffer::CVertexBuffer(size_t vertexSize,bool dynamic)
|
||||
: m_VertexSize(vertexSize), m_Dynamic(dynamic), m_SysMem(0), m_Handle(0)
|
||||
{
|
||||
// store max/free vertex counts
|
||||
m_MaxVertices=m_FreeVertices=MAX_VB_SIZE_BYTES/vertexSize;
|
||||
|
||||
// allocate raw buffer
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
glGenBuffersARB(1,&m_Handle);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
|
||||
} else {
|
||||
m_SysMem=new u8[MAX_VB_SIZE_BYTES];
|
||||
}
|
||||
|
||||
// create sole free chunk
|
||||
VBChunk* chunk=new VBChunk;
|
||||
chunk->m_Owner=this;
|
||||
chunk->m_Count=m_FreeVertices;
|
||||
chunk->m_Index=0;
|
||||
m_FreeList.push_front(chunk);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer destructor
|
||||
CVertexBuffer::~CVertexBuffer()
|
||||
{
|
||||
if (m_Handle) {
|
||||
glDeleteBuffersARB(1,&m_Handle);
|
||||
} else if (m_SysMem) {
|
||||
delete[] m_SysMem;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocate: try to allocate a buffer of given number of vertices (each of
|
||||
// given size), with the given type, and using the given texture - return null
|
||||
// if no free chunks available
|
||||
CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
|
||||
{
|
||||
// check this is the right kind of buffer
|
||||
if (dynamic!=m_Dynamic || vertexSize!=m_VertexSize) return 0;
|
||||
|
||||
// quick check there's enough vertices spare to allocate
|
||||
if (numVertices>m_FreeVertices) return 0;
|
||||
|
||||
// trawl free list looking for first free chunk with enough space
|
||||
VBChunk* chunk=0;
|
||||
typedef std::list<VBChunk*>::iterator Iter;
|
||||
for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) {
|
||||
chunk=*iter;
|
||||
if (numVertices<=chunk->m_Count) {
|
||||
// remove this chunk from the free list
|
||||
size_t size1=m_FreeList.size();
|
||||
m_FreeList.erase(iter);
|
||||
size_t size2=m_FreeList.size();
|
||||
// no need to search further ..
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunk) {
|
||||
// no big enough spare chunk available
|
||||
return 0;
|
||||
}
|
||||
|
||||
// split chunk into two; - allocate a new chunk using all unused vertices in the
|
||||
// found chunk, and add it to the free list
|
||||
VBChunk* newchunk=new VBChunk;
|
||||
newchunk->m_Owner=this;
|
||||
newchunk->m_Count=chunk->m_Count-numVertices;
|
||||
newchunk->m_Index=chunk->m_Index+numVertices;
|
||||
m_FreeList.push_front(newchunk);
|
||||
|
||||
// resize given chunk, resize total available free vertices
|
||||
chunk->m_Count=numVertices;
|
||||
m_FreeVertices-=numVertices;
|
||||
|
||||
// return found chunk
|
||||
return chunk;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Release: return given chunk to this buffer
|
||||
void CVertexBuffer::Release(VBChunk* chunk)
|
||||
{
|
||||
// add to free list
|
||||
// TODO, RC - need to merge available chunks where possible to avoid
|
||||
// excessive fragmentation of vertex buffer space
|
||||
m_FreeList.push_front(chunk);
|
||||
m_FreeVertices+=chunk->m_Count;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ClearBatchIndices: clear lists of all batches
|
||||
void CVertexBuffer::ClearBatchIndices()
|
||||
{
|
||||
for (uint i=0;i<m_Batches.size();i++) {
|
||||
m_Batches[i]->m_IndexData.clear();
|
||||
m_FreeBatches.push_back(m_Batches[i]);
|
||||
}
|
||||
m_Batches.clear();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// AppendBatch: add a batch to the render list for this buffer
|
||||
void CVertexBuffer::AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices)
|
||||
{
|
||||
// try and find a batch using this texture
|
||||
size_t i;
|
||||
Batch* batch=0;
|
||||
for (i=0;i<m_Batches.size();++i) {
|
||||
if (m_Batches[i]->m_Texture==texture) {
|
||||
batch=m_Batches[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!batch) {
|
||||
if (m_FreeBatches.size()) {
|
||||
batch=m_FreeBatches.back();
|
||||
m_FreeBatches.pop_back();
|
||||
} else {
|
||||
batch=new Batch;
|
||||
}
|
||||
m_Batches.push_back(batch);
|
||||
batch->m_Texture=texture;
|
||||
}
|
||||
|
||||
// resize the chunk's batch to fit it's indices
|
||||
size_t cursize=batch->m_IndexData.size();
|
||||
batch->m_IndexData.resize(cursize+1);
|
||||
// store batch
|
||||
batch->m_IndexData[cursize]=std::pair<size_t,u16*>(numIndices,indices);
|
||||
// memcpy(&batch->m_Indices[0]+cursize,indices,sizeof(u16)*numIndices);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UpdateChunkVertices: update vertex data for given chunk
|
||||
void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk,void* data)
|
||||
{
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
assert(m_Handle);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data);
|
||||
} else {
|
||||
assert(m_SysMem);
|
||||
memcpy(m_SysMem+chunk->m_Index*m_VertexSize,data,chunk->m_Count*m_VertexSize);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Bind: bind to this buffer; return pointer to address required as parameter
|
||||
// to glVertexPointer ( + etc) calls
|
||||
u8* CVertexBuffer::Bind()
|
||||
{
|
||||
u8* base;
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
base=(u8*) 0;
|
||||
} else {
|
||||
base=(u8*) m_SysMem;
|
||||
}
|
||||
return base;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBuffer.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "ogl.h"
|
||||
#include "Renderer.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// shared list of all free batch objects
|
||||
std::vector<CVertexBuffer::Batch*> CVertexBuffer::m_FreeBatches;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer constructor
|
||||
CVertexBuffer::CVertexBuffer(size_t vertexSize,bool dynamic)
|
||||
: m_VertexSize(vertexSize), m_Dynamic(dynamic), m_SysMem(0), m_Handle(0)
|
||||
{
|
||||
// store max/free vertex counts
|
||||
m_MaxVertices=m_FreeVertices=MAX_VB_SIZE_BYTES/vertexSize;
|
||||
|
||||
// allocate raw buffer
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
glGenBuffersARB(1,&m_Handle);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,MAX_VB_SIZE_BYTES,0,m_Dynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
|
||||
} else {
|
||||
m_SysMem=new u8[MAX_VB_SIZE_BYTES];
|
||||
}
|
||||
|
||||
// create sole free chunk
|
||||
VBChunk* chunk=new VBChunk;
|
||||
chunk->m_Owner=this;
|
||||
chunk->m_Count=m_FreeVertices;
|
||||
chunk->m_Index=0;
|
||||
m_FreeList.push_front(chunk);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer destructor
|
||||
CVertexBuffer::~CVertexBuffer()
|
||||
{
|
||||
if (m_Handle) {
|
||||
glDeleteBuffersARB(1,&m_Handle);
|
||||
} else if (m_SysMem) {
|
||||
delete[] m_SysMem;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocate: try to allocate a buffer of given number of vertices (each of
|
||||
// given size), with the given type, and using the given texture - return null
|
||||
// if no free chunks available
|
||||
CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
|
||||
{
|
||||
// check this is the right kind of buffer
|
||||
if (dynamic!=m_Dynamic || vertexSize!=m_VertexSize) return 0;
|
||||
|
||||
// quick check there's enough vertices spare to allocate
|
||||
if (numVertices>m_FreeVertices) return 0;
|
||||
|
||||
// trawl free list looking for first free chunk with enough space
|
||||
VBChunk* chunk=0;
|
||||
typedef std::list<VBChunk*>::iterator Iter;
|
||||
for (Iter iter=m_FreeList.begin();iter!=m_FreeList.end();++iter) {
|
||||
chunk=*iter;
|
||||
if (numVertices<=chunk->m_Count) {
|
||||
// remove this chunk from the free list
|
||||
size_t size1=m_FreeList.size();
|
||||
m_FreeList.erase(iter);
|
||||
size_t size2=m_FreeList.size();
|
||||
// no need to search further ..
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunk) {
|
||||
// no big enough spare chunk available
|
||||
return 0;
|
||||
}
|
||||
|
||||
// split chunk into two; - allocate a new chunk using all unused vertices in the
|
||||
// found chunk, and add it to the free list
|
||||
VBChunk* newchunk=new VBChunk;
|
||||
newchunk->m_Owner=this;
|
||||
newchunk->m_Count=chunk->m_Count-numVertices;
|
||||
newchunk->m_Index=chunk->m_Index+numVertices;
|
||||
m_FreeList.push_front(newchunk);
|
||||
|
||||
// resize given chunk, resize total available free vertices
|
||||
chunk->m_Count=numVertices;
|
||||
m_FreeVertices-=numVertices;
|
||||
|
||||
// return found chunk
|
||||
return chunk;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Release: return given chunk to this buffer
|
||||
void CVertexBuffer::Release(VBChunk* chunk)
|
||||
{
|
||||
// add to free list
|
||||
// TODO, RC - need to merge available chunks where possible to avoid
|
||||
// excessive fragmentation of vertex buffer space
|
||||
m_FreeList.push_front(chunk);
|
||||
m_FreeVertices+=chunk->m_Count;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ClearBatchIndices: clear lists of all batches
|
||||
void CVertexBuffer::ClearBatchIndices()
|
||||
{
|
||||
for (uint i=0;i<m_Batches.size();i++) {
|
||||
m_Batches[i]->m_IndexData.clear();
|
||||
m_FreeBatches.push_back(m_Batches[i]);
|
||||
}
|
||||
m_Batches.clear();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// AppendBatch: add a batch to the render list for this buffer
|
||||
void CVertexBuffer::AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices)
|
||||
{
|
||||
// try and find a batch using this texture
|
||||
size_t i;
|
||||
Batch* batch=0;
|
||||
for (i=0;i<m_Batches.size();++i) {
|
||||
if (m_Batches[i]->m_Texture==texture) {
|
||||
batch=m_Batches[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!batch) {
|
||||
if (m_FreeBatches.size()) {
|
||||
batch=m_FreeBatches.back();
|
||||
m_FreeBatches.pop_back();
|
||||
} else {
|
||||
batch=new Batch;
|
||||
}
|
||||
m_Batches.push_back(batch);
|
||||
batch->m_Texture=texture;
|
||||
}
|
||||
|
||||
// resize the chunk's batch to fit it's indices
|
||||
size_t cursize=batch->m_IndexData.size();
|
||||
batch->m_IndexData.resize(cursize+1);
|
||||
// store batch
|
||||
batch->m_IndexData[cursize]=std::pair<size_t,u16*>(numIndices,indices);
|
||||
// memcpy(&batch->m_Indices[0]+cursize,indices,sizeof(u16)*numIndices);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UpdateChunkVertices: update vertex data for given chunk
|
||||
void CVertexBuffer::UpdateChunkVertices(VBChunk* chunk,void* data)
|
||||
{
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
assert(m_Handle);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,chunk->m_Index*m_VertexSize,chunk->m_Count*m_VertexSize,data);
|
||||
} else {
|
||||
assert(m_SysMem);
|
||||
memcpy(m_SysMem+chunk->m_Index*m_VertexSize,data,chunk->m_Count*m_VertexSize);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Bind: bind to this buffer; return pointer to address required as parameter
|
||||
// to glVertexPointer ( + etc) calls
|
||||
u8* CVertexBuffer::Bind()
|
||||
{
|
||||
u8* base;
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_Handle);
|
||||
base=(u8*) 0;
|
||||
} else {
|
||||
base=(u8*) m_SysMem;
|
||||
}
|
||||
return base;
|
||||
}
|
@ -1,100 +1,100 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBuffer.h
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _VERTEXBUFFER_H
|
||||
#define _VERTEXBUFFER_H
|
||||
|
||||
#include "lib.h"
|
||||
#include "res/tex.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// absolute maximum (bytewise) size of each GL vertex buffer object
|
||||
#define MAX_VB_SIZE_BYTES (32*8192)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying
|
||||
// some additional functionality for batching and sharing buffers between
|
||||
// multiple objects
|
||||
class CVertexBuffer
|
||||
{
|
||||
public:
|
||||
// Batch: batch definition - defines indices into the VB to use when rendering,
|
||||
// and the texture used when doing so
|
||||
struct Batch {
|
||||
// list of indices into the vertex buffer of primitives within the batch
|
||||
std::vector<std::pair<size_t,u16*> > m_IndexData;
|
||||
// texture to apply when rendering batch
|
||||
Handle m_Texture;
|
||||
};
|
||||
|
||||
// VBChunk: describes a portion of this vertex buffer
|
||||
struct VBChunk
|
||||
{
|
||||
// owning buffer
|
||||
CVertexBuffer* m_Owner;
|
||||
// start index of this chunk in owner
|
||||
size_t m_Index;
|
||||
// number of vertices used by chunk
|
||||
size_t m_Count;
|
||||
};
|
||||
|
||||
public:
|
||||
// constructor, destructor
|
||||
CVertexBuffer(size_t vertexSize,bool dynamic);
|
||||
~CVertexBuffer();
|
||||
|
||||
// bind to this buffer; return pointer to address required as parameter
|
||||
// to glVertexPointer ( + etc) calls
|
||||
u8* Bind();
|
||||
|
||||
// clear lists of all batches
|
||||
void ClearBatchIndices();
|
||||
|
||||
// add a batch to the render list for this buffer
|
||||
void AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices);
|
||||
|
||||
// update vertex data for given chunk
|
||||
void UpdateChunkVertices(VBChunk* chunk,void* data);
|
||||
|
||||
// return this VBs batch list
|
||||
const std::vector<Batch*>& GetBatches() const { return m_Batches; }
|
||||
|
||||
protected:
|
||||
friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager
|
||||
|
||||
// try to allocate a buffer of given number of vertices (each of given size),
|
||||
// and with the given type - return null if no free chunks available
|
||||
VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
|
||||
// return given chunk to this buffer
|
||||
void Release(VBChunk* chunk);
|
||||
|
||||
|
||||
private:
|
||||
// set of all possible batches that can be used by this VB
|
||||
std::vector<Batch*> m_Batches;
|
||||
// vertex size of this vertex buffer
|
||||
size_t m_VertexSize;
|
||||
// number of vertices of above size in this buffer
|
||||
size_t m_MaxVertices;
|
||||
// list of free chunks in this buffer
|
||||
std::list<VBChunk*> m_FreeList;
|
||||
// available free vertices - total of all free vertices in the free list
|
||||
size_t m_FreeVertices;
|
||||
// handle to the actual GL vertex buffer object
|
||||
GLuint m_Handle;
|
||||
// raw system memory for systems not supporting VBOs
|
||||
u8* m_SysMem;
|
||||
// type of the buffer - dynamic?
|
||||
bool m_Dynamic;
|
||||
// list of all spare batches, shared between all vbs
|
||||
static std::vector<Batch*> m_FreeBatches;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBuffer.h
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _VERTEXBUFFER_H
|
||||
#define _VERTEXBUFFER_H
|
||||
|
||||
#include "lib.h"
|
||||
#include "res/tex.h"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
// absolute maximum (bytewise) size of each GL vertex buffer object
|
||||
#define MAX_VB_SIZE_BYTES (32*8192)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBuffer: encapsulation of ARB_vertex_buffer_object, also supplying
|
||||
// some additional functionality for batching and sharing buffers between
|
||||
// multiple objects
|
||||
class CVertexBuffer
|
||||
{
|
||||
public:
|
||||
// Batch: batch definition - defines indices into the VB to use when rendering,
|
||||
// and the texture used when doing so
|
||||
struct Batch {
|
||||
// list of indices into the vertex buffer of primitives within the batch
|
||||
std::vector<std::pair<size_t,u16*> > m_IndexData;
|
||||
// texture to apply when rendering batch
|
||||
Handle m_Texture;
|
||||
};
|
||||
|
||||
// VBChunk: describes a portion of this vertex buffer
|
||||
struct VBChunk
|
||||
{
|
||||
// owning buffer
|
||||
CVertexBuffer* m_Owner;
|
||||
// start index of this chunk in owner
|
||||
size_t m_Index;
|
||||
// number of vertices used by chunk
|
||||
size_t m_Count;
|
||||
};
|
||||
|
||||
public:
|
||||
// constructor, destructor
|
||||
CVertexBuffer(size_t vertexSize,bool dynamic);
|
||||
~CVertexBuffer();
|
||||
|
||||
// bind to this buffer; return pointer to address required as parameter
|
||||
// to glVertexPointer ( + etc) calls
|
||||
u8* Bind();
|
||||
|
||||
// clear lists of all batches
|
||||
void ClearBatchIndices();
|
||||
|
||||
// add a batch to the render list for this buffer
|
||||
void AppendBatch(VBChunk* chunk,Handle texture,size_t numIndices,u16* indices);
|
||||
|
||||
// update vertex data for given chunk
|
||||
void UpdateChunkVertices(VBChunk* chunk,void* data);
|
||||
|
||||
// return this VBs batch list
|
||||
const std::vector<Batch*>& GetBatches() const { return m_Batches; }
|
||||
|
||||
protected:
|
||||
friend class CVertexBufferManager; // allow allocate only via CVertexBufferManager
|
||||
|
||||
// try to allocate a buffer of given number of vertices (each of given size),
|
||||
// and with the given type - return null if no free chunks available
|
||||
VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
|
||||
// return given chunk to this buffer
|
||||
void Release(VBChunk* chunk);
|
||||
|
||||
|
||||
private:
|
||||
// set of all possible batches that can be used by this VB
|
||||
std::vector<Batch*> m_Batches;
|
||||
// vertex size of this vertex buffer
|
||||
size_t m_VertexSize;
|
||||
// number of vertices of above size in this buffer
|
||||
size_t m_MaxVertices;
|
||||
// list of free chunks in this buffer
|
||||
std::list<VBChunk*> m_FreeList;
|
||||
// available free vertices - total of all free vertices in the free list
|
||||
size_t m_FreeVertices;
|
||||
// handle to the actual GL vertex buffer object
|
||||
GLuint m_Handle;
|
||||
// raw system memory for systems not supporting VBOs
|
||||
u8* m_SysMem;
|
||||
// type of the buffer - dynamic?
|
||||
bool m_Dynamic;
|
||||
// list of all spare batches, shared between all vbs
|
||||
static std::vector<Batch*> m_FreeBatches;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,64 +1,65 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBufferManager.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "precompiled.h"
|
||||
#include <assert.h>
|
||||
#include "ogl.h"
|
||||
#include "VertexBufferManager.h"
|
||||
|
||||
CVertexBufferManager g_VBMan;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocate: try to allocate a buffer of given number of vertices (each of
|
||||
// given size), with the given type, and using the given texture - return null
|
||||
// if no free chunks available
|
||||
CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
|
||||
{
|
||||
CVertexBuffer::VBChunk* result=0;
|
||||
|
||||
// TODO, RC - run some sanity checks on allocation request
|
||||
|
||||
// iterate through all existing buffers testing for one that'll
|
||||
// satisfy the allocation
|
||||
typedef std::list<CVertexBuffer*>::iterator Iter;
|
||||
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
result=buffer->Allocate(vertexSize,numVertices,dynamic);
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
// got this far; need to allocate a new buffer
|
||||
CVertexBuffer* buffer=new CVertexBuffer(vertexSize,dynamic);
|
||||
m_Buffers.push_front(buffer);
|
||||
result=buffer->Allocate(vertexSize,numVertices,dynamic);
|
||||
|
||||
// TODO, RC - assert not really suitable? probably need to handle "failed to create
|
||||
// VBO case" better
|
||||
assert(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Release: return given chunk to it's owner
|
||||
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
|
||||
{
|
||||
assert(chunk);
|
||||
chunk->m_Owner->Release(chunk);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ClearBatchIndices: empty out the batch lists of all vertex buffers
|
||||
void CVertexBufferManager::ClearBatchIndices()
|
||||
{
|
||||
typedef std::list<CVertexBuffer*>::iterator Iter;
|
||||
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
buffer->ClearBatchIndices();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBufferManager.cpp
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "precompiled.h"
|
||||
#include <assert.h>
|
||||
#include "ogl.h"
|
||||
#include "VertexBufferManager.h"
|
||||
|
||||
CVertexBufferManager g_VBMan;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocate: try to allocate a buffer of given number of vertices (each of
|
||||
// given size), with the given type, and using the given texture - return null
|
||||
// if no free chunks available
|
||||
CVertexBuffer::VBChunk* CVertexBufferManager::Allocate(size_t vertexSize,size_t numVertices,bool dynamic)
|
||||
{
|
||||
CVertexBuffer::VBChunk* result=0;
|
||||
|
||||
// TODO, RC - run some sanity checks on allocation request
|
||||
|
||||
// iterate through all existing buffers testing for one that'll
|
||||
// satisfy the allocation
|
||||
typedef std::list<CVertexBuffer*>::iterator Iter;
|
||||
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
result=buffer->Allocate(vertexSize,numVertices,dynamic);
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
// got this far; need to allocate a new buffer
|
||||
CVertexBuffer* buffer=new CVertexBuffer(vertexSize,dynamic);
|
||||
m_Buffers.push_front(buffer);
|
||||
result=buffer->Allocate(vertexSize,numVertices,dynamic);
|
||||
|
||||
// TODO, RC - assert not really suitable? probably need to handle "failed to create
|
||||
// VBO case" better
|
||||
assert(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Release: return given chunk to it's owner
|
||||
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk)
|
||||
{
|
||||
assert(chunk);
|
||||
chunk->m_Owner->Release(chunk);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ClearBatchIndices: empty out the batch lists of all vertex buffers
|
||||
void CVertexBufferManager::ClearBatchIndices()
|
||||
{
|
||||
typedef std::list<CVertexBuffer*>::iterator Iter;
|
||||
for (Iter iter=m_Buffers.begin();iter!=m_Buffers.end();++iter) {
|
||||
CVertexBuffer* buffer=*iter;
|
||||
buffer->ClearBatchIndices();
|
||||
}
|
||||
}
|
@ -1,41 +1,41 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBufferManager.h
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _VERTEXBUFFERMANAGER_H
|
||||
#define _VERTEXBUFFERMANAGER_H
|
||||
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBufferManager: owner object for CVertexBuffer objects; acts as
|
||||
// 'front end' for their allocation and destruction
|
||||
class CVertexBufferManager
|
||||
{
|
||||
public:
|
||||
// try to allocate a buffer of given number of vertices (each of given size),
|
||||
// and with the given type - return null if no free chunks available
|
||||
CVertexBuffer::VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
|
||||
|
||||
// return given chunk to it's owner
|
||||
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk);
|
||||
|
||||
// empty out the batch lists of all vertex buffers
|
||||
void ClearBatchIndices();
|
||||
|
||||
// return list of all buffers
|
||||
const std::list<CVertexBuffer*>& GetBufferList() const { return m_Buffers; }
|
||||
|
||||
private:
|
||||
// list of all known vertex buffers
|
||||
std::list<CVertexBuffer*> m_Buffers;
|
||||
};
|
||||
|
||||
extern CVertexBufferManager g_VBMan;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: VertexBufferManager.h
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _VERTEXBUFFERMANAGER_H
|
||||
#define _VERTEXBUFFERMANAGER_H
|
||||
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CVertexBufferManager: owner object for CVertexBuffer objects; acts as
|
||||
// 'front end' for their allocation and destruction
|
||||
class CVertexBufferManager
|
||||
{
|
||||
public:
|
||||
// try to allocate a buffer of given number of vertices (each of given size),
|
||||
// and with the given type - return null if no free chunks available
|
||||
CVertexBuffer::VBChunk* Allocate(size_t vertexSize,size_t numVertices,bool dynamic);
|
||||
|
||||
// return given chunk to it's owner
|
||||
void CVertexBufferManager::Release(CVertexBuffer::VBChunk* chunk);
|
||||
|
||||
// empty out the batch lists of all vertex buffers
|
||||
void ClearBatchIndices();
|
||||
|
||||
// return list of all buffers
|
||||
const std::list<CVertexBuffer*>& GetBufferList() const { return m_Buffers; }
|
||||
|
||||
private:
|
||||
// list of all known vertex buffers
|
||||
std::list<CVertexBuffer*> m_Buffers;
|
||||
};
|
||||
|
||||
extern CVertexBufferManager g_VBMan;
|
||||
|
||||
|
||||
#endif
|
@ -1,9 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ogl.h"
|
||||
#include "ogl.h"
|
||||
#include "Renderer.h"
|
||||
#include "BrushShapeEditorTool.h"
|
||||
|
||||
#include "BrushShapeEditorTool.h"
|
||||
|
||||
|
||||
// default tool instance
|
||||
CBrushShapeEditorTool CBrushShapeEditorTool::m_BrushShapeEditorTool;
|
||||
|
@ -53,7 +53,7 @@ static void RenderTileOutline(int gx,int gz)
|
||||
|
||||
void CBrushTool::OnDraw()
|
||||
{
|
||||
g_Renderer.SetTexture(0,0);
|
||||
g_Renderer.SetTexture(0,0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,67 +6,67 @@
|
||||
#include "ogl.h"
|
||||
|
||||
extern CTerrain g_Terrain;
|
||||
|
||||
struct TGAHeader {
|
||||
// header stuff
|
||||
unsigned char iif_size;
|
||||
unsigned char cmap_type;
|
||||
unsigned char image_type;
|
||||
unsigned char pad[5];
|
||||
|
||||
// origin : unused
|
||||
unsigned short d_x_origin;
|
||||
unsigned short d_y_origin;
|
||||
|
||||
// dimensions
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
|
||||
// bits per pixel : 16, 24 or 32
|
||||
unsigned char bpp;
|
||||
|
||||
// image descriptor : Bits 3-0: size of alpha channel
|
||||
// Bit 4: must be 0 (reserved)
|
||||
// Bit 5: should be 0 (origin)
|
||||
// Bits 6-7: should be 0 (interleaving)
|
||||
unsigned char image_descriptor;
|
||||
};
|
||||
|
||||
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
|
||||
{
|
||||
FILE* fp=fopen(filename,"wb");
|
||||
if (!fp) return false;
|
||||
|
||||
// fill file header
|
||||
TGAHeader header;
|
||||
header.iif_size=0;
|
||||
header.cmap_type=0;
|
||||
header.image_type=2;
|
||||
memset(header.pad,0,sizeof(header.pad));
|
||||
header.d_x_origin=0;
|
||||
header.d_y_origin=0;
|
||||
header.width=width;
|
||||
header.height=height;
|
||||
header.bpp=bpp;
|
||||
header.image_descriptor=(bpp==32) ? 8 : 0;
|
||||
|
||||
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// write data
|
||||
if (fwrite(data,width*height*bpp/8,1,fp)!=1) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// return success ..
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct TGAHeader {
|
||||
// header stuff
|
||||
unsigned char iif_size;
|
||||
unsigned char cmap_type;
|
||||
unsigned char image_type;
|
||||
unsigned char pad[5];
|
||||
|
||||
// origin : unused
|
||||
unsigned short d_x_origin;
|
||||
unsigned short d_y_origin;
|
||||
|
||||
// dimensions
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
|
||||
// bits per pixel : 16, 24 or 32
|
||||
unsigned char bpp;
|
||||
|
||||
// image descriptor : Bits 3-0: size of alpha channel
|
||||
// Bit 4: must be 0 (reserved)
|
||||
// Bit 5: should be 0 (origin)
|
||||
// Bits 6-7: should be 0 (interleaving)
|
||||
unsigned char image_descriptor;
|
||||
};
|
||||
|
||||
static bool saveTGA(const char* filename,int width,int height,int bpp,unsigned char* data)
|
||||
{
|
||||
FILE* fp=fopen(filename,"wb");
|
||||
if (!fp) return false;
|
||||
|
||||
// fill file header
|
||||
TGAHeader header;
|
||||
header.iif_size=0;
|
||||
header.cmap_type=0;
|
||||
header.image_type=2;
|
||||
memset(header.pad,0,sizeof(header.pad));
|
||||
header.d_x_origin=0;
|
||||
header.d_y_origin=0;
|
||||
header.width=width;
|
||||
header.height=height;
|
||||
header.bpp=bpp;
|
||||
header.image_descriptor=(bpp==32) ? 8 : 0;
|
||||
|
||||
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// write data
|
||||
if (fwrite(data,width*height*bpp/8,1,fp)!=1) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// return success ..
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned int ScaleColor(unsigned int color,float x)
|
||||
{
|
||||
@ -94,7 +94,7 @@ void CMiniMap::Initialise()
|
||||
{
|
||||
// get rid of existing texture, if we've got one
|
||||
if (m_Handle) {
|
||||
glDeleteTextures(1,(GLuint*) &m_Handle);
|
||||
glDeleteTextures(1,(GLuint*) &m_Handle);
|
||||
delete[] m_Data;
|
||||
}
|
||||
|
||||
@ -103,12 +103,12 @@ void CMiniMap::Initialise()
|
||||
g_Renderer.BindTexture(0,m_Handle);
|
||||
|
||||
// allocate an image big enough to fit the entire map into
|
||||
m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide());
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
m_Size=RoundUpToPowerOf2(g_Terrain.GetVerticesPerSide());
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,m_Size,m_Size,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,0);
|
||||
|
||||
// allocate local copy
|
||||
m_Data=new u32[(mapSize-1)*(mapSize-1)];
|
||||
|
||||
// allocate local copy
|
||||
m_Data=new u32[(mapSize-1)*(mapSize-1)];
|
||||
|
||||
// set texture parameters
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||
@ -139,7 +139,7 @@ void CMiniMap::Render()
|
||||
int h=g_Renderer.GetHeight();
|
||||
glOrtho(0,w,0,h,-1,1);
|
||||
|
||||
// bind to the minimap
|
||||
// bind to the minimap
|
||||
g_Renderer.BindTexture(0,m_Handle);
|
||||
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
|
||||
|
||||
@ -207,18 +207,18 @@ void CMiniMap::Update(int x,int y,unsigned int color)
|
||||
int val=(hmap/3)+170;
|
||||
|
||||
// get modulated color
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
*(m_Data+(y*(mapSize-1)+x))=ScaleColor(color,float(val)/255.0f);
|
||||
|
||||
|
||||
UpdateTexture();
|
||||
}
|
||||
|
||||
void CMiniMap::Update(int x,int y,int w,int h,unsigned int color)
|
||||
{
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
|
||||
for (int j=0;j<h;j++) {
|
||||
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
|
||||
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
|
||||
for (int i=0;i<w;i++) {
|
||||
// get height at this pixel
|
||||
int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8;
|
||||
@ -228,33 +228,33 @@ void CMiniMap::Update(int x,int y,int w,int h,unsigned int color)
|
||||
*dataptr++=ScaleColor(color,float(val)/255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateTexture();
|
||||
}
|
||||
|
||||
void CMiniMap::Rebuild()
|
||||
{
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
{
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
Rebuild(0,0,mapSize-1,mapSize-1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UpdateTexture: send data to GL; update stored texture data
|
||||
void CMiniMap::UpdateTexture()
|
||||
{
|
||||
// bind to the minimap
|
||||
g_Renderer.BindTexture(0,m_Handle);
|
||||
// subimage to update pixels
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UpdateTexture: send data to GL; update stored texture data
|
||||
void CMiniMap::UpdateTexture()
|
||||
{
|
||||
// bind to the minimap
|
||||
g_Renderer.BindTexture(0,m_Handle);
|
||||
// subimage to update pixels
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,mapSize-1,mapSize-1,GL_BGRA_EXT,GL_UNSIGNED_BYTE,m_Data);
|
||||
}
|
||||
|
||||
void CMiniMap::Rebuild(int x,int y,int w,int h)
|
||||
{
|
||||
u32 mapSize=g_Terrain.GetVerticesPerSide();
|
||||
|
||||
for (int j=0;j<h;j++) {
|
||||
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
|
||||
u32* dataptr=m_Data+((y+j)*(mapSize-1))+x;
|
||||
for (int i=0;i<w;i++) {
|
||||
// get height at this pixel
|
||||
int hmap=int(g_Terrain.GetHeightMap()[(y+j)*mapSize + x+i])>>8;
|
||||
@ -276,6 +276,6 @@ void CMiniMap::Rebuild(int x,int y,int w,int h)
|
||||
*dataptr++=ScaleColor(color,float(val)/255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UpdateTexture();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef _RAISEELEVATIONTOOL_H
|
||||
#define _RAISEELEVATIONTOOL_H
|
||||
|
||||
#include <set>
|
||||
#include <set>
|
||||
#include "lib.h"
|
||||
#include "res/res.h"
|
||||
#include "BrushTool.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#define _IGNORE_WGL_H_
|
||||
#define _IGNORE_WGL_H_
|
||||
#include "MainFrm.h"
|
||||
#include "EditorData.h"
|
||||
#include "BrushShapeEditorTool.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
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <assert.h>
|
||||
#include <assert.h>
|
||||
#include "stdafx.h"
|
||||
#include "ToolManager.h"
|
||||
#include "ElevToolsDlgBar.h"
|
||||
|
@ -2,13 +2,13 @@
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
#define _IGNORE_WGL_H_
|
||||
#include "ogl.h"
|
||||
#include "ogl.h"
|
||||
#include "res/tex.h"
|
||||
#include "res/mem.h"
|
||||
#include "res/vfs.h"
|
||||
#undef _IGNORE_WGL_H_
|
||||
#undef _IGNORE_WGL_H_
|
||||
|
||||
#include "ScEd.h"
|
||||
#include "ScEdView.h"
|
||||
@ -20,8 +20,8 @@
|
||||
|
||||
#include "Unit.h"
|
||||
#include "UnitManager.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "TextureManager.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "TextureManager.h"
|
||||
#include "UIGlobals.h"
|
||||
#include "MainFrm.h"
|
||||
#include "OptionsPropSheet.h"
|
||||
@ -57,14 +57,14 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
|
||||
ON_COMMAND(ID_LIGHTING_SETTINGS, OnLightingSettings)
|
||||
ON_COMMAND(ID_VIEW_SCREENSHOT, OnViewScreenshot)
|
||||
ON_COMMAND(IDR_TEXTURE_TOOLS, OnTextureTools)
|
||||
ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions)
|
||||
ON_COMMAND(ID_TOOLS_OPTIONS, OnToolsOptions)
|
||||
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
|
||||
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
|
||||
ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
|
||||
ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
|
||||
ON_COMMAND(IDR_ELEVATION_TOOLS, OnElevationTools)
|
||||
ON_COMMAND(IDR_RESIZE_MAP, OnResizeMap)
|
||||
ON_COMMAND(ID_VIEW_TERRAIN_GRID, OnViewTerrainGrid)
|
||||
ON_COMMAND(ID_VIEW_TERRAIN_GRID, OnViewTerrainGrid)
|
||||
ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_GRID, OnUpdateViewTerrainGrid)
|
||||
ON_COMMAND(ID_VIEW_TERRAIN_SOLID, OnViewTerrainSolid)
|
||||
ON_UPDATE_COMMAND_UI(ID_VIEW_TERRAIN_SOLID, OnUpdateViewTerrainSolid)
|
||||
@ -86,8 +86,8 @@ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
|
||||
ON_COMMAND(ID_TEST_STOP, OnTestStop)
|
||||
ON_UPDATE_COMMAND_UI(ID_TEST_STOP, OnUpdateTestStop)
|
||||
ON_COMMAND(IDR_UNIT_TOOLS, OnUnitTools)
|
||||
ON_COMMAND(ID_RANDOM_MAP, OnRandomMap)
|
||||
//}}AFX_MSG_MAP
|
||||
ON_COMMAND(ID_RANDOM_MAP, OnRandomMap)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
static UINT indicators[] =
|
||||
@ -722,127 +722,127 @@ void CMainFrame::OnUpdateTestStop(CCmdUI* pCmdUI)
|
||||
else
|
||||
pCmdUI->Enable(FALSE);
|
||||
}
|
||||
|
||||
static float getExactGroundLevel( float x, float y )
|
||||
{
|
||||
// TODO MT: If OK with Rich, move to terrain core. Once this works, that is.
|
||||
|
||||
x /= 4.0f;
|
||||
y /= 4.0f;
|
||||
|
||||
int xi = (int)floor( x );
|
||||
int yi = (int)floor( y );
|
||||
float xf = x - (float)xi;
|
||||
float yf = y - (float)yi;
|
||||
|
||||
u16* heightmap = g_Terrain.GetHeightMap();
|
||||
unsigned long mapsize = g_Terrain.GetVerticesPerSide();
|
||||
|
||||
float h00 = heightmap[yi*mapsize + xi];
|
||||
float h01 = heightmap[yi*mapsize + xi + mapsize];
|
||||
float h10 = heightmap[yi*mapsize + xi + 1];
|
||||
float h11 = heightmap[yi*mapsize + xi + mapsize + 1];
|
||||
|
||||
/*
|
||||
if( xf < ( 1.0f - yf ) )
|
||||
{
|
||||
return( HEIGHT_SCALE * ( ( 1 - xf - yf ) * h00 + xf * h10 + yf * h01 ) );
|
||||
}
|
||||
else
|
||||
return( HEIGHT_SCALE * ( ( xf + yf - 1 ) * h11 + ( 1 - xf ) * h01 + ( 1 - yf ) * h10 ) );
|
||||
*/
|
||||
|
||||
/*
|
||||
if( xf > yf )
|
||||
{
|
||||
return( HEIGHT_SCALE * ( ( 1 - xf ) * h00 + ( xf - yf ) * h10 + yf * h11 ) );
|
||||
}
|
||||
else
|
||||
return( HEIGHT_SCALE * ( ( 1 - yf ) * h00 + ( yf - xf ) * h01 + xf * h11 ) );
|
||||
*/
|
||||
|
||||
return( HEIGHT_SCALE * ( ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ) );
|
||||
|
||||
}
|
||||
|
||||
static CObjectEntry* GetRandomActorTemplate()
|
||||
{
|
||||
if (g_ObjMan.m_ObjectTypes.size()==0) return 0;
|
||||
|
||||
CObjectEntry* found=0;
|
||||
int checkloop=250;
|
||||
do {
|
||||
u32 type=rand()%g_ObjMan.m_ObjectTypes.size();
|
||||
u32 actorsoftype=g_ObjMan.m_ObjectTypes[type].m_Objects.size();
|
||||
if (actorsoftype>0) {
|
||||
found=g_ObjMan.m_ObjectTypes[type].m_Objects[rand()%actorsoftype];
|
||||
if (found && found->m_Model && found->m_Model->GetModelDef()->GetNumBones()>0) {
|
||||
} else {
|
||||
found=0;
|
||||
}
|
||||
}
|
||||
} while (--checkloop && !found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static CTextureEntry* GetRandomTexture()
|
||||
{
|
||||
if (g_TexMan.m_TerrainTextures.size()==0) return 0;
|
||||
|
||||
CTextureEntry* found=0;
|
||||
do {
|
||||
u32 type=rand()%g_TexMan.m_TerrainTextures.size();
|
||||
u32 texturesoftype=g_TexMan.m_TerrainTextures[type].m_Textures.size();
|
||||
if (texturesoftype>0) {
|
||||
found=g_TexMan.m_TerrainTextures[type].m_Textures[rand()%texturesoftype];
|
||||
}
|
||||
} while (!found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void CMainFrame::OnRandomMap()
|
||||
{
|
||||
const u32 count=5000;
|
||||
const u32 unitsPerDir=u32(sqrt(float(count)));
|
||||
|
||||
u32 i,j;
|
||||
u32 vsize=g_Terrain.GetVerticesPerSide()-1;
|
||||
|
||||
for (i=0;i<unitsPerDir;i++) {
|
||||
for (j=0;j<unitsPerDir;j++) {
|
||||
// float x=CELL_SIZE*vsize*float(i+1)/float(unitsPerDir+1);
|
||||
// float z=CELL_SIZE*vsize*float(j+1)/float(unitsPerDir+1);
|
||||
float dx=float(rand())/float(RAND_MAX);
|
||||
float x=CELL_SIZE*vsize*dx;
|
||||
float dz=float(rand())/float(RAND_MAX);
|
||||
float z=CELL_SIZE*vsize*dz;
|
||||
float y=getExactGroundLevel(x,z);
|
||||
CObjectEntry* actortemplate=GetRandomActorTemplate();
|
||||
if (actortemplate && actortemplate->m_Model) {
|
||||
CUnit* unit=new CUnit(actortemplate,actortemplate->m_Model->Clone());
|
||||
g_UnitMan.AddUnit(unit);
|
||||
|
||||
CMatrix3D trans;
|
||||
trans.SetIdentity();
|
||||
trans.RotateY(2*PI*float(rand())/float(RAND_MAX));
|
||||
trans.Translate(x,y,z);
|
||||
unit->GetModel()->SetTransform(trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (j=0;j<vsize;j++) {
|
||||
CTextureEntry* tex=GetRandomTexture();
|
||||
CMiniPatch* mp=g_Terrain.GetTile(i,j);
|
||||
mp->Tex1=tex->GetHandle();
|
||||
mp->Tex1Priority=tex->GetType();
|
||||
mp->m_Parent->SetDirty(RENDERDATA_UPDATE_VERTICES | RENDERDATA_UPDATE_INDICES);
|
||||
}
|
||||
}
|
||||
g_MiniMap.Rebuild();
|
||||
*/
|
||||
}
|
||||
|
||||
static float getExactGroundLevel( float x, float y )
|
||||
{
|
||||
// TODO MT: If OK with Rich, move to terrain core. Once this works, that is.
|
||||
|
||||
x /= 4.0f;
|
||||
y /= 4.0f;
|
||||
|
||||
int xi = (int)floor( x );
|
||||
int yi = (int)floor( y );
|
||||
float xf = x - (float)xi;
|
||||
float yf = y - (float)yi;
|
||||
|
||||
u16* heightmap = g_Terrain.GetHeightMap();
|
||||
unsigned long mapsize = g_Terrain.GetVerticesPerSide();
|
||||
|
||||
float h00 = heightmap[yi*mapsize + xi];
|
||||
float h01 = heightmap[yi*mapsize + xi + mapsize];
|
||||
float h10 = heightmap[yi*mapsize + xi + 1];
|
||||
float h11 = heightmap[yi*mapsize + xi + mapsize + 1];
|
||||
|
||||
/*
|
||||
if( xf < ( 1.0f - yf ) )
|
||||
{
|
||||
return( HEIGHT_SCALE * ( ( 1 - xf - yf ) * h00 + xf * h10 + yf * h01 ) );
|
||||
}
|
||||
else
|
||||
return( HEIGHT_SCALE * ( ( xf + yf - 1 ) * h11 + ( 1 - xf ) * h01 + ( 1 - yf ) * h10 ) );
|
||||
*/
|
||||
|
||||
/*
|
||||
if( xf > yf )
|
||||
{
|
||||
return( HEIGHT_SCALE * ( ( 1 - xf ) * h00 + ( xf - yf ) * h10 + yf * h11 ) );
|
||||
}
|
||||
else
|
||||
return( HEIGHT_SCALE * ( ( 1 - yf ) * h00 + ( yf - xf ) * h01 + xf * h11 ) );
|
||||
*/
|
||||
|
||||
return( HEIGHT_SCALE * ( ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ) );
|
||||
|
||||
}
|
||||
|
||||
static CObjectEntry* GetRandomActorTemplate()
|
||||
{
|
||||
if (g_ObjMan.m_ObjectTypes.size()==0) return 0;
|
||||
|
||||
CObjectEntry* found=0;
|
||||
int checkloop=250;
|
||||
do {
|
||||
u32 type=rand()%g_ObjMan.m_ObjectTypes.size();
|
||||
u32 actorsoftype=g_ObjMan.m_ObjectTypes[type].m_Objects.size();
|
||||
if (actorsoftype>0) {
|
||||
found=g_ObjMan.m_ObjectTypes[type].m_Objects[rand()%actorsoftype];
|
||||
if (found && found->m_Model && found->m_Model->GetModelDef()->GetNumBones()>0) {
|
||||
} else {
|
||||
found=0;
|
||||
}
|
||||
}
|
||||
} while (--checkloop && !found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static CTextureEntry* GetRandomTexture()
|
||||
{
|
||||
if (g_TexMan.m_TerrainTextures.size()==0) return 0;
|
||||
|
||||
CTextureEntry* found=0;
|
||||
do {
|
||||
u32 type=rand()%g_TexMan.m_TerrainTextures.size();
|
||||
u32 texturesoftype=g_TexMan.m_TerrainTextures[type].m_Textures.size();
|
||||
if (texturesoftype>0) {
|
||||
found=g_TexMan.m_TerrainTextures[type].m_Textures[rand()%texturesoftype];
|
||||
}
|
||||
} while (!found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void CMainFrame::OnRandomMap()
|
||||
{
|
||||
const u32 count=5000;
|
||||
const u32 unitsPerDir=u32(sqrt(float(count)));
|
||||
|
||||
u32 i,j;
|
||||
u32 vsize=g_Terrain.GetVerticesPerSide()-1;
|
||||
|
||||
for (i=0;i<unitsPerDir;i++) {
|
||||
for (j=0;j<unitsPerDir;j++) {
|
||||
// float x=CELL_SIZE*vsize*float(i+1)/float(unitsPerDir+1);
|
||||
// float z=CELL_SIZE*vsize*float(j+1)/float(unitsPerDir+1);
|
||||
float dx=float(rand())/float(RAND_MAX);
|
||||
float x=CELL_SIZE*vsize*dx;
|
||||
float dz=float(rand())/float(RAND_MAX);
|
||||
float z=CELL_SIZE*vsize*dz;
|
||||
float y=getExactGroundLevel(x,z);
|
||||
CObjectEntry* actortemplate=GetRandomActorTemplate();
|
||||
if (actortemplate && actortemplate->m_Model) {
|
||||
CUnit* unit=new CUnit(actortemplate,actortemplate->m_Model->Clone());
|
||||
g_UnitMan.AddUnit(unit);
|
||||
|
||||
CMatrix3D trans;
|
||||
trans.SetIdentity();
|
||||
trans.RotateY(2*PI*float(rand())/float(RAND_MAX));
|
||||
trans.Translate(x,y,z);
|
||||
unit->GetModel()->SetTransform(trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (j=0;j<vsize;j++) {
|
||||
CTextureEntry* tex=GetRandomTexture();
|
||||
CMiniPatch* mp=g_Terrain.GetTile(i,j);
|
||||
mp->Tex1=tex->GetHandle();
|
||||
mp->Tex1Priority=tex->GetType();
|
||||
mp->m_Parent->SetDirty(RENDERDATA_UPDATE_VERTICES | RENDERDATA_UPDATE_INDICES);
|
||||
}
|
||||
}
|
||||
g_MiniMap.Rebuild();
|
||||
*/
|
||||
}
|
||||
|
@ -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()
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -2,12 +2,16 @@
|
||||
|
||||
#include "ScriptingHost.h"
|
||||
#include "ScriptGlue.h"
|
||||
#include "CConsole.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "float.h" // <- MT: Just for _finite(), converting certain strings was causing wierd bugs.
|
||||
|
||||
#pragma comment (lib, "js32.lib")
|
||||
|
||||
extern CConsole* g_Console;
|
||||
|
||||
namespace
|
||||
{
|
||||
const int RUNTIME_MEMORY_ALLOWANCE = 16 * 1024 * 1024;
|
||||
@ -76,6 +80,11 @@ ScriptingHost::~ScriptingHost()
|
||||
}
|
||||
}
|
||||
|
||||
JSContext* ScriptingHost::getContext()
|
||||
{
|
||||
return( m_Context );
|
||||
}
|
||||
|
||||
void ScriptingHost::LoadScriptFromDisk(const std::string & fileName)
|
||||
{
|
||||
std::string script;
|
||||
@ -124,6 +133,8 @@ jsval ScriptingHost::ExecuteScript(const std::string & script)
|
||||
|
||||
JSBool ok = JS_EvaluateScript(m_Context, m_GlobalObject, script.c_str(), (int)script.length(), "Console", 0, &rval);
|
||||
|
||||
if( !ok ) return( NULL );
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -223,6 +234,13 @@ void ScriptingHost::SetObjectProperty(JSObject * object, const std::string & pro
|
||||
JS_SetProperty(m_Context, object, propertyName.c_str(), &value);
|
||||
}
|
||||
|
||||
jsval ScriptingHost::GetObjectProperty( JSObject* object, const std::string& propertyName )
|
||||
{
|
||||
jsval vp;
|
||||
JS_GetProperty( m_Context, object, propertyName.c_str(), &vp );
|
||||
return( vp );
|
||||
}
|
||||
|
||||
int ScriptingHost::ValueToInt(const jsval value)
|
||||
{
|
||||
int32 i = 0;
|
||||
@ -264,7 +282,7 @@ double ScriptingHost::ValueToDouble(const jsval value)
|
||||
|
||||
JSBool ok = JS_ValueToNumber(m_Context, value, &d);
|
||||
|
||||
if (ok == JS_FALSE)
|
||||
if (ok == JS_FALSE || !_finite( d ) )
|
||||
{
|
||||
throw (std::string("Convert to double failed"));
|
||||
}
|
||||
@ -274,6 +292,14 @@ double ScriptingHost::ValueToDouble(const jsval value)
|
||||
|
||||
void ScriptingHost::ErrorReporter(JSContext * context, const char * message, JSErrorReport * report)
|
||||
{
|
||||
g_Console->InsertMessage( "%s ( %d )", report->filename, report->lineno );
|
||||
if( message )
|
||||
{
|
||||
g_Console->InsertMessage( message );
|
||||
}
|
||||
else
|
||||
g_Console->InsertMessage( "No error message available" );
|
||||
|
||||
if (report->filename != NULL)
|
||||
{
|
||||
std::cout << report->filename << " (" << report->lineno << ") ";
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -24,32 +24,25 @@
|
||||
#include "EntityProperties.h"
|
||||
#include "BoundingObjects.h"
|
||||
|
||||
class CBaseEntity
|
||||
class CBaseEntity : public IPropertyOwner
|
||||
{
|
||||
public:
|
||||
CBaseEntity() { m_bound_circle = NULL; m_bound_box = NULL; }
|
||||
CBaseEntity( const CBaseEntity& copy );
|
||||
CBaseEntity();
|
||||
~CBaseEntity();
|
||||
// Load from XML
|
||||
bool loadXML( CStr filename );
|
||||
|
||||
// Base stats
|
||||
|
||||
|
||||
CObjectEntry* m_actorObject;
|
||||
|
||||
CStr m_name;
|
||||
CProperty_CStr m_name;
|
||||
CBoundingCircle* m_bound_circle;
|
||||
CBoundingBox* m_bound_box;
|
||||
CBoundingObject::EBoundingType m_bound_type;
|
||||
|
||||
float m_speed;
|
||||
float m_turningRadius;
|
||||
|
||||
|
||||
// Extended properties table
|
||||
|
||||
STL_HASH_MAP<CStr,CGenericProperty,CStr_hash_compare> m_properties;
|
||||
CProperty_float m_speed;
|
||||
CProperty_float m_turningRadius;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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] );
|
||||
}
|
||||
|
@ -28,11 +28,12 @@
|
||||
|
||||
class CBaseEntityCollection : public Singleton<CBaseEntityCollection>
|
||||
{
|
||||
std::vector<CBaseEntity> m_templates;
|
||||
std::vector<CBaseEntity*> m_templates;
|
||||
public:
|
||||
~CBaseEntityCollection();
|
||||
CBaseEntity* getTemplate( CStr entityType );
|
||||
void loadTemplates();
|
||||
void addTemplate( CBaseEntity& temp );
|
||||
void addTemplate( CBaseEntity* temp );
|
||||
CBaseEntity* getTemplateByActor( CObjectEntry* actor );
|
||||
};
|
||||
|
||||
|
@ -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! ;)
|
||||
|
@ -47,29 +47,23 @@
|
||||
|
||||
class CEntityManager;
|
||||
|
||||
class CEntity
|
||||
class CEntity : public IPropertyOwner
|
||||
{
|
||||
friend class CEntityManager;
|
||||
private:
|
||||
// Intrinsic properties
|
||||
public:
|
||||
CStr m_name;
|
||||
float m_speed;
|
||||
float m_turningRadius;
|
||||
CVector3D m_position;
|
||||
// Intrinsic properties
|
||||
CProperty_CStr m_name;
|
||||
CProperty_float m_speed;
|
||||
CProperty_float m_turningRadius;
|
||||
CProperty_CVector3D m_position;
|
||||
CBoundingObject* m_bounds;
|
||||
float m_targetorientation;
|
||||
CVector2D m_ahead;
|
||||
float m_orientation;
|
||||
CBaseEntity* m_base;
|
||||
CProperty_float m_orientation;
|
||||
CUnit* m_actor;
|
||||
|
||||
std::deque<CEntityOrder> m_orderQueue;
|
||||
|
||||
// Extended properties table
|
||||
|
||||
STL_HASH_MAP<CStr,CGenericProperty,CStr_hash_compare> m_properties;
|
||||
|
||||
private:
|
||||
CEntity( CBaseEntity* base, CVector3D position, float orientation );
|
||||
|
||||
@ -88,6 +82,12 @@ public:
|
||||
void render();
|
||||
float getExactGroundLevel( float x, float y );
|
||||
void snapToGround();
|
||||
void repath();
|
||||
|
||||
void loadBase();
|
||||
void reorient();
|
||||
void teleport(); // Fixes things if the position is changed by something externally.
|
||||
|
||||
void pushOrder( CEntityOrder& order );
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,12 @@ HEntity CEntityManager::create( CStr templatename, CVector3D position, float ori
|
||||
return( create( templateobj, position, orientation ) );
|
||||
}
|
||||
|
||||
HEntity* CEntityManager::getByHandle( u16 index )
|
||||
{
|
||||
if( index >= MAX_HANDLES ) return( NULL );
|
||||
if( !m_entities[index].m_refcount ) return( NULL );
|
||||
return( new HEntity( index ) );
|
||||
}
|
||||
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate )
|
||||
{
|
||||
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
||||
|
@ -42,10 +42,11 @@ public:
|
||||
~CEntityManager();
|
||||
HEntity create( CBaseEntity* base, CVector3D position, float orientation );
|
||||
HEntity create( CStr templatename, CVector3D position, float orientation );
|
||||
HEntity* getByHandle( u16 index );
|
||||
void kill( HEntity ent );
|
||||
void updateAll( float timestep );
|
||||
void dispatchAll( CMessage* msg );
|
||||
void renderAll(); // TODO MT: What's the correct way to hook this up to the renderer?
|
||||
void renderAll();
|
||||
std::vector<HEntity>* matches( EntityPredicate predicate );
|
||||
std::vector<HEntity>* getActive();
|
||||
static inline bool extant() // True if the singleton is actively maintaining handles. When false, system is shutting down, handles are quietly dumped.
|
||||
|
@ -1,621 +1,368 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "EntityProperties.h"
|
||||
#include "BaseEntityCollection.h"
|
||||
#include "scripting/JSInterface_BaseEntity.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
CGenericProperty::CGenericProperty()
|
||||
void CProperty::associate( IPropertyOwner* owner, const CStr& name )
|
||||
{
|
||||
m_type = PROP_INTEGER;
|
||||
m_integer = 0;
|
||||
m_owner = owner;
|
||||
owner->m_properties[name] = this;
|
||||
m_updateFn = NULL;
|
||||
}
|
||||
|
||||
CGenericProperty::~CGenericProperty()
|
||||
void CProperty::associate( IPropertyOwner* owner, const CStr& name, void (IPropertyOwner::*updateFn)() )
|
||||
{
|
||||
releaseData();
|
||||
m_owner = owner;
|
||||
owner->m_properties[name] = this;
|
||||
m_updateFn = updateFn;
|
||||
}
|
||||
|
||||
void CGenericProperty::releaseData()
|
||||
CProperty& CProperty::operator=( jsval value )
|
||||
{
|
||||
switch( m_type & ~PROP_TYPELOCKED )
|
||||
{
|
||||
case PROP_STRING:
|
||||
delete( m_string ); break;
|
||||
case PROP_VECTOR:
|
||||
delete( m_vector ); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator i32()
|
||||
{
|
||||
return( toInteger() );
|
||||
}
|
||||
|
||||
CGenericProperty::operator float()
|
||||
{
|
||||
return( toFloat() );
|
||||
}
|
||||
|
||||
CGenericProperty::operator CStr()
|
||||
{
|
||||
return( toString() );
|
||||
}
|
||||
|
||||
CGenericProperty::operator CVector3D()
|
||||
{
|
||||
return( toVector() );
|
||||
}
|
||||
|
||||
CGenericProperty::operator void *()
|
||||
{
|
||||
return( toVoid() );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator=( int32_t value )
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
{
|
||||
fromInteger( value );
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseData();
|
||||
m_type = PROP_INTEGER;
|
||||
m_integer = value;
|
||||
}
|
||||
set( value );
|
||||
return( *this );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator=( float value )
|
||||
CProperty_i32::CProperty_i32()
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
{
|
||||
fromFloat( value );
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseData();
|
||||
m_type = PROP_FLOAT;
|
||||
m_float = value;
|
||||
}
|
||||
modifier = NULL;
|
||||
}
|
||||
|
||||
CProperty_i32::~CProperty_i32()
|
||||
{
|
||||
if( modifier )
|
||||
delete( modifier );
|
||||
}
|
||||
|
||||
inline CProperty_i32& CProperty_i32::operator =( i32 value )
|
||||
{
|
||||
if( !modifier )
|
||||
modifier = new SProperty_NumericModifier();
|
||||
*modifier = (float)value;
|
||||
data = value;
|
||||
return( *this );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator=( CStr& value )
|
||||
void CProperty_i32::set( jsval value )
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
if( !modifier )
|
||||
modifier = new SProperty_NumericModifier();
|
||||
try
|
||||
{
|
||||
fromString( value );
|
||||
*modifier = (float)g_ScriptingHost.ValueToInt( value );
|
||||
}
|
||||
else
|
||||
catch( ... )
|
||||
{
|
||||
releaseData();
|
||||
m_type = PROP_STRING;
|
||||
m_string = new CStr( value );
|
||||
*modifier = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CProperty_i32::rebuild( CProperty* parent, bool triggerFn )
|
||||
{
|
||||
CProperty_i32* _parent = (CProperty_i32*)parent;
|
||||
i32 newvalue = 0;
|
||||
if( _parent )
|
||||
newvalue = *_parent;
|
||||
if( modifier )
|
||||
{
|
||||
newvalue *= modifier->multiplicative;
|
||||
newvalue += modifier->additive;
|
||||
}
|
||||
if( data == newvalue )
|
||||
return( false ); // No change.
|
||||
data = newvalue;
|
||||
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
|
||||
return( true );
|
||||
}
|
||||
|
||||
inline CProperty_i32::operator i32()
|
||||
{
|
||||
return( data );
|
||||
}
|
||||
|
||||
CProperty_i32::operator jsval()
|
||||
{
|
||||
return( INT_TO_JSVAL( data ) );
|
||||
}
|
||||
|
||||
CProperty_float::CProperty_float()
|
||||
{
|
||||
modifier = NULL;
|
||||
}
|
||||
|
||||
CProperty_float::~CProperty_float()
|
||||
{
|
||||
if( modifier )
|
||||
modifier = NULL;
|
||||
}
|
||||
|
||||
CProperty_float& CProperty_float::operator =( const float& value )
|
||||
{
|
||||
if( !modifier )
|
||||
modifier = new SProperty_NumericModifier();
|
||||
*modifier = value;
|
||||
data = value;
|
||||
return( *this );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator=( CVector3D& value )
|
||||
void CProperty_float::set( const jsval value )
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
if( !modifier )
|
||||
modifier = new SProperty_NumericModifier();
|
||||
try
|
||||
{
|
||||
fromVector( value );
|
||||
*modifier = (float)g_ScriptingHost.ValueToDouble( value );
|
||||
}
|
||||
else
|
||||
catch( ... )
|
||||
{
|
||||
releaseData();
|
||||
m_type = PROP_VECTOR;
|
||||
m_vector = new CVector3D( value );
|
||||
*modifier = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
bool CProperty_float::rebuild( CProperty* parent, bool triggerFn )
|
||||
{
|
||||
CProperty_float* _parent = (CProperty_float*)parent;
|
||||
float newvalue = 0;
|
||||
if( _parent )
|
||||
newvalue = *_parent;
|
||||
if( modifier )
|
||||
{
|
||||
newvalue *= modifier->multiplicative;
|
||||
newvalue += modifier->additive;
|
||||
}
|
||||
if( data == newvalue )
|
||||
return( false ); // No change.
|
||||
data = newvalue;
|
||||
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
|
||||
return( true );
|
||||
}
|
||||
|
||||
CProperty_float::operator float()
|
||||
{
|
||||
return( data );
|
||||
}
|
||||
|
||||
CProperty_float::operator jsval()
|
||||
{
|
||||
return( DOUBLE_TO_JSVAL( JS_NewDouble( g_ScriptingHost.getContext(), (jsdouble)data ) ) );
|
||||
}
|
||||
|
||||
CProperty_float::operator bool()
|
||||
{
|
||||
return( data );
|
||||
}
|
||||
|
||||
float CProperty_float::operator+( float value )
|
||||
{
|
||||
return( data + value );
|
||||
}
|
||||
|
||||
float CProperty_float::operator-( float value )
|
||||
{
|
||||
return( data - value );
|
||||
}
|
||||
|
||||
float CProperty_float::operator*( float value )
|
||||
{
|
||||
return( data * value );
|
||||
}
|
||||
|
||||
float CProperty_float::operator/( float value )
|
||||
{
|
||||
return( data / value );
|
||||
}
|
||||
|
||||
bool CProperty_float::operator<( float value )
|
||||
{
|
||||
return( data < value );
|
||||
}
|
||||
|
||||
bool CProperty_float::operator>( float value )
|
||||
{
|
||||
return( data > value );
|
||||
}
|
||||
|
||||
bool CProperty_float::operator==( float value )
|
||||
{
|
||||
return( data == value );
|
||||
}
|
||||
|
||||
CProperty_CStr::CProperty_CStr()
|
||||
{
|
||||
modifier = NULL;
|
||||
}
|
||||
|
||||
CProperty_CStr::~CProperty_CStr()
|
||||
{
|
||||
if( modifier )
|
||||
delete( modifier );
|
||||
}
|
||||
|
||||
CProperty_CStr& CProperty_CStr::operator=( const CStr& value )
|
||||
{
|
||||
if( !modifier )
|
||||
modifier = new SProperty_StringModifier();
|
||||
*modifier = value;
|
||||
m_String = value;
|
||||
return( *this );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator =( void* value )
|
||||
void CProperty_CStr::set( jsval value )
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
if( !modifier )
|
||||
modifier = new SProperty_StringModifier();
|
||||
try
|
||||
{
|
||||
fromVoid( value );
|
||||
*modifier = g_ScriptingHost.ValueToString( value );
|
||||
}
|
||||
else
|
||||
catch( ... )
|
||||
{
|
||||
releaseData();
|
||||
m_type = PROP_PTR;
|
||||
m_ptr = value;
|
||||
*modifier = CStr();
|
||||
m_String.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool CProperty_CStr::rebuild( CProperty* parent, bool triggerFn )
|
||||
{
|
||||
CProperty_CStr* _parent = (CProperty_CStr*)parent;
|
||||
CStr newvalue = "";
|
||||
if( _parent )
|
||||
newvalue = *_parent;
|
||||
if( modifier )
|
||||
newvalue = modifier->replacement;
|
||||
|
||||
if( *this == newvalue )
|
||||
return( false ); // No change.
|
||||
m_String = newvalue;
|
||||
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
|
||||
return( true );
|
||||
}
|
||||
|
||||
CProperty_CStr::operator jsval()
|
||||
{
|
||||
return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.getContext(), m_String.c_str() ) ) );
|
||||
}
|
||||
|
||||
CProperty_CVector3D& CProperty_CVector3D::operator =( const CVector3D& value )
|
||||
{
|
||||
*( (CVector3D*)this ) = value;
|
||||
return( *this );
|
||||
}
|
||||
|
||||
void CGenericProperty::associate( i32* value )
|
||||
void CProperty_CVector3D::set( jsval value )
|
||||
{
|
||||
i32 current = toInteger();
|
||||
releaseData();
|
||||
m_type = (EPropTypes)( PROP_INTEGER | PROP_INTRINSIC | PROP_TYPELOCKED );
|
||||
m_integerptr = value;
|
||||
//*m_integerptr = current;
|
||||
}
|
||||
|
||||
void CGenericProperty::associate( float* value )
|
||||
{
|
||||
float current = toFloat();
|
||||
releaseData();
|
||||
m_type = (EPropTypes)( PROP_FLOAT | PROP_INTRINSIC | PROP_TYPELOCKED );
|
||||
m_floatptr = value;
|
||||
//*m_floatptr = current;
|
||||
}
|
||||
|
||||
void CGenericProperty::associate( CStr* value )
|
||||
{
|
||||
CStr current = toString();
|
||||
releaseData();
|
||||
m_type = (EPropTypes)( PROP_STRING | PROP_VECTOR | PROP_TYPELOCKED );
|
||||
m_string = value;
|
||||
//*m_string = current;
|
||||
}
|
||||
|
||||
void CGenericProperty::associate( CVector3D* value )
|
||||
{
|
||||
CVector3D current = toVector();
|
||||
releaseData();
|
||||
m_type = (EPropTypes)( PROP_VECTOR | PROP_INTRINSIC | PROP_TYPELOCKED );
|
||||
m_vector = value;
|
||||
//*value = current;
|
||||
}
|
||||
|
||||
void CGenericProperty::typelock( EPropTypes type )
|
||||
{
|
||||
if( m_type & PROP_INTRINSIC ) return;
|
||||
switch( type )
|
||||
JSObject* vector3d = JSVAL_TO_OBJECT( value );
|
||||
if( !JSVAL_IS_OBJECT( value ) || ( JS_GetClass( vector3d ) != &JSI_Vector3D::JSI_class ) )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
X = 0.0f; Y = 0.0f; Z = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
CVector3D* copy = ( (JSI_Vector3D::Vector3D_Info*)JS_GetPrivate( g_ScriptingHost.getContext(), vector3d ) )->vector;
|
||||
X = copy->X;
|
||||
Y = copy->Y;
|
||||
Z = copy->Z;
|
||||
}
|
||||
}
|
||||
|
||||
bool CProperty_CVector3D::rebuild( CProperty* parent, bool triggerFn )
|
||||
{
|
||||
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
|
||||
return( false ); // Vector properties aren't inheritable.
|
||||
}
|
||||
|
||||
CProperty_CVector3D::operator jsval()
|
||||
{
|
||||
JSObject* vector3d = JS_NewObject( g_ScriptingHost.getContext(), &JSI_Vector3D::JSI_class, NULL, NULL );
|
||||
JS_SetPrivate( g_ScriptingHost.getContext(), vector3d, new JSI_Vector3D::Vector3D_Info( this, m_owner, m_updateFn ) );
|
||||
return( OBJECT_TO_JSVAL( vector3d ) );
|
||||
}
|
||||
|
||||
CProperty_CBaseEntityPtr& CProperty_CBaseEntityPtr::operator =( CBaseEntity* value )
|
||||
{
|
||||
data = value;
|
||||
return( *this );
|
||||
}
|
||||
|
||||
void CProperty_CBaseEntityPtr::set( jsval value )
|
||||
{
|
||||
JSObject* baseEntity = JSVAL_TO_OBJECT( value );
|
||||
if( JSVAL_IS_OBJECT( value ) && ( JS_GetClass( baseEntity ) == &JSI_BaseEntity::JSI_class ) )
|
||||
data = (CBaseEntity*)JS_GetPrivate( g_ScriptingHost.getContext(), baseEntity );
|
||||
}
|
||||
|
||||
bool CProperty_CBaseEntityPtr::rebuild( CProperty* parent, bool triggerFn )
|
||||
{
|
||||
if( triggerFn && m_updateFn ) (m_owner->*m_updateFn)();
|
||||
return( false ); // CBaseEntity* properties aren't inheritable.
|
||||
}
|
||||
|
||||
CProperty_CBaseEntityPtr::operator jsval()
|
||||
{
|
||||
JSObject* baseEntity = JS_NewObject( g_ScriptingHost.getContext(), &JSI_BaseEntity::JSI_class, NULL, NULL );
|
||||
JS_SetPrivate( g_ScriptingHost.getContext(), baseEntity, data );
|
||||
return( OBJECT_TO_JSVAL( baseEntity ) );
|
||||
}
|
||||
|
||||
CProperty_CBaseEntityPtr::operator bool()
|
||||
{
|
||||
return( data != NULL );
|
||||
}
|
||||
|
||||
CProperty_CBaseEntityPtr::operator CBaseEntity*()
|
||||
{
|
||||
return( data );
|
||||
}
|
||||
|
||||
CBaseEntity& CProperty_CBaseEntityPtr::operator *() const
|
||||
{
|
||||
return( *data );
|
||||
}
|
||||
|
||||
CBaseEntity* CProperty_CBaseEntityPtr::operator ->() const
|
||||
{
|
||||
return( data );
|
||||
}
|
||||
|
||||
void IPropertyOwner::rebuild( CStr propertyName )
|
||||
{
|
||||
CProperty* thisProperty = m_properties[propertyName];
|
||||
CProperty* baseProperty = NULL;
|
||||
if( m_base )
|
||||
{
|
||||
if( m_base->m_properties.find( propertyName ) != m_base->m_properties.end() )
|
||||
baseProperty = m_base->m_properties[propertyName];
|
||||
}
|
||||
if( thisProperty->rebuild( baseProperty ) )
|
||||
{
|
||||
std::vector<IPropertyOwner*>::iterator it;
|
||||
for( it = m_inheritors.begin(); it != m_inheritors.end(); it++ )
|
||||
(*it)->rebuild( propertyName );
|
||||
}
|
||||
}
|
||||
|
||||
void IPropertyOwner::rebuild()
|
||||
{
|
||||
STL_HASH_MAP<CStr,CProperty*,CStr_hash_compare>::iterator property;
|
||||
if( m_base )
|
||||
{
|
||||
for( property = m_properties.begin(); property != m_properties.end(); property++ )
|
||||
{
|
||||
i32 current = toInteger();
|
||||
releaseData();
|
||||
m_integer = current;
|
||||
CProperty* baseProperty = NULL;
|
||||
if( m_base->m_properties.find( property->first ) != m_base->m_properties.end() )
|
||||
baseProperty = m_base->m_properties[property->first];
|
||||
(property->second)->rebuild( baseProperty, false );
|
||||
}
|
||||
break;
|
||||
case PROP_FLOAT:
|
||||
{
|
||||
float current = toFloat();
|
||||
releaseData();
|
||||
m_float = current;
|
||||
}
|
||||
break;
|
||||
case PROP_STRING:
|
||||
{
|
||||
CStr* current = new CStr( toString() );
|
||||
releaseData();
|
||||
m_string = current;
|
||||
}
|
||||
break;
|
||||
case PROP_VECTOR:
|
||||
{
|
||||
CVector3D* current = new CVector3D( toVector() );
|
||||
releaseData();
|
||||
m_vector = current;
|
||||
}
|
||||
break;
|
||||
case PROP_PTR:
|
||||
{
|
||||
void* current = toVoid();
|
||||
releaseData();
|
||||
m_ptr = current;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
m_type = (EPropTypes)( type | PROP_TYPELOCKED );
|
||||
}
|
||||
|
||||
void CGenericProperty::typeloose()
|
||||
{
|
||||
if( m_type & PROP_INTRINSIC ) return;
|
||||
m_type = (EPropTypes)( m_type & ~PROP_TYPELOCKED );
|
||||
}
|
||||
|
||||
i32& CGenericProperty::asInteger()
|
||||
{
|
||||
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_INTEGER );
|
||||
if( m_type & PROP_INTRINSIC )
|
||||
return( *m_integerptr );
|
||||
return( m_integer );
|
||||
}
|
||||
|
||||
float& CGenericProperty::asFloat()
|
||||
{
|
||||
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_FLOAT );
|
||||
if( m_type & PROP_INTRINSIC )
|
||||
return( *m_floatptr );
|
||||
return( m_float );
|
||||
}
|
||||
|
||||
CStr& CGenericProperty::asString()
|
||||
{
|
||||
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_STRING );
|
||||
return( *m_string );
|
||||
}
|
||||
|
||||
CVector3D& CGenericProperty::asVector()
|
||||
{
|
||||
assert( ( m_type & PROP_STRIPFLAGS ) == PROP_VECTOR );
|
||||
return( *m_vector );
|
||||
}
|
||||
|
||||
i32 CGenericProperty::toInteger()
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
else
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
return( asInteger() );
|
||||
case PROP_FLOAT:
|
||||
return( (i32)asFloat() );
|
||||
case PROP_STRING:
|
||||
case PROP_STRING_INTRINSIC:
|
||||
return( (i32)( asString().ToInt() ) );
|
||||
case PROP_VECTOR:
|
||||
case PROP_VECTOR_INTRINSIC:
|
||||
case PROP_PTR:
|
||||
return( 0 );
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
for( property = m_properties.begin(); property != m_properties.end(); property++ )
|
||||
(property->second)->rebuild( NULL, false );
|
||||
}
|
||||
return( 0 );
|
||||
|
||||
std::vector<IPropertyOwner*>::iterator it;
|
||||
for( it = m_inheritors.begin(); it != m_inheritors.end(); it++ )
|
||||
(*it)->rebuild();
|
||||
|
||||
}
|
||||
|
||||
float CGenericProperty::toFloat()
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
return( (float)asInteger() );
|
||||
case PROP_FLOAT:
|
||||
return( asFloat() );
|
||||
case PROP_STRING:
|
||||
case PROP_STRING_INTRINSIC:
|
||||
return( asString().ToFloat() );
|
||||
case PROP_VECTOR:
|
||||
case PROP_VECTOR_INTRINSIC:
|
||||
case PROP_PTR:
|
||||
return( 0.0f );
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
return( 0.0f );
|
||||
}
|
||||
|
||||
CStr CGenericProperty::toString()
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
return( CStr( asInteger() ) );
|
||||
case PROP_FLOAT:
|
||||
return( CStr( asFloat() ) );
|
||||
case PROP_STRING:
|
||||
return( CStr( asString() ) );
|
||||
case PROP_VECTOR:
|
||||
{
|
||||
char buffer[256];
|
||||
snprintf( buffer, 250, "{ %f, %f, %f }", asVector().X, asVector().Y, asVector().Z );
|
||||
return( CStr( buffer ) );
|
||||
}
|
||||
case PROP_PTR:
|
||||
return CStr();
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
return CStr();
|
||||
}
|
||||
|
||||
CVector3D CGenericProperty::toVector()
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_VECTOR:
|
||||
return( CVector3D( asVector() ) );
|
||||
case PROP_INTEGER:
|
||||
case PROP_FLOAT:
|
||||
case PROP_STRING:
|
||||
case PROP_PTR:
|
||||
return CVector3D();
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
return CVector3D();
|
||||
}
|
||||
|
||||
void* CGenericProperty::toVoid()
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_PTR:
|
||||
return( m_ptr );
|
||||
case PROP_INTEGER:
|
||||
case PROP_INTEGER_INTRINSIC:
|
||||
case PROP_FLOAT:
|
||||
case PROP_FLOAT_INTRINSIC:
|
||||
case PROP_STRING:
|
||||
case PROP_STRING_INTRINSIC:
|
||||
case PROP_VECTOR:
|
||||
case PROP_VECTOR_INTRINSIC:
|
||||
return( NULL );
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
void CGenericProperty::fromInteger( i32 value )
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
asInteger() = value; return;
|
||||
case PROP_FLOAT:
|
||||
asFloat() = (float)value; return;
|
||||
case PROP_STRING:
|
||||
asString() = value; return;
|
||||
case PROP_VECTOR:
|
||||
asVector() = CVector3D(); return;
|
||||
case PROP_PTR:
|
||||
m_ptr = NULL; return;
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
}
|
||||
|
||||
void CGenericProperty::fromFloat( float value )
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
asInteger() = (i32)value; return;
|
||||
case PROP_FLOAT:
|
||||
asFloat() = value; return;
|
||||
case PROP_STRING:
|
||||
asString() = value; return;
|
||||
case PROP_VECTOR:
|
||||
asVector() = CVector3D(); return;
|
||||
case PROP_PTR:
|
||||
m_ptr = NULL; return;
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
}
|
||||
|
||||
void CGenericProperty::fromString( CStr& value )
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
asInteger() = value.ToInt(); return;
|
||||
case PROP_FLOAT:
|
||||
asFloat() = value.ToFloat(); return;
|
||||
case PROP_STRING:
|
||||
asString() = value; return;
|
||||
case PROP_VECTOR:
|
||||
asVector() = CVector3D(); return;
|
||||
case PROP_PTR:
|
||||
m_ptr = NULL; return;
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
}
|
||||
|
||||
void CGenericProperty::fromVector( CVector3D& value )
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
asInteger() = 0; return;
|
||||
case PROP_FLOAT:
|
||||
asFloat() = 0.0f; return;
|
||||
case PROP_STRING:
|
||||
{
|
||||
char buffer[256];
|
||||
snprintf( buffer, 250, "{ %f, %f, %f }", value.X, value.Y, value.Z );
|
||||
asString() = CStr( buffer );
|
||||
}
|
||||
return;
|
||||
case PROP_VECTOR:
|
||||
asVector() = CVector3D( value ); return;
|
||||
case PROP_PTR:
|
||||
m_ptr = NULL; return;
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
}
|
||||
|
||||
void CGenericProperty::fromVoid( void* value )
|
||||
{
|
||||
switch( m_type & PROP_STRIPFLAGS )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
asInteger() = 0; return;
|
||||
case PROP_FLOAT:
|
||||
asFloat() = 0.0f; return;
|
||||
case PROP_STRING:
|
||||
asString() = CStr(); return;
|
||||
case PROP_VECTOR:
|
||||
asVector() = CVector3D(); return;
|
||||
case PROP_PTR:
|
||||
m_ptr = value; return;
|
||||
default:
|
||||
assert( 0 && "Invalid property type" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here lies the old version of CGenericProperty. Will remove it when I know the new one works.
|
||||
|
||||
CGenericProperty::CGenericProperty()
|
||||
{
|
||||
m_type = PROP_INTEGER;
|
||||
m_integer = 0;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( i32 value )
|
||||
{
|
||||
m_type = PROP_INTEGER;
|
||||
m_integer = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( float value )
|
||||
{
|
||||
m_type = PROP_FLOAT;
|
||||
m_float = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( CStr& value )
|
||||
{
|
||||
m_type = PROP_STRING;
|
||||
m_string = new CStr( value );
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( CVector3D& value )
|
||||
{
|
||||
m_type = PROP_VECTOR;
|
||||
m_vector = new CVector3D( value );
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( void* value )
|
||||
{
|
||||
m_type = PROP_PTR;
|
||||
m_ptr = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( i32* value )
|
||||
{
|
||||
m_type = PROP_INTEGER_INTRINSIC;
|
||||
m_integerptr = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( float* value )
|
||||
{
|
||||
m_type = PROP_FLOAT_INTRINSIC;
|
||||
m_floatptr = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( CStr* value )
|
||||
{
|
||||
m_type = PROP_STRING_INTRINSIC;
|
||||
m_string = value;
|
||||
}
|
||||
|
||||
CGenericProperty::CGenericProperty( CVector3D* value )
|
||||
{
|
||||
m_type = PROP_VECTOR_INTRINSIC;
|
||||
m_vector = value;
|
||||
}
|
||||
|
||||
CGenericProperty::~CGenericProperty()
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_STRING:
|
||||
delete( m_string ); break;
|
||||
case PROP_VECTOR:
|
||||
delete( m_vector ); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator CStr&()
|
||||
{
|
||||
char working[64];
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_STRING:
|
||||
case PROP_STRING_INTRINSIC:
|
||||
return( *m_string );
|
||||
case PROP_VECTOR:
|
||||
case PROP_VECTOR_INTRINSIC:
|
||||
snprintf( working, 63, "{ %f, %f, %f }", m_vector->X, m_vector->Y, m_vector->Z );
|
||||
working[63] = 0;
|
||||
return( CStr( working ) );
|
||||
case PROP_INTEGER:
|
||||
return( CStr( m_integer ) );
|
||||
case PROP_INTEGER_INTRINSIC:
|
||||
return( CStr( *m_integerptr ) );
|
||||
case PROP_FLOAT:
|
||||
return( CStr( m_float ) );
|
||||
case PROP_FLOAT_INTRINSIC:
|
||||
return( CStr( *m_floatptr ) );
|
||||
default:
|
||||
return CStr();
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator CVector3D()
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_VECTOR:
|
||||
return( *m_vector );
|
||||
default:
|
||||
return CVector3D();
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator i32()
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
return( m_integer );
|
||||
case PROP_INTEGER_INTRINSIC:
|
||||
return( *m_integerptr );
|
||||
case PROP_FLOAT:
|
||||
return( (i32)m_float );
|
||||
case PROP_FLOAT_INTRINSIC:
|
||||
return( (i32)*m_floatptr );
|
||||
case PROP_STRING:
|
||||
return( m_string->ToInt() );
|
||||
default:
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator float()
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_INTEGER:
|
||||
return( (float)m_integer );
|
||||
case PROP_INTEGER_INTRINSIC:
|
||||
return( (float)*m_integerptr );
|
||||
case PROP_FLOAT:
|
||||
return( m_float );
|
||||
case PROP_FLOAT_INTRINSIC:
|
||||
return( *m_floatptr );
|
||||
case PROP_STRING:
|
||||
return( m_string->ToFloat() );
|
||||
default:
|
||||
return( 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
CGenericProperty::operator void*()
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PROP_PTR:
|
||||
return( m_ptr );
|
||||
default:
|
||||
return( NULL );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
#include "CStr.h"
|
||||
#include "Vector3D.h"
|
||||
#include "scripting/ScriptingHost.h"
|
||||
#include "scripting/JSInterface_Entity.h"
|
||||
#include "scripting/JSInterface_Vector3D.h"
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
||||
@ -35,89 +38,126 @@
|
||||
|
||||
#endif
|
||||
|
||||
class CGenericProperty
|
||||
class IPropertyOwner;
|
||||
class CBaseEntity;
|
||||
class CProperty;
|
||||
struct SProperty_NumericModifier;
|
||||
struct SProperty_StringModifier;
|
||||
|
||||
class CProperty
|
||||
{
|
||||
protected:
|
||||
IPropertyOwner* m_owner;
|
||||
void (IPropertyOwner::*m_updateFn)();
|
||||
virtual void set( const jsval value ) = 0;
|
||||
public:
|
||||
CProperty& operator=( const jsval value );
|
||||
virtual operator jsval() = 0;
|
||||
virtual bool rebuild( CProperty* parent, bool triggerFn = true ) = 0; // Returns true if the rebuild changed the value of this property.
|
||||
void associate( IPropertyOwner* owner, const CStr& name );
|
||||
void associate( IPropertyOwner* owner, const CStr& name, void (IPropertyOwner::*updateFn)() );
|
||||
};
|
||||
|
||||
class CProperty_i32 : public CProperty
|
||||
{
|
||||
i32 data;
|
||||
SProperty_NumericModifier* modifier;
|
||||
public:
|
||||
CProperty_i32();
|
||||
~CProperty_i32();
|
||||
void set( const jsval value );
|
||||
operator jsval();
|
||||
bool rebuild( CProperty* parent, bool triggerFn = true );
|
||||
CProperty_i32& operator=( const i32 value );
|
||||
operator i32();
|
||||
};
|
||||
|
||||
class CProperty_float : public CProperty
|
||||
{
|
||||
float data;
|
||||
SProperty_NumericModifier* modifier;
|
||||
public:
|
||||
CProperty_float();
|
||||
~CProperty_float();
|
||||
void set( const jsval value );
|
||||
operator jsval();
|
||||
bool rebuild( CProperty* parent, bool triggerFn = true );
|
||||
CProperty_float& operator=( const float& value );
|
||||
operator float();
|
||||
operator bool();
|
||||
float operator+( float value );
|
||||
float operator-( float value );
|
||||
float operator*( float value );
|
||||
float operator/( float value );
|
||||
bool operator<( float value );
|
||||
bool operator>( float value );
|
||||
bool operator==( float value );
|
||||
};
|
||||
|
||||
class CProperty_CStr : public CProperty, public CStr
|
||||
{
|
||||
SProperty_StringModifier* modifier;
|
||||
public:
|
||||
CProperty_CStr();
|
||||
~CProperty_CStr();
|
||||
void set( const jsval value );
|
||||
operator jsval();
|
||||
bool rebuild( CProperty* parent, bool triggerFn = true );
|
||||
CProperty_CStr& operator=( const CStr& value );
|
||||
};
|
||||
|
||||
class CProperty_CVector3D : public CProperty, public CVector3D
|
||||
{
|
||||
public:
|
||||
enum EPropTypes
|
||||
{
|
||||
PROP_INTRINSIC = 256,
|
||||
PROP_TYPELOCKED = 512,
|
||||
PROP_STRIPFLAGS = 255,
|
||||
PROP_INTEGER = 0,
|
||||
PROP_FLOAT,
|
||||
PROP_STRING,
|
||||
PROP_VECTOR,
|
||||
PROP_PTR,
|
||||
PROP_INTEGER_INTRINSIC = PROP_INTEGER | PROP_INTRINSIC,
|
||||
PROP_FLOAT_INTRINSIC = PROP_FLOAT | PROP_INTRINSIC,
|
||||
PROP_STRING_INTRINSIC = PROP_STRING | PROP_INTRINSIC,
|
||||
PROP_VECTOR_INTRINSIC = PROP_VECTOR | PROP_INTRINSIC
|
||||
};
|
||||
EPropTypes m_type;
|
||||
private:
|
||||
union
|
||||
{
|
||||
i32 m_integer;
|
||||
i32* m_integerptr;
|
||||
float m_float;
|
||||
float* m_floatptr;
|
||||
CStr* m_string;
|
||||
CVector3D* m_vector;
|
||||
void* m_ptr;
|
||||
};
|
||||
void set( const jsval value );
|
||||
operator jsval();
|
||||
bool rebuild( CProperty* parent, bool triggerFn = true );
|
||||
CProperty_CVector3D& operator=( const CVector3D& value );
|
||||
};
|
||||
|
||||
class CProperty_CBaseEntityPtr : public CProperty
|
||||
{
|
||||
CBaseEntity* data;
|
||||
public:
|
||||
CGenericProperty(); // Create an integer property containing 0.
|
||||
~CGenericProperty();
|
||||
void releaseData();
|
||||
void set( const jsval value );
|
||||
operator jsval();
|
||||
bool rebuild( CProperty* parent, bool triggerFn = true );
|
||||
operator CBaseEntity*();
|
||||
operator bool();
|
||||
CBaseEntity& operator*() const;
|
||||
CBaseEntity* operator->() const;
|
||||
CProperty_CBaseEntityPtr& operator=( CBaseEntity* value );
|
||||
};
|
||||
|
||||
// Associator functions: Links the property with the specified engine variable.
|
||||
void associate( i32* value );
|
||||
void associate( float* value );
|
||||
void associate( CStr* value );
|
||||
void associate( CVector3D* value );
|
||||
|
||||
// Getter functions: Attempts to convert the property to the given type.
|
||||
operator i32(); // Convert to an integer if possible (integer, float, some strings), otherwise returns 0.
|
||||
operator float(); // Convert to a float if possible (integer, float, some strings), otherwise returns 0.0f.
|
||||
operator CStr(); // Convert to a string if possible (all except generic pointer), otherwise returns CStr().
|
||||
operator CVector3D(); // If this property is a vector, returns that vector, otherwise returns CVector3D().
|
||||
operator void*(); // If this property is a generic pointer, returns that pointer, otherwise returns NULL.
|
||||
// e.g. Entities and their templates.
|
||||
class IPropertyOwner
|
||||
{
|
||||
public:
|
||||
CProperty_CBaseEntityPtr m_base;
|
||||
STL_HASH_MAP<CStr,CProperty*,CStr_hash_compare> m_properties;
|
||||
std::vector<IPropertyOwner*> m_inheritors;
|
||||
void rebuild( CStr propName ); // Recursively rebuild just the named property over the inheritance tree.
|
||||
void rebuild(); // Recursively rebuild everything over the inheritance tree.
|
||||
};
|
||||
|
||||
// Setter functions: If this is a typelocked property, attempts to convert the given data
|
||||
// into the appropriate type, otherwise setting the associated value to 0, 0.0f, CStr() or CVector3D().
|
||||
// If this property is typeloose, converts this property into one of the same type
|
||||
// as the given value, then stores that value in this property.
|
||||
CGenericProperty& operator=( i32 value );
|
||||
CGenericProperty& operator=( float value );
|
||||
CGenericProperty& operator=( CStr& value );
|
||||
CGenericProperty& operator=( CVector3D& value );
|
||||
CGenericProperty& operator=( void* value ); // Be careful with this one. A lot of things will cast to void*.
|
||||
// Especially pointers you meant to associate().
|
||||
struct SProperty_NumericModifier
|
||||
{
|
||||
float multiplicative;
|
||||
float additive;
|
||||
void operator=( float value )
|
||||
{
|
||||
multiplicative = 0.0f;
|
||||
additive = value;
|
||||
}
|
||||
};
|
||||
|
||||
// Typelock functions. Use these when you want to make sure the property has the given type.
|
||||
void typelock( EPropTypes type );
|
||||
void typeloose();
|
||||
|
||||
private:
|
||||
// resolve-as functions. References the data, whereever it is.
|
||||
i32& asInteger();
|
||||
float& asFloat();
|
||||
CStr& asString();
|
||||
CVector3D& asVector();
|
||||
|
||||
// to functions. Convert whatever this is now to the chosen type.
|
||||
i32 toInteger();
|
||||
float toFloat();
|
||||
CStr toString();
|
||||
CVector3D toVector();
|
||||
void* toVoid();
|
||||
|
||||
// from functions. Convert the given value to whatever type this is now.
|
||||
void fromInteger( i32 value );
|
||||
void fromFloat( float value );
|
||||
void fromString( CStr& value );
|
||||
void fromVector( CVector3D& value );
|
||||
void fromVoid( void* value );
|
||||
struct SProperty_StringModifier
|
||||
{
|
||||
CStr replacement;
|
||||
void operator=( const CStr& value )
|
||||
{
|
||||
replacement = value;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
68
source/simulation/scripting/JSInterface_BaseEntity.cpp
Executable file
68
source/simulation/scripting/JSInterface_BaseEntity.cpp
Executable file
@ -0,0 +1,68 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "JSInterface_BaseEntity.h"
|
||||
#include "BaseEntity.h"
|
||||
#include "EntityHandles.h"
|
||||
|
||||
JSClass JSI_BaseEntity::JSI_class = {
|
||||
"EntityTemplate", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JSI_BaseEntity::getProperty, JSI_BaseEntity::setProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub, NULL,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
JSPropertySpec JSI_BaseEntity::JSI_props[] =
|
||||
{
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSFunctionSpec JSI_BaseEntity::JSI_methods[] =
|
||||
{
|
||||
{ "toString", JSI_BaseEntity::toString, 0, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSBool JSI_BaseEntity::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
|
||||
CStr propName = g_ScriptingHost.ValueToString( id );
|
||||
|
||||
if( e->m_properties.find( propName ) != e->m_properties.end() )
|
||||
{
|
||||
*vp = *(e->m_properties[propName]);
|
||||
return( JS_TRUE );
|
||||
}
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_BaseEntity::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
|
||||
CStr propName = g_ScriptingHost.ValueToString( id );
|
||||
|
||||
if( e->m_properties.find( propName ) != e->m_properties.end() )
|
||||
{
|
||||
*(e->m_properties[propName]) = *vp;
|
||||
e->rebuild( propName );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
void JSI_BaseEntity::init()
|
||||
{
|
||||
g_ScriptingHost.DefineCustomObjectType( &JSI_class, NULL, 0, JSI_props, JSI_methods, NULL, NULL );
|
||||
}
|
||||
|
||||
JSBool JSI_BaseEntity::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
CBaseEntity* e = (CBaseEntity*)JS_GetPrivate( cx, obj );
|
||||
|
||||
char buffer[256];
|
||||
snprintf( buffer, 256, "[object EntityTemplate: %s]", (const TCHAR*)e->m_name );
|
||||
buffer[255] = 0;
|
||||
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
|
||||
return( JS_TRUE );
|
||||
}
|
30
source/simulation/scripting/JSInterface_BaseEntity.h
Executable file
30
source/simulation/scripting/JSInterface_BaseEntity.h
Executable file
@ -0,0 +1,30 @@
|
||||
// JSInterface_BaseEntity.h
|
||||
//
|
||||
// Last modified: 08 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
//
|
||||
// An interface between CBaseEntity and the JavaScript class EntityTemplate
|
||||
//
|
||||
// Usage: Used when manipulating objects of class 'EntityTemplate' in JavaScript.
|
||||
//
|
||||
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
|
||||
#include "scripting/ScriptingHost.h"
|
||||
|
||||
#ifndef JSI_BASEENTITY_INCLUDED
|
||||
#define JSI_BASEENTITY_INCLUDED
|
||||
|
||||
namespace JSI_BaseEntity
|
||||
{
|
||||
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
|
||||
extern JSClass JSI_class;
|
||||
extern JSPropertySpec JSI_props[];
|
||||
extern JSFunctionSpec JSI_methods[];
|
||||
JSBool addProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool delProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
void finalize( JSContext* cx, JSObject* obj );
|
||||
void init();
|
||||
};
|
||||
|
||||
#endif
|
136
source/simulation/scripting/JSInterface_Entity.cpp
Executable file
136
source/simulation/scripting/JSInterface_Entity.cpp
Executable file
@ -0,0 +1,136 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "JSInterface_Entity.h"
|
||||
#include "scripting/JSInterface_BaseEntity.h"
|
||||
#include "scripting/JSInterface_Vector3D.h"
|
||||
#include "EntityHandles.h"
|
||||
#include "Entity.h"
|
||||
#include "EntityManager.h"
|
||||
#include "BaseEntityCollection.h"
|
||||
#include "CConsole.h"
|
||||
|
||||
JSClass JSI_Entity::JSI_class = {
|
||||
"Entity", JSCLASS_HAS_PRIVATE,
|
||||
JS_PropertyStub, JS_PropertyStub,
|
||||
JSI_Entity::getProperty, JSI_Entity::setProperty,
|
||||
JS_EnumerateStub, JS_ResolveStub,
|
||||
JS_ConvertStub, JSI_Entity::finalize,
|
||||
NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
JSPropertySpec JSI_Entity::JSI_props[] =
|
||||
{
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSFunctionSpec JSI_Entity::JSI_methods[] =
|
||||
{
|
||||
{ "toString", JSI_Entity::toString, 0, 0, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSBool JSI_Entity::getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
|
||||
if( !e )
|
||||
{
|
||||
*vp = JSVAL_NULL;
|
||||
return( JS_TRUE );
|
||||
}
|
||||
CStr propName = g_ScriptingHost.ValueToString( id );
|
||||
|
||||
if( (*e)->m_properties.find( propName ) != (*e)->m_properties.end() )
|
||||
{
|
||||
*vp = *((*e)->m_properties[propName]);
|
||||
return( JS_TRUE );
|
||||
}
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_Entity::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )
|
||||
{
|
||||
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
|
||||
CStr propName = g_ScriptingHost.ValueToString( id );
|
||||
|
||||
if( (*e)->m_properties.find( propName ) != (*e)->m_properties.end() )
|
||||
{
|
||||
*((*e)->m_properties[propName]) = *vp;
|
||||
(*e)->rebuild( propName );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
JSBool JSI_Entity::construct( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
assert( argc >= 2 );
|
||||
CBaseEntity* baseEntity;
|
||||
CVector3D position;
|
||||
float orientation = 0.0f;
|
||||
JSObject* jsBaseEntity = JSVAL_TO_OBJECT( argv[0] );
|
||||
if( JSVAL_IS_OBJECT( argv[0] ) && ( JS_GetClass( jsBaseEntity ) == &JSI_BaseEntity::JSI_class ) )
|
||||
{
|
||||
baseEntity = (CBaseEntity*)JS_GetPrivate( cx, jsBaseEntity );
|
||||
}
|
||||
else
|
||||
{
|
||||
CStr templateName;
|
||||
try
|
||||
{
|
||||
templateName = g_ScriptingHost.ValueToString( argv[0] );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
*rval = JSVAL_NULL;
|
||||
return( JS_TRUE );
|
||||
}
|
||||
baseEntity = g_EntityTemplateCollection.getTemplate( templateName );
|
||||
}
|
||||
if( !baseEntity )
|
||||
{
|
||||
*rval = JSVAL_NULL;
|
||||
return( JS_TRUE );
|
||||
}
|
||||
JSObject* jsVector3D = JSVAL_TO_OBJECT( argv[1] );
|
||||
if( JSVAL_IS_OBJECT( argv[1] ) && ( JS_GetClass( jsVector3D ) == &JSI_Vector3D::JSI_class ) )
|
||||
position = *( ( (JSI_Vector3D::Vector3D_Info*)JS_GetPrivate( cx, jsVector3D ) )->vector );
|
||||
if( argc >= 3 )
|
||||
{
|
||||
try
|
||||
{
|
||||
orientation = (float)g_ScriptingHost.ValueToDouble( argv[2] );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
orientation = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
HEntity* handle = new HEntity( g_EntityManager.create( baseEntity, position, orientation ) );
|
||||
(*handle)->dispatch( &CMessage( CMessage::EMSG_INIT ) );
|
||||
JSObject* entity = JS_NewObject( cx, &JSI_Entity::JSI_class, NULL, NULL );
|
||||
JS_SetPrivate( cx, entity, handle );
|
||||
*rval = OBJECT_TO_JSVAL( entity );
|
||||
return( JS_TRUE );
|
||||
}
|
||||
|
||||
void JSI_Entity::finalize( JSContext* cx, JSObject* obj )
|
||||
{
|
||||
delete( JS_GetPrivate( cx, obj ) );
|
||||
}
|
||||
|
||||
void JSI_Entity::init()
|
||||
{
|
||||
g_ScriptingHost.DefineCustomObjectType( &JSI_class, construct, 2, JSI_props, JSI_methods, NULL, NULL );
|
||||
}
|
||||
|
||||
JSBool JSI_Entity::toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
HEntity* e = (HEntity*)JS_GetPrivate( cx, obj );
|
||||
|
||||
char buffer[256];
|
||||
snprintf( buffer, 256, "[object Entity: \"%s\" (%s)]", (const TCHAR*)(*e)->m_name, (const TCHAR*)(*e)->m_base->m_name );
|
||||
buffer[255] = 0;
|
||||
*rval = STRING_TO_JSVAL( JS_NewStringCopyZ( cx, buffer ) );
|
||||
return( JS_TRUE );
|
||||
}
|
31
source/simulation/scripting/JSInterface_Entity.h
Executable file
31
source/simulation/scripting/JSInterface_Entity.h
Executable file
@ -0,0 +1,31 @@
|
||||
// JSInterface_Entity.h
|
||||
//
|
||||
// Last modified: 03 June 04, Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
//
|
||||
// The interface layer between JavaScript code and the actual CEntity object.
|
||||
//
|
||||
// Usage: Used when manipulating objects of class 'Entity' in JavaScript.
|
||||
//
|
||||
// Mark Thompson mot20@cam.ac.uk / mark@wildfiregames.com
|
||||
|
||||
#include "scripting/ScriptingHost.h"
|
||||
|
||||
#ifndef JSI_ENTITY_INCLUDED
|
||||
#define JSI_ENTITY_INCLUDED
|
||||
|
||||
namespace JSI_Entity
|
||||
{
|
||||
JSBool toString( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval );
|
||||
extern JSClass JSI_class;
|
||||
extern JSPropertySpec JSI_props[];
|
||||
extern JSFunctionSpec JSI_methods[];
|
||||
JSBool addProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool delProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool getProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool setProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp );
|
||||
JSBool construct( JSContext* cx, JSObject* obj, unsigned int argc, jsval* argv, jsval* rval );
|
||||
void finalize( JSContext* cx, JSObject* obj );
|
||||
void init();
|
||||
};
|
||||
|
||||
#endif
|
@ -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") },
|
||||
|
Loading…
Reference in New Issue
Block a user