#include "SimpleOpenGL2App.h" #define USE_OPENGL2 #include "OpenGLInclude.h" #include "ShapeData.h" #include "Bullet3Common/b3Logging.h"//b3Assert? #include "Bullet3Common/b3Scalar.h" #include "Bullet3Common/b3AlignedObjectArray.h" #include "Bullet3Common/b3Vector3.h" #include "Bullet3Common/b3Quaternion.h" #include "../CommonInterfaces/CommonRenderInterface.h" #include "../OpenGLWindow/GLPrimitiveRenderer.h" #include "GLInstanceGraphicsShape.h" #include "stdlib.h" #include "TwFonts.h" #include "SimpleOpenGL2Renderer.h" #ifdef B3_USE_GLFW #include "GLFWOpenGLWindow.h" #else #ifdef __APPLE__ #include "MacOpenGLWindow.h" #else //#include "GL/glew.h" #ifdef _WIN32 #include "Win32OpenGLWindow.h" #else //let's cross the fingers it is Linux/X11 #ifdef BT_USE_EGL #include "EGLOpenGLWindow.h" #else #include "X11OpenGLWindow.h" #endif //BT_USE_EGL #endif //_WIN32 #endif//__APPLE__ #endif //#ifdef B3_USE_GLFW #include #include "../CommonInterfaces/CommonRenderInterface.h" static SimpleOpenGL2App* gApp2=0; static void Simple2ResizeCallback( float widthf, float heightf) { int width = (int)widthf; int height = (int)heightf; if (gApp2->m_renderer && gApp2->m_window) gApp2->m_renderer->resize(width,height);//*gApp2->m_window->getRetinaScale(),height*gApp2->m_window->getRetinaScale()); } static void Simple2KeyboardCallback(int key, int state) { if (key==B3G_ESCAPE && gApp2 && gApp2->m_window) { gApp2->m_window->setRequestExit(); } else { //gApp2->defaultKeyboardCallback(key,state); } } void Simple2MouseButtonCallback( int button, int state, float x, float y) { if (gApp2 && gApp2->m_window) { gApp2->defaultMouseButtonCallback(button,state,x,y); } } void Simple2MouseMoveCallback( float x, float y) { if (gApp2 && gApp2->m_window) { gApp2->defaultMouseMoveCallback(x,y); } } void Simple2WheelCallback( float deltax, float deltay) { gApp2->defaultWheelCallback(deltax,deltay); } struct SimpleOpenGL2AppInternalData { GLuint m_fontTextureId; GLuint m_largeFontTextureId; int m_upAxis; SimpleOpenGL2AppInternalData() :m_upAxis(1) { } }; static GLuint BindFont2(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_LUMINANCE , _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_LUMINANCE , 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; } SimpleOpenGL2App::SimpleOpenGL2App(const char* title, int width, int height) { gApp2 = this; m_data = new SimpleOpenGL2AppInternalData; m_window = new b3gDefaultOpenGLWindow(); b3gWindowConstructionInfo ci; ci.m_title = title; ci.m_openglVersion = 2; ci.m_width = width; ci.m_height = height; m_window->createWindow(ci); m_window->setWindowTitle(title); #ifndef NO_GLEW #ifndef __APPLE__ #ifndef _WIN32 #ifndef B3_USE_GLFW //some Linux implementations need the 'glewExperimental' to be true #endif//B3_USE_GLFW #endif //_WIN32 #ifndef B3_USE_GLFW //gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); #if 0 if (glewInit() != GLEW_OK) { b3Error("glewInit failed"); exit(1); } if (!GLEW_VERSION_2_1) // check that the machine supports the 2.1 API. { b3Error("GLEW_VERSION_2_1 needs to support 2_1"); exit(1); // or handle the error in a nicer way } #endif #endif //B3_USE_GLFW #endif //__APPLE__ #endif //NO_GLEW TwGenerateDefaultFonts(); m_data->m_fontTextureId = BindFont2(g_DefaultNormalFont); m_data->m_largeFontTextureId = BindFont2(g_DefaultLargeFont); glGetError();//don't remove this call, it is needed for Ubuntu glClearColor( m_backgroundColorRGB[0], m_backgroundColorRGB[1], m_backgroundColorRGB[2], 1.f); b3Assert(glGetError() ==GL_NO_ERROR); //m_primRenderer = new GLPrimitiveRenderer(width,height); m_parameterInterface = 0; b3Assert(glGetError() ==GL_NO_ERROR); //m_renderer = new GLInstancingRenderer(128*1024,32*1024*1024); //m_renderer->init(); //m_renderer->resize(width,height); b3Assert(glGetError() ==GL_NO_ERROR); //m_renderer->InitShaders(); m_window->setMouseMoveCallback(Simple2MouseMoveCallback); m_window->setMouseButtonCallback(Simple2MouseButtonCallback); m_window->setKeyboardCallback(Simple2KeyboardCallback); m_window->setWheelCallback(Simple2WheelCallback); m_window->setResizeCallback(Simple2ResizeCallback); m_renderer = new SimpleOpenGL2Renderer(width,height); } SimpleOpenGL2App::~SimpleOpenGL2App() { gApp2 = 0; delete m_data; } void SimpleOpenGL2App::setBackgroundColor(float red, float green, float blue) { CommonGraphicsApp::setBackgroundColor(red,green,blue); glClearColor(m_backgroundColorRGB[0],m_backgroundColorRGB[1],m_backgroundColorRGB[2],1.f); } void SimpleOpenGL2App::drawGrid(DrawGridData data) { glEnable(GL_COLOR_MATERIAL); int gridSize = data.gridSize; float upOffset = data.upOffset; int upAxis = data.upAxis; float gridColor[4]; gridColor[0] = data.gridColor[0]; gridColor[1] = data.gridColor[1]; gridColor[2] = data.gridColor[2]; gridColor[3] = data.gridColor[3]; 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 indices; b3AlignedObjectArray 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_renderer->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_renderer->drawLine(from,to,gridColor); } } m_renderer->drawLines(&vertices[0].x, gridColor, vertices.size(),sizeof(b3Vector3),&indices[0],indices.size(),1); m_renderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(1,0,0),b3MakeVector3(1,0,0),3); m_renderer->drawLine(b3MakeVector3(0,0,0),b3MakeVector3(0,1,0),b3MakeVector3(0,1,0),3); m_renderer->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_renderer->drawPoints(&points[0].x, b3MakeVector3(1, 0, 0), 3, sizeof(b3Vector3), 6); } void SimpleOpenGL2App::setUpAxis(int axis) { this->m_data->m_upAxis = axis; } int SimpleOpenGL2App::getUpAxis() const { return this->m_data->m_upAxis; } void SimpleOpenGL2App::swapBuffer() { m_window->endRendering(); m_window->startRendering(); } void SimpleOpenGL2App::drawText( const char* txt, int posXi, int posYi, float size, float colorRGBA[4]) { } static void restoreOpenGLState() { glPopClientAttrib(); glPopAttrib(); } static void saveOpenGLState(int screenWidth, int screenHeight) { glPushAttrib(GL_ALL_ATTRIB_BITS); glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); glDisable(GL_LINE_SMOOTH); // glDisable(GL_LINE_STIPPLE); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); } void SimpleOpenGL2App::drawText3D( const char* txt, float position[3], float orientation[4], float color[4], float size, int optionFlag) { } void SimpleOpenGL2App::drawText3D( const char* txt, float worldPosX, float worldPosY, float worldPosZ, float size1) { saveOpenGLState(gApp2->m_renderer->getScreenWidth(),gApp2->m_renderer->getScreenHeight()); float viewMat[16]; float projMat[16]; CommonCameraInterface* cam = gApp2->m_renderer->getActiveCamera(); cam->getCameraViewMatrix(viewMat); cam->getCameraProjectionMatrix(projMat); float camPos[4]; cam->getCameraPosition(camPos); //b3Vector3 cp= b3MakeVector3(camPos[0],camPos[2],camPos[1]); // b3Vector3 p = b3MakeVector3(worldPosX,worldPosY,worldPosZ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc( GL_GREATER, 1.0f ); int viewport[4]={0,0,gApp2->m_renderer->getScreenWidth(),gApp2->m_renderer->getScreenHeight()}; float posX = 450.f; float posY = 100.f; float winx,winy, winz; if (!projectWorldCoordToScreen(worldPosX, worldPosY, worldPosZ,viewMat,projMat,viewport,&winx, &winy, &winz)) { return; } posX = winx; posY = gApp2->m_renderer->getScreenHeight()/2+(gApp2->m_renderer->getScreenHeight()/2)-winy; { //float width = 0.f; int pos=0; //float color[]={0.2f,0.2,0.2f,1.f}; glActiveTexture(GL_TEXTURE0); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBindTexture(GL_TEXTURE_2D,m_data->m_largeFontTextureId); glEnable(GL_TEXTURE_2D);//BindTexture //float width = r.x; //float extraSpacing = 0.; float startX = posX; float startY = posY-g_DefaultLargeFont->m_CharHeight*size1; glEnable(GL_COLOR_MATERIAL); while (txt[pos]) { int c = txt[pos]; //r.h = g_DefaultNormalFont->m_CharHeight; //r.w = g_DefaultNormalFont->m_CharWidth[c]+extraSpacing; float endX = startX+g_DefaultLargeFont->m_CharWidth[c]*size1; float endY = posY; float currentColor[]={1.f,0.2,0.2f,1.f}; float u0 = g_DefaultLargeFont->m_CharU0[c]; float u1 = g_DefaultLargeFont->m_CharU1[c]; float v0 = g_DefaultLargeFont->m_CharV0[c]; float v1 = g_DefaultLargeFont->m_CharV1[c]; float color[4] = {currentColor[0],currentColor[1],currentColor[2],currentColor[3]}; float x0 = startX; float x1 = endX; float y0 = startY; float y1 = endY; int screenWidth = gApp2->m_renderer->getScreenWidth(); int screenHeight = gApp2->m_renderer->getScreenHeight(); float z = 2.f*winz-1.f;//*(far /*float identity[16]={1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; */ PrimVertex vertexData[4] = { PrimVertex( PrimVec4(-1.f+2.f*x0/float(screenWidth), 1.f-2.f*y0/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v0)), PrimVertex( PrimVec4(-1.f+2.f*x0/float(screenWidth), 1.f-2.f*y1/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u0,v1)), PrimVertex(PrimVec4( -1.f+2.f*x1/float(screenWidth), 1.f-2.f*y1/float(screenHeight), z, 1.f ), PrimVec4(color[0], color[1], color[2], color[3]) ,PrimVec2(u1,v1)), PrimVertex( PrimVec4( -1.f+2.f*x1/float(screenWidth), 1.f-2.f*y0/float(screenHeight), z, 1.f ), PrimVec4( color[0], color[1], color[2], color[3] ) ,PrimVec2(u1,v0)) }; glBegin(GL_TRIANGLES); //use red colored text for now glColor4f(1,0,0,1); float scaling = 1; glTexCoord2f(vertexData[0].uv.p[0],vertexData[0].uv.p[1]); glVertex3d(vertexData[0].position.p[0]*scaling, vertexData[0].position.p[1]*scaling,vertexData[0].position.p[2]*scaling); glTexCoord2f(vertexData[1].uv.p[0],vertexData[1].uv.p[1]); glVertex3d(vertexData[1].position.p[0]*scaling, vertexData[1].position.p[1]*scaling,vertexData[1].position.p[2]*scaling); glTexCoord2f(vertexData[2].uv.p[0],vertexData[2].uv.p[1]); glVertex3d(vertexData[2].position.p[0]*scaling, vertexData[2].position.p[1]*scaling,vertexData[2].position.p[2]*scaling); glTexCoord2f(vertexData[0].uv.p[0],vertexData[0].uv.p[1]); glVertex3d(vertexData[0].position.p[0]*scaling, vertexData[0].position.p[1]*scaling,vertexData[0].position.p[2]*scaling); glTexCoord2f(vertexData[2].uv.p[0],vertexData[2].uv.p[1]); glVertex3d(vertexData[2].position.p[0]*scaling, vertexData[2].position.p[1]*scaling,vertexData[2].position.p[2]*scaling); glTexCoord2f(vertexData[3].uv.p[0],vertexData[3].uv.p[1]); glVertex3d(vertexData[3].position.p[0]*scaling, vertexData[3].position.p[1]*scaling,vertexData[3].position.p[2]*scaling); glEnd(); startX = endX; pos++; } } glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); restoreOpenGLState(); } void SimpleOpenGL2App::registerGrid(int cells_x, int cells_z, float color0[4], float color1[4]) { b3Vector3 cubeExtents=b3MakeVector3(0.5,0.5,0.5); double halfHeight=0.1; cubeExtents[m_data->m_upAxis] = halfHeight; int cubeId = registerCubeShape(cubeExtents[0],cubeExtents[1],cubeExtents[2]); b3Quaternion orn(0,0,0,1); b3Vector3 center=b3MakeVector3(0,0,0,1); b3Vector3 scaling=b3MakeVector3(1,1,1,1); for ( int i = 0; i < cells_x; i++) { for (int j = 0; j < cells_z; j++) { float* color =0; if ((i + j) % 2 == 0) { color = (float*)color0; } else { color = (float*)color1; } if (this->m_data->m_upAxis==1) { center =b3MakeVector3((i + 0.5f) - cells_x * 0.5f, -halfHeight, (j + 0.5f) - cells_z * 0.5f); } else { center =b3MakeVector3((i + 0.5f) - cells_x * 0.5f, (j + 0.5f) - cells_z * 0.5f,-halfHeight ); } m_renderer->registerGraphicsInstance(cubeId,center,orn,color,scaling); } } } int SimpleOpenGL2App::registerGraphicsUnitSphereShape(EnumSphereLevelOfDetail lod, int textureId) { int strideInBytes = 9*sizeof(float); int graphicsShapeIndex = -1; switch (lod) { case SPHERE_LOD_POINT_SPRITE: { int numVertices = sizeof(point_sphere_vertices)/strideInBytes; int numIndices = sizeof(point_sphere_indices)/sizeof(int); graphicsShapeIndex = m_renderer->registerShape(&point_sphere_vertices[0],numVertices,point_sphere_indices,numIndices,B3_GL_POINTS,textureId); break; } case SPHERE_LOD_LOW: { int numVertices = sizeof(low_sphere_vertices)/strideInBytes; int numIndices = sizeof(low_sphere_indices)/sizeof(int); graphicsShapeIndex = m_renderer->registerShape(&low_sphere_vertices[0],numVertices,low_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId); break; } case SPHERE_LOD_MEDIUM: { int numVertices = sizeof(medium_sphere_vertices)/strideInBytes; int numIndices = sizeof(medium_sphere_indices)/sizeof(int); graphicsShapeIndex = m_renderer->registerShape(&medium_sphere_vertices[0],numVertices,medium_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId); break; } case SPHERE_LOD_HIGH: default: { int numVertices = sizeof(detailed_sphere_vertices)/strideInBytes; int numIndices = sizeof(detailed_sphere_indices)/sizeof(int); graphicsShapeIndex = m_renderer->registerShape(&detailed_sphere_vertices[0],numVertices,detailed_sphere_indices,numIndices,B3_GL_TRIANGLES,textureId); break; } }; return graphicsShapeIndex; } int SimpleOpenGL2App::registerCubeShape(float halfExtentsX,float halfExtentsY, float halfExtentsZ, int textureIndex, float textureScaling ) { int strideInBytes = 9*sizeof(float); int numVertices = sizeof(cube_vertices_textured)/strideInBytes; int numIndices = sizeof(cube_indices)/sizeof(int); b3AlignedObjectArray verts; verts.resize(numVertices); for (int i=0;iregisterShape(&verts[0].xyzw[0],numVertices,cube_indices,numIndices,B3_GL_TRIANGLES,textureIndex); return shapeId; }