add ImplicitCloth demo, by Stan Melax

add SimpleOpenGL3App, used in ImplicitCloth demo. The Bullet 3.x demos should use this as a template, it will clean up some of the mess.
This commit is contained in:
erwincoumans
2013-11-09 12:12:33 -08:00
parent a6bc61ad1a
commit 8f3051fdf1
35 changed files with 3297 additions and 2035 deletions

View File

@@ -65,7 +65,7 @@ B3_ATTRIBUTE_ALIGNED16(struct) b3SimParams
m_gravity.setValue(0,-.3,0.f);
m_particleRad = 0.01f;
m_globalDamping = 1.0f;
m_boundaryDamping = -1.f;
m_boundaryDamping = -0.99f;
m_collisionDamping = 0.025f;//0.02f;
m_spring = 0.5f;
m_shear = 0.1f;
@@ -187,7 +187,7 @@ void ParticleDemo::setupScene(const ConstructionInfo& ci)
cl_int pErrNum;
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clData->m_clContext,m_clData->m_clDevice,particleKernelsString,0,"",INTEROPKERNEL_SRC_PATH);
cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_clData->m_clContext,m_clData->m_clDevice,particleKernelsString,0,"",INTEROPKERNEL_SRC_PATH,true);
m_data->m_updatePositionsKernel = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice,particleKernelsString, "updatePositionsKernel" ,&pErrNum,prog);
oclCHECKERROR(pErrNum, CL_SUCCESS);
m_data->m_updatePositionsKernel2 = b3OpenCLUtils::compileCLKernelFromString(m_clData->m_clContext, m_clData->m_clDevice,particleKernelsString, "integrateMotionKernel" ,&pErrNum,prog);
@@ -415,7 +415,7 @@ void ParticleDemo::clientMoveAndDisplay()
cl_mem pairsGPU = 0;
{
m_data->m_broadphaseGPU->calculateOverlappingPairs(64*numParticles);
//m_data->m_broadphaseGPU->calculateOverlappingPairs(64*numParticles);
pairsGPU = m_data->m_broadphaseGPU->getOverlappingPairBuffer();
numPairsGPU = m_data->m_broadphaseGPU->getNumOverlap();
}

View File

@@ -78,7 +78,7 @@ __kernel void integrateMotionKernel( int numParticles,
if(pos.y < (worldMin.y + 2*particleRad))
{
pos.y = worldMin.y + 2*particleRad;
vel.y *= -1.f;//1000*boundaryDamping;
vel.y *= boundaryDamping;
}
/*
if(pos.y > (worldMax.y - 2*particleRad))

View File

@@ -84,12 +84,13 @@ enum
};
b3AlignedObjectArray<const char*> demoNames;
int selectedDemo = 0;
int selectedDemo = 1;
GpuDemo::CreateFunc* allDemos[]=
{
//ConcaveCompound2Scene::MyCreateFunc,
//ConcaveSphereScene::MyCreateFunc,
@@ -100,6 +101,7 @@ GpuDemo::CreateFunc* allDemos[]=
ConcaveScene::MyCreateFunc,
GpuBoxPlaneScene::MyCreateFunc,
GpuConstraintsDemo::MyCreateFunc,
//GpuConvexPlaneScene::MyCreateFunc,

View File

@@ -0,0 +1,83 @@
#include "stan/vecmath.h"
#include "stan/Cloth.h"
#include "Bullet3Common/b3Vector3.h"
#include "../../btgui/OpenGLWindow/SimpleOpenGL3App.h"
Cloth* cloth = 0;
int numX = 60, numY=60;
const size_t total_points = (numX)*(numY);
void drawCloth(class GLInstancingRenderer* renderer)
{
GLint err = glGetError();
assert(err==GL_NO_ERROR);
err = glGetError();
assert(err==GL_NO_ERROR);
b3AlignedObjectArray<unsigned int> indices;
for (int i=0;i<cloth->springs.count;i++)
{
indices.push_back(cloth->springs[i].a);
indices.push_back(cloth->springs[i].b);
}
float lineColor[4]={0.4,0.4,1.0,1};
renderer->drawLines(&cloth->X[0].x,lineColor,total_points,sizeof(float3),&indices[0],indices.size(),1);
err = glGetError();
assert(err==GL_NO_ERROR);
float pointColor[4]={1,0.4,0.4,1};
renderer->drawPoints(&cloth->X[0].x,pointColor,total_points,sizeof(float3),6);
err = glGetError();
assert(err==GL_NO_ERROR);
}
int main(int argc, char* argv[])
{
float size=10;
cloth = ClothCreate(numX,numY,size);
float dt = 1./120.f;
SimpleOpenGL3App* app = new SimpleOpenGL3App("title",1024,768);
app->m_instancingRenderer->setCameraDistance(13);
app->m_instancingRenderer->setCameraPitch(0);
app->m_instancingRenderer->setCameraTargetPosition(b3MakeVector3(0,0,0));
GLint err = glGetError();
assert(err==GL_NO_ERROR);
do
{
GLint err = glGetError();
assert(err==GL_NO_ERROR);
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
app->drawGrid();
app->drawText("Cloth simulation using implicit integration, by Stan Melax",10,10);
cloth->Simulate(dt);
cloth->cloth_gravity.y = -9.8;//-9.8;//-9.8;//-9.8;//0;//-9.8;//0;//-9.8;//0;//-9.8;
cloth->cloth_gravity.z =-9.8;//0;//-9.8;//0;//-9.8;
cloth->spring_struct=10000000.0f;
cloth->spring_shear=10000000.0f;
//cloth->spring_struct=1000000.0f;
//cloth->spring_shear=1000000.0f;
cloth->spring_damp = 0;//100;
drawCloth(app->m_instancingRenderer);
app->swapBuffer();
} while (!app->m_window->requestedExit());
delete cloth;
delete app;
return 0;
}

View File

@@ -0,0 +1,70 @@
project "App_ImplicitCloth"
language "C++"
kind "ConsoleApp"
targetdir "../../bin"
includedirs {
".",
"../../btgui"
}
initOpenGL()
initGlew()
--links{"gwen"}
files {
"**.cpp",
"**.h",
"../../btgui/OpenGLWindow/SimpleOpenGL3App.cpp",
"../../btgui/OpenGLWindow/SimpleOpenGL3App.h",
"../../btgui/OpenGLWindow/TwFonts.cpp",
"../../btgui/OpenGLWindow/TwFonts.h",
"../../btgui/OpenGLWindow/LoadShader.cpp",
"../../btgui/OpenGLWindow/LoadShader.h",
"../../btgui/OpenGLWindow/GLPrimitiveRenderer.cpp",
"../../btgui/OpenGLWindow/GLPrimitiveRenderer.h",
"../../btgui/OpenGLWindow/GwenOpenGL3CoreRenderer.h",
"../../btgui/OpenGLWindow/GLInstancingRenderer.cpp",
"../../btgui/OpenGLWindow/GLInstancingRenderer.h",
"../../btgui/OpenGLWindow/GLRenderToTexture.cpp",
"../../btgui/OpenGLWindow/GLRenderToTexture.h",
"../../btgui/OpenGLWindow/TwFonts.cpp",
"../../btgui/OpenGLWindow/TwFonts.h",
"../../btgui/FontFiles/OpenSans.cpp",
"../../btgui/OpenGLTrueTypeFont/fontstash.cpp",
"../../btgui/OpenGLTrueTypeFont/fontstash.h",
"../../btgui/OpenGLTrueTypeFont/opengl_fontstashcallbacks.cpp",
"../../btgui/OpenGLTrueTypeFont/opengl_fontstashcallbacks.h",
"../../btgui/Bullet3Common/**.cpp",
"../../btgui/Bullet3Common/**.h",
"../../btgui/Timing/b3Clock.cpp",
"../../btgui/Timing/b3Clock.h"
}
if os.is("Windows") then
files {
"../../btgui/OpenGLWindow/Win32OpenGLWindow.cpp",
"../../btgui/OpenGLWindow/Win32OpenGLWindow.h",
"../../btgui/OpenGLWindow/Win32Window.cpp",
"../../btgui/OpenGLWindow/Win32Window.h",
}
end
if os.is("Linux") then
links ("X11")
files{
"../../btgui/OpenGLWindow/X11OpenGLWindow.h",
"../../btgui/OpenGLWindow/X11OpenGLWindow.cpp"
}
end
if os.is("MacOSX") then
links{"Cocoa.framework"}
files{
"../../btgui/OpenGLWindow/MacOpenGLWindow.mm",
"../../btgui/OpenGLWindow/MacOpenGLWindow.h",
}
end

View File

@@ -0,0 +1,96 @@
//-----------------------------------------------------------------------------------------------
//
// The remainder of this file shows how to use the spring network class with backward integration
// in order to implement a cloth system within a 3D game environment.
// The cloth class extends the springnetwork class in order to provide
// import/export, rendering support, and hooks into the game.
//
#include "Cloth.h"
Array<Cloth*> cloths;
Cloth::Cloth(const char *_name,int _n):SpringNetwork(_n),
color(0,0.5f,1.0f)
{
cloths.Add(this);
}
Cloth::~Cloth()
{
cloths.Remove(this);
}
//
// I/O support for serialization of our springnetwork and cloth objects.
//
int cloth_showbbox = 0; // for debug visualization shows bounding box.
float cloth_showvert = 0.025f; // size of box to put around current vert selected, 0 turns off
Cloth *ClothCreate(int w,int h,float size)
{
// simple cloth generation routine that creates a typical square cloth.
// better to use a real pipeline to generate these, this is just for testing.
int i,j;
Cloth *cloth = new Cloth("cloth",w*h);
cloth->w=w;
cloth->h=h; // later for rendering.
for(i=0;i<h;i++)
for(j=0;j<w;j++)
{
cloth->X[i*w+j] = (float3(-0.5f,-0.5f,0)+float3((float)j/(w-1.0f),1.0f-(float)i/(h-1.0f),0)) * size;
}
for(i=0;i<h;i++)
for(j=0;j<w;j++)
{
if(i<h-1) cloth->CreateSpring(SPRING_STRUCT,i*w+j,(i+1)*w+j); // structural
if(j<w-1) cloth->CreateSpring(SPRING_STRUCT,i*w+j,i*w+(j+1)); // structural
if(j<w-1&&i<h-1) cloth->CreateSpring(SPRING_SHEAR ,i*w+j,(i+1)*w+(j+1)); // shear
if(j>0 &&i<h-1) cloth->CreateSpring(SPRING_SHEAR ,i*w+j,(i+1)*w+(j-1)); // shear
if(i<h-2) cloth->CreateSpring(SPRING_BEND ,i*w+j,(i+2)*w+j); // benders
if(j<w-2) cloth->CreateSpring(SPRING_BEND ,i*w+j,i*w+(j+2)); // benders
}
cloth->UpdateLimits();
return cloth;
}
int cloth_tess = 20;
float3 cloth_spawnpoint(0,3,5.0f);
static void ClothDrawSprings(Cloth *cloth)
{
static const float3 color[3]={float3(1,1,0),float3(1,0,1),float3(0,1,1)};
float3N &X = cloth->X;
for(int i=0;i<cloth->springs.count;i++)
{
SpringNetwork::Spring &s = cloth->springs[i];
extern void Line(const float3 &,const float3 &,const float3 &color_rgb);
Line(X[s.a],X[s.b],color[s.type]);
}
}
int cloth_showsprings=0;
void DoCloths()
{
int i;
for(i=0;i<cloths.count;i++)
{
Cloth *cloth=cloths[i];
// cloth->Simulate((cloth->cloth_step<0)?DeltaT:cloth->cloth_step);
//if(cloth_showsprings)
// ClothDrawSprings(cloth); // debug visualization
}
}

View File

@@ -0,0 +1,18 @@
#ifndef STAN_CLOTH_H
#define STAN_CLOTH_H
#include "SpringNetwork.h"
class Cloth : public SpringNetwork
{
public:
int w,h;
float3 color; // for debug rendering
Cloth(const char* _name,int _n);
~Cloth();
};
Cloth *ClothCreate(int w,int h,float size);
#endif //STAN_CLOTH_H

View File

@@ -0,0 +1,198 @@
#include "vec3n.h"
//#include "console.h"
extern int numX;
//
// Cloth - Backward Integrated Spring Network
//
// (c) Stan Melax 2006
// http://www.melax.com/cloth
// freeware demo and source
// Although its free software, I'll gaurantee and support this software as much as is reasonable.
// However, if you choose to use any of this code, then you agree that
// I assume no financial liability should the software not meet your expectations.
// But do feel free to send any feedback.
//
// The core backward integration functionality has all been extracted into the SpringNetwork class.
// This makes it easy for you if you just want to look at or use the math and the algorithms.
// The remainder of the code builds a cloth system with basic render support, I/O, and manipulators,
// so its possible to make use of the technology within a 3D application.
// This code is separated from the SpringNetwork class in order to avoid pushing a particular style
// and prevent any dependancies of the algorithms onto unrelated systems.
// Feel free to adapt any of this into your own 3D engine/environment.
//
// Instead of having unique Hooke force and damping coefficients on each spring, the SpringNetwork
// code uses a spring 'type' that indexes a short list of shared named coefficients.
// This was just more practical for the typical application of this technology.
// Over-designed systems that are too general can be slower for
// the next guy to understand and more painful to use.
// Editing/creation is easier when only 1 number needs to be changed.
// Nonetheless, feel free to adapt to your own needs.
//
#include <stdio.h>
#include <float.h>
#include "vec3n.h"
//#include "console.h"
//#include "manipulatori.h"
//#include "object.h"
//#include "xmlparse.h"
static const float3x3 I(1,0,0,0,1,0,0,0,1);
inline float3x3 dfdx_spring(const float3 &dir,float length,float rest,float k)
{
// dir is unit length direction, rest is spring's restlength, k is spring constant.
return ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k;
}
inline float3x3 dfdx_damp(const float3 &dir,float length,const float3& vel,float rest,float damping)
{
// inner spring damping vel is the relative velocity of the endpoints.
return (I-outerprod(dir,dir)) * (-damping * -(dot(dir,vel)/Max(length,rest)));
}
inline float3x3 dfdv_damp(const float3 &dir,float damping)
{
// derivative of force wrt velocity.
return outerprod(dir,dir) * damping;
}
#include "SpringNetwork.h"
SpringNetwork::SpringNetwork(int _n):X(_n),V(_n),F(_n),dV(_n),A(_n),dFdX(_n),dFdV(_n)
{
assert(SPRING_STRUCT==0);
assert(&spring_shear == &spring_struct +SPRING_SHEAR);
assert(&spring_bend == &spring_struct +SPRING_BEND);
assert(&spring_struct== &spring_k[SPRING_STRUCT]);
assert(&spring_shear == &spring_k[SPRING_SHEAR ]);
assert(&spring_bend == &spring_k[SPRING_BEND ]);
// spring_struct=1000000.0f;
// spring_shear=1000000.0f;
spring_struct=1000.0f;
spring_shear=100.0f;
spring_bend=25.0f;
spring_damp=5.0f;
spring_air=1.0f;
spring_air=1.0f;
cloth_step = 0.25f; // delta time for cloth
cloth_gravity=float3(0,-10,0);
cloth_sleepthreshold = 0.001f;
cloth_sleepcount = 100;
awake = cloth_sleepcount;
//fix/pin two points in worldspace
float3Nx3N::Block zero;
zero.m = float3x3(0,0,0,0,0,0,0,0,0);
zero.c = 0;
zero.r = 0;
S.blocks.Add(zero);
zero.r = numX-1;
S.blocks.Add(zero);
}
SpringNetwork::Spring &SpringNetwork::AddBlocks(Spring &s)
{
// Called during initial creation of springs in our spring network.
// Sets up the sparse matrices corresponding to connections.
// Note the indices (s.iab,s.iba) are also stored with spring to avoid looking them up each time a spring is applied
// All 3 matrices A,dFdX, and dFdV are contstructed identically so the block array layout will be the same for each.
s.iab = A.blocks.count; // added 'ab' blocks will have this index.
A.blocks.Add(float3Nx3N::Block(s.a,s.b));
dFdX.blocks.Add(float3Nx3N::Block(s.a,s.b));
dFdV.blocks.Add(float3Nx3N::Block(s.a,s.b));
s.iba = A.blocks.count; // added 'ba' blocks will have this index.
A.blocks.Add(float3Nx3N::Block(s.b,s.a));
dFdX.blocks.Add(float3Nx3N::Block(s.b,s.a));
dFdV.blocks.Add(float3Nx3N::Block(s.b,s.a));
return s;
}
void SpringNetwork::PreSolveSpring(const SpringNetwork::Spring &s)
{
// Adds this spring's contribution into force vector F and force derivitves dFdX and dFdV
// One optimization would be premultiply dfdx by dt*dt and F and dFdV by dt right here in this function.
// However, for educational purposes we wont do that now and intead just follow the paper directly.
//assert(dFdX.blocks[s.a].c==s.a); // delete this assert, no bugs here
//assert(dFdX.blocks[s.a].r==s.a);
float3 extent = X[s.b] - X[s.a];
float length = magnitude(extent);
float3 dir = (length==0)?float3(0,0,0): extent * 1.0f/length;
float3 vel = V[s.b] - V[s.a];
float k = spring_k[s.type];
float3 f = dir * ((k * (length-s.restlen) ) + spring_damp * dot(vel,dir)); // spring force + damping force
F[s.a] += f;
F[s.b] -= f;
float3x3 dfdx = dfdx_spring(dir,length,s.restlen,k) + dfdx_damp(dir,length,vel,s.restlen,spring_damp);
dFdX.blocks[s.a].m -= dfdx; // diagonal chunk dFdX[a,a]
dFdX.blocks[s.b].m -= dfdx; // diagonal chunk dFdX[b,b]
dFdX.blocks[s.iab].m += dfdx; // off-diag chunk dFdX[a,b]
dFdX.blocks[s.iba].m += dfdx; // off-diag chunk dFdX[b,a]
float3x3 dfdv = dfdv_damp(dir,spring_damp);
dFdV.blocks[s.a].m -= dfdv; // diagonal chunk dFdV[a,a]
dFdV.blocks[s.b].m -= dfdv; // diagonal chunk dFdV[b,b]
dFdV.blocks[s.iab].m += dfdv; // off-diag chunk dFdV[a,b]
dFdV.blocks[s.iba].m += dfdv; // off-diag chunk dFdV[b,a]
}
void SpringNetwork::CalcForces()
{
// Collect forces and derivatives: F,dFdX,dFdV
dFdX.Zero();
dFdV.InitDiagonal(-spring_air);
F.Init(cloth_gravity);
F.element[0]=float3(0,0,0);
F.element[numX-1]=float3(0,0,0);
F -= V * spring_air;
for(int i=0;i<springs.count;i++)
{
PreSolveSpring(springs[i]); // will add to F,dFdX,dFdV
}
}
void SpringNetwork::Simulate(float dt)
{
// Get ready for conjugate gradient iterative solver step.
// Initialize operands.
if(!awake) return;
CalcForces();
int n=X.count; // all our big vectors are of this size
float3N dFdXmV(n); // temp to store result of matrix multiply
float3N B(n);
dV.Zero();
A.Identity(); // build up the big matrix we feed to solver
A -= dFdV * dt + dFdX * (dt*dt) ;
dFdXmV = dFdX * V;
B = F * dt + dFdXmV * (dt*dt);
ConjGradientFiltered(dV,A,B,S);
V = V + dV;
// V.element[0] = float3(0,0,0);
// V.element[numX-1] = float3(0,0,0);
X = X + V*dt;
UpdateLimits();
awake = (dot(V,V)<cloth_sleepthreshold)?awake-1:awake=cloth_sleepcount;
}

View File

@@ -0,0 +1,63 @@
#ifndef STAN_SPRING_NETWORK_H
#define STAN_SPRING_NETWORK_H
#include "vec3n.h"
#define SPRING_STRUCT (0)
#define SPRING_SHEAR (1)
#define SPRING_BEND (2)
class SpringNetwork
{
public:
class Spring
{
public:
int type; // index into coefficients spring_k[]
float restlen;
int a,b; // spring endpoints vector indices
int iab,iba; // indices into off-diagonal blocks of sparse matrix
Spring(){}
Spring(int _type,int _a,int _b,float _restlen):type(_type),a(_a),b(_b),restlen(_restlen){iab=iba=-1;}
};
Array<Spring> springs;
float3N X; // positions of all points
float3N V; // velocities
float3N F; // force on each point
float3N dV; // change in velocity
float3Nx3N A; // big matrix we solve system with
float3Nx3N dFdX; // big matrix of derivative of force wrt position
float3Nx3N dFdV; // big matrix of derivative of force wrt velocity
float3Nx3N S; // used for our constraints - contains only some diagonal blocks as needed S[i,i]
int awake;
float3 bmin,bmax;
union
{
struct
{
float spring_struct;
float spring_shear;
float spring_bend;
};
float spring_k[3];
};
float spring_damp;
float spring_air;
float cloth_step; // delta time for cloth
float3 cloth_gravity;
float cloth_sleepthreshold;
int cloth_sleepcount;
SpringNetwork(int _n);
Spring &AddBlocks(Spring &s);
Spring &CreateSpring(int type,int a,int b,float restlen){return AddBlocks(springs.Add(Spring(type,a,b,restlen)));}
Spring &CreateSpring(int type,int a,int b){return CreateSpring(type,a,b,magnitude(X[b]-X[a]));}
void UpdateLimits() { BoxLimits(X.element,X.count,bmin,bmax);}
void Wake(){awake=cloth_sleepcount;}
void Simulate(float dt);
void PreSolveSpring(const Spring &s);
void CalcForces();
};
#endif //STAN_SPRING_NETWORK_H

View File

@@ -0,0 +1,284 @@
//
// Typical template dynamic array container class.
// By S Melax 1998
//
// anyone is free to use, inspect, learn from, or ignore
// the code here as they see fit.
//
// A very simple template array class.
// Its easiest to understand this array
// class by seeing how it is used in code.
//
// For example:
// for(i=0;i<myarray.count;i++)
// myarray[i] = somefunction(i);
//
// When the array runs out of room, it
// reallocates memory and doubles the size of its
// storage buffer. The reason for *doubleing* the amount of
// memory is so the order of any algorithm using this class
// is the same as it would be had you used a regular C array.
// The penalty for reallocating and copying
// For example consider adding n elements to a list.
// Lets sum the number of times elements are "copied".
// The worst case occurs when n=2^k+1 where k is integer.
// In this case we do a big reallocation when we add the last element.
// n elements are copied once, n/2 elements are copied twice,
// n/4 elements are copied 3 times, and so on ...
// total == n* (1+1/2 + 1/4 + 1/8 + ...) == n * 2
// So we do n*2 copies. Therefore adding n
// elements to an Array is still O(n).
// The memory usage is also of the same order as if a C array was used.
// An Array uses less than double the minimum needed space. Again, we
// see that we are within a small constant multiple.
//
// Why no "realloc" to avoid the copy when reallocating memory?
// You have a choice to either use malloc/free and friends
// or to use new/delete. Its bad mojo to mix these. new/delete was
// chosen to be C++ish and have the array elements constructors/destructors
// invoked as expected.
//
//
#ifndef SM_ARRAY_H
#define SM_ARRAY_H
#include <assert.h>
#include <stdio.h>
template <class Type> class Array {
public:
Array(int s=0);
Array(Array<Type> &array);
~Array();
void allocate(int s);
void SetSize(int s);
void Pack();
Type& Add(Type);
void AddUnique(Type);
int Contains(Type);
void Insert(Type,int);
int IndexOf(Type);
void Remove(Type);
void DelIndex(int i);
Type& DelIndexWithLast(int i);
Type * element;
int count;
int array_size;
const Type &operator[](int i) const { assert(i>=0 && i<count); return element[i]; }
Type &operator[](int i) { assert(i>=0 && i<count); return element[i]; }
Type &Pop() { assert(count); count--; return element[count]; }
Array<Type> &copy(const Array<Type> &array);
Array<Type> &operator=(Array<Type> &array);
};
template <class Type> Array<Type>::Array(int s)
{
if(s==-1) return;
count=0;
array_size = 0;
element = NULL;
if(s)
{
allocate(s);
}
}
template <class Type> Array<Type>::Array(Array<Type> &array)
{
count=0;
array_size = 0;
element = NULL;
*this = array;
}
template <class Type> Array<Type> &Array<Type>::copy(const Array<Type> &array)
{
assert(array.array_size>=0);
count=0;
for(int i=0;i<array.count;i++)
{
Add(array[i]);
}
return *this;
}
template <class Type> Array<Type> &Array<Type>::operator=( Array<Type> &array)
{
if(array.array_size<0) // negative number means steal the data buffer instead of copying
{
delete[] element;
element = array.element;
array_size = -array.array_size;
count = array.count;
array.count =array.array_size = 0;
array.element = NULL;
return *this;
}
count=0;
for(int i=0;i<array.count;i++)
{
Add(array[i]);
}
return *this;
}
template <class Type> Array<Type>::~Array()
{
if (element != NULL && array_size!=0)
{
delete[] element;
}
count=0;array_size=0;element=NULL;
}
template <class Type> void Array<Type>::allocate(int s)
{
assert(s>0);
assert(s>=count);
if(s==array_size) return;
Type *old = element;
array_size =s;
element = new Type[array_size];
assert(element);
for(int i=0;i<count;i++)
{
element[i]=old[i];
}
if(old) delete[] old;
}
template <class Type> void Array<Type>::SetSize(int s)
{
if(s==0)
{
if(element)
{
delete[] element;
element = NULL;
}
array_size = s;
}
else
{
allocate(s);
}
count=s;
}
template <class Type> void Array<Type>::Pack()
{
allocate(count);
}
template <class Type> Type& Array<Type>::Add(Type t)
{
assert(count<=array_size);
if(count==array_size)
{
allocate((array_size)?array_size *2:16);
}
//int i;
//for(i=0;i<count;i++) {
// dissallow duplicates
// assert(element[i] != t);
//}
element[count++] = t;
return element[count-1];
}
template <class Type> int Array<Type>::Contains(Type t)
{
int i;
int found=0;
for(i=0;i<count;i++)
{
if(element[i] == t) found++;
}
return found;
}
template <class Type> void Array<Type>::AddUnique(Type t)
{
if(!Contains(t)) Add(t);
}
template <class Type> void Array<Type>::DelIndex(int i)
{
assert(i<count);
count--;
while(i<count)
{
element[i] = element[i+1];
i++;
}
}
template <class Type> Type& Array<Type>::DelIndexWithLast(int i)
{
assert(i<count);
count--;
if(i<count)
{
Type r=element[i];
element[i] = element[count];
element[count]=r;
}
return element[count];
}
template <class Type> void Array<Type>::Remove(Type t)
{
int i;
for(i=0;i<count;i++)
{
if(element[i] == t)
{
break;
}
}
assert(i<count); // assert object t is in the array.
DelIndex(i);
for(i=0;i<count;i++)
{
assert(element[i] != t);
}
}
template <class Type> void Array<Type>::Insert(Type t,int k)
{
int i=count;
Add(t); // to allocate space
while(i>k)
{
element[i]=element[i-1];
i--;
}
assert(i==k);
element[k]=t;
}
template <class Type> int Array<Type>::IndexOf(Type t)
{
int i;
for(i=0;i<count;i++)
{
if(element[i] == t)
{
return i;
}
}
assert(0);
return -1;
}
#endif

View File

@@ -0,0 +1,152 @@
//
// Big Vector and Sparse Matrix Classes
//
#include <float.h>
#include "vec3n.h"
float conjgrad_lasterror;
float conjgrad_epsilon = 0.1f;
int conjgrad_loopcount;
int conjgrad_looplimit = 100;
/*EXPORTVAR(conjgrad_lasterror);
EXPORTVAR(conjgrad_epsilon );
EXPORTVAR(conjgrad_loopcount);
EXPORTVAR(conjgrad_looplimit);
*/
int ConjGradient(float3N &X, float3Nx3N &A, float3N &B)
{
// Solves for unknown X in equation AX=B
conjgrad_loopcount=0;
int n=B.count;
float3N q(n),d(n),tmp(n),r(n);
r = B - Mul(tmp,A,X); // just use B if X known to be zero
d = r;
float s = dot(r,r);
float starget = s * squared(conjgrad_epsilon);
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
{
Mul(q,A,d); // q = A*d;
float a = s/dot(d,q);
X = X + d*a;
if(conjgrad_loopcount%50==0)
{
r = B - Mul(tmp,A,X);
}
else
{
r = r - q*a;
}
float s_prev = s;
s = dot(r,r);
d = r+d*(s/s_prev);
}
conjgrad_lasterror = s;
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
}
int ConjGradientMod(float3N &X, float3Nx3N &A, float3N &B,int3 hack)
{
// obsolete!!!
// Solves for unknown X in equation AX=B
conjgrad_loopcount=0;
int n=B.count;
float3N q(n),d(n),tmp(n),r(n);
r = B - Mul(tmp,A,X); // just use B if X known to be zero
r[hack[0]] = r[hack[1]] = r[hack[2]] = float3(0,0,0);
d = r;
float s = dot(r,r);
float starget = s * squared(conjgrad_epsilon);
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
{
Mul(q,A,d); // q = A*d;
q[hack[0]] = q[hack[1]] = q[hack[2]] = float3(0,0,0);
float a = s/dot(d,q);
X = X + d*a;
if(conjgrad_loopcount%50==0)
{
r = B - Mul(tmp,A,X);
r[hack[0]] = r[hack[1]] = r[hack[2]] = float3(0,0,0);
}
else
{
r = r - q*a;
}
float s_prev = s;
s = dot(r,r);
d = r+d*(s/s_prev);
d[hack[0]] = d[hack[1]] = d[hack[2]] = float3(0,0,0);
}
conjgrad_lasterror = s;
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
}
static inline void filter(float3N &V,const float3Nx3N &S)
{
for(int i=0;i<S.blocks.count;i++)
{
V[S.blocks[i].r] = V[S.blocks[i].r]*S.blocks[i].m;
}
}
int ConjGradientFiltered(float3N &X, const float3Nx3N &A, const float3N &B,const float3Nx3N &S)
{
// Solves for unknown X in equation AX=B
conjgrad_loopcount=0;
int n=B.count;
float3N q(n),d(n),tmp(n),r(n);
r = B - Mul(tmp,A,X); // just use B if X known to be zero
filter(r,S);
d = r;
float s = dot(r,r);
float starget = s * squared(conjgrad_epsilon);
while( s>starget && conjgrad_loopcount++ < conjgrad_looplimit)
{
Mul(q,A,d); // q = A*d;
filter(q,S);
float a = s/dot(d,q);
X = X + d*a;
if(conjgrad_loopcount%50==0)
{
r = B - Mul(tmp,A,X);
filter(r,S);
}
else
{
r = r - q*a;
}
float s_prev = s;
s = dot(r,r);
d = r+d*(s/s_prev);
filter(d,S);
}
conjgrad_lasterror = s;
return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable
}
// test big vector math library:
static void testfloat3N()
{
float3N a(2),b(2),c(2);
a[0] = float3(1,2,3);
a[1] = float3(4,5,6);
b[0] = float3(10,20,30);
b[1] = float3(40,50,60);
// c = a+b+b * 10.0f;
// float d = dot(a+b,-b);
int k;
k=0;
}
class dotest{public:dotest(){testfloat3N();}}do_test_at_program_startup;

View File

@@ -0,0 +1,340 @@
//
// Big Vector and Sparse Matrix Classes
//
// (c) S Melax 2006
//
// The focus is on 3D applications, so
// the big vector is an array of float3s
// and the matrix class uses 3x3 blocks.
//
// This file includes both:
// - basic non-optimized version
// - an expression optimized version
//
// Optimized Expressions
//
// We want to write sweet looking code such as V=As+Bt with big vectors.
// However, we dont want the extra overheads with allocating memory for temps and excessing copying.
// Instead of a full Template Metaprogramming approach, we explicitly write
// classes to specifically handle all the expressions we are likely to use.
// Most applicable lines of code will be of the same handful of basic forms,
// but with different parameters for the operands.
// In the future, if we ever need a longer expression with more operands,
// then we will just add whatever additional building blocks that are necessary - not a big deal.
// This approach is much simpler to develop, debug and optimize (restrict keyword, simd etc)
// than template metaprogramming is. We do not rely on the implementation
// of a particular compiler to be able to expand extensive nested inline codes.
// Additionally, we reliably get our optimizations even within a debug build.
// Therefore we believe that our Optimized Expressions
// are a good compromise that give us the best of both worlds.
// The code within those important algorithms, which use this library,
// can now remain clean and readable yet still execute quickly.
//
#ifndef SM_VEC3N_H
#define SM_VEC3N_H
#include "vecmath.h"
#include "array.h"
//#include <malloc.h>
//template <class T> void * vec4<T>::operator new[](size_t n){ return _mm_malloc(n,64); }
//template <class T> void vec4<T>::operator delete[](void *a) { _mm_free(a); }
struct HalfConstraint {
float3 n;int vi;
float s,t;
HalfConstraint(const float3& _n,int _vi,float _t):n(_n),vi(_vi),s(0),t(_t){}
HalfConstraint():vi(-1){}
};
class float3Nx3N
{
public:
class Block
{
public:
float3x3 m;
int r,c;
float unused[16];
Block(){}
Block(short _r,short _c):r(_r),c(_c){m.x=m.y=m.z=float3(0,0,0);}
};
Array<Block> blocks; // the first n blocks use as the diagonal.
int n;
void Zero();
void InitDiagonal(float d);
void Identity(){InitDiagonal(1.0f);}
float3Nx3N():n(0){}
float3Nx3N(int _n):n(_n) {for(int i=0;i<n;i++) blocks.Add(Block((short)i,(short)i));}
template<class E> float3Nx3N &operator= (const E& expression) {expression.evalequals(*this);return *this;}
template<class E> float3Nx3N &operator+=(const E& expression) {expression.evalpluseq(*this);return *this;}
template<class E> float3Nx3N &operator-=(const E& expression) {expression.evalmnuseq(*this);return *this;}
};
class float3N: public Array<float3>
{
public:
float3N(int _count=0)
{
SetSize(_count);
}
void Zero();
void Init(const float3 &v); // sets each subvector to v
template<class E> float3N &operator= (const E& expression) {expression.evalequals(*this);return *this;}
template<class E> float3N &operator+=(const E& expression) {expression.evalpluseq(*this);return *this;}
template<class E> float3N &operator-=(const E& expression) {expression.evalmnuseq(*this);return *this;}
float3N &operator=( const float3N &V) { this->copy(V); return *this;}
};
int ConjGradient(float3N &X, float3Nx3N &A, float3N &B);
int ConjGradientFiltered(float3N &X, const float3Nx3N &A, const float3N &B,const float3Nx3N &S,Array<HalfConstraint> &H);
int ConjGradientFiltered(float3N &X, const float3Nx3N &A, const float3N &B,const float3Nx3N &S);
inline float3N& Mul(float3N &r,const float3Nx3N &m, const float3N &v)
{
int i;
for(i=0;i<r.count;i++) r[i]=float3(0,0,0);
for(i=0;i<m.blocks.count;i++)
{
r[m.blocks[i].r] += m.blocks[i].m * v[m.blocks[i].c];
}
return r;
}
inline float dot(const float3N &a,const float3N &b)
{
float d=0;
for(int i=0;i<a.count;i++)
{
d+= dot(a[i],b[i]);
}
return d;
}
inline void float3Nx3N::Zero()
{
for(int i=0;i<blocks.count;i++)
{
blocks[i].m = float3x3(0,0,0,0,0,0,0,0,0);
}
}
inline void float3Nx3N::InitDiagonal(float d)
{
for(int i=0;i<blocks.count;i++)
{
blocks[i].m = (blocks[i].c==blocks[i].r) ? float3x3(d,0,0,0,d,0,0,0,d) : float3x3(0,0,0,0,0,0,0,0,0);
}
}
inline void float3N::Zero()
{
for(int i=0;i<count;i++)
{
element[i] = float3(0,0,0);
}
}
inline void float3N::Init(const float3 &v)
{
for(int i=0;i<count;i++)
{
element[i] = v;
}
}
#ifdef WE_LIKE_SLOW_CODE
// Unoptimized Slow Basic Version of big vector operators.
// Uses typical implmentation for operators +/-*=
// These operators cause lots of unnecessary construction, memory allocation, and copying.
inline float3N operator +(const float3N &a,const float3N &b)
{
float3N r(a.count);
for(int i=0;i<a.count;i++) r[i]=a[i]+b[i];
return r;
}
inline float3N operator *(const float3N &a,const float &s)
{
float3N r(a.count);
for(int i=0;i<a.count;i++) r[i]=a[i]*s;
return r;
}
inline float3N operator /(const float3N &a,const float &s)
{
float3N r(a.count);
return Mul(r,a, 1.0f/s );
}
inline float3N operator -(const float3N &a,const float3N &b)
{
float3N r(a.count);
for(int i=0;i<a.count;i++) r[i]=a[i]-b[i];
return r;
}
inline float3N operator -(const float3N &a)
{
float3N r(a.count);
for(int i=0;i<a.count;i++) r[i]=-a[i];
return r;
}
inline float3N operator *(const float3Nx3N &m,const float3N &v)
{
float3N r(v.count);
return Mul(r,m,v);
}
inline float3N &operator-=(float3N &A, const float3N &B)
{
assert(A.count==B.count);
for(int i=0;i<A.count;i++) A[i] -= B[i];
return A;
}
inline float3N &operator+=(float3N &A, const float3N &B)
{
assert(A.count==B.count);
for(int i=0;i<A.count;i++) A[i] += B[i];
return A;
}
#else
// Optimized Expressions
class exVneg
{
public:
const float3N &v;
exVneg(const float3N &_v): v(_v){}
void evalequals(float3N &r)const { for(int i=0;i<v.count;i++) r[i] =-v[i];}
void evalpluseq(float3N &r)const { for(int i=0;i<v.count;i++) r[i]+=-v[i];}
void evalmnuseq(float3N &r)const { for(int i=0;i<v.count;i++) r[i]-=-v[i];}
};
class exVaddV
{
public:
const float3N &a;
const float3N &b;
exVaddV(const float3N &_a,const float3N &_b): a(_a),b(_b){}
void evalequals(float3N &r)const { for(int i=0;i<a.count;i++) r[i] =a[i]+b[i];}
void evalpluseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]+=a[i]+b[i];}
void evalmnuseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]-=a[i]+b[i];}
};
class exVsubV
{
public:
const float3N &a;
const float3N &b;
exVsubV(const float3N &_a,const float3N &_b): a(_a),b(_b){}
void evalequals(float3N &r)const { for(int i=0;i<a.count;i++) r[i] =a[i]-b[i];}
void evalpluseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]+=a[i]-b[i];}
void evalmnuseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]-=a[i]-b[i];}
};
class exVs
{
public:
const float3N &v;
const float s;
exVs(const float3N &_v,const float &_s): v(_v),s(_s){}
void evalequals(float3N &r)const { for(int i=0;i<v.count;i++) r[i] =v[i]*s;}
void evalpluseq(float3N &r)const { for(int i=0;i<v.count;i++) r[i]+=v[i]*s;}
void evalmnuseq(float3N &r)const { for(int i=0;i<v.count;i++) r[i]-=v[i]*s;}
};
class exAsaddB
{
public:
const float3N &a;
const float3N &b;
const float s;
exAsaddB(const float3N &_a,const float &_s,const float3N &_b): a(_a),s(_s),b(_b){}
void evalequals(float3N &r)const { for(int i=0;i<a.count;i++) r[i] =a[i]*s+b[i];}
void evalpluseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]+=a[i]*s+b[i];}
void evalmnuseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]-=a[i]*s+b[i];}
};
class exAsaddBt
{
public:
const float3N &a;
const float3N &b;
const float s;
const float t;
exAsaddBt(const float3N &_a,const float &_s,const float3N &_b,const float &_t): a(_a),s(_s),b(_b),t(_t){}
void evalequals(float3N &r)const { for(int i=0;i<a.count;i++) r[i] =a[i]*s+b[i]*t;}
void evalpluseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]+=a[i]*s+b[i]*t;}
void evalmnuseq(float3N &r)const { for(int i=0;i<a.count;i++) r[i]-=a[i]*s+b[i]*t;}
};
class exMv
{
public:
const float3Nx3N &m;
const float3N &v;
exMv(const float3Nx3N &_m,const float3N &_v): m(_m),v(_v){}
void evalequals(float3N &r)const { Mul(r,m,v);}
};
class exMs
{
public:
const float3Nx3N &m;
const float s;
exMs(const float3Nx3N &_m,const float &_s): m(_m),s(_s){}
void evalequals(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m = m.blocks[i].m*s;}
void evalpluseq(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m += m.blocks[i].m*s;}
void evalmnuseq(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m -= m.blocks[i].m*s;}
};
class exMAsMBt
{
public:
const float3Nx3N &a;
const float s;
const float3Nx3N &b;
const float t;
exMAsMBt(const float3Nx3N &_a,const float &_s,const float3Nx3N &_b,const float &_t): a(_a),s(_s),b(_b),t(_t){}
void evalequals(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m = a.blocks[i].m*s + b.blocks[i].m*t;}
void evalpluseq(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m += a.blocks[i].m*s + b.blocks[i].m*t;}
void evalmnuseq(float3Nx3N &r)const { for(int i=0;i<r.blocks.count;i++) r.blocks[i].m -= a.blocks[i].m*s + b.blocks[i].m*t;}
};
inline exVaddV operator +(const float3N &a,const float3N &b) {return exVaddV(a,b);}
inline exVsubV operator +(const exVneg &E,const float3N &b) {return exVsubV(b,E.v);}
inline exVsubV operator -(const float3N &a,const float3N &b) {return exVsubV(a,b);}
inline exVs operator *(const float3N &V,const float &s) {return exVs(V,s); }
inline exVs operator *(const exVs &E,const float &s) {return exVs(E.v,E.s*s); }
inline exAsaddB operator +(const exVs &E,const float3N &b) {return exAsaddB(E.v, E.s,b);}
inline exAsaddB operator +(const float3N &b,const exVs &E) {return exAsaddB(E.v, E.s,b);}
inline exAsaddB operator -(const float3N &b,const exVs &E) {return exAsaddB(E.v,-E.s,b);}
inline exAsaddBt operator +(const exVs &Ea,const exVs &Eb) {return exAsaddBt(Ea.v,Ea.s,Eb.v, Eb.s);}
inline exAsaddBt operator -(const exVs &Ea,const exVs &Eb) {return exAsaddBt(Ea.v,Ea.s,Eb.v,-Eb.s);}
inline exMv operator *(const float3Nx3N &m,const float3N &v) {return exMv(m,v); }
inline exMs operator *(const exMs &E,const float &s) {return exMs(E.m,E.s*s); }
inline exMs operator *(const float3Nx3N &m,const float &s) {return exMs(m,s); }
inline exMAsMBt operator +(const exMs &Ea,const exMs &Eb) {return exMAsMBt(Ea.m,Ea.s, Eb.m,Eb.s);}
inline exMAsMBt operator -(const exMs &Ea,const exMs &Eb) {return exMAsMBt(Ea.m,Ea.s, Eb.m,-Eb.s);}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,466 @@
//
//
// Typical 3d vector math code.
// By S Melax 1998-2008
//
//
#ifndef SM_VEC_MATH_H
#define SM_VEC_MATH_H
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <xmmintrin.h>
#define M_PIf (3.1415926535897932384626433832795f)
inline float DegToRad(float angle_degrees) { return angle_degrees * M_PIf / 180.0f; } // returns Radians.
inline float RadToDeg(float angle_radians) { return angle_radians * 180.0f / M_PIf; } // returns Degrees.
#define OFFSET(Class,Member) (((char*) (&(((Class*)NULL)-> Member )))- ((char*)NULL))
int argmin(const float a[],int n);
int argmax(const float a[],int n);
float squared(float a);
float clamp(float a,const float minval=0.0f, const float maxval=1.0f);
int clamp(int a,const int minval,const int maxval) ;
float Round(float a,float precision);
float Interpolate(const float &f0,const float &f1,float alpha) ;
template <class T>
void Swap(T &a,T &b)
{
T tmp = a;
a=b;
b=tmp;
}
template <class T>
T Max(const T &a,const T &b)
{
return (a>b)?a:b;
}
template <class T>
T Min(const T &a,const T &b)
{
return (a<b)?a:b;
}
//for template normalize functions:
inline float squareroot(float a){return sqrtf(a);}
inline double squareroot(double a){return sqrt(a); }
//----------------------------------
//-------- 2D --------
template<class T>
class vec2
{
public:
T x,y;
inline vec2(){x=0;y=0;}
inline vec2(const T &_x, const T &_y){x=_x;y=_y;}
inline T& operator[](int i) {return ((T*)this)[i];}
inline const T& operator[](int i) const {return ((T*)this)[i];}
};
typedef vec2<int> int2;
typedef vec2<float> float2;
template<class T> inline int operator ==(const vec2<T> &a,const vec2<T> &b) {return (a.x==b.x && a.y==b.y);}
template<class T> inline vec2<T> operator-( const vec2<T>& a, const vec2<T>& b ){return vec2<T>(a.x-b.x,a.y-b.y);}
template<class T> inline vec2<T> operator+( const vec2<T>& a, const vec2<T>& b ){return float2(a.x+b.x,a.y+b.y);}
//--------- 3D ---------
template<class T>
class vec3
{
public:
T x,y,z;
inline vec3(){x=0;y=0;z=0;};
inline vec3(const T &_x,const T &_y,const T &_z){x=_x;y=_y;z=_z;};
inline T& operator[](int i) {return ((T*)this)[i];}
inline const T& operator[](int i) const {return ((T*)this)[i];}
};
typedef vec3<int> int3;
typedef vec3<short> short3;
typedef vec3<float> float3;
// due to ambiguity there is no overloaded operators for v3*v3 use dot,cross,outerprod,cmul
template<class T> inline int operator==(const vec3<T> &a,const vec3<T> &b) {return (a.x==b.x && a.y==b.y && a.z==b.z);}
template<class T> inline int operator!=(const vec3<T> &a,const vec3<T> &b) {return !(a==b);}
template<class T> inline vec3<T> operator+(const vec3<T>& a, const vec3<T>& b ){return vec3<T>(a.x+b.x, a.y+b.y, a.z+b.z);}
template<class T> inline vec3<T> operator-(const vec3<T>& a, const vec3<T>& b ){return vec3<T>(a.x-b.x, a.y-b.y, a.z-b.z);}
template<class T> inline vec3<T> operator-(const vec3<T>& v){return vec3<T>(-v.x,-v.y,-v.z );}
template<class T> inline vec3<T> operator*(const vec3<T>& v, const T &s ){ return vec3<T>( v.x*s, v.y*s, v.z*s );}
template<class T> inline vec3<T> operator*(T s, const vec3<T>& v ){return v*s;}
template<class T> inline vec3<T> operator/(const vec3<T>& v, T s ){return vec3<T>( v.x/s, v.y/s, v.z/s );}
template<class T> inline T dot (const vec3<T>& a, const vec3<T>& b){return a.x*b.x + a.y*b.y + a.z*b.z;}
template<class T> inline vec3<T> cmul (const vec3<T>& a, const vec3<T>& b){return vec3<T>(a.x*b.x, a.y*b.y, a.z*b.z);}
template<class T> inline vec3<T> cross(const vec3<T>& a, const vec3<T>& b){return vec3<T>(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);}
template<class T> inline T magnitude( const vec3<T>& v ){return squareroot(dot(v,v));}
template<class T> inline vec3<T> normalize( const vec3<T>& v ){return v/magnitude(v);}
template<class T> inline vec3<T>& operator+=(vec3<T>& a, const vec3<T>& b){a.x+=b.x;a.y+=b.y;a.z+=b.z;return a;}
template<class T> inline vec3<T>& operator-=(vec3<T>& a, const vec3<T>& b){a.x-=b.x;a.y-=b.y;a.z-=b.z;return a;}
template<class T> inline vec3<T>& operator*=(vec3<T>& v, T s){v.x*=s;v.y*=s;v.z*= s;return v;}
template<class T> inline vec3<T>& operator/=(vec3<T>& v, T s){v.x/=s;v.y/=s;v.z/=s;return v;}
float3 safenormalize(const float3 &v);
float3 vabs(const float3 &v);
float3 Interpolate(const float3 &v0,const float3 &v1,float alpha);
float3 Round(const float3& a,float precision);
template<class T> inline vec3<T>VectorMin(const vec3<T> &a,const vec3<T> &b) {return vec3<T>(Min(a.x,b.x),Min(a.y,b.y),Min(a.z,b.z));}
template<class T> inline vec3<T>VectorMax(const vec3<T> &a,const vec3<T> &b) {return vec3<T>(Max(a.x,b.x),Max(a.y,b.y),Max(a.z,b.z));}
int overlap(const float3 &bmina,const float3 &bmaxa,const float3 &bminb,const float3 &bmaxb);
template <class T>
class mat3x3
{
public:
vec3<T> x,y,z; // the 3 rows of the Matrix
inline mat3x3(){}
inline mat3x3(const T &xx,const T &xy,const T &xz,const T &yx,const T &yy,const T &yz,const T &zx,const T &zy,const T &zz):x(xx,xy,xz),y(yx,yy,yz),z(zx,zy,zz){}
inline mat3x3(const vec3<T> &_x,const vec3<T> &_y,const vec3<T> &_z):x(_x),y(_y),z(_z){}
inline vec3<T>& operator[](int i) {return (&x)[i];}
inline const vec3<T>& operator[](int i) const {return (&x)[i];}
inline T& operator()(int r, int c) {return ((&x)[r])[c];}
inline const T& operator()(int r, int c) const {return ((&x)[r])[c];}
};
typedef mat3x3<float> float3x3;
float3x3 Transpose( const float3x3& m );
template<class T> vec3<T> operator*( const vec3<T>& v , const mat3x3<T>& m )
{
return vec3<T>((m.x.x*v.x + m.y.x*v.y + m.z.x*v.z),
(m.x.y*v.x + m.y.y*v.y + m.z.y*v.z),
(m.x.z*v.x + m.y.z*v.y + m.z.z*v.z));
}
float3 operator*( const float3x3& m , const float3& v );
float3x3 operator*( const float3x3& m , const float& s );
float3x3 operator*( const float3x3& ma, const float3x3& mb );
float3x3 operator/( const float3x3& a, const float& s ) ;
float3x3 operator+( const float3x3& a, const float3x3& b );
float3x3 operator-( const float3x3& a, const float3x3& b );
float3x3 &operator+=( float3x3& a, const float3x3& b );
float3x3 &operator-=( float3x3& a, const float3x3& b );
float3x3 &operator*=( float3x3& a, const float& s );
float Determinant(const float3x3& m );
float3x3 Inverse(const float3x3& a); // its just 3x3 so we simply do that cofactor method
float3x3 outerprod(const float3& a,const float3& b);
//-------- 4D Math --------
template<class T>
class vec4
{
public:
T x,y,z,w;
inline vec4(){x=0;y=0;z=0;w=0;};
inline vec4(const T &_x, const T &_y, const T &_z, const T &_w){x=_x;y=_y;z=_z;w=_w;}
inline vec4(const vec3<T> &v,const T &_w){x=v.x;y=v.y;z=v.z;w=_w;}
//operator float *() { return &x;};
T& operator[](int i) {return ((T*)this)[i];}
const T& operator[](int i) const {return ((T*)this)[i];}
inline const vec3<T>& xyz() const { return *((vec3<T>*)this);}
inline vec3<T>& xyz() { return *((vec3<T>*)this);}
};
typedef vec4<float> float4;
typedef vec4<int> int4;
typedef vec4<unsigned char> byte4;
template<class T> inline int operator==(const vec4<T> &a,const vec4<T> &b) {return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);}
template<class T> inline int operator!=(const vec4<T> &a,const vec4<T> &b) {return !(a==b);}
template<class T> inline vec4<T> operator+(const vec4<T>& a, const vec4<T>& b ){return vec4<T>(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);}
template<class T> inline vec4<T> operator-(const vec4<T>& a, const vec4<T>& b ){return vec4<T>(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);}
template<class T> inline vec4<T> operator-(const vec4<T>& v){return vec4<T>(-v.x,-v.y,-v.z,-v.w);}
template<class T> inline vec4<T> operator*(const vec4<T>& v, const T &s ){ return vec4<T>( v.x*s, v.y*s, v.z*s,v.w*s);}
template<class T> inline vec4<T> operator*(T s, const vec4<T>& v ){return v*s;}
template<class T> inline vec4<T> operator/(const vec4<T>& v, T s ){return vec4<T>( v.x/s, v.y/s, v.z/s,v.w/s );}
template<class T> inline T dot(const vec4<T>& a, const vec4<T>& b ){return a.x*b.x + a.y*b.y + a.z*b.z+a.w*b.w;}
template<class T> inline vec4<T> cmul(const vec4<T> &a, const vec4<T> &b) {return vec4<T>(a.x*b.x, a.y*b.y, a.z*b.z,a.w*b.w);}
template<class T> inline vec4<T>& operator+=(vec4<T>& a, const vec4<T>& b ){a.x+=b.x;a.y+=b.y;a.z+=b.z;a.w+=b.w;return a;}
template<class T> inline vec4<T>& operator-=(vec4<T>& a, const vec4<T>& b ){a.x-=b.x;a.y-=b.y;a.z-=b.z;a.w-=b.w;return a;}
template<class T> inline vec4<T>& operator*=(vec4<T>& v, T s){v.x*=s;v.y*=s;v.z*=s;v.w*=s;return v;}
template<class T> inline vec4<T>& operator/=(vec4<T>& v, T s){v.x/=s;v.y/=s;v.z/=s;v.w/=s;return v;}
template<class T> inline T magnitude( const vec4<T>& v ){return squareroot(dot(v,v));}
template<class T> inline vec4<T> normalize( const vec4<T>& v ){return v/magnitude(v);}
struct D3DXMATRIX;
template<class T>
class mat4x4
{
public:
vec4<T> x,y,z,w; // the 4 rows
inline mat4x4(){}
inline mat4x4(const vec4<T> &_x, const vec4<T> &_y, const vec4<T> &_z, const vec4<T> &_w):x(_x),y(_y),z(_z),w(_w){}
inline mat4x4(const T& m00, const T& m01, const T& m02, const T& m03,
const T& m10, const T& m11, const T& m12, const T& m13,
const T& m20, const T& m21, const T& m22, const T& m23,
const T& m30, const T& m31, const T& m32, const T& m33 )
:x(m00,m01,m02,m03),y(m10,m11,m12,m13),z(m20,m21,m22,m23),w(m30,m31,m32,m33){}
inline vec4<T>& operator[](int i) {assert(i>=0&&i<4);return (&x)[i];}
inline const vec4<T>& operator[](int i) const {assert(i>=0&&i<4);return (&x)[i];}
inline T& operator()(int r, int c) {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
inline const T& operator()(int r, int c) const {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
inline operator T* () {return &x.x;}
inline operator const T* () const {return &x.x;}
operator struct D3DXMATRIX* () { return (struct D3DXMATRIX*) this;}
operator const struct D3DXMATRIX* () const { return (struct D3DXMATRIX*) this;}
};
typedef mat4x4<float> float4x4;
float4x4 operator*( const float4x4& a, const float4x4& b );
float4 operator*( const float4& v, const float4x4& m );
float4x4 Inverse(const float4x4 &m);
float4x4 MatrixRigidInverse(const float4x4 &m);
float4x4 MatrixTranspose(const float4x4 &m);
float4x4 MatrixPerspectiveFov(float fovy, float Aspect, float zn, float zf );
float4x4 MatrixTranslation(const float3 &t);
float4x4 MatrixRotationZ(const float angle_radians);
float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up);
int operator==( const float4x4 &a, const float4x4 &b );
//-------- Quaternion ------------
template<class T>
class quaternion : public vec4<T>
{
public:
inline quaternion() { this->x = this->y = this->z = 0.0f; this->w = 1.0f; }
inline quaternion(const T &_x, const T &_y, const T &_z, const T &_w){this->x=_x;this->y=_y;this->z=_z;this->w=_w;}
inline explicit quaternion(const vec4<T> &v):vec4<T>(v){}
T angle() const { return acosf(this->w)*2.0f; }
vec3<T> axis() const { vec3<T> a(this->x,this->y,this->z); if(fabsf(angle())<0.0000001f) return vec3<T>(1,0,0); return a*(1/sinf(angle()/2.0f)); }
inline vec3<T> xdir() const { return vec3<T>( 1-2*(this->y*this->y+this->z*this->z), 2*(this->x*this->y+this->w*this->z),
2*(this->x*this->z-this->w*this->y) ); }
inline vec3<T> ydir() const { return vec3<T>( 2*(this->x*this->y-this->w*this->z),1-2*(this->x*this->x+this->z*this->z), 2*(this->y*this->z+this->w*this->x) ); }
inline vec3<T> zdir() const { return vec3<T>( 2*(this->x*this->z+this->w*this->y),
2*(this->y*this->z-this->w*this->x),1-
2*(this->x*this->x+this->y*this->y) ); }
inline mat3x3<T> getmatrix() const { return mat3x3<T>( xdir(), ydir(), zdir() ); }
//operator float3x3() { return getmatrix(); }
void Normalize();
};
template<class T>
inline quaternion<T> quatfrommat(const mat3x3<T> &m)
{
T magw = m[0 ][ 0] + m[1 ][ 1] + m[2 ][ 2];
T magxy;
T magzw;
vec3<T> pre;
vec3<T> prexy;
vec3<T> prezw;
quaternion<T> postxy;
quaternion<T> postzw;
quaternion<T> post;
int wvsz = (magw > m[2][2] ) ;
magzw = (wvsz) ? magw : m[2][2];
prezw = (wvsz) ? vec3<T>(1.0f,1.0f,1.0f) : vec3<T>(-1.0f,-1.0f,1.0f) ;
postzw = (wvsz) ? quaternion<T>(0.0f,0.0f,0.0f,1.0f): quaternion<T>(0.0f,0.0f,1.0f,0.0f);
int xvsy = (m[0][0]>m[1][1]);
magxy = (xvsy) ? m[0][0] : m[1][1];
prexy = (xvsy) ? vec3<T>(1.0f,-1.0f,-1.0f) : vec3<T>(-1.0f,1.0f,-1.0f) ;
postxy = (xvsy) ? quaternion<T>(1.0f,0.0f,0.0f,0.0f): quaternion<T>(0.0f,1.0f,0.0f,0.0f);
int zwvsxy = (magzw > magxy);
pre = (zwvsxy) ? prezw : prexy ;
post = (zwvsxy) ? postzw : postxy;
T t = pre.x * m[0 ][ 0] + pre.y * m[1 ][ 1] + pre.z * m[2 ][ 2] + 1.0f;
T s = 1/sqrt(t) * 0.5f;
quaternion<T> qp;
qp.x = ( pre.y * m[1][2] - pre.z * m[2][1] ) * s;
qp.y = ( pre.z * m[2][0] - pre.x * m[0][2] ) * s;
qp.z = ( pre.x * m[0][1] - pre.y * m[1][0] ) * s;
qp.w = t * s ;
return qp * post ;
}
typedef quaternion<float> Quaternion;
inline Quaternion QuatFromAxisAngle(const float3 &_v, float angle_radians )
{
float3 v = normalize(_v)*sinf(angle_radians/2.0f);
return Quaternion(v.x,v.y,v.z,cosf(angle_radians/2.0f));
}
template<class T> inline quaternion<T> Conjugate(const quaternion<T> &q){return quaternion<T>(-q.x,-q.y,-q.z,q.w);}
template<class T> inline quaternion<T> Inverse(const quaternion<T> &q){return Conjugate(q);}
template<class T> inline quaternion<T> normalize( const quaternion<T> & a ){return quaternion<T> (normalize((vec4<T>&)a));}
template<class T> inline quaternion<T>& operator*=(quaternion<T>& a, T s ){return (quaternion<T>&)((vec4<T>&)a *=s);}
template<class T> inline quaternion<T> operator*( const quaternion<T>& a, float s ){return quaternion<T>((vec4<T>&)a*s);}
template<class T> inline quaternion<T> operator+( const quaternion<T>& a, const quaternion<T>& b){return quaternion<T>((vec4<T>&)a+(vec4<T>&)b);}
template<class T> inline quaternion<T> operator-( const quaternion<T>& a, const quaternion<T>& b){return quaternion<T>((vec4<T>&)a-(vec4<T>&)b);}
template<class T> inline quaternion<T> operator-( const quaternion<T>& b){return quaternion<T>(-(vec4<T>&)b);}
template<class T> inline quaternion<T> operator*( const quaternion<T>& a, const quaternion<T>& b)
{
return quaternion<T>(
a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y, //x
a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x, //y
a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w, //z
a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z ); //w
}
float3 rotate( const Quaternion& q, const float3& v );
//float3 operator*( const Quaternion& q, const float3& v );
//float3 operator*( const float3& v, const Quaternion& q );
Quaternion slerp(const Quaternion &a, const Quaternion& b, float t );
Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,float t);
Quaternion RotationArc(float3 v0, float3 v1 ); // returns quat q where q*v0*q^-1=v1
float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v);
inline Quaternion QuatFromMat(const float3 &t, const float3 &b, const float3 &n)
{
return normalize(quatfrommat<float>(float3x3(t,b,n)));
}
//---------------- Pose ------------------
class Pose
{
public:
float3 position;
Quaternion orientation;
Pose(){}
Pose(const float3 &p,const Quaternion &q):position(p),orientation(q){}
Pose &pose(){return *this;}
const Pose &pose() const {return *this;}
};
inline float3 operator*(const Pose &a,const float3 &v)
{
return a.position + rotate(a.orientation,v);
}
inline Pose operator*(const Pose &a,const Pose &b)
{
return Pose(a.position + rotate(a.orientation,b.position),a.orientation*b.orientation);
}
inline Pose Inverse(const Pose &a)
{
Quaternion q = Inverse(a.orientation);
return Pose(rotate(q,-a.position),q);
}
inline Pose slerp(const Pose &p0,const Pose &p1,float t)
{
return Pose(p0.position * (1.0f-t) + p1.position * t,slerp(p0.orientation,p1.orientation,t));
}
inline float4x4 MatrixFromPose(const Pose &pose)
{
return MatrixFromQuatVec(pose.orientation,pose.position);
}
//------ Euler Angle -----
Quaternion YawPitchRoll( float yaw, float pitch, float roll );
float Yaw( const Quaternion& q );
float Pitch( const Quaternion& q );
float Roll( const Quaternion &q );
float Yaw( const float3& v );
float Pitch( const float3& v );
//------- Plane ----------
class Plane : public float4
{
public:
float3& normal(){ return xyz(); }
const float3& normal() const { return xyz(); }
float& dist(){return w;} // distance below origin - the D from plane equasion Ax+By+Cz+D=0
const float& dist() const{return w;} // distance below origin - the D from plane equasion Ax+By+Cz+D=0
Plane(const float3 &n,float d):float4(n,d){}
Plane(){dist()=0;}
explicit Plane(const float4 &v):float4(v){}
};
Plane Transform(const Plane &p, const float3 &translation, const Quaternion &rotation);
inline Plane PlaneFlip(const Plane &p){return Plane(-p.normal(),-p.dist());}
inline int operator==( const Plane &a, const Plane &b ) { return (a.normal()==b.normal() && a.dist()==b.dist()); }
inline int coplanar( const Plane &a, const Plane &b ) { return (a==b || a==PlaneFlip(b)); }
float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1);
float3 PlaneProject(const Plane &plane, const float3 &point);
float3 PlanesIntersection(const Plane &p0,const Plane &p1, const Plane &p2);
float3 PlanesIntersection(const Plane *planes,int planes_count,const float3 &seed=float3(0,0,0));
int Clip(const Plane &p,const float3 *verts_in,int count,float* verts_out); // verts_out must be preallocated with sufficient size >= count+1 or more if concave
int ClipPolyPoly(const float3 &normal,const float3 *clipper,int clipper_count,const float3 *verts_in, int in_count,float3 *scratch); //scratch must be preallocated
//--------- Utility Functions ------
float3 PlaneLineIntersection(const float3 &normal,const float dist, const float3 &p0, const float3 &p1);
float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a); // projects a onto infinite line p0p1
float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a);
int BoxInside(const float3 &p,const float3 &bmin, const float3 &bmax) ;
int BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax, float3 *impact);
float DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint=NULL, float3 *vpoint=NULL);
float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2);
float3 NormalOf(const float3 *vert, const int n);
Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir0, const float3 &dir1);
int Clip(const float3 &plane_normal,float plane_dist,const float3 *verts_in,int count,float* verts_out); // verts_out must be preallocated with sufficient size >= count+1 or more if concave
int ClipPolyPoly(const float3 &normal,const float3 *clipper,int clipper_count,const float3 *verts_in, int in_count,float3 *scratch); //scratch must be preallocated
float3 Diagonal(const float3x3 &M);
Quaternion Diagonalizer(const float3x3 &A);
float3 Orth(const float3& v);
int SolveQuadratic(float a,float b,float c,float *ta,float *tb); // if true returns roots ta,tb where ta<=tb
int HitCheckPoly(const float3 *vert,const int n,const float3 &v0, const float3 &v1, float3 *impact=NULL, float3 *normal=NULL);
int HitCheckRaySphere(const float3& sphereposition,float radius, const float3& _v0, const float3& _v1, float3 *impact,float3 *normal);
int HitCheckRayCylinder(const float3 &p0,const float3 &p1,float radius,const float3& _v0,const float3& _v1, float3 *impact,float3 *normal);
int HitCheckSweptSphereTri(const float3 &p0,const float3 &p1,const float3 &p2,float radius, const float3& v0,const float3& _v1, float3 *impact,float3 *normal);
void BoxLimits(const float3 *verts,int verts_count, float3 &bmin_out,float3 &bmax_out);
void BoxLimits(const float4 *verts,int verts_count, float3 &bmin_out,float3 &bmax_out);
template<class T>
inline int maxdir(const T *p,int count,const T &dir)
{
assert(count);
int m=0;
for(int i=1;i<count;i++)
{
if(dot(p[i],dir)>dot(p[m],dir)) m=i;
}
return m;
}
float3 CenterOfMass(const float3 *vertices, const int3 *tris, const int count) ;
float3x3 Inertia(const float3 *vertices, const int3 *tris, const int count, const float3& com=float3(0,0,0)) ;
float Volume(const float3 *vertices, const int3 *tris, const int count) ;
int calchull(float3 *verts,int verts_count, int3 *&tris_out, int &tris_count,int vlimit); // computes convex hull see hull.cpp
#endif // VEC_MATH_H

View File

@@ -1,28 +0,0 @@
#include "Bullet2GpuDemo.h"
#include "../b3GpuDynamicsWorld.h"
#include "GpuRigidBodyDemoInternalData.h"
#include "BulletCollision/CollisionShapes/b3BoxShape.h"
#include "gpu_rigidbody/host/b3RigidBody.h"
void Bullet2GpuDemo::setupScene(const ConstructionInfo& ci)
{
// m_data->m_np = np;
// m_data->m_bp = bp;
// m_data->m_rigidBodyPipeline
m_gpuDynamicsWorld = new b3GpuDynamicsWorld(m_data->m_bp,m_data->m_np,m_data->m_rigidBodyPipeline);
b3Vector3 halfExtents(100,1,100);
b3BoxShape* boxShape = new b3BoxShape(halfExtents);
b3Vector3 localInertia;
b3Scalar mass=1.f;
boxShape->calculateLocalInertia(mass,localInertia);
b3RigidBody* body = new b3RigidBody(mass,0,boxShape,localInertia);
m_gpuDynamicsWorld->addRigidBody(body);
}
void Bullet2GpuDemo::destroyScene()
{
delete m_gpuDynamicsWorld;
m_gpuDynamicsWorld = 0;
}

View File

@@ -1,31 +0,0 @@
#ifndef BULLET2_GPU_DEMO_H
#define BULLET2_GPU_DEMO_H
#include "GpuRigidBodyDemo.h"
class Bullet2GpuDemo : public GpuRigidBodyDemo
{
protected:
class b3GpuDynamicsWorld* m_gpuDynamicsWorld;
public:
Bullet2GpuDemo(){}
virtual ~Bullet2GpuDemo(){}
virtual const char* getName()
{
return "Bullet2Gpu";
}
static GpuDemo* MyCreateFunc()
{
GpuDemo* demo = new Bullet2GpuDemo;
return demo;
}
virtual void setupScene(const ConstructionInfo& ci);
virtual void destroyScene();
};
#endif //BULLET2_GPU_DEMO_H

View File

@@ -1,611 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "b3CpuDynamicsWorld.h"
#include "b3GpuDynamicsWorld.h"
#define SCALING 1.
#define START_POS_X -5
#define START_POS_Y 10
#define START_POS_Z -3
#include "LinearMath/b3Vector3.h"
#include "GpuDemo.h"
//#include "GlutStuff.h"
///b3BulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
//#include "b3BulletDynamicsCommon.h"
#include "BulletCollision/CollisionShapes/b3TriangleMesh.h"
#include "BulletCollision/CollisionShapes/b3BvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/b3SphereShape.h"
#include "BulletCollision/CollisionShapes/b3ConvexHullShape.h"
#include "BulletCollision/CollisionShapes/b3BoxShape.h"
#include "BulletCollision/CollisionShapes/b3CompoundShape.h"
#include "BulletCollision/CollisionShapes/b3StaticPlaneShape.h"
#include "BulletDynamics/Dynamics/b3RigidBody.h"
#include "LinearMath/b3DefaultMotionState.h"
#include "LinearMath/b3Quickprof.h"
#include <stdio.h> //printf debugging
void GpuDemo::clientMoveAndDisplay()
{
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//simple dynamics world doesn't handle fixed-time-stepping
float dt = getDeltaTimeInSeconds();
///step the simulation
if (m_dynamicsWorld)
{
static bool once = true;
if (once)
{
once=false;
b3DefaultSerializer* serializer = new b3DefaultSerializer();
m_dynamicsWorld->serialize(serializer);
FILE* file = fopen("testFile.bullet","wb");
fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file);
fclose(file);
}
m_dynamicsWorld->stepSimulation(dt);
static int count=0;
count++;
if (count==25)
{
//b3ProfileManager::dumpAll();
}
}
// renderme();
//swapBuffers();
}
b3AlignedObjectArray<b3Vector3> vertices;
void EmptyDemo::setupScene(const ConstructionInfo& ci)
{
//empty test
}
void SpheresDemo::setupScene(const ConstructionInfo& ci)
{
if (1)
{
b3SphereShape* sphere = new b3SphereShape(1);
m_collisionShapes.push_back(sphere);
/// Create Dynamic Objects
b3Transform startTransform;
startTransform.setIdentity();
float start_x = START_POS_X - ci.gapX*ci.arraySizeX/2;
float start_y = START_POS_Y;
float start_z = START_POS_Z - ci.gapZ*ci.arraySizeZ/2;
for (int k=0;k<ci.arraySizeY;k++)
{
int sizeX = ci.arraySizeX;
int startX = -sizeX/2;
float gapX = ci.gapX;
for (int i=0;i<sizeX;i++)
{
int sizeZ = ci.arraySizeZ;
int startZ = -sizeX/2;
float gapZ =ci.gapZ;
for(int j = 0;j<sizeZ;j++)
{
//b3CollisionShape* shape = k==0? boxShape : colShape;
b3CollisionShape* shape = sphere;
b3Scalar mass = 1;
if (!ci.m_useConcaveMesh && k==0)
mass = k==0? 0.f : 1.f;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
if (isDynamic)
shape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(SCALING*b3Vector3(
b3Scalar(gapX*i + start_x),
b3Scalar(ci.gapY*k + start_y),
b3Scalar(gapZ*j + start_z)));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(startTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body);
}
}
}
}
{
b3Vector3 planeNormal(0,1,0);
b3Scalar planeConstant=0;
b3CollisionShape* shape = new b3StaticPlaneShape(planeNormal,planeConstant);
//b3BoxShape* plane = new b3BoxShape(b3Vector3(100,1,100));
//plane->initializePolyhedralFeatures();
//b3SphereShape* shape = new b3SphereShape(1000);
b3Scalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
b3Transform groundTransform;
groundTransform.setIdentity();
groundTransform.setRotation(b3Quaternion(b3Vector3(1,0,0),0.3));
groundTransform.setOrigin(b3Vector3(0,0,0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(groundTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
}
void GpuCompoundDemo::setupScene(const ConstructionInfo& ci)
{
b3CollisionShape* groundShape =0;
// b3CollisionShape* groundShape = new b3StaticPlaneShape(b3Vector3(0,1,0),50);
if (ci.m_useConcaveMesh)
{
b3TriangleMesh* meshInterface = new b3TriangleMesh();
b3AlignedObjectArray<b3Vector3> concaveVertices;
concaveVertices.push_back(b3Vector3(0,-20,0));
concaveVertices.push_back(b3Vector3(80,10,80));
concaveVertices.push_back(b3Vector3(80,10,-80));
concaveVertices.push_back(b3Vector3(-80,10,-80));
concaveVertices.push_back(b3Vector3(-80,10,80));
meshInterface->addTriangle(concaveVertices[0],concaveVertices[1],concaveVertices[2],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[2],concaveVertices[3],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[3],concaveVertices[4],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[4],concaveVertices[1],true);
#if 0
groundShape = new b3BvhTriangleMeshShape(meshInterface,true);//b3StaticPlaneShape(b3Vector3(0,1,0),50);
#else
b3BoxShape* shape =new b3BoxShape(b3Vector3(b3Scalar(250.),b3Scalar(10.),b3Scalar(250.)));
shape->initializePolyhedralFeatures();
groundShape = shape;
#endif
} else
{
groundShape = new b3BoxShape(b3Vector3(b3Scalar(250.),b3Scalar(50.),b3Scalar(250.)));
}
m_collisionShapes.push_back(groundShape);
b3Transform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(b3Vector3(0,0,0));
//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
if (ci.m_useConcaveMesh)
{
b3Scalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(groundTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
//vertices.push_back(b3Vector3(0,1,0));
vertices.push_back(b3Vector3(1,1,1));
vertices.push_back(b3Vector3(1,1,-1));
vertices.push_back(b3Vector3(-1,1,-1));
vertices.push_back(b3Vector3(-1,1,1));
vertices.push_back(b3Vector3(1,-1,1));
vertices.push_back(b3Vector3(1,-1,-1));
vertices.push_back(b3Vector3(-1,-1,-1));
vertices.push_back(b3Vector3(-1,-1,1));
#if 0
b3PolyhedralConvexShape* colShape = new b3ConvexHullShape(&vertices[0].getX(),vertices.size());
colShape->initializePolyhedralFeatures();
#else
b3CompoundShape* compoundShape = 0;
{
b3PolyhedralConvexShape* colShape = new b3ConvexHullShape(&vertices[0].getX(),vertices.size());
colShape->initializePolyhedralFeatures();
compoundShape = new b3CompoundShape();
b3Transform tr;
tr.setIdentity();
tr.setOrigin(b3Vector3(0,-1,0));
compoundShape->addChildShape(tr,colShape);
tr.setOrigin(b3Vector3(0,0,2));
compoundShape->addChildShape(tr,colShape);
tr.setOrigin(b3Vector3(2,0,0));
compoundShape->addChildShape(tr,colShape);
}
b3CollisionShape* colShape = compoundShape;
#endif
b3PolyhedralConvexShape* boxShape = new b3BoxShape(b3Vector3(SCALING*1,SCALING*1,SCALING*1));
boxShape->initializePolyhedralFeatures();
//b3CollisionShape* colShape = new b3SphereShape(b3Scalar(1.));
m_collisionShapes.push_back(colShape);
m_collisionShapes.push_back(boxShape);
/// Create Dynamic Objects
b3Transform startTransform;
startTransform.setIdentity();
float start_x = START_POS_X - ci.arraySizeX/2;
float start_y = START_POS_Y;
float start_z = START_POS_Z - ci.arraySizeZ/2;
for (int k=0;k<ci.arraySizeY;k++)
{
int sizeX = ci.arraySizeX;
if (!ci.m_useConcaveMesh && k==0)
sizeX = 50;
int startX = !ci.m_useConcaveMesh&&k==0? -20 : 0;
float gapX = !ci.m_useConcaveMesh&&k==0? 3.05 : ci.gapX;
for (int i=0;i<sizeX;i++)
{
int sizeZ = !ci.m_useConcaveMesh&&k==0? 50 : ci.arraySizeZ;
int startZ = (!ci.m_useConcaveMesh)&&k==0? -20 : 0;
float gapZ = !ci.m_useConcaveMesh&&k==0? 3.05 : ci.gapZ;
for(int j = 0;j<sizeZ;j++)
{
//b3CollisionShape* shape = k==0? boxShape : colShape;
b3CollisionShape* shape = colShape;
b3Scalar mass = 1;
if (!ci.m_useConcaveMesh && k==0)
mass = k==0? 0.f : 1.f;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
if (isDynamic)
shape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(SCALING*b3Vector3(
b3Scalar(startX+gapX*i + start_x),
b3Scalar(20+ci.gapY*k + start_y),
b3Scalar(startZ+gapZ*j + start_z)));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(startTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body);
}
}
}
}
}
void GpuBoxDemo::setupScene(const ConstructionInfo& ci)
{
b3CollisionShape* groundShape =0;
// b3CollisionShape* groundShape = new b3StaticPlaneShape(b3Vector3(0,1,0),50);
if (ci.m_useConcaveMesh)
{
b3TriangleMesh* meshInterface = new b3TriangleMesh();
b3AlignedObjectArray<b3Vector3> concaveVertices;
concaveVertices.push_back(b3Vector3(0,-20,0));
concaveVertices.push_back(b3Vector3(80,10,80));
concaveVertices.push_back(b3Vector3(80,10,-80));
concaveVertices.push_back(b3Vector3(-80,10,-80));
concaveVertices.push_back(b3Vector3(-80,10,80));
meshInterface->addTriangle(concaveVertices[0],concaveVertices[1],concaveVertices[2],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[2],concaveVertices[3],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[3],concaveVertices[4],true);
meshInterface->addTriangle(concaveVertices[0],concaveVertices[4],concaveVertices[1],true);
#if 0
groundShape = new b3BvhTriangleMeshShape(meshInterface,true);//b3StaticPlaneShape(b3Vector3(0,1,0),50);
#else
b3BoxShape* shape =new b3BoxShape(b3Vector3(b3Scalar(250.),b3Scalar(10.),b3Scalar(250.)));
shape->initializePolyhedralFeatures();
groundShape = shape;
#endif
} else
{
groundShape = new b3BoxShape(b3Vector3(b3Scalar(250.),b3Scalar(50.),b3Scalar(250.)));
}
m_collisionShapes.push_back(groundShape);
b3Transform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(b3Vector3(0,0,0));
//We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
if (ci.m_useConcaveMesh)
{
b3Scalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
if (isDynamic)
groundShape->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(groundTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
//add the body to the dynamics world
m_dynamicsWorld->addRigidBody(body);
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
//vertices.push_back(b3Vector3(0,1,0));
vertices.push_back(b3Vector3(1,1,1));
vertices.push_back(b3Vector3(1,1,-1));
vertices.push_back(b3Vector3(-1,1,-1));
vertices.push_back(b3Vector3(-1,1,1));
vertices.push_back(b3Vector3(1,-1,1));
vertices.push_back(b3Vector3(1,-1,-1));
vertices.push_back(b3Vector3(-1,-1,-1));
vertices.push_back(b3Vector3(-1,-1,1));
#if 1
b3PolyhedralConvexShape* colShape = new b3ConvexHullShape(&vertices[0].getX(),vertices.size());
colShape->initializePolyhedralFeatures();
#else
b3CompoundShape* compoundShape = 0;
{
b3PolyhedralConvexShape* colShape = new b3ConvexHullShape(&vertices[0].getX(),vertices.size());
colShape->initializePolyhedralFeatures();
compoundShape = new b3CompoundShape();
b3Transform tr;
tr.setIdentity();
tr.setOrigin(b3Vector3(0,-1,0));
compoundShape->addChildShape(tr,colShape);
tr.setOrigin(b3Vector3(0,0,2));
compoundShape->addChildShape(tr,colShape);
tr.setOrigin(b3Vector3(2,0,0));
compoundShape->addChildShape(tr,colShape);
}
b3CollisionShape* colShape = compoundShape;
#endif
b3PolyhedralConvexShape* boxShape = new b3BoxShape(b3Vector3(SCALING*1,SCALING*1,SCALING*1));
boxShape->initializePolyhedralFeatures();
//b3CollisionShape* colShape = new b3SphereShape(b3Scalar(1.));
m_collisionShapes.push_back(colShape);
m_collisionShapes.push_back(boxShape);
/// Create Dynamic Objects
b3Transform startTransform;
startTransform.setIdentity();
float start_x = START_POS_X - ci.arraySizeX/2;
float start_y = START_POS_Y;
float start_z = START_POS_Z - ci.arraySizeZ/2;
for (int k=0;k<ci.arraySizeY;k++)
{
int sizeX = ci.arraySizeX;
if (!ci.m_useConcaveMesh && k==0)
sizeX = 50;
int startX = !ci.m_useConcaveMesh&&k==0? -20 : 0;
float gapX = !ci.m_useConcaveMesh&&k==0? 3.05 : ci.gapX;
for (int i=0;i<sizeX;i++)
{
int sizeZ = !ci.m_useConcaveMesh&&k==0? 50 : ci.arraySizeZ;
int startZ = (!ci.m_useConcaveMesh)&&k==0? -20 : 0;
float gapZ = !ci.m_useConcaveMesh&&k==0? 3.05 : ci.gapZ;
for(int j = 0;j<sizeZ;j++)
{
//b3CollisionShape* shape = k==0? boxShape : colShape;
b3CollisionShape* shape = colShape;
b3Scalar mass = 1;
if (!ci.m_useConcaveMesh && k==0)
mass = k==0? 0.f : 1.f;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
b3Vector3 localInertia(0,0,0);
if (isDynamic)
shape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(SCALING*b3Vector3(
b3Scalar(startX+gapX*i + start_x),
b3Scalar(ci.gapY*(k+0.5) + start_y),
b3Scalar(startZ+gapZ*j + start_z)));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
b3DefaultMotionState* myMotionState = new b3DefaultMotionState(startTransform);
b3RigidBody::b3RigidBodyConstructionInfo rbInfo(mass,myMotionState,shape,localInertia);
b3RigidBody* body = new b3RigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body);
}
}
}
}
}
void GpuDemo::initPhysics(const ConstructionInfo& ci)
{
// setTexturing(true);
//setShadows(false);
// setCameraDistance(b3Scalar(SCALING*250.));
///collision configuration contains default setup for memory, collision setup
if (ci.useOpenCL)
{
m_dynamicsWorld = new b3GpuDynamicsWorld(ci.preferredOpenCLPlatformIndex,ci.preferredOpenCLDeviceIndex);
} else
{
m_dynamicsWorld = new b3CpuDynamicsWorld();
}
m_dynamicsWorld->setGravity(b3Vector3(0,-10,0));
///create a few basic rigid bodies
setupScene(ci);
}
/*void GpuDemo::clientResetScene()
{
exitPhysics();
initPhysics();
}
*/
void GpuDemo::exitPhysics()
{
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
int i;
if (m_dynamicsWorld)
{
for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
b3CollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
b3RigidBody* body = b3RigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
m_dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
}
//delete collision shapes
for (int j=0;j<m_collisionShapes.size();j++)
{
b3CollisionShape* shape = m_collisionShapes[j];
delete shape;
}
m_collisionShapes.clear();
delete m_dynamicsWorld;
m_dynamicsWorld=0;
}

View File

@@ -1,184 +0,0 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef GPU_DEMO_H
#define GPU_DEMO_H
#include "Bullet3Common/b3AlignedObjectArray.h"
class b3BroadphaseInterface;
class b3CollisionShape;
class b3OverlappingPairCache;
class b3CollisionDispatcher;
class b3ConstraintSolver;
struct b3CollisionAlgorithmCreateFunc;
class b3DefaultCollisionConfiguration;
class b3DynamicsWorld;
class GLInstancingRenderer;
///GpuDemo is good starting point for learning the code base and porting.
class GpuDemo
{
protected:
b3DynamicsWorld* m_dynamicsWorld;
//keep the collision shapes, for deletion/cleanup
b3AlignedObjectArray<b3CollisionShape*> m_collisionShapes;
float getDeltaTimeInSeconds()
{
return 1./60.f;
}
public:
typedef class GpuDemo* (CreateFunc)();
struct ConstructionInfo
{
bool useOpenCL;
int preferredOpenCLPlatformIndex;
int preferredOpenCLDeviceIndex;
int arraySizeX;
int arraySizeY;
int arraySizeZ;
bool m_useConcaveMesh;
float gapX;
float gapY;
float gapZ;
GLInstancingRenderer* m_instancingRenderer;
ConstructionInfo()
:useOpenCL(false),//true),
preferredOpenCLPlatformIndex(-1),
preferredOpenCLDeviceIndex(-1),
arraySizeX(10),
arraySizeY(10 ),
arraySizeZ(10),
m_useConcaveMesh(false),
gapX(4.3),
gapY(4.0),
gapZ(4.3),
m_instancingRenderer(0)
{
}
};
protected:
virtual void setupScene(const ConstructionInfo& ci)=0;
public:
GpuDemo()
{
m_dynamicsWorld=0;
}
virtual ~GpuDemo()
{
exitPhysics();
}
virtual void initPhysics(const ConstructionInfo& ci);
virtual const char* getName()=0;
virtual void exitPhysics();
virtual const b3DynamicsWorld* getDynamicsWorld() const
{
return m_dynamicsWorld;
}
virtual void renderScene()
{
}
virtual void clientMoveAndDisplay();
//virtual void clientResetScene();
};
class GpuCompoundDemo : public GpuDemo
{
public:
virtual void setupScene(const ConstructionInfo& ci);
virtual const char* getName()
{
return "GpuCompoundDemo";
}
static GpuDemo* CreateFunc()
{
GpuDemo* demo = new GpuCompoundDemo;
return demo;
}
};
class GpuBoxDemo : public GpuDemo
{
public:
virtual void setupScene(const ConstructionInfo& ci);
virtual const char* getName()
{
return "GpuBoxDemo";
}
static GpuDemo* CreateFunc()
{
GpuDemo* demo = new GpuBoxDemo;
return demo;
}
};
class EmptyDemo : public GpuDemo
{
public:
virtual void setupScene(const ConstructionInfo& ci);
virtual const char* getName()
{
return "EmptyDemo";
}
static GpuDemo* CreateFunc()
{
GpuDemo* demo = new EmptyDemo;
return demo;
}
};
class SpheresDemo : public GpuDemo
{
public:
virtual void setupScene(const ConstructionInfo& ci);
virtual const char* getName()
{
return "SpheresDemo";
}
static GpuDemo* CreateFunc()
{
GpuDemo* demo = new SpheresDemo;
return demo;
}
};
#endif //GPU_DEMO_H

View File

@@ -1,678 +0,0 @@
#include "OpenGL3CoreRenderer.h"
#include "OpenGLWindow/GLInstancingRenderer.h"
#include "OpenGLWindow/ShapeData.h"
//#include "BulletDynamics/Dynamics/b3DiscreteDynamicsWorld.h"
//#include "BulletCollision/CollisionDispatch/b3CollisionObject.h"
#include "Bullet3Common/b3Quickprof.h"
/*#include "BulletCollision/CollisionShapes/b3BvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/b3ConvexPolyhedron.h"
#include "BulletCollision/CollisionShapes/b3ConvexHullShape.h"
#include "BulletCollision/CollisionShapes/b3CollisionShape.h"
#include "BulletCollision/CollisionShapes/b3BoxShape.h"
#include "BulletCollision/CollisionShapes/b3CompoundShape.h"
#include "BulletCollision/CollisionShapes/b3SphereShape.h"
#include "BulletCollision/CollisionShapes/b3StaticPlaneShape.h"
#include "../../rendering/WavefrontObjLoader/objLoader.h"
*/
OpenGL3CoreRenderer::OpenGL3CoreRenderer()
{
int maxNumObjects = 2*1024*1024;
m_instancingRenderer = new GLInstancingRenderer(maxNumObjects);
m_instancingRenderer->setCameraDistance(150);
}
OpenGL3CoreRenderer::~OpenGL3CoreRenderer()
{
delete m_instancingRenderer;
}
void OpenGL3CoreRenderer::init()
{
m_instancingRenderer->InitShaders();
}
void OpenGL3CoreRenderer::reshape(int w, int h)
{
m_instancingRenderer->resize(w,h);
}
void OpenGL3CoreRenderer::keyboardCallback(unsigned char key)
{
}
struct GraphicsVertex
{
float xyzw[4];
float normal[3];
float uv[2];
};
struct GraphicsShape
{
const float* m_vertices;
int m_numvertices;
const int* m_indices;
int m_numIndices;
float m_scaling[4];
};
GraphicsShape* createGraphicsShapeFromConvexHull(const b3ConvexPolyhedron* utilPtr)
{
b3AlignedObjectArray<GraphicsVertex>* vertices = new b3AlignedObjectArray<GraphicsVertex>;
{
int numVertices = utilPtr->m_vertices.size();
int numIndices = 0;
b3AlignedObjectArray<int>* indicesPtr = new b3AlignedObjectArray<int>;
for (int f=0;f<utilPtr->m_faces.size();f++)
{
const b3Face& face = utilPtr->m_faces[f];
b3Vector3 normal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
if (face.m_indices.size()>2)
{
GraphicsVertex vtx;
const b3Vector3& orgVertex = utilPtr->m_vertices[face.m_indices[0]];
vtx.xyzw[0] = orgVertex[0];vtx.xyzw[1] = orgVertex[1];vtx.xyzw[2] = orgVertex[2];vtx.xyzw[3] = 0.f;
vtx.normal[0] = normal[0];vtx.normal[1] = normal[1];vtx.normal[2] = normal[2];
vtx.uv[0] = 0.5f;vtx.uv[1] = 0.5f;
int newvtxindex0 = vertices->size();
vertices->push_back(vtx);
for (int j=1;j<face.m_indices.size()-1;j++)
{
indicesPtr->push_back(newvtxindex0);
{
GraphicsVertex vtx;
const b3Vector3& orgVertex = utilPtr->m_vertices[face.m_indices[j]];
vtx.xyzw[0] = orgVertex[0];vtx.xyzw[1] = orgVertex[1];vtx.xyzw[2] = orgVertex[2];vtx.xyzw[3] = 0.f;
vtx.normal[0] = normal[0];vtx.normal[1] = normal[1];vtx.normal[2] = normal[2];
vtx.uv[0] = 0.5f;vtx.uv[1] = 0.5f;
int newvtxindexj = vertices->size();
vertices->push_back(vtx);
indicesPtr->push_back(newvtxindexj);
}
{
GraphicsVertex vtx;
const b3Vector3& orgVertex = utilPtr->m_vertices[face.m_indices[j+1]];
vtx.xyzw[0] = orgVertex[0];vtx.xyzw[1] = orgVertex[1];vtx.xyzw[2] = orgVertex[2];vtx.xyzw[3] = 0.f;
vtx.normal[0] = normal[0];vtx.normal[1] = normal[1];vtx.normal[2] = normal[2];
vtx.uv[0] = 0.5f;vtx.uv[1] = 0.5f;
int newvtxindexj1 = vertices->size();
vertices->push_back(vtx);
indicesPtr->push_back(newvtxindexj1);
}
}
}
}
GraphicsShape* gfxShape = new GraphicsShape;
gfxShape->m_vertices = &vertices->at(0).xyzw[0];
gfxShape->m_numvertices = vertices->size();
gfxShape->m_indices = &indicesPtr->at(0);
gfxShape->m_numIndices = indicesPtr->size();
for (int i=0;i<4;i++)
gfxShape->m_scaling[i] = 1;//bake the scaling into the vertices
return gfxShape;
}
}
GraphicsShape* createGraphicsShapeFromCompoundShape(b3CompoundShape* compound)
{
GraphicsShape* gfxShape = new GraphicsShape();
b3AlignedObjectArray<GraphicsVertex>* vertexArray = new b3AlignedObjectArray<GraphicsVertex>;
b3AlignedObjectArray<int>* indexArray = new b3AlignedObjectArray<int>;
//create a graphics shape for each child, combine them into a single graphics shape using their child transforms
for (int i=0;i<compound->getNumChildShapes();i++)
{
b3Assert(compound->getChildShape(i)->isPolyhedral());
if (compound->getChildShape(i)->isPolyhedral())
{
b3PolyhedralConvexShape* convexHull = (b3PolyhedralConvexShape*) compound->getChildShape(i);
b3Transform tr = compound->getChildTransform(i);
const b3ConvexPolyhedron* polyhedron = convexHull->getConvexPolyhedron();
GraphicsShape* childGfxShape = createGraphicsShapeFromConvexHull(polyhedron);
int baseIndex = vertexArray->size();
for (int j=0;j<childGfxShape->m_numIndices;j++)
indexArray->push_back(childGfxShape->m_indices[j]+baseIndex);
GraphicsVertex* orgVerts = (GraphicsVertex*)childGfxShape->m_vertices;
for (int j=0;j<childGfxShape->m_numvertices;j++)
{
GraphicsVertex vtx;
b3Vector3 pos(orgVerts[j].xyzw[0],orgVerts[j].xyzw[1],orgVerts[j].xyzw[2]);
pos = tr*pos;
vtx.xyzw[0] = childGfxShape->m_scaling[0]*pos.getX();
vtx.xyzw[1] = childGfxShape->m_scaling[1]*pos.getY();
vtx.xyzw[2] = childGfxShape->m_scaling[2]*pos.getZ();
vtx.xyzw[3] = 10.f;
vtx.uv[0] = 0.5f;
vtx.uv[1] = 0.5f;
b3Vector3 normal(orgVerts[j].normal[0],orgVerts[j].normal[1],orgVerts[j].normal[2]);
normal = tr.getBasis()*normal;
vtx.normal[0] = normal.getX();
vtx.normal[1] = normal.getY();
vtx.normal[2] = normal.getZ();
vertexArray->push_back(vtx);
}
}
}
b3PolyhedralConvexShape* convexHull = (b3PolyhedralConvexShape*) compound->getChildShape(0);
const b3ConvexPolyhedron* polyhedron = convexHull->getConvexPolyhedron();
GraphicsShape* childGfxShape = createGraphicsShapeFromConvexHull(polyhedron);
gfxShape->m_indices = &indexArray->at(0);
gfxShape->m_numIndices = indexArray->size();
gfxShape->m_vertices = &vertexArray->at(0).xyzw[0];
gfxShape->m_numvertices = vertexArray->size();
gfxShape->m_scaling[0] = 1;
gfxShape->m_scaling[1] = 1;
gfxShape->m_scaling[2] = 1;
gfxShape->m_scaling[3] = 1;
return gfxShape;
}
GraphicsShape* createGraphicsShapeFromConcaveMesh(const b3BvhTriangleMeshShape* trimesh)
{
b3AlignedObjectArray<GraphicsVertex>* vertices = new b3AlignedObjectArray<GraphicsVertex>;
b3AlignedObjectArray<int>* indicesPtr = new b3AlignedObjectArray<int>;
const b3StridingMeshInterface* meshInterface = trimesh->getMeshInterface();
b3Vector3 trimeshScaling(1,1,1);
for (int partId=0;partId<meshInterface->getNumSubParts();partId++)
{
const unsigned char *vertexbase = 0;
int numverts = 0;
PHY_ScalarType type = PHY_INTEGER;
int stride = 0;
const unsigned char *indexbase = 0;
int indexstride = 0;
int numfaces = 0;
PHY_ScalarType indicestype = PHY_INTEGER;
//PHY_ScalarType indexType=0;
b3Vector3 triangleVerts[3];
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
b3Vector3 aabbMin,aabbMax;
for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
{
unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
if (type == PHY_FLOAT)
{
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
triangleVerts[j] = b3Vector3(
graphicsbase[0]*trimeshScaling.getX(),
graphicsbase[1]*trimeshScaling.getY(),
graphicsbase[2]*trimeshScaling.getZ());
}
else
{
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
triangleVerts[j] = b3Vector3( b3Scalar(graphicsbase[0]*trimeshScaling.getX()),
b3Scalar(graphicsbase[1]*trimeshScaling.getY()),
b3Scalar(graphicsbase[2]*trimeshScaling.getZ()));
}
}
b3Vector3 normal = (triangleVerts[2]-triangleVerts[0]).cross(triangleVerts[1]-triangleVerts[0]);
normal.normalize();
GraphicsVertex vtx0,vtx1,vtx2;
vtx0.xyzw[0] = triangleVerts[0].getX();
vtx0.xyzw[1] = triangleVerts[0].getY();
vtx0.xyzw[2] = triangleVerts[0].getZ();
vtx0.xyzw[3] = 0;
vtx0.uv[0] = 0.5f;
vtx0.uv[1] = 0.5f;
vtx0.normal[0] = normal[0];
vtx0.normal[1] = normal[1];
vtx0.normal[2] = normal[2];
vtx1.xyzw[0] = triangleVerts[1].getX();
vtx1.xyzw[1] = triangleVerts[1].getY();
vtx1.xyzw[2] = triangleVerts[1].getZ();
vtx1.xyzw[3] = 0;
vtx1.uv[0] = 0.5f;
vtx1.uv[1] = 0.5f;
vtx1.normal[0] = normal[0];
vtx1.normal[1] = normal[1];
vtx1.normal[2] = normal[2];
vtx2.xyzw[0] = triangleVerts[2].getX();
vtx2.xyzw[1] = triangleVerts[2].getY();
vtx2.xyzw[2] = triangleVerts[2].getZ();
vtx2.xyzw[3] = 0;
vtx2.uv[0] = 0.5f;
vtx2.uv[1] = 0.5f;
vtx2.normal[0] = normal[0];
vtx2.normal[1] = normal[1];
vtx2.normal[2] = normal[2];
// triangleVerts[1]
// triangleVerts[1]
// triangleVerts[2]
vertices->push_back(vtx0);
vertices->push_back(vtx1);
vertices->push_back(vtx2);
indicesPtr->push_back(indicesPtr->size());
indicesPtr->push_back(indicesPtr->size());
indicesPtr->push_back(indicesPtr->size());
}
}
GraphicsShape* gfxShape = new GraphicsShape;
gfxShape->m_vertices = &vertices->at(0).xyzw[0];
gfxShape->m_numvertices = vertices->size();
gfxShape->m_indices = &indicesPtr->at(0);
gfxShape->m_numIndices = indicesPtr->size();
for (int i=0;i<4;i++)
gfxShape->m_scaling[i] = 1;//bake the scaling into the vertices
return gfxShape;
}
GraphicsShape* createGraphicsShapeFromWavefrontObj(objLoader* obj)
{
b3AlignedObjectArray<GraphicsVertex>* vertices = new b3AlignedObjectArray<GraphicsVertex>;
{
// int numVertices = obj->vertexCount;
// int numIndices = 0;
b3AlignedObjectArray<int>* indicesPtr = new b3AlignedObjectArray<int>;
/*
for (int v=0;v<obj->vertexCount;v++)
{
vtx.xyzw[0] = obj->vertexList[v]->e[0];
vtx.xyzw[1] = obj->vertexList[v]->e[1];
vtx.xyzw[2] = obj->vertexList[v]->e[2];
b3Vector3 n(vtx.xyzw[0],vtx.xyzw[1],vtx.xyzw[2]);
if (n.length2()>B3_EPSILON)
{
n.normalize();
vtx.normal[0] = n[0];
vtx.normal[1] = n[1];
vtx.normal[2] = n[2];
} else
{
vtx.normal[0] = 0; //todo
vtx.normal[1] = 1;
vtx.normal[2] = 0;
}
vtx.uv[0] = 0.5f;vtx.uv[1] = 0.5f; //todo
vertices->push_back(vtx);
}
*/
for (int f=0;f<obj->faceCount;f++)
{
obj_face* face = obj->faceList[f];
//b3Vector3 normal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
if (face->vertex_count>=3)
{
b3Vector3 normal(0,1,0);
int vtxBaseIndex = vertices->size();
if (face->vertex_count<=4)
{
indicesPtr->push_back(vtxBaseIndex);
indicesPtr->push_back(vtxBaseIndex+1);
indicesPtr->push_back(vtxBaseIndex+2);
GraphicsVertex vtx0;
vtx0.xyzw[0] = obj->vertexList[face->vertex_index[0]]->e[0];
vtx0.xyzw[1] = obj->vertexList[face->vertex_index[0]]->e[1];
vtx0.xyzw[2] = obj->vertexList[face->vertex_index[0]]->e[2];
vtx0.uv[0] = obj->textureList[face->vertex_index[0]]->e[0];
vtx0.uv[1] = obj->textureList[face->vertex_index[0]]->e[1];
GraphicsVertex vtx1;
vtx1.xyzw[0] = obj->vertexList[face->vertex_index[1]]->e[0];
vtx1.xyzw[1] = obj->vertexList[face->vertex_index[1]]->e[1];
vtx1.xyzw[2] = obj->vertexList[face->vertex_index[1]]->e[2];
vtx1.uv[0] = obj->textureList[face->vertex_index[1]]->e[0];
vtx1.uv[1] = obj->textureList[face->vertex_index[1]]->e[1];
GraphicsVertex vtx2;
vtx2.xyzw[0] = obj->vertexList[face->vertex_index[2]]->e[0];
vtx2.xyzw[1] = obj->vertexList[face->vertex_index[2]]->e[1];
vtx2.xyzw[2] = obj->vertexList[face->vertex_index[2]]->e[2];
vtx2.uv[0] = obj->textureList[face->vertex_index[2]]->e[0];
vtx2.uv[1] = obj->textureList[face->vertex_index[2]]->e[1];
b3Vector3 v0(vtx0.xyzw[0],vtx0.xyzw[1],vtx0.xyzw[2]);
b3Vector3 v1(vtx1.xyzw[0],vtx1.xyzw[1],vtx1.xyzw[2]);
b3Vector3 v2(vtx2.xyzw[0],vtx2.xyzw[1],vtx2.xyzw[2]);
normal = (v1-v0).cross(v2-v0);
normal.normalize();
vtx0.normal[0] = normal[0];
vtx0.normal[1] = normal[1];
vtx0.normal[2] = normal[2];
vtx1.normal[0] = normal[0];
vtx1.normal[1] = normal[1];
vtx1.normal[2] = normal[2];
vtx2.normal[0] = normal[0];
vtx2.normal[1] = normal[1];
vtx2.normal[2] = normal[2];
vertices->push_back(vtx0);
vertices->push_back(vtx1);
vertices->push_back(vtx2);
}
if (face->vertex_count==4)
{
indicesPtr->push_back(vtxBaseIndex);
indicesPtr->push_back(vtxBaseIndex+1);
indicesPtr->push_back(vtxBaseIndex+2);
indicesPtr->push_back(vtxBaseIndex+3);
//
GraphicsVertex vtx3;
vtx3.xyzw[0] = obj->vertexList[face->vertex_index[3]]->e[0];
vtx3.xyzw[1] = obj->vertexList[face->vertex_index[3]]->e[1];
vtx3.xyzw[2] = obj->vertexList[face->vertex_index[3]]->e[2];
vtx3.uv[0] = 0.5;
vtx3.uv[1] = 0.5;
vtx3.normal[0] = normal[0];
vtx3.normal[1] = normal[1];
vtx3.normal[2] = normal[2];
vertices->push_back(vtx3);
}
}
}
GraphicsShape* gfxShape = new GraphicsShape;
gfxShape->m_vertices = &vertices->at(0).xyzw[0];
gfxShape->m_numvertices = vertices->size();
gfxShape->m_indices = &indicesPtr->at(0);
gfxShape->m_numIndices = indicesPtr->size();
for (int i=0;i<4;i++)
gfxShape->m_scaling[i] = 1;//bake the scaling into the vertices
return gfxShape;
}
}
//very incomplete conversion from physics to graphics
void graphics_from_physics(GLInstancingRenderer& renderer, bool syncTransformsOnly, int numObjects, b3CollisionObject** colObjArray)
{
///@todo: we need to sort the objects based on collision shape type, so we can share instances
B3_PROFILE("graphics_from_physics");
int strideInBytes = sizeof(float)*9;
int prevGraphicsShapeIndex = -1;
b3CollisionShape* prevShape = 0;
int numColObj = numObjects;
int curGraphicsIndex = 0;
float localScaling[4] = {1,1,1,1};
for (int i=0;i<numColObj;i++)
{
b3CollisionObject* colObj = colObjArray[i];
b3Vector3 pos = colObj->getWorldTransform().getOrigin();
b3Quaternion orn = colObj->getWorldTransform().getRotation();
float position[4] = {pos.getX(),pos.getY(),pos.getZ(),0.f};
float orientation[4] = {orn.getX(),orn.getY(),orn.getZ(),orn.getW()};
float color[4] = {0,0,0,1};
b3Vector3 localScaling = colObj->getCollisionShape()->getLocalScaling();
if (colObj->isStaticOrKinematicObject())
{
color[0]=1.f;
}else
{
color[1]=1.f;
}
if (!syncTransformsOnly)
{
if (prevShape != colObj->getCollisionShape())
{
if (colObj->getCollisionShape()->isPolyhedral())
{
b3PolyhedralConvexShape* polyShape = (b3PolyhedralConvexShape*)colObj->getCollisionShape();
const b3ConvexPolyhedron* pol = polyShape->getConvexPolyhedron();
GraphicsShape* gfxShape = createGraphicsShapeFromConvexHull(pol);
prevGraphicsShapeIndex = renderer.registerShape(&gfxShape->m_vertices[0],gfxShape->m_numvertices,gfxShape->m_indices,gfxShape->m_numIndices);
prevShape = colObj->getCollisionShape();
const b3Vector3& scaling = prevShape->getLocalScaling();
localScaling[0] = scaling.getX();localScaling[1] = scaling.getY();localScaling[2] = scaling.getZ();
} else
{
if (colObj->getCollisionShape()->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
b3BvhTriangleMeshShape* trimesh = (b3BvhTriangleMeshShape*) colObj->getCollisionShape();
GraphicsShape* gfxShape = createGraphicsShapeFromConcaveMesh(trimesh);
prevGraphicsShapeIndex = renderer.registerShape(&gfxShape->m_vertices[0],gfxShape->m_numvertices,gfxShape->m_indices,gfxShape->m_numIndices);
prevShape = colObj->getCollisionShape();
const b3Vector3& scaling = prevShape->getLocalScaling();
localScaling[0] = scaling.getX();localScaling[1] = scaling.getY();localScaling[2] = scaling.getZ();
} else
{
if (colObj->getCollisionShape()->getShapeType()==COMPOUND_SHAPE_PROXYTYPE)
{
b3CompoundShape* compound = (b3CompoundShape*) colObj->getCollisionShape();
GraphicsShape* gfxShape = createGraphicsShapeFromCompoundShape(compound);
if (gfxShape)
{
prevGraphicsShapeIndex = renderer.registerShape(&gfxShape->m_vertices[0],gfxShape->m_numvertices,gfxShape->m_indices,gfxShape->m_numIndices);
prevShape = colObj->getCollisionShape();
const b3Vector3& scaling = prevShape->getLocalScaling();
localScaling[0] = scaling.getX();localScaling[1] = scaling.getY();localScaling[2] = scaling.getZ();
} else
{
prevGraphicsShapeIndex = -1;
}
} else
{
if (colObj->getCollisionShape()->getShapeType()==SPHERE_SHAPE_PROXYTYPE)
{
b3SphereShape* sphere = (b3SphereShape*) colObj->getCollisionShape();
b3Scalar radius = sphere->getRadius();
//b3ConvexHullShape* spherePoly = new b3ConvexHullShape(
//const b3ConvexPolyhedron* pol = polyShape->getConvexPolyhedron();
/*
objLoader loader;
int result = loader.load("../../bin/wavefront/sphere_low.obj");
GraphicsShape* gfxShape = createGraphicsShapeFromWavefrontObj(&loader);
int vertexStrideInBytes = 9*sizeof(float);
printf("vertices (%d):\n",gfxShape->m_numvertices);
for (int i=0;i<gfxShape->m_numvertices;i++)
{
gfxShape->m_vertices[i*9+4] = gfxShape->m_vertices[i*9];
gfxShape->m_vertices[i*9+5] = gfxShape->m_vertices[i*9+1];
gfxShape->m_vertices[i*9+6] = gfxShape->m_vertices[i*9+2];
printf("%f,%f,%f,%f,%f,%f,%f,%f,%f,\n",
gfxShape->m_vertices[i*9],
gfxShape->m_vertices[i*9+1],
gfxShape->m_vertices[i*9+2],
0.f,//gfxShape->m_vertices[i*9+3],
//gfxShape->m_vertices[i*9+4],//face normals
//gfxShape->m_vertices[i*9+5],
//gfxShape->m_vertices[i*9+6],
gfxShape->m_vertices[i*9+0],
gfxShape->m_vertices[i*9+1],
gfxShape->m_vertices[i*9+2],
gfxShape->m_vertices[i*9+7],
gfxShape->m_vertices[i*9+8]);
}
printf("indices (%d):\n",gfxShape->m_numIndices);
for (int i=0;i<gfxShape->m_numIndices/3;i++)
{
printf("%d,%d,%d,\n",gfxShape->m_indices[i*3],
gfxShape->m_indices[i*3+1],
gfxShape->m_indices[i*3+2]);
}
prevGraphicsShapeIndex = renderer.registerShape(&gfxShape->m_vertices[0],gfxShape->m_numvertices,gfxShape->m_indices,gfxShape->m_numIndices);
*/
if (radius>=100)
{
int numVertices = sizeof(detailed_sphere_vertices)/strideInBytes;
int numIndices = sizeof(detailed_sphere_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&detailed_sphere_vertices[0],numVertices,detailed_sphere_indices,numIndices);
} else
{
bool usePointSprites = true;
if (usePointSprites)
{
int numVertices = sizeof(point_sphere_vertices)/strideInBytes;
int numIndices = sizeof(point_sphere_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS);
} else
{
if (radius>=10)
{
int numVertices = sizeof(medium_sphere_vertices)/strideInBytes;
int numIndices = sizeof(medium_sphere_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&medium_sphere_vertices[0],numVertices,medium_sphere_indices,numIndices);
} else
{
int numVertices = sizeof(low_sphere_vertices)/strideInBytes;
int numIndices = sizeof(low_sphere_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&low_sphere_vertices[0],numVertices,low_sphere_indices,numIndices);
}
}
}
prevShape = sphere;
const b3Vector3& scaling = prevShape->getLocalScaling();
//assume uniform scaling, using X component
float sphereScale = radius*scaling.getX();
localScaling[0] = sphereScale;
localScaling[1] = sphereScale;
localScaling[2] = sphereScale;
} else
{
if (colObj->getCollisionShape()->getShapeType()==STATIC_PLANE_PROXYTYPE)
{
b3StaticPlaneShape* plane= (b3StaticPlaneShape*) colObj->getCollisionShape();
prevShape = colObj->getCollisionShape();
//plane->getPlaneNormal()
//plane->getPlaneConstant()
if (1)
{
int numVertices = sizeof(quad_vertices)/strideInBytes;
int numIndices = sizeof(quad_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&quad_vertices[0],numVertices,quad_indices,numIndices);
} else
{
int numVertices = sizeof(detailed_sphere_vertices)/strideInBytes;
int numIndices = sizeof(detailed_sphere_indices)/sizeof(int);
prevGraphicsShapeIndex = renderer.registerShape(&detailed_sphere_vertices[0],numVertices,detailed_sphere_indices,numIndices);
}
localScaling[0] = 100;
localScaling[1] = 1;
localScaling[2] = 100;
} else
{
printf("Error: unsupported collision shape type in %s %d\n", __FILE__, __LINE__);
prevGraphicsShapeIndex = -1;
b3Assert(0);
}
}
}
}
}
}
}
{
if (!syncTransformsOnly)
{
if (prevShape && prevGraphicsShapeIndex>=0)
{
renderer.registerGraphicsInstance(prevGraphicsShapeIndex,position,orientation,color,localScaling);
}
}
else
{
renderer.writeSingleInstanceTransformToCPU(position,orientation,curGraphicsIndex);
}
curGraphicsIndex++;
}
}
}
void OpenGL3CoreRenderer::renderPhysicsWorld(int numObjects, b3CollisionObject** colObjArray, bool syncOnly)
{
//sync changes from physics world to render world
//for now, we don't deal with adding/removing objects to the world during the simulation, to keep the rendererer simpler
m_instancingRenderer->writeTransforms();
graphics_from_physics(*m_instancingRenderer,syncOnly,numObjects, colObjArray);
//render
m_instancingRenderer->RenderScene();
}

View File

@@ -1,26 +0,0 @@
#ifndef OPENGL3_CORE_RENDERER_H
#define OPENGL3_CORE_RENDERER_H
class b3CollisionObject;
class GLInstancingRenderer;
class OpenGL3CoreRenderer
{
GLInstancingRenderer* m_instancingRenderer;
public:
OpenGL3CoreRenderer();
virtual ~OpenGL3CoreRenderer();
void init();
void reshape(int w, int h);
void keyboardCallback(unsigned char key);
void renderPhysicsWorld(int numObjects, b3CollisionObject** colObjArray, bool syncOnly);
GLInstancingRenderer* getInstancingRenderer()
{
return m_instancingRenderer;
}
};
#endif //OPENGL3_CORE_RENDERER_H

View File

@@ -1,17 +0,0 @@
#include "b3CpuDynamicsWorld.h"
#include "b3BulletDynamicsCommon.h"
b3CpuDynamicsWorld::b3CpuDynamicsWorld()
:b3DiscreteDynamicsWorld(
new b3CollisionDispatcher(new b3DefaultCollisionConfiguration()),
new b3DynamicBvhBroadphase(),new b3SequentialImpulseConstraintSolver(),
new b3DefaultCollisionConfiguration()//todo: remove this!
)
{
}
b3CpuDynamicsWorld::~b3CpuDynamicsWorld()
{
}

View File

@@ -1,24 +0,0 @@
#ifndef B3_CPU_DYNAMICS_WORLD_H
#define B3_CPU_DYNAMICS_WORLD_H
class b3DefaultCollisionConfiguration;
class b3CollisionDispatcher;
struct b3DynamicBvhBroadphase;
class b3SequentialImpulseConstraintSolver;
#include "BulletDynamics/Dynamics/b3DiscreteDynamicsWorld.h"
class b3CpuDynamicsWorld : public b3DiscreteDynamicsWorld
{
public:
b3CpuDynamicsWorld();
virtual ~b3CpuDynamicsWorld();
};
#endif //B3_CPU_DYNAMICS_WORLD_H

View File

@@ -1,300 +0,0 @@
#include "b3GpuDynamicsWorld.h"
#include "BulletDynamics/Dynamics/b3RigidBody.h"
#include "../../../opencl/gpu_rigidbody_pipeline2/CLPhysicsDemo.h"
#include "../../../opencl/gpu_rigidbody_pipeline/b3GpuNarrowPhaseAndSolver.h"
#include "BulletCollision/CollisionShapes/b3PolyhedralConvexShape.h"
#include "BulletCollision/CollisionShapes/b3BvhTriangleMeshShape.h"
#include "BulletCollision/CollisionShapes/b3CompoundShape.h"
#include "BulletCollision/CollisionShapes/b3SphereShape.h"
#include "BulletCollision/CollisionShapes/b3StaticPlaneShape.h"
#include "LinearMath/b3Quickprof.h"
#ifdef _WIN32
#include <wiNdOws.h>
#endif
b3GpuDynamicsWorld::b3GpuDynamicsWorld(int preferredOpenCLPlatformIndex,int preferredOpenCLDeviceIndex)
:b3DynamicsWorld(0,0,0),
m_gravity(0,-10,0),
m_once(true)
{
m_gpuPhysics = new CLPhysicsDemo(512*1024, MAX_CONVEX_BODIES_CL);
bool useInterop = false;
///platform and device are swapped, todo: fix this and make it consistent
m_gpuPhysics->init(preferredOpenCLDeviceIndex,preferredOpenCLPlatformIndex,useInterop);
}
b3GpuDynamicsWorld::~b3GpuDynamicsWorld()
{
delete m_gpuPhysics;
}
void b3GpuDynamicsWorld::exitOpenCL()
{
}
int b3GpuDynamicsWorld::stepSimulation( b3Scalar timeStep,int maxSubSteps, b3Scalar fixedTimeStep)
{
#ifndef B3_NO_PROFILE
// b3ProfileManager::Reset();
#endif //B3_NO_PROFILE
B3_PROFILE("stepSimulation");
//convert all shapes now, and if any change, reset all (todo)
if (m_once)
{
m_once = false;
m_gpuPhysics->writeBodiesToGpu();
}
m_gpuPhysics->stepSimulation();
{
{
B3_PROFILE("readbackBodiesToCpu");
//now copy info back to rigid bodies....
m_gpuPhysics->readbackBodiesToCpu();
}
{
B3_PROFILE("scatter transforms into rigidbody (CPU)");
for (int i=0;i<this->m_collisionObjects.size();i++)
{
b3Vector3 pos;
b3Quaternion orn;
m_gpuPhysics->getObjectTransformFromCpu(&pos[0],&orn[0],i);
b3Transform newTrans;
newTrans.setOrigin(pos);
newTrans.setRotation(orn);
this->m_collisionObjects[i]->setWorldTransform(newTrans);
}
}
}
#ifndef B3_NO_PROFILE
//b3ProfileManager::Increment_Frame_Counter();
#endif //B3_NO_PROFILE
return 1;
}
void b3GpuDynamicsWorld::setGravity(const b3Vector3& gravity)
{
}
int b3GpuDynamicsWorld::findOrRegisterCollisionShape(const b3CollisionShape* colShape)
{
int index = m_uniqueShapes.findLinearSearch(colShape);
if (index==m_uniqueShapes.size())
{
if (colShape->isPolyhedral())
{
m_uniqueShapes.push_back(colShape);
b3PolyhedralConvexShape* convex = (b3PolyhedralConvexShape*)colShape;
int numVertices=convex->getNumVertices();
int strideInBytes=sizeof(b3Vector3);
b3AlignedObjectArray<b3Vector3> tmpVertices;
tmpVertices.resize(numVertices);
for (int i=0;i<numVertices;i++)
convex->getVertex(i,tmpVertices[i]);
const float scaling[4]={1,1,1,1};
bool noHeightField=true;
int gpuShapeIndex = m_gpuPhysics->registerConvexPolyhedron(&tmpVertices[0].getX(), strideInBytes, numVertices, scaling, noHeightField);
m_uniqueShapeMapping.push_back(gpuShapeIndex);
} else
{
if (colShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
m_uniqueShapes.push_back(colShape);
b3BvhTriangleMeshShape* trimesh = (b3BvhTriangleMeshShape*) colShape;
b3StridingMeshInterface* meshInterface = trimesh->getMeshInterface();
b3AlignedObjectArray<b3Vector3> vertices;
b3AlignedObjectArray<int> indices;
b3Vector3 trimeshScaling(1,1,1);
for (int partId=0;partId<meshInterface->getNumSubParts();partId++)
{
const unsigned char *vertexbase = 0;
int numverts = 0;
PHY_ScalarType type = PHY_INTEGER;
int stride = 0;
const unsigned char *indexbase = 0;
int indexstride = 0;
int numfaces = 0;
PHY_ScalarType indicestype = PHY_INTEGER;
//PHY_ScalarType indexType=0;
b3Vector3 triangleVerts[3];
meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
b3Vector3 aabbMin,aabbMax;
for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
{
unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
for (int j=2;j>=0;j--)
{
int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
if (type == PHY_FLOAT)
{
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
triangleVerts[j] = b3Vector3(
graphicsbase[0]*trimeshScaling.getX(),
graphicsbase[1]*trimeshScaling.getY(),
graphicsbase[2]*trimeshScaling.getZ());
}
else
{
double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
triangleVerts[j] = b3Vector3( b3Scalar(graphicsbase[0]*trimeshScaling.getX()),
b3Scalar(graphicsbase[1]*trimeshScaling.getY()),
b3Scalar(graphicsbase[2]*trimeshScaling.getZ()));
}
}
vertices.push_back(triangleVerts[0]);
vertices.push_back(triangleVerts[1]);
vertices.push_back(triangleVerts[2]);
indices.push_back(indices.size());
indices.push_back(indices.size());
indices.push_back(indices.size());
}
}
//GraphicsShape* gfxShape = 0;//b3BulletDataExtractor::createGraphicsShapeFromWavefrontObj(objData);
//GraphicsShape* gfxShape = b3BulletDataExtractor::createGraphicsShapeFromConvexHull(&sUnitSpherePoints[0],MY_UNITSPHERE_POINTS);
float meshScaling[4] = {1,1,1,1};
//int shapeIndex = renderer.registerShape(gfxShape->m_vertices,gfxShape->m_numvertices,gfxShape->m_indices,gfxShape->m_numIndices);
float groundPos[4] = {0,0,0,0};
//renderer.registerGraphicsInstance(shapeIndex,groundPos,rotOrn,color,meshScaling);
if (vertices.size() && indices.size())
{
int gpuShapeIndex = m_gpuPhysics->registerConcaveMesh(&vertices,&indices, meshScaling);
m_uniqueShapeMapping.push_back(gpuShapeIndex);
} else
{
printf("Error: no vertices in mesh in b3GpuDynamicsWorld::addRigidBody\n");
index = -1;
b3Assert(0);
}
} else
{
if (colShape->getShapeType()==COMPOUND_SHAPE_PROXYTYPE)
{
b3CompoundShape* compound = (b3CompoundShape*) colShape;
b3AlignedObjectArray<b3GpuChildShape> childShapes;
for (int i=0;i<compound->getNumChildShapes();i++)
{
//for now, only support polyhedral child shapes
b3Assert(compound->getChildShape(i)->isPolyhedral());
b3GpuChildShape child;
child.m_shapeIndex = findOrRegisterCollisionShape(compound->getChildShape(i));
b3Vector3 pos = compound->getChildTransform(i).getOrigin();
b3Quaternion orn = compound->getChildTransform(i).getRotation();
for (int v=0;v<4;v++)
{
child.m_childPosition[v] = pos[v];
child.m_childOrientation[v] = orn[v];
}
childShapes.push_back(child);
}
index = m_uniqueShapes.size();
m_uniqueShapes.push_back(colShape);
int gpuShapeIndex = m_gpuPhysics->registerCompoundShape(&childShapes);
m_uniqueShapeMapping.push_back(gpuShapeIndex);
/*printf("Error: unsupported compound type (%d) in b3GpuDynamicsWorld::addRigidBody\n",colShape->getShapeType());
index = -1;
b3Assert(0);
*/
} else
{
if (colShape->getShapeType()==SPHERE_SHAPE_PROXYTYPE)
{
m_uniqueShapes.push_back(colShape);
b3SphereShape* sphere = (b3SphereShape*)colShape;
int gpuShapeIndex = m_gpuPhysics->registerSphereShape(sphere->getRadius());
m_uniqueShapeMapping.push_back(gpuShapeIndex);
} else
{
if (colShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
{
m_uniqueShapes.push_back(colShape);
b3StaticPlaneShape* plane = (b3StaticPlaneShape*)colShape;
int gpuShapeIndex = m_gpuPhysics->registerPlaneShape(plane->getPlaneNormal(),plane->getPlaneConstant());
m_uniqueShapeMapping.push_back(gpuShapeIndex);
} else
{
printf("Error: unsupported shape type (%d) in b3GpuDynamicsWorld::addRigidBody\n",colShape->getShapeType());
index = -1;
b3Assert(0);
}
}
}
}
}
}
return index;
}
void b3GpuDynamicsWorld::addRigidBody(b3RigidBody* body)
{
body->setMotionState(0);
int index = findOrRegisterCollisionShape(body->getCollisionShape());
if (index>=0)
{
int gpuShapeIndex= m_uniqueShapeMapping[index];
float mass = body->getInvMass() ? 1.f/body->getInvMass() : 0.f;
b3Vector3 pos = body->getWorldTransform().getOrigin();
b3Quaternion orn = body->getWorldTransform().getRotation();
m_gpuPhysics->registerPhysicsInstance(mass,&pos.getX(),&orn.getX(),gpuShapeIndex,m_collisionObjects.size());
m_collisionObjects.push_back(body);
}
}
void b3GpuDynamicsWorld::removeCollisionObject(b3CollisionObject* colObj)
{
b3DynamicsWorld::removeCollisionObject(colObj);
}

View File

@@ -1,109 +0,0 @@
#ifndef B3_GPU_DYNAMICS_WORLD_H
#define B3_GPU_DYNAMICS_WORLD_H
class b3Vector3;
class b3RigidBody;
class b3CollisionObject;
struct b3GpuInternalData;//use this struct to avoid 'leaking' all OpenCL headers into clients code base
class CLPhysicsDemo;
#include "Bullet3Common/b3AlignedObjectArray.h"
//#include "BulletDynamics/Dynamics/b3DynamicsWorld.h"
class b3GpuDynamicsWorld //: public b3DynamicsWorld
{
b3AlignedObjectArray<const class b3CollisionShape*> m_uniqueShapes;
b3AlignedObjectArray<int> m_uniqueShapeMapping;
CLPhysicsDemo* m_gpuPhysics;
b3Vector3 m_gravity;
bool m_once;
bool initOpenCL(int preferredDeviceIndex, int preferredPlatformIndex, bool useInterop);
void exitOpenCL();
int findOrRegisterCollisionShape(const b3CollisionShape* colShape);
public:
b3GpuDynamicsWorld(int preferredOpenCLPlatformIndex,int preferredOpenCLDeviceIndex);
virtual ~b3GpuDynamicsWorld();
virtual int stepSimulation( b3Scalar timeStep,int maxSubSteps=1, b3Scalar fixedTimeStep=b3Scalar(1.)/b3Scalar(60.));
virtual void synchronizeMotionStates()
{
b3Assert(0);
}
void debugDrawWorld() {}
void setGravity(const b3Vector3& gravity);
void addRigidBody(b3RigidBody* body);
void removeCollisionObject(b3CollisionObject* colObj);
b3AlignedObjectArray<class b3CollisionObject*>& getCollisionObjectArray();
const b3AlignedObjectArray<class b3CollisionObject*>& getCollisionObjectArray() const;
virtual void addAction(b3ActionInterface* action)
{
b3Assert(0);
}
virtual void removeAction(b3ActionInterface* action)
{
b3Assert(0);
}
b3Vector3 getGravity () const
{
return m_gravity;
}
virtual void addRigidBody(b3RigidBody* body, short group, short mask)
{
addRigidBody(body);
}
virtual void removeRigidBody(b3RigidBody* body)
{
b3Assert(0);
}
virtual void setConstraintSolver(b3ConstraintSolver* solver)
{
b3Assert(0);
}
virtual b3ConstraintSolver* getConstraintSolver()
{
b3Assert(0);
return 0;
}
virtual b3DynamicsWorldType getWorldType() const
{
return B3_GPU_PHYSICS_WORLD;
}
virtual void clearForces()
{
b3Assert(0);
}
};
#endif //B3_GPU_DYNAMICS_WORLD_H

View File

@@ -13,7 +13,6 @@
"..",
".",
"../../src"
}
initOpenGL()
@@ -37,11 +36,6 @@
"../OpenGLTrueTypeFont/fontstash.h",
"../OpenGLTrueTypeFont/opengl_fontstashcallbacks.cpp",
"../OpenGLTrueTypeFont/opengl_fontstashcallbacks.h",
"../../src/Bullet3Geometry/b3ConvexHullComputer.cpp",
"../../src/Bullet3Geometry/b3ConvexHullComputer.h",
"../../src/Bullet3Common/b3Logging.h",
"../../src/Bullet3Common/b3Logging.cpp",
"../../src/Bullet3Common/b3AlignedAllocator.cpp",
"../../btgui/Timing/b3Clock.cpp",
"../../btgui/Timing/b3Clock.h",
"**.cpp",

View File

@@ -322,7 +322,7 @@ static GLint lines_position=0;
static GLint lines_colour=0;
GLuint lineVertexBufferObject=0;
GLuint lineVertexArrayObject=0;
GLuint lineIndexVbo = 0;
@@ -720,17 +720,21 @@ void GLInstancingRenderer::InitShaders()
int SCALE_BUFFER_SIZE = (m_maxNumObjectCapacity*sizeof(float)*3);
linesShader = gltLoadShaderPair(linesVertexShader,linesFragmentShader);
glLinkProgram(linesShader);
glUseProgram(linesShader);
lines_ModelViewMatrix = glGetUniformLocation(linesShader, "ModelViewMatrix");
lines_ProjectionMatrix = glGetUniformLocation(linesShader, "ProjectionMatrix");
lines_colour=glGetUniformLocation(linesShader, "colour");
lines_position=glGetAttribLocation(linesShader, "position");
glLinkProgram(linesShader);
glUseProgram(linesShader);
glGenBuffers(1, &lineVertexBufferObject);
glGenVertexArrays(1, &lineVertexArrayObject);
glBindVertexArray(lineVertexArrayObject);
glGenBuffers(1, &lineVertexBufferObject);
glGenBuffers(1, &lineIndexVbo);
glBindVertexArray(0);
//glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range);
glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, lineWidthRange);
@@ -1315,16 +1319,85 @@ void GLInstancingRenderer::drawPoints(const float* positions, const float color[
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, numPoints*pointStrideInBytes, positions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
// glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
glEnableVertexAttribArray(0);
int numFloats = 3;//pointStrideInBytes/sizeof(float);
glVertexAttribPointer(0, numFloats, GL_FLOAT, GL_FALSE, pointStrideInBytes, 0);
int numFloats = pointStrideInBytes/sizeof(float);
glVertexAttribPointer(0, numFloats, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINTS, 0, numPoints);
glBindVertexArray(0);
glPointSize(1);
}
void GLInstancingRenderer::drawLines(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, const unsigned int* indices, int numIndices, float pointDrawSize)
{
glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
GLint err = glGetError();
b3Assert(err==GL_NO_ERROR);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,0);
int curOffset = 0;
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glUseProgram(linesShader);
glUniformMatrix4fv(lines_ProjectionMatrix, 1, false, &projectionMatrix[0]);
glUniformMatrix4fv(lines_ModelViewMatrix, 1, false, &modelviewMatrix[0]);
glUniform4f(lines_colour,color[0],color[1],color[2],color[3]);
// glPointSize(pointDrawSize);
glBindVertexArray(lineVertexArrayObject);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, numPoints*pointStrideInBytes, positions, GL_STATIC_DRAW);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, lineVertexBufferObject);
glEnableVertexAttribArray(0);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
int numFloats = pointStrideInBytes/sizeof(float);
glVertexAttribPointer(0, numFloats, GL_FLOAT, GL_FALSE, 0, 0);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lineIndexVbo);
int indexBufferSizeInBytes = numIndices*sizeof(int);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSizeInBytes, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,indexBufferSizeInBytes,indices);
glDrawElements(GL_LINES, numIndices, GL_UNSIGNED_INT,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// for (int i=0;i<numIndices;i++)
// printf("indicec[i]=%d]\n",indices[i]);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glBindVertexArray(0);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
glPointSize(1);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
}
void GLInstancingRenderer::drawLine(const float from[4], const float to[4], const float color[4], float lineWidth)
{
GLint err = glGetError();

View File

@@ -90,6 +90,7 @@ public:
struct GLInstanceRendererInternalData* getInternalData();
void drawLine(const float from[4], const float to[4], const float color[4], float lineWidth=1);
void drawLines(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, const unsigned int* indices, int numIndices, float pointDrawSize);
void drawPoints(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, float pointDrawSize);
void drawPoint(const float* position, const float color[4], float pointSize=1);
void updateCamera();

View File

@@ -288,6 +288,8 @@ void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y
glUniform2fv(m_data->m_positionUniform, 1, (const GLfloat *)&p);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
err = glGetError();
assert(err==GL_NO_ERROR);
err = glGetError();
@@ -316,6 +318,7 @@ void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y
err = glGetError();
assert(err==GL_NO_ERROR);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
err = glGetError();
assert(err==GL_NO_ERROR);

View File

@@ -3,7 +3,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "Bullet3Common/b3Logging.h"
// Load the shader from the source text
void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader)
@@ -90,8 +90,8 @@ GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg)
&actualLen,
infoLog);
b3Error("Warning/Error in GLSL shader:\n");
b3Error("%s\n",infoLog);
printf("Warning/Error in GLSL shader:\n");
printf("%s\n",infoLog);
glDeleteProgram(hReturn);
return (GLuint)NULL;
}

View File

@@ -0,0 +1,215 @@
#include "SimpleOpenGL3App.h"
#ifdef __APPLE__
#include "OpenGLWindow/MacOpenGLWindow.h"
#else
#include "GL/glew.h"
#ifdef _WIN32
#include "OpenGLWindow/Win32OpenGLWindow.h"
#else
//let's cross the fingers it is Linux/X11
#include "OpenGLWindow/X11OpenGLWindow.h"
#endif //_WIN32
#endif//__APPLE__
#include "OpenGLWindow/GLPrimitiveRenderer.h"
#include "OpenGLWindow/GLInstancingRenderer.h"
#include "Bullet3Common/b3Vector3.h"
#include "../btgui/OpenGLTrueTypeFont/fontstash.h"
#include "../btgui/OpenGLWindow/TwFonts.h"
struct SimpleInternalData
{
GLuint m_fontTextureId;
};
static SimpleOpenGL3App* gApp=0;
void SimpleResizeCallback( float width, float height)
{
gApp->m_instancingRenderer->resize(width,height);
gApp->m_primRenderer->setScreenSize(width,height);
}
static GLuint BindFont(const CTexFont *_Font)
{
GLuint TexID = 0;
glGenTextures(1, &TexID);
glBindTexture(GL_TEXTURE_2D, TexID);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
return TexID;
}
SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height)
{
gApp = this;
m_data = new SimpleInternalData;
m_window = new b3gDefaultOpenGLWindow();
b3gWindowConstructionInfo ci;
ci.m_title = title;
ci.m_width = width;
ci.m_height = height;
m_window->createWindow(ci);
m_window->setWindowTitle(title);
glClearColor(1,1,1,1);
m_window->startRendering();
#ifndef __APPLE__
glewInit();
#endif
m_primRenderer = new GLPrimitiveRenderer(width,height);
m_instancingRenderer = new GLInstancingRenderer(128*1024,4*1024*1024);
m_instancingRenderer->init();
m_instancingRenderer->resize(width,height);
m_instancingRenderer->InitShaders();
m_window->setMouseMoveCallback(b3DefaultMouseMoveCallback);
m_window->setMouseButtonCallback(b3DefaultMouseButtonCallback);
m_window->setKeyboardCallback(b3DefaultKeyboardCallback);
m_window->setWheelCallback(b3DefaultWheelCallback);
m_window->setResizeCallback(SimpleResizeCallback);
TwGenerateDefaultFonts();
m_data->m_fontTextureId = BindFont(g_DefaultNormalFont);
}
void SimpleOpenGL3App::drawText( const char* txt, int posX, int posY)
{
//
//printf("str = %s\n",unicodeText);
int xpos=0;
int ypos=0;
float dx;
int measureOnly=0;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
if (m_useTrueTypeFont)
{
float yoffset = 0.f;
if (m_retinaScale==2.0f)
{
yoffset = -12;
}
Translate(r);
sth_draw_text(m_font,
1,m_fontScaling,
r.x,r.y+yoffset,
unicodeText,&dx, m_screenWidth,m_screenHeight,measureOnly,m_retinaScale);
} else
*/
{
//float width = 0.f;
int pos=0;
float color[]={0.2f,0.2,0.2f,1.f};
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,m_data->m_fontTextureId);
//float width = r.x;
float extraSpacing = 0.;
int startX = posX;
int startY = posY;
while (txt[pos])
{
int c = txt[pos];
//r.h = g_DefaultNormalFont->m_CharHeight;
//r.w = g_DefaultNormalFont->m_CharWidth[c]+extraSpacing;
int endX = startX+g_DefaultNormalFont->m_CharWidth[c];
int endY = startY+g_DefaultNormalFont->m_CharHeight;
//Gwen::Rect rect = r;
//Translate( rect );
float currentColor[]={0.2f,0.2,0.2f,1.f};
m_primRenderer->drawTexturedRect(startX, startY, endX, endY, currentColor,g_DefaultNormalFont->m_CharU0[c],g_DefaultNormalFont->m_CharV0[c],g_DefaultNormalFont->m_CharU1[c],g_DefaultNormalFont->m_CharV1[c]);
//DrawTexturedRect(0,r,g_DefaultNormalFont->m_CharU0[c],g_DefaultNormalFont->m_CharV0[c],g_DefaultNormalFont->m_CharU1[c],g_DefaultNormalFont->m_CharV1[c]);
// DrawFilledRect(r);
startX = endX;
//startY = endY;
pos++;
}
glBindTexture(GL_TEXTURE_2D,0);
}
glDisable(GL_BLEND);
}
void SimpleOpenGL3App::drawGrid(int gridSize)
{
b3Vector3 gridColor = b3MakeVector3(0.5,0.5,0.5);
for(int i=-gridSize;i<=gridSize;i++)
{
GLint err = glGetError();
b3Assert(err==GL_NO_ERROR);
m_instancingRenderer->drawLine(b3MakeVector3(float(i),0,float(-gridSize)),b3MakeVector3(float(i),0,float(gridSize)),gridColor);
err = glGetError();
b3Assert(err==GL_NO_ERROR);
m_instancingRenderer->drawLine(b3MakeVector3(float(-gridSize),0,float(i)),b3MakeVector3(float(gridSize),0,float(i)),gridColor);
}
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(1,0,0),b3MakeVector3(1,0,0),3);
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,1,0),b3MakeVector3(0,1,0),3);
m_instancingRenderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,0,1),b3MakeVector3(0,0,1),3);
m_instancingRenderer->drawPoint(b3MakeVector3(1,0,0),b3MakeVector3(1,0,0),6);
m_instancingRenderer->drawPoint(b3MakeVector3(0,1,0),b3MakeVector3(0,1,0),6);
m_instancingRenderer->drawPoint(b3MakeVector3(0,0,1),b3MakeVector3(0,0,1),6);
}
SimpleOpenGL3App::~SimpleOpenGL3App()
{
delete m_primRenderer ;
m_window->closeWindow();
delete m_window;
delete m_data ;
}
void SimpleOpenGL3App::swapBuffer()
{
m_window->endRendering();
m_window->startRendering();
}

View File

@@ -0,0 +1,25 @@
#ifndef SIMPLE_OPENGL3_APP_H
#define SIMPLE_OPENGL3_APP_H
#include "OpenGLWindow/GLInstancingRenderer.h"
#include "OpenGLWindow/GLPrimitiveRenderer.h"
#include "OpenGLWindow/b3gWindowInterface.h"
struct SimpleOpenGL3App
{
struct SimpleInternalData* m_data;
class b3gWindowInterface* m_window;
class GLPrimitiveRenderer* m_primRenderer;
class GLInstancingRenderer* m_instancingRenderer;
SimpleOpenGL3App(const char* title, int width,int height);
virtual ~SimpleOpenGL3App();
void drawGrid(int gridSize=10);
void swapBuffer();
void drawText( const char* txt, int posX, int posY);
};
#endif //SIMPLE_OPENGL3_APP_H

View File

@@ -18,14 +18,14 @@ subject to the following restrictions:
#include "OpenGLInclude.h"
#include "Bullet3Common/b3Vector3.h"
//#include "Bullet3Common/b3Vector3.h"
#include "Win32InternalWindowData.h"
#include <stdio.h>
static void printGLString(const char *name, GLenum s) {
const char *v = (const char *) glGetString(s);
b3Printf("GL %s = %s\n", name, v);
printf("%s = %s\n",name, v);
}

View File

@@ -17,7 +17,7 @@ subject to the following restrictions:
#include "Win32Window.h"
#include "OpenGLInclude.h"
#include "Bullet3Common/b3Vector3.h"
#include <wchar.h>
static InternalData2* sData = 0;

View File

@@ -29,6 +29,8 @@
"GLInstancingRenderer.h",
"GLPrimitiveRenderer.h",
"GLPrimitiveRenderer.cpp",
"SimpleOpenGL3App.cpp",
"SimpleOpenGL3App.h",
"LoadShader.cpp",
"LoadShader.h",
"gwenWindow.cpp",

View File

@@ -101,11 +101,13 @@
if not _OPTIONS["ios"] then
-- include "../Demos3/CpuDemos"
include "../Demos3/GpuDemos"
-- include "../Demos3/CpuDemos"
include "../Demos3/Wavefront"
include "../btgui/MultiThreading"
include "../Demos3/ImplicitCloth"
-- include "../demo/gpudemo"
-- include "../btgui/MidiTest"