Added new GPU physics demo into both trunk and branch.

This commit is contained in:
sjbaker
2006-09-27 19:18:52 +00:00
parent e48c81c55e
commit 2b286e4748
5 changed files with 220 additions and 157 deletions

View File

@@ -1,5 +1,15 @@
(Add new stuff at the top!)
Sept 27th:
==========
* Added a 'collisionMap' and pre-populated it with the handles of
four of the cubes (which are coloured RED so you can see them).
* Non-red cubes are painted in shades of blue/green.
* Every cube (including the red ones) is gravitationally attracted
to all four red cubes in inverse proportion to their ranges.
Sept 9th:
=========
* Merged in my latest changes into SVN repository.
* Arranged to avoid reading/writing textures at same time.
* Removed depth and stencil buffers from FBO's.

View File

@@ -29,27 +29,7 @@ help with our debugging problems.
without that, doing physics in the GPU is going to be
virtually impossible).
3) Run without forces being applied:
GPU_physics -f
This sets the cubes off moving at constant speed (each cube
going at a different speed and spinning).
Run without collision against the ground:
GPU_physics -c
The cubes move under gravity - but don't interact with the
notional ground plane so the eventually fall off the bottom
of the screen..
If either (3) or (4) fails but (1) and (2) worked then the
problem is probably something to do with render-to-texture.
This is the most likely scenario.
4) Run without vertex texturing:
3) Run without vertex texturing:
GPU_physics_demo -v

View File

@@ -2,18 +2,23 @@
#include "fboSupport.h"
#include "shaderSupport.h"
#define TIMESTEP 0.016f
enum DebugOptions
{
DRAW_WITHOUT_SHADERS,
DRAW_WITHOUT_PHYSICS,
DRAW_WITHOUT_COLLISIONS,
DRAW_WITHOUT_FORCES,
DRAW_ALL
} ;
inline float idToFloat ( int i, int j )
{
return float ( (i*2) & 255 ) + float ( (j*2) & 255 ) / 256.0f ;
}
static float *positionData = NULL ;
static float *rotationData = NULL ;
static float *positionData = NULL ;
static float *rotationData = NULL ;
static bool noVertexTextureSupport = false ;
static DebugOptions debugOpt = DRAW_ALL ;
@@ -63,18 +68,20 @@ float frand ( float max )
}
static GLSL_ShaderPair *velocityGenerator ;
static GLSL_ShaderPair *positionGenerator ;
static GLSL_ShaderPair *collisionGenerator ;
static GLSL_ShaderPair *cubeShader ;
static GLSL_ShaderPair *velocityGenerator ;
static GLSL_ShaderPair *positionGenerator ;
static GLSL_ShaderPair *grndCollisionGenerator ;
static GLSL_ShaderPair *forceGenerator ;
static GLSL_ShaderPair *cubeShader ;
static FrameBufferObject *position ;
static FrameBufferObject *rotation ;
static FrameBufferObject *velocity ;
static FrameBufferObject *rotvelocity ;
static FrameBufferObject *force ;
static FrameBufferObject *massXX ;
static FrameBufferObject *massSizeX ;
static FrameBufferObject *old ;
static FrameBufferObject *collisions ;
#define TEX_SIZE 128
#define NUM_CUBES ( TEX_SIZE * TEX_SIZE )
@@ -139,23 +146,16 @@ void initMotionTextures ()
velocity = NULL ;
rotvelocity = NULL ;
force = NULL ;
massXX = NULL ;
massSizeX = NULL ;
collisions = NULL ;
}
else
{
velocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
rotvelocity = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
if ( debugOpt == DRAW_WITHOUT_FORCES )
{
force = NULL ;
massXX = NULL ;
}
else
{
force = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
massXX = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
}
force = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
massSizeX = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 3, FBO_FLOAT ) ;
collisions = new FrameBufferObject ( TEX_SIZE, TEX_SIZE, 4, FBO_FLOAT ) ;
}
positionData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
@@ -164,30 +164,24 @@ void initMotionTextures ()
float *velocityData ;
float *rotvelocityData ;
float *forceData ;
float *massXXData ;
float *massSizeXData ;
float *collisionData ;
if ( debugOpt == DRAW_WITHOUT_PHYSICS )
{
velocityData = NULL ;
rotvelocityData = NULL ;
forceData = NULL ;
massXXData = NULL ;
massSizeXData = NULL ;
collisionData = NULL ;
}
else
{
velocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
rotvelocityData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
if ( debugOpt == DRAW_WITHOUT_FORCES )
{
forceData = NULL ;
massXXData= NULL ;
}
else
{
forceData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
massXXData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
}
forceData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
massSizeXData = new float [ TEX_SIZE * TEX_SIZE * 3 ] ;
collisionData = new float [ TEX_SIZE * TEX_SIZE * 4 ] ;
}
/* Give the objects some initial position, rotation, mass, force, etc */
@@ -221,21 +215,47 @@ void initMotionTextures ()
rotvelocityData [ (i*TEX_SIZE + j) * 3 + 1 ] = frand ( 3.0f ) ;
rotvelocityData [ (i*TEX_SIZE + j) * 3 + 2 ] = frand ( 3.0f ) ;
if ( debugOpt != DRAW_WITHOUT_FORCES )
{
/* Zero forces (just gravity) */
forceData [ (i*TEX_SIZE + j) * 3 + 0 ] = 0.0f ;
forceData [ (i*TEX_SIZE + j) * 3 + 1 ] = 0.0f ;
forceData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ;
/* Zero forces (just gravity) */
forceData [ (i*TEX_SIZE + j) * 3 + 0 ] = 0.0f ;
forceData [ (i*TEX_SIZE + j) * 3 + 1 ] = 0.0f ;
forceData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ;
/* One kg in weight each */
massXXData [ (i*TEX_SIZE + j) * 3 + 0 ] = 1.0f ;
massXXData [ (i*TEX_SIZE + j) * 3 + 1 ] = 0.0f ; /* Unused */
massXXData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ; /* Unused */
}
/* One kg in weight each */
massSizeXData [ (i*TEX_SIZE + j) * 3 + 0 ] = 0.0005f ; /* Mass */
massSizeXData [ (i*TEX_SIZE + j) * 3 + 1 ] = 1.0f ; /* Radius */
massSizeXData [ (i*TEX_SIZE + j) * 3 + 2 ] = 0.0f ; /* Unused */
/* Everyone collides with object 0, 1 and 2 */
/*SJB*/
collisionData [ (i*TEX_SIZE + j) * 3 + 0 ] = idToFloat ( 20, 20 ) ;
collisionData [ (i*TEX_SIZE + j) * 3 + 1 ] = idToFloat ( 20, 100 ) ;
collisionData [ (i*TEX_SIZE + j) * 3 + 2 ] = idToFloat ( 100, 20 ) ;
collisionData [ (i*TEX_SIZE + j) * 3 + 3 ] = idToFloat ( 100, 100 ) ;
}
}
if ( debugOpt != DRAW_WITHOUT_PHYSICS )
{
/*
Object zero is the 'null' object for collision detection
so put it far away and stop it from moving around.
*/
positionData [ 0 ] = 10.0f ;
positionData [ 1 ] = 10.0f ;
positionData [ 2 ] = 10.0f ;
velocityData [ 0 ] = 0.0f ;
velocityData [ 1 ] = 0.0f ;
velocityData [ 2 ] = 0.0f ;
massSizeXData [ 0 ] = 10000000.0f ; /* Mass */
massSizeXData [ 1 ] = 0.00000001f ; /* Radius */
massSizeXData [ 2 ] = 0.0f ; /* Unused */
collisionData [ 0 ] = 128.5 ; /* Not collide with self! */
collisionData [ 1 ] = 128.5 ;
collisionData [ 2 ] = 128.5 ;
collisionData [ 3 ] = 128.5 ;
}
/* Initialise the textures */
position -> fillTexture ( positionData ) ;
@@ -246,12 +266,9 @@ void initMotionTextures ()
{
velocity -> fillTexture ( velocityData ) ;
rotvelocity -> fillTexture ( rotvelocityData ) ;
if ( debugOpt != DRAW_WITHOUT_FORCES )
{
force -> fillTexture ( forceData ) ;
massXX -> fillTexture ( massXXData ) ;
}
force -> fillTexture ( forceData ) ;
massSizeX -> fillTexture ( massSizeXData ) ;
collisions -> fillTexture ( collisionData ) ;
}
}
@@ -262,35 +279,28 @@ void initPhysicsShaders ()
debugOpt == DRAW_WITHOUT_PHYSICS )
return ;
if ( debugOpt == DRAW_WITHOUT_FORCES )
{
velocityGenerator = NULL ;
}
else
{
/*
The velocity generator shader calculates:
/*
The velocity generator shader calculates:
velocity = old_velocity + delta_T * ( F / m ) ;
*/
velocity = old_velocity + delta_T * ( F / m ) ;
*/
velocityGenerator = new GLSL_ShaderPair (
"VelocityGenerator",
NULL, NULL,
"uniform vec4 g_dt ;"
"uniform sampler2D old_velocity ;"
"uniform sampler2D force ;"
"uniform sampler2D massXX ;"
"void main() {"
" gl_FragColor = vec4 ("
" texture2D ( old_velocity, gl_TexCoord[0].st ).xyz +"
" g_dt.w * ( g_dt.xyz +"
" texture2D ( force , gl_TexCoord[0].st ).xyz /"
" texture2D ( massXX , gl_TexCoord[0].st ).x),"
" 1.0 ) ; }",
"VelocityGenerator Frag Shader" ) ;
velocityGenerator = new GLSL_ShaderPair (
"VelocityGenerator",
NULL, NULL,
"uniform vec4 g_dt ;"
"uniform sampler2D old_velocity ;"
"uniform sampler2D force ;"
"uniform sampler2D massSizeX ;"
"void main() {"
" gl_FragColor = vec4 ("
" texture2D ( old_velocity, gl_TexCoord[0].st ).xyz +"
" g_dt.w * ( g_dt.xyz +"
" texture2D ( force , gl_TexCoord[0].st ).xyz /"
" texture2D ( massSizeX , gl_TexCoord[0].st ).x),"
" 1.0 ) ; }",
"VelocityGenerator Frag Shader" ) ;
assert ( velocityGenerator -> compiledOK () ) ;
}
/*
The position generater shader calculates:
@@ -315,25 +325,56 @@ void initPhysicsShaders ()
"PositionGenerator Frag Shader" ) ;
assert ( positionGenerator -> compiledOK () ) ;
if ( debugOpt == DRAW_WITHOUT_COLLISIONS )
{
collisionGenerator = NULL ;
}
else
{
collisionGenerator = new GLSL_ShaderPair (
"CollisionGenerator",
NULL, NULL,
"uniform sampler2D position ;"
"uniform sampler2D old_velocity ;"
"void main() {"
" vec3 pos = texture2D ( position , gl_TexCoord[0].st ).xyz ;"
" vec3 vel = texture2D ( old_velocity, gl_TexCoord[0].st ).xyz ;"
" if ( pos [ 1 ] < 0.0 ) vel *= vec3(0.90,-0.90,0.90) ;"
" gl_FragColor = vec4 ( vel, 1.0 ) ; }",
"CollisionGenerator Frag Shader" ) ;
assert ( collisionGenerator -> compiledOK () ) ;
}
forceGenerator = new GLSL_ShaderPair (
"ForceGenerator",
NULL, NULL,
"uniform sampler2D position ;"
"uniform sampler2D collisions ;"
"void main() {"
" vec3 pos = texture2D ( position , gl_TexCoord[0].st ).xyz ;"
" vec4 coll = texture2D ( collisions, gl_TexCoord[0].st ).xyzw ;"
" vec2 ctc ;"
" vec3 rel ;"
" float lrel ;"
" vec3 force = vec3 ( 0.0, 0.0, 0.0 ) ;"
/* First 'collision' */
" ctc = vec2 ( coll.x / 256.0, coll.x ) ;"
" rel = pos - texture2D ( position, ctc ).xyz ;"
" lrel = max ( length ( rel ), 0.001 ) ;"
" force += (rel/lrel) * -1.0 / (lrel) ;"
/* Second 'collision' */
" ctc = vec2 ( coll.y / 256.0, coll.y ) ;"
" rel = pos - texture2D ( position, ctc ).xyz ;"
" lrel = max ( length ( rel ), 0.001 ) ;"
" force += (rel/lrel) * -1.0 / (lrel) ;"
/* Third 'collision' */
" ctc = vec2 ( coll.z / 256.0, coll.z ) ;"
" rel = pos - texture2D ( position, ctc ).xyz ;"
" lrel = max ( length ( rel ), 0.001 ) ;"
" force += (rel/lrel) * -1.0 / (lrel) ;"
/* Fourth 'collision' */
" ctc = vec2 ( coll.w / 256.0, coll.w ) ;"
" rel = pos - texture2D ( position, ctc ).xyz ;"
" lrel = max ( length ( rel ), 0.001 ) ;"
" force += (rel/lrel) * -1.0 / (lrel) ;"
/* Write out results */
" gl_FragColor = vec4 ( force, 1.0 ) ;"
"}",
"ForceCollisionGenerator Frag Shader" ) ;
assert ( forceGenerator -> compiledOK () ) ;
grndCollisionGenerator = new GLSL_ShaderPair (
"GroundCollisionGenerator",
NULL, NULL,
"uniform sampler2D position ;"
"uniform sampler2D old_velocity ;"
"void main() {"
" vec3 pos = texture2D ( position , gl_TexCoord[0].st ).xyz ;"
" vec3 vel = texture2D ( old_velocity, gl_TexCoord[0].st ).xyz ;"
" if ( pos [ 1 ] < 0.0 ) vel *= vec3(0.90,-0.90,0.90) ;"
" gl_FragColor = vec4 ( vel, 1.0 ) ; }",
"GroundCollisionGenerator Frag Shader" ) ;
assert ( grndCollisionGenerator -> compiledOK () ) ;
}
@@ -366,10 +407,20 @@ void initCubeVBO ()
*t++ = ((float)i+0.5f)/(float)TEX_SIZE ;
*t++ = ((float)j+0.5f)/(float)TEX_SIZE ;
*c++ = frand ( 1.0f ) ;
*c++ = frand ( 1.0f ) ;
*c++ = frand ( 1.0f ) ;
*c++ = 1.0f ;
if ( (i==20||i==100) && (j==20||j==100) )
{
*c++ = 1.0f ;
*c++ = 0.0f ;
*c++ = 0.0f ;
*c++ = 1.0f ;
}
else
{
*c++ = 0.0f ;
*c++ = frand ( 1.0f ) ;
*c++ = frand ( 1.0f ) ;
*c++ = 1.0f ;
}
}
float dx, dy, dz ;
@@ -571,20 +622,22 @@ void display ( void )
{
/* Do some simple physics calculations in four stages */
if ( debugOpt != DRAW_WITHOUT_FORCES )
{
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
forceGenerator -> use () ;
forceGenerator -> applyTexture ( "position" , position , 0 ) ;
forceGenerator -> applyTexture ( "collisions", collisions, 1 ) ;
force -> paint () ;
velocityGenerator -> use () ;
velocityGenerator -> applyTexture ( "old_velocity", old , 0 ) ;
velocityGenerator -> applyTexture ( "force" , force , 1 ) ;
velocityGenerator -> applyTexture ( "massXX" , massXX , 2 ) ;
velocityGenerator -> setUniform4f ( "g_dt", 0.0f, -9.8f, 0.0f, 0.016f ) ;
velocity -> paint () ;
}
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
velocityGenerator -> use () ;
velocityGenerator -> applyTexture ( "old_velocity", old , 0 ) ;
velocityGenerator -> applyTexture ( "force" , force , 1 ) ;
velocityGenerator -> applyTexture ( "massSizeX" , massSizeX, 2 ) ;
velocityGenerator -> setUniform4f ( "g_dt", 0.0f, -9.8f, 0.0f, TIMESTEP ) ;
velocity -> paint () ;
/* Copy old position into old. */
tmp = old ;
@@ -594,21 +647,18 @@ void display ( void )
positionGenerator -> use () ;
positionGenerator -> applyTexture ( "old_position", old , 0 ) ;
positionGenerator -> applyTexture ( "velocity" , velocity, 1 ) ;
positionGenerator -> setUniform1f ( "delta_T", 0.016f ) ;
positionGenerator -> setUniform1f ( "delta_T", TIMESTEP ) ;
position -> paint () ;
if ( debugOpt != DRAW_WITHOUT_COLLISIONS )
{
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
/* Copy old velocity into old. */
tmp = old ;
old = velocity ;
velocity = tmp ;
collisionGenerator -> use () ;
collisionGenerator -> applyTexture ( "position" , position, 0 ) ;
collisionGenerator -> applyTexture ( "old_velocity", old , 1 ) ;
velocity -> paint () ;
}
grndCollisionGenerator -> use () ;
grndCollisionGenerator -> applyTexture ( "position" , position, 0 ) ;
grndCollisionGenerator -> applyTexture ( "old_velocity", old , 1 ) ;
velocity -> paint () ;
/* Copy old rotation into old. */
tmp = old ;
@@ -618,7 +668,7 @@ void display ( void )
positionGenerator -> use () ;
positionGenerator -> applyTexture ( "old_position", old , 0 ) ;
positionGenerator -> applyTexture ( "velocity" , rotvelocity, 1 ) ;
positionGenerator -> setUniform1f ( "delta_T", 0.016f ) ;
positionGenerator -> setUniform1f ( "delta_T", TIMESTEP ) ;
rotation -> paint () ;
/* Now render the scene using the results */
@@ -644,8 +694,6 @@ void help ()
fprintf ( stderr, "Where:\n" ) ;
fprintf ( stderr, " -s -- Draw with shaders at all\n" ) ;
fprintf ( stderr, " -p -- Draw with shaders but no physics\n" ) ;
fprintf ( stderr, " -c -- Draw with physics but no ground collisions\n" ) ;
fprintf ( stderr, " -f -- Draw with physics but no forces\n" ) ;
fprintf ( stderr, " -a -- Draw with all features enabled [default]\n" ) ;
fprintf ( stderr, " -v -- Disable vertex textures even if "
"they are supported in hardware\n" ) ;
@@ -666,8 +714,6 @@ int main ( int argc, char **argv )
{
case 's' : debugOpt = DRAW_WITHOUT_SHADERS ; break ;
case 'p' : debugOpt = DRAW_WITHOUT_PHYSICS ; break ;
case 'c' : debugOpt = DRAW_WITHOUT_COLLISIONS ; break ;
case 'f' : debugOpt = DRAW_WITHOUT_FORCES ; break ;
case 'a' : debugOpt = DRAW_ALL ; break ;
case 'v' : disableVertexTextureSupport = true ; break ;

View File

@@ -174,8 +174,8 @@ FrameBufferObject::FrameBufferObject ( int _width ,
glBindTexture ( GL_TEXTURE_2D, textureHandle ) ;
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ) ;
glTexParameterf ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ) ;
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 ) ;
fillTexture ( (void *) NULL ) ;
glGenFramebuffersEXT ( 1, & fboHandle ) ;
@@ -260,6 +260,19 @@ void FrameBufferObject::fetchTexture ( unsigned char *data )
void FrameBufferObject::fetchTexture ( unsigned short *data )
{
if ( type != FBO_UNSIGNED_SHORT )
{
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
return ;
}
fetchTexture ( (void *)data ) ;
}
void FrameBufferObject::fetchTexture ( float *data )
{
if ( type != FBO_FLOAT )
@@ -298,6 +311,18 @@ void FrameBufferObject::fillTexture ( unsigned char *data )
fillTexture ( (void *)data ) ;
}
void FrameBufferObject::fillTexture ( unsigned short *data )
{
if ( type != FBO_UNSIGNED_SHORT )
{
fprintf ( stderr, "FBO: Data format mismatch!" ) ;
return ;
}
fillTexture ( (void *)data ) ;
}
void FrameBufferObject::fillTexture ( float *data )
{
if ( type != FBO_FLOAT )

View File

@@ -75,11 +75,13 @@ public:
void paint () ;
void fillTexture ( float *data ) ;
void fillTexture ( unsigned char *data ) ;
void fillTexture ( float *data ) ;
void fillTexture ( unsigned short *data ) ;
void fillTexture ( unsigned char *data ) ;
void fetchTexture ( float *data ) ;
void fetchTexture ( unsigned char *data ) ;
void fetchTexture ( float *data ) ;
void fetchTexture ( unsigned short *data ) ;
void fetchTexture ( unsigned char *data ) ;
} ;