Initial commit
This commit is contained in:
336
Torque/SDK/engine/dgl/gVectorField.cc
Normal file
336
Torque/SDK/engine/dgl/gVectorField.cc
Normal file
@@ -0,0 +1,336 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Vector Field Rendering Object
|
||||
//------------------------------------------------------------------------------
|
||||
#include "dgl/gVectorField.h"
|
||||
#include "core/fileStream.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "math/mRect.h"
|
||||
#include "core/color.h"
|
||||
#include "core/frameAllocator.h"
|
||||
#include "util/safeDelete.h"
|
||||
|
||||
#define NUM_VERTS mFieldResolution.x * mFieldResolution.y
|
||||
#define NUM_IDXS mFieldResolution.x * 2
|
||||
#define NUM_STRIPS mFieldResolution.y - 1
|
||||
|
||||
#define INDEX(x, y) (x + y * mFieldResolution.x)
|
||||
#define VERT(x, y) mFieldVerts[INDEX(x,y)]
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
VectorField::VectorField()
|
||||
{
|
||||
nullField();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
VectorField::VectorField( const Point2I &resolution, F32 maxX /* = 1.f */,
|
||||
F32 maxY /* = 1.f */, TextureCoordFlip flip /* = Flip_None */,
|
||||
VectorFieldInitFn initFn /* = NULL */ )
|
||||
{
|
||||
nullField();
|
||||
|
||||
allocVectorField( resolution );
|
||||
initVectorField( maxX, maxY, flip, initFn );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
VectorField::VectorField( const char *fileName )
|
||||
{
|
||||
nullField();
|
||||
|
||||
loadField( fileName );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
VectorField::~VectorField()
|
||||
{
|
||||
destroyVectorField();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void VectorField::destroyVectorField()
|
||||
{
|
||||
SAFE_DELETE_ARRAY( mVectorField );
|
||||
SAFE_DELETE_ARRAY( mFieldIndices );
|
||||
SAFE_DELETE_ARRAY( mFieldVerts );
|
||||
|
||||
#ifdef ENABLE_FIELD_VISUALIZE
|
||||
SAFE_DELETE_ARRAY( mUnflippedVecField );
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void VectorField::allocVectorField( const Point2I &resolution )
|
||||
{
|
||||
destroyVectorField();
|
||||
mFieldResolution = resolution;
|
||||
mVectorField = new Point2F[NUM_VERTS];
|
||||
|
||||
// Create index buffer
|
||||
mFieldIndices = new U16[NUM_IDXS];
|
||||
|
||||
bool up = false;
|
||||
U32 x = 0, y = 0;
|
||||
|
||||
// It would be way more efficent if we did one index buffer with degenerate
|
||||
// polys but you know what, I hate writing that stuff, and after 3 hours on a
|
||||
// friday night, I'm going with the easy way.
|
||||
for( int i = 0; i < NUM_IDXS; i++ )
|
||||
{
|
||||
mFieldIndices[i] = INDEX(x, y);
|
||||
|
||||
if( up )
|
||||
{
|
||||
x++;
|
||||
y--;
|
||||
}
|
||||
else
|
||||
y++;
|
||||
|
||||
up = !up;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FIELD_VISUALIZE
|
||||
mUnflippedVecField = new Point2F[NUM_VERTS];
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void FN_CDECL defaultInitFn( const int x, const int y, const Point2I &resolution,
|
||||
const F32 maxX, const F32 maxY, Point2F *outVec )
|
||||
{
|
||||
outVec->x = ( (F32)x / ( (F32)resolution.x - 1.f ) ) * maxX;
|
||||
outVec->y = ( (F32)y / ( (F32)resolution.y - 1.f ) ) * maxY;
|
||||
}
|
||||
|
||||
void VectorField::initVectorField( F32 maxX /* = 1.f */, F32 maxY /* = 1.f */, TextureCoordFlip flip /* = Flip_None */, VectorFieldInitFn initFn /* = NULL */ )
|
||||
{
|
||||
mMax.x = maxX;
|
||||
mMax.y = maxY;
|
||||
|
||||
// Create the vertex buffer to render the field
|
||||
mFieldVerts = new Point2F[NUM_VERTS];
|
||||
|
||||
// Initialize all this stuff at once since we are working in the same space
|
||||
for( int x = 0; x < mFieldResolution.x; x++ )
|
||||
{
|
||||
for( int y = 0; y < mFieldResolution.y; y++ )
|
||||
{
|
||||
// Vertices
|
||||
defaultInitFn( x, y, mFieldResolution, maxX, maxY, &VERT(x, y) );
|
||||
|
||||
// Initialize the texture coordinates to their normal values
|
||||
defaultInitFn( x, y, mFieldResolution, maxX, maxY, &getVector( x, y ) );
|
||||
|
||||
// If provided, pass the normal values on to a custom function
|
||||
if( initFn != NULL )
|
||||
(*initFn)( x, y, mFieldResolution, maxX, maxY, &getVector( x, y ) );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FIELD_VISUALIZE
|
||||
dMemcpy( mUnflippedVecField, mVectorField, sizeof(Point2F) * NUM_VERTS );
|
||||
#endif
|
||||
|
||||
// Flip?
|
||||
if( flip != Flip_None )
|
||||
{
|
||||
FrameAllocatorMarker marker; // Ben = teh win
|
||||
|
||||
// Make this easy, create a copy of the coord array
|
||||
Point2F *fieldCopy = (Point2F *)marker.alloc( sizeof(Point2F) * NUM_VERTS );
|
||||
dMemcpy( fieldCopy, mVectorField, sizeof(Point2F) * NUM_VERTS );
|
||||
|
||||
for( int i = 0; i < NUM_VERTS; i++ )
|
||||
{
|
||||
if( flip & Flip_X )
|
||||
mVectorField[i].x = fieldCopy[NUM_VERTS - i - 1].x;
|
||||
|
||||
if( flip & Flip_Y )
|
||||
mVectorField[i].y = fieldCopy[NUM_VERTS - i - 1].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define WRITEPOINT2X( p, s ) s->write( p.x ); s->write( p.y );
|
||||
#define READPOINT2X( p, s ) s->read( &p.x ); s->read( &p.y );
|
||||
|
||||
void VectorField::serialize( Stream *stream ) const
|
||||
{
|
||||
WRITEPOINT2X( mFieldResolution, stream );
|
||||
|
||||
for( int x = 0; x < mFieldResolution.x; x++ )
|
||||
{
|
||||
for( int y = 0; y < mFieldResolution.y; y++ )
|
||||
{
|
||||
WRITEPOINT2X( getVector( x, y ), stream );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void VectorField::unserialize( Stream *stream )
|
||||
{
|
||||
READPOINT2X( mFieldResolution, stream );
|
||||
|
||||
allocVectorField( mFieldResolution );
|
||||
|
||||
for( int x = 0; x < mFieldResolution.x; x++ )
|
||||
{
|
||||
for( int y = 0; y < mFieldResolution.y; y++ )
|
||||
{
|
||||
READPOINT2X( getVector( x, y ), stream );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool VectorField::loadField( const char *fileName )
|
||||
{
|
||||
FileStream fs;
|
||||
|
||||
if( !fs.open( fileName, FileStream::Read ) )
|
||||
return false;
|
||||
|
||||
unserialize( &fs );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool VectorField::saveField( const char *fileName ) const
|
||||
{
|
||||
FileStream fs;
|
||||
|
||||
if( !fs.open( fileName, FileStream::Write ) )
|
||||
return false;
|
||||
|
||||
serialize( &fs );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void VectorField::renderField( bool texture /* = false */ ) const
|
||||
{
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D( 0.0, mMax.x, 0.0, mMax.y );
|
||||
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
if( texture )
|
||||
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glColor4f( 1.f, 1.f, 1.f, 1.f );
|
||||
for( int i = 0; i < NUM_STRIPS; i++ )
|
||||
{
|
||||
glTexCoordPointer( 2, GL_FLOAT, 0, &mVectorField[i * mFieldResolution.x] );
|
||||
glVertexPointer( 2, GL_FLOAT, 0, &mFieldVerts[i * mFieldResolution.x] );
|
||||
|
||||
glDrawElements( GL_QUAD_STRIP, NUM_IDXS, GL_UNSIGNED_SHORT, mFieldIndices );
|
||||
}
|
||||
|
||||
if( texture )
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPopMatrix();
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FIELD_VISUALIZE
|
||||
|
||||
void VectorField::visualizeField( F32 alpha /* = 1.0f */ ) const
|
||||
{
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D( 0.0, mMax.x, 0.0, mMax.y );
|
||||
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable( GL_TEXTURE_2D );
|
||||
glEnable( GL_BLEND );
|
||||
|
||||
// Draw the field in wireframe, apparently it's a back facing poly...whatever
|
||||
GLint mode[2];
|
||||
glGetIntegerv( GL_POLYGON_MODE, mode );
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glColor4f( 1.f, 1.f, 1.f, alpha );
|
||||
|
||||
for( int i = 0; i < NUM_STRIPS; i++ )
|
||||
{
|
||||
glVertexPointer( 2, GL_FLOAT, 0, &mFieldVerts[i * mFieldResolution.x] );
|
||||
glDrawElements( GL_QUAD_STRIP, NUM_IDXS, GL_UNSIGNED_SHORT, mFieldIndices );
|
||||
}
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glPolygonMode( GL_FRONT, mode[0] );
|
||||
glPolygonMode( GL_BACK, mode[1] );
|
||||
|
||||
// Draw the vectors
|
||||
glBegin( GL_LINES );
|
||||
glColor4f( 0.f, 1.f, 0.f, 1.f );
|
||||
for( int i = 0; i < NUM_VERTS; i++ )
|
||||
{
|
||||
// Base point
|
||||
glVertex2fv( (F32 *)&mFieldVerts[i] );
|
||||
glVertex2fv( (F32 *)&mUnflippedVecField[i]);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw the verts
|
||||
glPointSize( 3.f );
|
||||
glEnable( GL_POINT_SMOOTH );
|
||||
|
||||
glBegin( GL_POINTS );
|
||||
glColor4f( 1.f, 0.f, 0.f, alpha );
|
||||
for( int i = 0; i < NUM_VERTS; i++ )
|
||||
glVertex2fv( (F32 *)&mFieldVerts[i] );
|
||||
glEnd();
|
||||
|
||||
glDisable( GL_POINT_SMOOTH );
|
||||
glPointSize( 1.f );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glPopMatrix();
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user