403 lines
11 KiB
C++
403 lines
11 KiB
C++
#include "SimpleOpenGL3App.h"
|
|
#include "ShapeData.h"
|
|
#ifdef __APPLE__
|
|
#include "OpenGLWindow/MacOpenGLWindow.h"
|
|
#else
|
|
|
|
#include "OpenGLWindow/GlewWindows/GL/glew.h"
|
|
//#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 "Bullet3Common/b3Logging.h"
|
|
|
|
#include "OpenGLTrueTypeFont/fontstash.h"
|
|
#include "OpenGLWindow/TwFonts.h"
|
|
#include "OpenGLTrueTypeFont/opengl_fontstashcallbacks.h"
|
|
#include <assert.h>
|
|
|
|
struct SimpleInternalData
|
|
{
|
|
GLuint m_fontTextureId;
|
|
struct sth_stash* m_fontStash;
|
|
OpenGL2RenderCallbacks* m_renderCallbacks;
|
|
int m_droidRegular;
|
|
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
extern char OpenSansData[];
|
|
|
|
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);
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
glClearColor(1,1,1,1);
|
|
m_window->startRendering();
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
#ifndef __APPLE__
|
|
#ifndef _WIN32
|
|
//some Linux implementations need the 'glewExperimental' to be true
|
|
glewExperimental = GL_TRUE;
|
|
#endif
|
|
|
|
|
|
if (glewInit() != GLEW_OK)
|
|
exit(1); // or handle the error in a nicer way
|
|
if (!GLEW_VERSION_2_1) // check that the machine supports the 2.1 API.
|
|
exit(1); // or handle the error in a nicer way
|
|
|
|
#endif
|
|
glGetError();//don't remove this call, it is needed for Ubuntu
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
m_primRenderer = new GLPrimitiveRenderer(width,height);
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
m_instancingRenderer = new GLInstancingRenderer(128*1024,4*1024*1024);
|
|
m_instancingRenderer->init();
|
|
m_instancingRenderer->resize(width,height);
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
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);
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_data->m_renderCallbacks = new OpenGL2RenderCallbacks(m_primRenderer);
|
|
m_data->m_fontStash = sth_create(512,512,m_data->m_renderCallbacks);//256,256);//,1024);//512,512);
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
|
|
if (!m_data->m_fontStash)
|
|
{
|
|
b3Warning("Could not create stash");
|
|
//fprintf(stderr, "Could not create stash.\n");
|
|
}
|
|
|
|
|
|
char* data2 = OpenSansData;
|
|
unsigned char* data = (unsigned char*) data2;
|
|
if (!(m_data->m_droidRegular = sth_add_font_from_memory(m_data->m_fontStash, data)))
|
|
{
|
|
b3Warning("error!\n");
|
|
}
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
}
|
|
}
|
|
|
|
|
|
struct sth_stash* SimpleOpenGL3App::getFontStash()
|
|
{
|
|
return m_data->m_fontStash;
|
|
}
|
|
|
|
|
|
|
|
void SimpleOpenGL3App::drawText( const char* txt, int posX, int posY)
|
|
{
|
|
|
|
|
|
|
|
|
|
//
|
|
//printf("str = %s\n",unicodeText);
|
|
|
|
float dx=0;
|
|
|
|
//int measureOnly=0;
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
if (1)//m_useTrueTypeFont)
|
|
{
|
|
bool measureOnly = false;
|
|
|
|
float fontSize= 64;//512;//128;
|
|
sth_draw_text(m_data->m_fontStash,
|
|
m_data->m_droidRegular,fontSize,posX,posY,
|
|
txt,&dx, this->m_instancingRenderer->getScreenWidth(),this->m_instancingRenderer->getScreenHeight(),measureOnly,m_window->getRetinaScale());
|
|
sth_end_draw(m_data->m_fontStash);
|
|
sth_flush_draw(m_data->m_fontStash);
|
|
} 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);
|
|
}
|
|
|
|
struct GfxVertex
|
|
{
|
|
float x,y,z,w;
|
|
float nx,ny,nz;
|
|
float u,v;
|
|
};
|
|
|
|
int SimpleOpenGL3App::registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ)
|
|
{
|
|
|
|
|
|
int strideInBytes = 9*sizeof(float);
|
|
int numVertices = sizeof(cube_vertices)/strideInBytes;
|
|
int numIndices = sizeof(cube_indices)/sizeof(int);
|
|
|
|
b3AlignedObjectArray<GfxVertex> verts;
|
|
verts.resize(numVertices);
|
|
for (int i=0;i<numVertices;i++)
|
|
{
|
|
verts[i].x = halfExtentsX*cube_vertices[i*9];
|
|
verts[i].y = halfExtentsY*cube_vertices[i*9+1];
|
|
verts[i].z = halfExtentsZ*cube_vertices[i*9+2];
|
|
verts[i].w = cube_vertices[i*9+3];
|
|
verts[i].nx = cube_vertices[i*9+4];
|
|
verts[i].ny = cube_vertices[i*9+5];
|
|
verts[i].nz = cube_vertices[i*9+6];
|
|
verts[i].u = cube_vertices[i*9+7];
|
|
verts[i].v = cube_vertices[i*9+8];
|
|
}
|
|
|
|
int shapeId = m_instancingRenderer->registerShape(&verts[0].x,numVertices,cube_indices,numIndices);
|
|
return shapeId;
|
|
}
|
|
|
|
|
|
int SimpleOpenGL3App::registerGraphicsSphereShape(float radius, bool usePointSprites, int largeSphereThreshold, int mediumSphereThreshold)
|
|
{
|
|
|
|
int strideInBytes = 9*sizeof(float);
|
|
|
|
int graphicsShapeIndex = -1;
|
|
|
|
if (radius>=largeSphereThreshold)
|
|
{
|
|
int numVertices = sizeof(detailed_sphere_vertices)/strideInBytes;
|
|
int numIndices = sizeof(detailed_sphere_indices)/sizeof(int);
|
|
graphicsShapeIndex = m_instancingRenderer->registerShape(&detailed_sphere_vertices[0],numVertices,detailed_sphere_indices,numIndices);
|
|
} else
|
|
{
|
|
|
|
if (usePointSprites)
|
|
{
|
|
int numVertices = sizeof(point_sphere_vertices)/strideInBytes;
|
|
int numIndices = sizeof(point_sphere_indices)/sizeof(int);
|
|
graphicsShapeIndex = m_instancingRenderer->registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS);
|
|
} else
|
|
{
|
|
if (radius>=mediumSphereThreshold)
|
|
{
|
|
int numVertices = sizeof(medium_sphere_vertices)/strideInBytes;
|
|
int numIndices = sizeof(medium_sphere_indices)/sizeof(int);
|
|
graphicsShapeIndex = m_instancingRenderer->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);
|
|
graphicsShapeIndex = m_instancingRenderer->registerShape(&low_sphere_vertices[0],numVertices,low_sphere_indices,numIndices);
|
|
}
|
|
}
|
|
}
|
|
return graphicsShapeIndex;
|
|
}
|
|
|
|
void SimpleOpenGL3App::drawGrid(int gridSize, float upOffset, int upAxis)
|
|
{
|
|
int sideAxis=-1;
|
|
int forwardAxis=-1;
|
|
|
|
switch (upAxis)
|
|
{
|
|
case 1:
|
|
forwardAxis=2;
|
|
sideAxis=0;
|
|
break;
|
|
case 2:
|
|
forwardAxis=1;
|
|
sideAxis=0;
|
|
break;
|
|
default:
|
|
b3Assert(0);
|
|
};
|
|
b3Vector3 gridColor = b3MakeVector3(0.5,0.5,0.5);
|
|
|
|
b3AlignedObjectArray<unsigned int> indices;
|
|
b3AlignedObjectArray<b3Vector3> vertices;
|
|
int lineIndex=0;
|
|
for(int i=-gridSize;i<=gridSize;i++)
|
|
{
|
|
{
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
b3Vector3 from = b3MakeVector3(0,0,0);
|
|
from[sideAxis] = float(i);
|
|
from[upAxis] = upOffset;
|
|
from[forwardAxis] = float(-gridSize);
|
|
b3Vector3 to=b3MakeVector3(0,0,0);
|
|
to[sideAxis] = float(i);
|
|
to[upAxis] = upOffset;
|
|
to[forwardAxis] = float(gridSize);
|
|
vertices.push_back(from);
|
|
indices.push_back(lineIndex++);
|
|
vertices.push_back(to);
|
|
indices.push_back(lineIndex++);
|
|
m_instancingRenderer->drawLine(from,to,gridColor);
|
|
}
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
{
|
|
|
|
b3Assert(glGetError() ==GL_NO_ERROR);
|
|
b3Vector3 from=b3MakeVector3(0,0,0);
|
|
from[sideAxis] = float(-gridSize);
|
|
from[upAxis] = upOffset;
|
|
from[forwardAxis] = float(i);
|
|
b3Vector3 to=b3MakeVector3(0,0,0);
|
|
to[sideAxis] = float(gridSize);
|
|
to[upAxis] = upOffset;
|
|
to[forwardAxis] = float(i);
|
|
vertices.push_back(from);
|
|
indices.push_back(lineIndex++);
|
|
vertices.push_back(to);
|
|
indices.push_back(lineIndex++);
|
|
m_instancingRenderer->drawLine(from,to,gridColor);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*m_instancingRenderer->drawLines(&vertices[0].x,
|
|
gridColor,
|
|
vertices.size(),sizeof(b3Vector3),&indices[0],indices.size(),1);
|
|
*/
|
|
|
|
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);
|
|
|
|
// void GLInstancingRenderer::drawPoints(const float* positions, const float color[4], int numPoints, int pointStrideInBytes, float pointDrawSize)
|
|
|
|
//we don't use drawPoints because all points would have the same color
|
|
// b3Vector3 points[3] = { b3MakeVector3(1, 0, 0), b3MakeVector3(0, 1, 0), b3MakeVector3(0, 0, 1) };
|
|
// m_instancingRenderer->drawPoints(&points[0].x, b3MakeVector3(1, 0, 0), 3, sizeof(b3Vector3), 6);
|
|
|
|
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();
|
|
}
|