dbacchet avatar dbacchet committed 3e97b5c

renamed test7c

Comments (0)

Files changed (65)

sources/opengl2_samples/SConscript

 
 
 # build opengl tests
-SConscript( 'test0_context/SConscript', exports={'env':env_local} )
-SConscript( 'test1_simpleshaders/SConscript', exports={'env':env_local} )
-SConscript( 'test2_vbo/SConscript', exports={'env':env_local} )
-SConscript( 'test3_vbo_nodeprecated/SConscript', exports={'env':env_local} )
-SConscript( 'test4_batches/SConscript', exports={'env':env_local} )
-SConscript( 'test5_textures/SConscript', exports={'env':env_local} )
-SConscript( 'test6_model/SConscript', exports={'env':env_local} )
-SConscript( 'test7_simplerenderer/SConscript', exports={'env':env_local} )
+SConscript( 'test0_context/SConscript', 			  exports={'env':env_local} )
+SConscript( 'test1_simpleshaders/SConscript', 		  exports={'env':env_local} )
+SConscript( 'test2_vbo/SConscript', 				  exports={'env':env_local} )
+SConscript( 'test3_vbo_nodeprecated/SConscript', 	  exports={'env':env_local} )
+SConscript( 'test4_batches/SConscript', 			  exports={'env':env_local} )
+SConscript( 'test5_textures/SConscript', 			  exports={'env':env_local} )
+SConscript( 'test6_model/SConscript', 				  exports={'env':env_local} )
+SConscript( 'test7_simplerenderer/SConscript', 		  exports={'env':env_local} )
 SConscript( 'test7b_trackballmanipulator/SConscript', exports={'env':env_local} )
-SConscript( 'test7c_trackballmanipulatorcamera/SConscript', exports={'env':env_local} )
+SConscript( 'test7c_cameramanipulator/SConscript',    exports={'env':env_local} )
 
 # SConscript( 'gltut19/SConscript', exports={'env':env_local} )

sources/opengl2_samples/test7c_cameramanipulator/GLCamera.h

+#ifndef __DBGLCamera_H__
+#define __DBGLCamera_H__
+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// BF mesh class
+
+#include <vector>
+#include <string>
+
+#include "vmath.h"
+#include "mathutils.h"
+#include "GLTransform.h"
+
+
+/// @class GLCamera
+/// @brief component implementing a camera
+/// @details this component implements the abstaction of a camera, used by the engine
+/// to set the projection and relative transformation matrix.\n
+/// The values leftPlane, rightPlane, topPlane, bottomPlane represent the coordinates of 
+/// the cutting planes intersecting with the nearPlane (in orthographic mode these values
+/// also correspond to the intersection with the farPlane, because of the parallel projection)
+class GLCamera
+{
+public:
+
+    enum eCameraModes {
+        evOrthographic,     ///< orthographic camera
+        evPerspective,      ///< perspective camera
+        evCameraModesNum    ///< number of camera modes
+    };
+    
+    /// standard constructor
+    GLCamera();
+    /// copy constructor
+    GLCamera(const GLCamera &cam);
+    /// destructor
+    virtual ~GLCamera();
+    
+    /// update projection matrix
+    bool updateProjectionMatrix( void );
+    
+    /// setup ortho projection
+    void setOrtho(float nearpl, float farpl, float left, float right, float bottom, float top)
+    {
+        mode = GLCamera::evOrthographic;
+        nearPlane   = nearpl;
+        farPlane    = farpl;
+        leftPlane   = left;
+        rightPlane  = right;
+        bottomPlane = bottom;
+        topPlane    = top;
+    }
+
+    /// setup perspective projection
+    void setPerspective(float nearpl, float farpl, float _fov)
+    {
+        mode = GLCamera::evPerspective;
+        nearPlane = nearpl;
+        farPlane  = farpl;
+        fov       = _fov;
+    }
+    
+    
+    /// get actual transformation matrices (also update current projection matrix)
+    Matrix4f getTransformationMatrix(void);
+    Matrix4f getInverseTransformationMatrix(void);
+
+
+public:
+        
+    // properties
+    eCameraModes mode;          ///< projection mode (orthographic or perspective)
+    float fov;                  ///< field-of-view angle (only used in perspective mode)
+    float aspectRatio;          ///< aspect ratio (width/height)
+    Matrix4f projectionMatrix;  ///< current projection matrix
+    float leftPlane;            ///< left plane coord (overwritten if fov or aspectRatio are used)
+    float rightPlane;           ///< right plane coord (overwritten if fov or aspectRatio are used)
+    float bottomPlane;          ///< bottom plane coord (overwritten if fov or aspectRatio are used)
+    float topPlane;             ///< top plane coord (overwritten if fov or aspectRatio are used)
+    float nearPlane;            ///< near plane distance (must be >0 in perspective mode)
+    float farPlane;             ///< far plane distance
+    
+    GLTransformf transform;     ///< position/rotation associated transformation
+        
+protected:
+    
+    /// create ortographic projection
+    bool createOrthographicProjection( void );
+    /// create perspective projection
+    bool createPerspectiveProjection( void );
+
+    /// basic initialization
+    void init( void );
+    
+};
+
+
+// ///////////////////////////// //
+//        IMPLEMENTATION         //
+// ///////////////////////////// //
+
+// standard constructor
+inline
+GLCamera::GLCamera()
+{
+    init();
+}
+
+
+// copy constructor
+inline
+GLCamera::GLCamera(const GLCamera &cam)
+{
+    init();
+    
+    mode             = cam.mode;            
+    fov              = cam.fov;             
+    aspectRatio      = cam.aspectRatio;
+    projectionMatrix = cam.projectionMatrix;
+    leftPlane        = cam.leftPlane;
+    rightPlane       = cam.rightPlane; 
+    bottomPlane      = cam.bottomPlane;
+    topPlane         = cam.topPlane;   
+    nearPlane        = cam.nearPlane; 
+    farPlane         = cam.farPlane;      
+}
+
+
+// destructor
+inline
+GLCamera::~GLCamera()
+{
+    
+}
+
+    
+// update projection matrix
+inline
+bool GLCamera::updateProjectionMatrix( void )
+{
+    if (mode==evPerspective)
+        return createPerspectiveProjection();
+    if (mode==evOrthographic)
+        return createOrthographicProjection();
+    return false;
+}
+    
+
+// get actual transformation matrices
+inline
+Matrix4f GLCamera::getTransformationMatrix(void)
+{
+    return transform.getTransformationMatrix();
+}
+
+
+inline
+Matrix4f GLCamera::getInverseTransformationMatrix(void)
+{
+    return transform.inverse().getTransformationMatrix();
+}
+
+
+// create ortographic projection
+inline
+bool GLCamera::createOrthographicProjection( void )
+{
+    mode = evOrthographic;
+    // compensate with aspect ratio
+    float w = rightPlane-leftPlane;
+    float co = (rightPlane+leftPlane)/2.0f;
+    float h = topPlane-bottomPlane;
+    float cv = (topPlane+bottomPlane)/2.0f;
+    if ((w/h) >= aspectRatio)
+    {
+        h = w/aspectRatio;
+        topPlane = cv+h/2.0f;
+        bottomPlane = cv-h/2.0f;
+    }
+    else
+    {
+        w = h*aspectRatio;
+        leftPlane = co-w/2.0f;
+        rightPlane = co+w/2.0f;
+    }
+    // create projection matrix
+    float a = (rightPlane-leftPlane);
+    float b = (topPlane-bottomPlane);
+    float c = (farPlane-nearPlane);
+    float tx = -(rightPlane+leftPlane)/a;
+    float ty = -(topPlane+bottomPlane)/b;
+    float tz = -(farPlane+nearPlane)/c;
+    projectionMatrix.identity();
+    projectionMatrix(1,1) = 2.0f/a;
+    projectionMatrix(2,2) = 2.0f/b;
+    projectionMatrix(3,3) = -2.0f/c;
+    projectionMatrix(1,4) = tx;
+    projectionMatrix(2,4) = ty;
+    projectionMatrix(3,4) = tz;
+    return true;
+}
+
+
+// create perspective projection
+inline
+bool GLCamera::createPerspectiveProjection( void )
+{
+    mode = evPerspective;
+    // create left, right, top, bottom using fov+aspect ratio
+    if (nearPlane<1E-6f) 
+        nearPlane = 1E-6f;
+    float h = nearPlane*tan(fov/2.0f);   
+    float w = h*aspectRatio;
+    topPlane = h;
+    bottomPlane = -h;
+    rightPlane = w;
+    leftPlane = -w;
+    // fill projection matrix
+    float a = (rightPlane-leftPlane);
+    float b = (topPlane-bottomPlane);
+    float c = (farPlane-nearPlane);
+    float A = (rightPlane+leftPlane)/a;
+    float B = (topPlane+bottomPlane)/b;
+    float C = -(farPlane+nearPlane)/c;
+    float D = -(2*farPlane*nearPlane)/c;
+    projectionMatrix = projectionMatrix*0.0f;
+    projectionMatrix(1,1) = 2.0f*nearPlane/a;
+    projectionMatrix(2,2) = 2.0f*nearPlane/b;
+    projectionMatrix(1,3) = A;
+    projectionMatrix(2,3) = B;
+    projectionMatrix(3,3) = C;
+    projectionMatrix(4,3) = -1.0f;
+    projectionMatrix(3,4) = D;
+    
+    return true;
+}
+
+    
+// basic initialization
+inline
+void GLCamera::init( void )
+{
+    // default values
+    mode        = evPerspective;
+    fov         = degToRad(45.0f); 
+    aspectRatio = 16.0f/9.0f;
+    projectionMatrix.identity();
+    leftPlane   = -50.0f;
+    rightPlane  = 50.0f;
+    bottomPlane = -50.0f;
+    topPlane    = 50.0f;
+    nearPlane   = 1.0f;     
+    farPlane    = 100.0f;
+    // default to ortho
+    createOrthographicProjection();
+}
+ 
+
+
+#endif //__DBGLCamera_H__
+

sources/opengl2_samples/test7c_cameramanipulator/GLCameraManipulator.h

+#ifndef __DBGLTrackBallManipulator__
+#define __DBGLTrackBallManipulator__
+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// trackball manipulator; add the pan/zoom functionality to the standard trackball
+
+
+#include "vmath.h"
+
+#include "GLTrackball.h"
+
+
+/// @class GLCameraManipulator 
+/// trackball 
+template <typename real_type=float>
+class GLCameraManipulator
+{
+public:
+
+    enum eMode {
+            evRotate,   ///< rotate mode
+            evPan,      ///< pan the manipulator
+            evZoom,     ///< zoom mode
+            evModeNum
+    };
+
+public:
+
+    /// standard constructor
+    GLCameraManipulator()
+    : trackball()
+    , currMode(evRotate)
+    , radius(10.0)
+    , center(0.0,1.0,0.0)
+    {}
+    /// destructor
+    virtual ~GLCameraManipulator()
+    {}
+    
+    /// begin the dragging
+    virtual void beginDrag(real_type x, real_type y)
+    {
+        if (currMode==evRotate)
+            trackball.beginDrag(x,y);
+        else if (currMode==evPan || currMode==evZoom)
+        {
+            anchorPan = center; // set anchor point to the current position
+            anchorPanSS = Vector3<real_type>(-x,-y,0.0);
+            incremPan = Vector3<real_type>(0,0,0);
+        }
+    }
+    
+    /// mouse drag
+    virtual void drag(real_type x, real_type y)
+    {
+        if (currMode==evRotate)
+            trackball.drag(x,y);
+        else if (currMode==evPan)
+        {
+            Vector3<real_type> delta = Vector3<real_type>(-x,-y,0.0)-anchorPanSS;
+            incremPan = delta*radius; // compensate with radius to 'normalize' the translation (effective when connected to a camera) 
+            incremPan = trackball.getRotation().inverse()*incremPan; // to use object local orientation
+            center = anchorPan+incremPan;
+        }
+        else if (currMode==evZoom)
+        {
+            radius += radius*(anchorPanSS.y+y)/100; // too minimalistic zoom implementation (+y here because in the camera manipualtor the y coord is inverted)
+            if (radius<0.1) radius=0.1;
+        }
+    }
+    
+    /// get current center
+    Vector3<real_type> getCenter( void ) 
+    {
+        return center;
+    }
+    /// get current rotation
+    Matrix4<real_type> getRotation( void ) 
+    {
+        return trackball.getRotation().inverse();
+    }
+    /// get current transformation
+    Matrix4<real_type> getTransformation( void ) 
+    {
+        currentTransf = trackball.getRotation().inverse();
+        Vector3<real_type> offsetRad = currentTransf*Vector3<real_type>(0.0,0.0,radius); // radius offset in local orientation
+        currentTransf.setTranslation(center+offsetRad);
+        return currentTransf;
+    }
+
+    void setMode( eMode mode )
+    { 
+        currMode = mode;
+    }
+
+    // ///////////////////////////////////// //
+    // camera manipulator placement routines //
+    // ///////////////////////////////////// //
+
+    // set the current transform given camera position, target and up vector
+    void setLookAt( const Vector3<real_type> &camPos, const Vector3<real_type> &target, const Vector3<real_type> &up)
+    {
+        // update trackball rotation
+        Vector3<real_type> z = camPos-target;
+        z.normalize();
+        Vector3<real_type> y = up;
+        y.normalize();
+        Vector3<real_type> x = y.crossProduct(z); 
+        if (x.lengthSq()<1e-6)
+            return; // return if up vector (y) and z are parallel
+        x.normalize();
+        y = z.crossProduct(x);
+        trackball.currentRot.at(0,0) = x.x; trackball.currentRot.at(0,1) = y.x; trackball.currentRot.at(0,2) = z.x; 
+        trackball.currentRot.at(1,0) = x.y; trackball.currentRot.at(1,1) = y.y; trackball.currentRot.at(1,2) = z.y; 
+        trackball.currentRot.at(2,0) = x.z; trackball.currentRot.at(2,1) = y.z; trackball.currentRot.at(2,2) = z.z; 
+        // set center and radius
+        center = target;
+        radius = (camPos-target).length();
+    }
+
+
+protected:
+    
+    // member variables
+    eMode currMode;               ///< manipulator current mode
+    
+    real_type           radius;      ///< trackball radius
+    Vector3<real_type>  center;      ///< trackball center (current pan value)
+    Vector3<real_type>  anchorPan;   ///< anchor point for pan
+    Vector3<real_type>  anchorPanSS; ///< anchor point for pan (screen-space)
+    Vector3<real_type>  incremPan;   ///< increment for pan
+
+    Matrix4<real_type>  currentTransf;  ///< current transformation matrix
+
+    GLTrackball<real_type> trackball;   ///< manage rotations
+        
+};
+
+
+typedef GLCameraManipulator<float>  GLCameraManipulatorf;
+typedef GLCameraManipulator<double> GLCameraManipulatord;
+
+#endif

sources/opengl2_samples/test7c_cameramanipulator/GLMaterial.cpp

+#include <map>
+
+#include "glfw_utils.h" // just to retrieve opengl symbols without conflicting with the include order
+#include "stb_image.h"
+
+#include "logger.h"
+
+#include "GLShader.h"
+#include "GLMaterial.h"
+
+
+// ////////////// //
+// local function //
+// ////////////// //
+
+namespace 
+{
+
+    // texture map
+    std::map<std::string,GLuint> textures;
+
+
+    // get or create an image, given its filename
+    static GLuint getOrCreateImage(const std::string &name)
+    {
+        // check if already present
+        if(textures.count(name)>0)
+            return textures[name];
+
+        // read image from file
+        printf("loading Texture from file %s\n",name.c_str());
+        int  w,h,n;
+        unsigned char *data = stbi_load(name.c_str(), &w, &h, &n, 4);   // force rgba
+        if (!data)
+            return 0;
+        stbi_flip_y(data,w,h,4);
+
+        // create and load texture
+        GLuint tid=0;
+        glGenTextures(1, &tid);
+        glBindTexture(GL_TEXTURE_2D, tid);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 
+                                    0, GL_RGBA, GL_UNSIGNED_BYTE, data); // Texture specification
+        glGenerateMipmap(GL_TEXTURE_2D);  //Generate mipmaps
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+        // add anisotropic filtering
+        /// \warning NOT SAFE!!! no check if the extension is available
+        GLfloat fLargest;
+        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
+        fLargest = fLargest>4.0f ? 4.0f : fLargest; // limit to 4 the anisotropic filtering
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
+
+        stbi_image_free(data);
+
+        // add to map and return 
+        textures[name]=tid;
+
+        printf("created Texture from file %s, with id=%u\n",name.c_str(),tid);
+        return tid;
+    }
+
+
+
+
+}
+
+
+
+
+// initialize the current material: 
+// performa all the needed initializations here
+bool initializeMaterial( GLMaterial *mat )
+{
+    // if invalid material: skip
+    if (!mat)
+    {
+        logMessage("invalid material. skip\n");
+        return false;        
+    }
+    if (!mat->shader)
+    {
+        logMessage("no shader associated to current material. skip\n");
+        return false;        
+    }
+
+    // init material textures and uniforms
+    for (unsigned int i=0; i<GLMaterial::evTextureTypeCount; i++)
+    {
+        if (mat->textures[i]!="")
+        {
+            mat->textureIds[i]       = getOrCreateImage(mat->textures[i]);
+            mat->textureUniforms[i]  = glGetUniformLocation(mat->shader->programId, textureUniformNames[i]);
+        }
+    }
+
+    return true;
+
+}
+
+
+// set the given material as the current 
+bool applyMaterial( const GLMaterial *mat )
+{
+    // if invalid material: skip
+    if (!mat)
+    {
+        logMessage("invalid material. skip\n");
+        return false;        
+    }
+    // bind textures and uniforms
+    unsigned int idx=0;
+    for (unsigned int i=0; i<GLMaterial::evTextureTypeCount; i++)
+    {
+        if (mat->textures[i]!="")
+        {
+            glActiveTexture(GL_TEXTURE0+idx);
+            glBindTexture(GL_TEXTURE_2D, mat->textureIds[i]);
+            glUniform1i(mat->textureUniforms[i], idx);  // associate the current texture to the named uniform
+            idx++;
+        }
+    }
+
+    return true;
+
+}
+
+

sources/opengl2_samples/test7c_cameramanipulator/GLMaterial.h

+#ifndef __GLMaterial_H__
+#define __GLMaterial_H__
+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// GL material class, loosely based on the BF engine material
+
+#include <string>
+
+#include "GLMaterialSystem.h"
+
+// forward declarations
+class GLShader;
+
+static const char* textureUniformNames[] = {
+    "u_tex_ambient",
+    "u_tex_diffuse",
+    "u_tex_emissive",
+    "u_tex_normal",
+    "u_tex_shininess",
+    "u_tex_specular"
+};
+
+/// @class GLMaterial
+/// @brief Material definition
+/// this class represent the material used by the rendering context while drawing
+class GLMaterial
+{
+public:
+    friend GLMaterial* materialsystem::getOrCreateMaterial(const std::string &materialName, const std::string &shaderName ); 
+public:
+
+    /// available texture types
+    enum eTextureType {
+        evTextureAmbient,   ///< ambient texture flag
+        evTextureDiffuse,   ///< diffuse texture flag
+        evTextureEmissive,  ///< emissive texture flag
+        evTextureNormal,    ///< normal texture flag
+        evTextureShininess, ///< shininess texture flag
+        evTextureSpecular,  ///< specular texture flag
+        evTextureTypeCount  ///< number of texture types
+    };
+        
+    std::string  name;                                  ///< material name
+    std::string  textures[evTextureTypeCount];          ///< array with texture names
+    unsigned int textureIds[evTextureTypeCount];        ///< array with texture ids
+    int          textureUniforms[evTextureTypeCount];   ///< array with texture uniform locations
+
+    unsigned int materialId;     ///< material id (created/used by the renderer)
+
+    GLShader *shader;       ///< associated shader
+
+protected:
+
+    /// standard constructor
+    GLMaterial( const std::string &_name, GLShader *shd )
+    : name(_name), shader(shd)
+    {  init();  }
+    /// copy constructor
+    GLMaterial(const GLMaterial &mat)
+    {
+        name = mat.name;
+        for (unsigned int i=0; i<evTextureTypeCount; i++)
+        {
+            textures[i]        = mat.textures[i];
+            textureIds[i]      = mat.textureIds[i];
+            textureUniforms[i] = mat.textureUniforms[i];
+        }
+        shader = mat.shader;
+    }
+    /// destructor
+    virtual ~GLMaterial()
+    {}
+    
+    /// basic initialization
+    void init( void )
+    {
+        for (unsigned int i=0; i<evTextureTypeCount; i++)
+        {
+            textures[i]        = "";
+            textureIds[i]      = 0;
+            textureUniforms[i] = 0;
+        }
+    }
+    
+};
+
+inline bool operator == (const GLMaterial& a, const GLMaterial& b)
+{
+    bool res = true;
+    for (unsigned int i=0; i<GLMaterial::evTextureTypeCount; i++)
+        res = res && a.textures[i] == b.textures[i];
+    return res;
+}
+
+
+// /////////////////////////////////// //
+// function for manipulating materials //
+// /////////////////////////////////// //
+
+/// initialize the current material: 
+/// performa all the needed initializations here
+bool initializeMaterial( GLMaterial *mat );
+
+/// set the given material as the current 
+bool applyMaterial( const GLMaterial *mat );
+
+
+#endif //__GLMaterial_H__

sources/opengl2_samples/test7c_cameramanipulator/GLMaterialSystem.cpp

+#include <string>
+#include <map>
+
+#include "logger.h"
+
+#include "GLShader.h"
+#include "GLMaterial.h"
+
+#include "GLMaterialsystem.h"
+
+
+// local functions/data
+namespace 
+{
+	std::map<std::string, GLShader*>   shadermap;
+	std::map<std::string, GLMaterial*> materialmap;
+}
+
+
+
+
+namespace materialsystem
+{
+	// retrieve a shader. NULL if the shader don't exist
+    GLShader* getShader(const std::string &name)
+    {
+		// check if shader exists
+		if (shadermap.count(name)>0)
+			return shadermap[name];
+		else
+			return NULL;
+    }
+
+	// create a shader from a set of files; if the shader already exists return a pointer to the current one
+	GLShader* getOrCreateShaderFromFiles(const std::string &name, const std::string &vertex, const std::string &fragment, const std::string &geometry)
+	{
+		// check if shader exists
+		if (shadermap.count(name)>0)
+			return shadermap[name];
+
+		// create shader
+		logMessage("Creating shader '%s' using files '%s', '%s', '%s'\n",name.c_str(),vertex.c_str(),fragment.c_str(),geometry.c_str());
+		GLShader *shader = new GLShader(name);
+		if (shader->initFromFile(vertex, fragment, geometry) )
+		{
+			shadermap[name] = shader;
+			return shader;
+		}
+		else
+		{
+			logError("Unable to create shader '%s' from files '%s', '%s', '%s'\n",name.c_str(),vertex.c_str(),fragment.c_str(),geometry.c_str());
+			delete shader;
+			return NULL;
+		}
+	}
+
+
+	// delete all the created shaders
+	void deleteShaders( void )
+	{
+		for (std::map<std::string,GLShader*>::iterator it=shadermap.begin(); it!=shadermap.end(); it++)
+			delete it->second;
+		shadermap.clear();
+	}
+
+
+	// retrieve a material. NULL if the material don't exist
+    GLMaterial* getMaterial(const std::string &name)
+    {
+		// check if material exists
+		if (materialmap.count(name)>0)
+			return materialmap[name];
+		else
+			return NULL;
+    }
+
+
+	// create a material; if the material already exists return a pointer to the current one
+    GLMaterial* getOrCreateMaterial(const std::string &name,
+    							    const std::string &shaderName )
+    {
+		// check if material exists
+		if (materialmap.count(name)>0)
+			return materialmap[name];
+
+		// check if the given shader exists
+		if (shadermap.count(shaderName)<=0)
+		{
+			logError("Unable to create material '%s': the shader '%s' does not exist.\n",name.c_str(), shaderName.c_str());
+			return NULL;
+		}
+		// create material
+		logMessage("Creating material '%s' with shader '%s'\n",name.c_str(), shaderName.c_str());
+		GLMaterial *material = new GLMaterial(name, shadermap[shaderName]);
+		if (material)
+		{
+			materialmap[name] = material;
+			return material;
+		}
+		else
+		{
+			logError("Unable to create material '%s' with shader '%s'\n",name.c_str(), shaderName.c_str());
+			delete material;
+			return NULL;
+		}
+    }
+
+
+    // delete all the created materials
+    void      deleteMaterials( void );
+
+}
+

sources/opengl2_samples/test7c_cameramanipulator/GLMaterialSystem.h

+#ifndef __GLMaterialSystem_H__
+#define __GLMaterialSystem_H__
+
+#include <string>
+
+// forward declarations
+class GLShader;
+class GLMaterial;
+
+/// \namespace materialsystem
+/// \brief system managing creation/retrieval/destruction of shaders and materials
+namespace materialsystem
+{
+    /// retrieve a shader. NULL if the shader don't exist
+    GLShader* getShader(const std::string &name);
+    /// create a shader from a set of files; if the shader already exists return a pointer to the current one
+    GLShader* getOrCreateShaderFromFiles(const std::string &shaderName,
+                                         const std::string &vertex, const std::string &fragment, const std::string &geometry="");
+    /// delete all the created shaders
+    void      deleteShaders( void );
+
+    /// retrieve a material. NULL if the material don't exist
+    GLMaterial* getMaterial(const std::string &name);
+    /// create a material; if the material already exists return a pointer to the current one
+    GLMaterial* getOrCreateMaterial(const std::string &materialName, const std::string &shaderName ="");
+    /// delete all the created materials
+    void        deleteMaterials( void );
+}
+
+#endif

sources/opengl2_samples/test7c_cameramanipulator/GLMesh.cpp

+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// BF mesh class
+
+#include <vector>
+#include <string>
+
+#include "GLMaterial.h"
+#include "GLMesh.h"
+    
+// standard constructor
+GLSubMesh::GLSubMesh()
+{
+    init();
+}
+
+
+// copy constructor
+GLSubMesh::GLSubMesh(const GLSubMesh &sm)
+{
+    init();
+    material  = sm.material;
+    indices   = sm.indices;
+    vertices  = sm.vertices;
+}
+
+
+// destructor
+GLSubMesh::~GLSubMesh()
+{
+}
+    
+
+// basic initialization
+void GLSubMesh::init( void )
+{
+    // default values
+    indices.clear();
+    vertices.clear();
+    material = NULL;
+}
+
+
+
+
+// //////// //
+//   MESH   //
+// //////// //
+
+
+
+/// standard constructor
+GLMesh::GLMesh()
+{
+    init();
+}
+
+
+// copy constructor
+GLMesh::GLMesh(const GLMesh &mesh)
+{
+    submeshes = mesh.submeshes;
+}
+
+
+// destructor
+GLMesh::~GLMesh()
+{
+    
+}
+
+
+// basic initialization
+void GLMesh::init( void )
+{
+    submeshes.clear();
+}
+
+
+// add a submesh
+bool GLMesh::addSubMesh( const GLSubMesh &sm )
+{
+    submeshes.push_back(sm);
+    return true;
+}
+
+    
+// remove a submesh by index
+bool GLMesh::removeSubMeshByIndex( unsigned int idx )
+{
+    if (idx>=submeshes.size())
+        return false;
+    submeshes.erase(submeshes.begin()+idx);
+    return true;
+}
+
+
+
+
+

sources/opengl2_samples/test7c_cameramanipulator/GLMesh.h

+#ifndef __GLMesh_H__
+#define __GLMesh_H__
+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// GL mesh class. Loosely based on the mesh format in the BF2 engine
+
+#include <vector>
+
+#include "vertex.h"
+#include "GLMaterial.h"
+#include "GLTransform.h"
+
+
+/// @class GLMesh
+/// @brief a submesh is a graphic representation of an entity
+/// @details a submesh is a graphical representation of an object, or part of it; 
+/// it is associated to a single material
+class GLSubMesh
+{
+public:
+    
+    // data
+    
+    /// standard constructor
+    GLSubMesh();
+    /// standard constructor
+    GLSubMesh(const std::string &nm);
+    /// copy constructor
+    GLSubMesh(const GLSubMesh &mesh);
+    /// destructor
+    virtual ~GLSubMesh();
+    
+public:
+    
+    // associated material
+    GLMaterial *material;
+    // data buffers
+    std::vector<unsigned int> indices;
+    std::vector<Vertex_t> vertices;
+    
+protected:
+    
+    /// basic initialization
+    void init( void );
+    
+};
+
+
+/// @class GLMesh
+/// @brief a mesh is a graphic representation of an entity
+/// @details a mesh is composed by one or more submeshes, each having its own material. 
+/// All the submeshes share the same reference system
+class GLMesh
+{
+public:
+    
+    // data
+    
+    /// standard constructor
+    GLMesh();
+    /// copy constructor
+    GLMesh(const GLMesh &mesh);
+    /// destructor
+    virtual ~GLMesh();
+    
+    /// add a submesh
+    bool addSubMesh( const GLSubMesh &sm );
+    
+    /// remove a submesh by index
+    bool removeSubMeshByIndex( unsigned int idx );
+    
+public:
+        
+    // data
+    std::vector<GLSubMesh> submeshes;   ///< vector containing all the submeshes
+    
+protected:
+    
+    /// basic initialization
+    void init( void );
+    
+};
+
+
+// ///////////////// //
+// utility functions //
+// ///////////////// //
+
+/// apply a transformation to the mesh nodes
+inline void applyTransform(GLMesh *mesh, const GLTransformf &tr)
+{
+    Matrix4f M = tr.getTransformationMatrix();
+    Matrix3f R = tr.getRotationMatrix();
+    for(unsigned int k=0; k<mesh->submeshes.size(); k++)
+    {
+        for (unsigned int i=0; i<mesh->submeshes[k].vertices.size(); i++)
+        {
+            mesh->submeshes[k].vertices[i].pos  = M*mesh->submeshes[k].vertices[i].pos;
+            mesh->submeshes[k].vertices[i].norm = R*mesh->submeshes[k].vertices[i].norm;
+            mesh->submeshes[k].vertices[i].tang = R*mesh->submeshes[k].vertices[i].tang;
+        }
+    }
+}
+
+
+/// apply a transformation to the mesh nodes
+inline void applyTransform(GLMesh *mesh, const Matrix4f &M)
+{
+    Matrix3f R;
+      R(1,1) = M(1,1); R(1,2) = M(1,2); R(1,3) = M(1,3); 
+      R(2,1) = M(2,1); R(2,2) = M(2,2); R(2,3) = M(2,3); 
+      R(3,1) = M(3,1); R(3,2) = M(3,2); R(3,3) = M(3,3); 
+    for(unsigned int k=0; k<mesh->submeshes.size(); k++)
+    {
+        for (unsigned int i=0; i<mesh->submeshes[k].vertices.size(); i++)
+        {
+            mesh->submeshes[k].vertices[i].pos  = M*mesh->submeshes[k].vertices[i].pos;
+            mesh->submeshes[k].vertices[i].norm = R*mesh->submeshes[k].vertices[i].norm;
+            mesh->submeshes[k].vertices[i].tang = R*mesh->submeshes[k].vertices[i].tang;
+        }
+    }
+}
+
+
+#endif //__GLMesh_H__
+

sources/opengl2_samples/test7c_cameramanipulator/GLMeshTools.cpp

+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// BF tools for creating/manipulating meshes
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+
+#include "assimp/importer.hpp"  
+#include "assimp/postprocess.h"
+#include "assimp/scene.h"
+
+#include "vmath.h"
+#include "vertex.h"
+#include "GLMesh.h"
+#include "GLMaterial.h"
+
+#include "GLMaterialSystem.h"
+
+// logging functs
+#include "logger.h"
+
+namespace 
+{   
+            // GLMaterial *mat = materialsystem::getOrCreateMaterial("material_matte","shader_matte");
+        // mat->textures[GLMaterial::evTextureDiffuse] = "Concrete.jpg";
+        // mat->textures[GLMaterial::evTextureNormal] = "normal1.png";
+
+    // extract material properties
+    GLMaterial* getMaterial(const aiScene* scene, unsigned int index, bool *success=NULL)
+    {
+        if (index>scene->mNumMaterials)
+        {
+            logError("Error: attempt to access nonexisting material%d\n",0);
+            if (success) *success=false;
+            return NULL;
+        }
+        
+        aiMaterial* aiMat = scene->mMaterials[index];
+
+        std::stringstream mname;
+        // static int idx = 1;
+        mname << "ai_material_" << index;
+        GLShader *shader2 = materialsystem::getOrCreateShaderFromFiles("shader_default","shader_default.vert", "shader_default.frag");
+        GLMaterial *mat = materialsystem::getOrCreateMaterial(mname.str(),"shader_default");
+
+        // fill material with data
+
+        // render attributes
+        // int flag = 0;
+        // if (AI_SUCCESS == aiMat->Get(AI_MATKEY_ENABLE_WIREFRAME,flag))
+        //     bfmat.wireframe = (flag!=0);
+        // // shininess
+        // float value = 0.0;
+        // if (AI_SUCCESS == aiMat->Get(AI_MATKEY_SHININESS,value))
+        //     bfmat.shininess = value;
+        // // printf("Imported material shininess: %f\n",bfmat.shininess);
+        // if (AI_SUCCESS == aiMat->Get(AI_MATKEY_SHININESS_STRENGTH,value))
+        //     bfmat.shininess *= value; 
+        // // printf("Imported material shininess*strength: %f\n",bfmat.shininess);
+        // /// \todo rescale shininess accordingly
+        // bfmat.shininess = clamp(bfmat.shininess/10.0,0.0,1.0);
+
+        // get textures
+        int texIndex = 0;   /// \todo only the first texture for each channel is retrieved!
+        aiString texPath;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_AMBIENT, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureAmbient] = texPath.data;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureDiffuse] = texPath.data;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_EMISSIVE, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureEmissive] = texPath.data;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_HEIGHT, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureNormal] = texPath.data;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_SHININESS, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureShininess] = texPath.data;
+        if(AI_SUCCESS == aiMat->GetTexture(aiTextureType_SPECULAR, texIndex, &texPath))
+            mat->textures[GLMaterial::evTextureSpecular] = texPath.data;
+ 
+        logMessage("Material textures:\n");
+        logMessage("   Ambient: %s\n",mat->textures[GLMaterial::evTextureAmbient].c_str());
+        logMessage("   Diffuse: %s\n",mat->textures[GLMaterial::evTextureDiffuse].c_str());
+        logMessage("   Emissive: %s\n",mat->textures[GLMaterial::evTextureEmissive].c_str());
+        logMessage("   Normal: %s\n",mat->textures[GLMaterial::evTextureNormal].c_str());
+        logMessage("   Shininess: %s\n",mat->textures[GLMaterial::evTextureShininess].c_str());
+        logMessage("   Specular: %s\n",mat->textures[GLMaterial::evTextureSpecular].c_str());
+        if (success) *success = true;
+        return mat;
+    }
+
+
+    // add a submesh with corresponding material
+    bool addSubMesh( GLMesh *mesh, const aiScene* scene, const aiMesh* aimesh, const aiMatrix4x4 &tr)
+    {
+        GLSubMesh submesh;
+
+        // fill mesh data
+        if (!aimesh)        
+            return false;
+        // vertices
+        submesh.vertices.clear();
+        submesh.vertices.resize(aimesh->mNumVertices);
+        for (unsigned int i=0; i<aimesh->mNumVertices; i++)
+        {
+            // get vertex data
+            Vertex_t vertex;        
+            if (aimesh->HasPositions())
+            {
+                aiVector3D v = tr*aimesh->mVertices[i];
+                vertex.pos = Vector3f(v.x,v.y,v.z);
+            }
+            if (aimesh->HasNormals())
+            {
+                aiVector3D v = tr*aimesh->mNormals[i];
+                vertex.norm = Vector3f(v.x,v.y,v.z);
+            }
+            if (aimesh->HasTangentsAndBitangents())
+            {
+                aiVector3D v = tr*aimesh->mTangents[i];
+                vertex.tang = Vector3f(v.x,v.y,v.z);
+            }
+            if (aimesh->HasVertexColors(0))   /// \todo only first color set extracted: replace with more generic formulation
+            {
+                vertex.color = Vector4f(aimesh->mColors[0][i].r,aimesh->mColors[0][i].g,aimesh->mColors[0][i].b,aimesh->mColors[0][i].a);
+            }
+            if (aimesh->HasTextureCoords(0))   /// \todo only first texture coord set extracted: replace with more generic formulation
+            {
+                vertex.tex0 = Vector2f(aimesh->mTextureCoords[0][i].x,aimesh->mTextureCoords[0][i].y);
+            }
+            // add vertex
+            submesh.vertices[i] = vertex;
+        }
+        // indices
+        submesh.indices.clear();
+        for (int i=0; i< aimesh->mNumFaces; i++)
+        {
+            const aiFace *face = &(aimesh->mFaces[i]);
+            /// \todo only triangles are extracted from the input mesh: make this code generic
+            if (face->mNumIndices==3)
+            {
+                for (unsigned int k=0; k<face->mNumIndices; k++)
+                    submesh.indices.push_back(face->mIndices[k]);
+            }
+        }
+
+        // extract material
+        submesh.material = getMaterial(scene,aimesh->mMaterialIndex);
+        
+        logMessage("Mesh Info:\n");
+        logMessage("   indices:   %lu\n", submesh.indices.size());
+        logMessage("   vertices:  %lu\n", submesh.vertices.size());
+        return mesh->addSubMesh(submesh);
+    }
+    
+
+    // parse a node hierarchy and add each submesh to the mesh->submeshes vector
+    bool flattenNestedMeshes( GLMesh *mesh, const aiScene* scene, const aiNode* node)
+    {
+        // calc trnasformation relative to root node
+        aiMatrix4x4 tr = node->mTransformation;
+        const aiNode *curr = node;
+        while (curr->mParent)
+        {
+            curr = curr->mParent;
+            tr = curr->mTransformation*tr;
+        }
+                  
+        for (unsigned int i=0; i<node->mNumMeshes;i++)
+        {
+            logMessage(" +- add mesh %d\n", i);
+            if (!addSubMesh( mesh, scene, scene->mMeshes[node->mMeshes[i]], tr))
+                return false;
+        }    
+        // recursive call
+        for (unsigned int k=0; k<node->mNumChildren;k++)
+        {    
+            logMessage(" +- recurse into child %d\n", k);
+            if (!flattenNestedMeshes( mesh, scene, node->mChildren[k]))
+                return false;
+        }
+        return true;
+    }
+    
+    
+
+    // fill a submesh with subdivided quad data
+    void fillFaceData( GLSubMesh &sm, const Vector3f &norm, 
+                       const Vector3f &p1, const Vector3f &p2,
+                       const Vector3f &p3, const Vector3f &p4, 
+                       const Vector4f &col )
+    {
+        Vector3f tang = p2-p1;
+        tang.normalize();
+        Vertex_t v1;
+          v1.pos = p1;
+          v1.norm = norm;
+          v1.tang = tang;
+          v1.color = col;
+          v1.tex0 = Vector2f(0.0f,0.0f);
+        Vertex_t v2;
+          v2.pos = p2;
+          v2.norm = norm;
+          v2.tang = tang;
+          v2.color = col;
+          v2.tex0 = Vector2f(1.0f,0.0f);
+        Vertex_t v3;
+          v3.pos = p3;
+          v3.norm = norm;
+          v3.tang = tang;
+          v3.color = col;
+          v3.tex0 = Vector2f(1.0f,1.0f);
+        Vertex_t v4;
+          v4.pos = p4;
+          v4.norm = norm;
+          v4.tang = tang;
+          v4.color = col;
+          v4.tex0 = Vector2f(0.0f,1.0f);
+        // set vertices
+		sm.vertices.push_back(v1);
+        sm.vertices.push_back(v2);
+        sm.vertices.push_back(v3);
+        sm.vertices.push_back(v4);
+        // set indices
+        unsigned int i0 = sm.vertices.size()-4;
+        sm.indices.push_back(i0+0);
+        sm.indices.push_back(i0+1);
+        sm.indices.push_back(i0+2);
+        sm.indices.push_back(i0+0);
+        sm.indices.push_back(i0+2);
+        sm.indices.push_back(i0+3);
+    }
+
+
+
+}
+
+#include "GLShader.h"
+
+namespace meshtools
+{
+    // global variables
+    Assimp::Importer importer;  // assimp importer
+
+    
+    // create a mesh reading from a file
+    GLMesh* createMeshFromFile( const std::string &filename )
+    {
+        //check if file exists
+        std::ifstream fin(filename.c_str());
+        if(!fin.fail())
+            fin.close();
+        else
+        {
+            logError("Unable to open mesh file: %s\n",filename.c_str());
+            return NULL;
+        }
+
+        const aiScene *scene = importer.ReadFile( filename,  aiProcessPreset_TargetRealtime_Quality );
+        if( !scene)
+        {
+            logError("Error importing mesh file: %s\n",filename.c_str());
+            return NULL;
+        }
+                
+	    // flatten node hierarchy and add all submeshes with their materials
+        GLMesh *mesh = new GLMesh;
+        if (!flattenNestedMeshes( mesh, scene, scene->mRootNode))
+        {
+            logError("Error extracting sub-meshes from file: %s\n",filename.c_str());
+            delete mesh;
+            return NULL;
+        }
+        // get some debug statistics
+        float minx=1E8, maxx=-1E8,
+              miny=1E8, maxy=-1E8,
+              minz=1E8, maxz=-1E8;
+        for (unsigned int i=0; i<mesh->submeshes.size(); i++)
+            for (unsigned int j=0; j<mesh->submeshes[i].vertices.size(); j++)
+            {
+                Vector3f &pos = mesh->submeshes[i].vertices[j].pos;
+                if (pos.x<minx) minx = pos.x;
+                if (pos.x>maxx) maxx = pos.x;
+                if (pos.y<miny) miny = pos.y;
+                if (pos.y>maxy) maxy = pos.y;
+                if (pos.z<minz) minz = pos.z;
+                if (pos.z>maxz) maxz = pos.z;
+            }
+        logInfo("created mesh from file '%s'\n", filename.c_str());
+        logInfo("      x range [%f : %f]\n", minx, maxx);
+        logInfo("      y range [%f : %f]\n", miny, maxy);
+        logInfo("      z range [%f : %f]\n", minz, maxz);
+        return mesh;
+    }
+    
+    
+    // only one submesh
+    GLSubMesh createBoxSubMesh( Vector3f size, Vector4f color)
+    {
+        GLSubMesh sm;
+        sm.indices.clear();
+        sm.vertices.clear();
+    
+        // main vertices coords
+        float sx = size.x/2.0;
+        float sy = size.y/2.0;
+        float sz = size.z/2.0;
+        Vector3f p0(-sx,-sy,+sz);
+        Vector3f p1(+sx,-sy,+sz);
+        Vector3f p2(+sx,+sy,+sz);
+        Vector3f p3(-sx,+sy,+sz);
+        Vector3f p4(-sx,-sy,-sz);
+        Vector3f p5(+sx,-sy,-sz);
+        Vector3f p6(+sx,+sy,-sz);
+        Vector3f p7(-sx,+sy,-sz);
+        // fill sm vertices, indices and normals
+        fillFaceData( sm, Vector3f( 0.0f, 0.0f, 1.0f), p0,p1,p2,p3, color);   // front
+        fillFaceData( sm, Vector3f( 0.0f, 0.0f,-1.0f), p5,p4,p7,p6, color);   // rear
+        fillFaceData( sm, Vector3f(-1.0f, 0.0f, 0.0f), p4,p0,p3,p7, color);   // left
+        fillFaceData( sm, Vector3f( 1.0f, 0.0f, 0.0f), p1,p5,p6,p2, color);   // right
+        fillFaceData( sm, Vector3f( 0.0f, 1.0f, 0.0f), p3,p2,p6,p7, color);   // top
+        fillFaceData( sm, Vector3f( 0.0f,-1.0f, 0.0f), p4,p5,p1,p0, color);   // bottom
+
+        return sm;
+    }
+
+    
+    // only one submesh
+    GLSubMesh createXZPlaneSubMesh( float sideLen, unsigned int sideQuads, Vector4f color)
+    {
+        GLSubMesh sm;
+        sm.indices.clear();
+        sm.vertices.clear();
+
+        if (sideQuads<1) sideQuads = 1;
+    
+        float quadLen = 2.0*sideLen/sideQuads;
+
+        for (unsigned int u=0; u<sideQuads; u++)
+            for (unsigned int v=0; v<sideQuads; v++)
+            {
+                float offx = -sideLen + u*quadLen;
+                float offz = -sideLen + v*quadLen;
+                // quad vertices
+                Vector3f p0(offx,0.0,offz);
+                Vector3f p1(offx+quadLen,0.0,offz);
+                Vector3f p2(offx+quadLen,0.0,offz+quadLen);
+                Vector3f p3(offx,0.0,offz+quadLen);
+                // fill sm vertices, indices and normals
+                fillFaceData( sm, Vector3f( 0.0f, 1.0f, 0.0f), p0,p1,p2,p3, color);
+            }
+        
+        return sm;
+    }
+
+    
+    // create a box prefab
+    GLMesh* createPrefabPlane( float sideLen, unsigned int sideQuads, Vector4f color )
+    {
+        GLMesh *mesh = new GLMesh;
+
+        GLSubMesh sm = createXZPlaneSubMesh( sideLen, sideQuads, color);
+        // set material
+        GLShader *shader = materialsystem::getOrCreateShaderFromFiles("shader_matte","shader_matte.vert", "shader_matte.frag");
+        GLMaterial *mat  = materialsystem::getOrCreateMaterial("material_matte","shader_matte");
+        sm.material = mat;
+        
+        mesh->addSubMesh(sm);
+        return mesh;
+    }
+
+
+    // create a box prefab
+    GLMesh* createPrefabPlane( float sideLen, unsigned int sideQuads, GLMaterial *mat )
+    {
+        GLMesh *mesh = new GLMesh;
+
+        GLSubMesh sm = createXZPlaneSubMesh( sideLen, sideQuads, Vector4f(1.0,1.0,1.0,1.0));
+        // set material
+        sm.material = mat;
+        
+        mesh->addSubMesh(sm);
+        return mesh;
+    }
+
+
+    // create a box prefab
+    GLMesh* createPrefabBox( Vector3f size, Vector4f color )
+    {
+        GLMesh *mesh = new GLMesh;
+
+        GLSubMesh sm = createBoxSubMesh( size, color);
+        // set material
+        GLShader *shader = materialsystem::getOrCreateShaderFromFiles("shader_matte","shader_matte.vert", "shader_matte.frag");
+        // GLShader *shader = new GLShader();
+        // shader->initFromFile("normal_sh_tex.vert", "normal_sh_tex.frag");
+        GLMaterial *mat = materialsystem::getOrCreateMaterial("material_matte","shader_matte");
+        // mat->textures[GLMaterial::evTextureDiffuse] = "Concrete.jpg";
+        // mat->textures[GLMaterial::evTextureNormal] = "normal1.png";
+        sm.material = mat;
+        //initializeMaterial(mat);
+        
+        mesh->addSubMesh(sm);
+        return mesh;
+    }
+
+
+    // create a box prefab
+    GLMesh* createPrefabBox( Vector3f size, GLMaterial *mat )
+    {
+        GLMesh *mesh = new GLMesh;
+
+        GLSubMesh sm = createBoxSubMesh( size, Vector4f(1.0,1.0,1.0,1.0));
+        // set material
+        sm.material = mat;
+        //initializeMaterial(mat);
+        
+        mesh->addSubMesh(sm);
+        return mesh;
+    }
+
+
+}
+

sources/opengl2_samples/test7c_cameramanipulator/GLMeshTools.h

+#ifndef __GLMeshTools_H__
+#define __GLMeshTools_H__
+// /////////////////////////////////////////////////////////////////////// //
+// Copyright (c) 2012, Davide Bacchet (davide.bacchet@gmail.com)           //
+// All rights reserved.                                                    //
+//                                                                         //
+// The software is released under the Creative Commons Attribution         //
+// NonCommercial (CC BY-NC) license. The full license text is available    //
+// at http://creativecommons.org/licenses/by-nc/3.0/legalcode              //
+//                                                                         //
+// You are free to distribute and adapt the work under the conditions:     //
+// * Redistributions of source code must retain the above copyright notice //
+// * You must attribute the work in the manner specified by the author     //
+// * You may not use this work for commercial purposes.                    //
+//                                                                         //
+// Commercial Usage:                                                       //
+// To use this software as part of a commercial product, you must          //
+// obtain a written agreement from the author.                             //
+// /////////////////////////////////////////////////////////////////////// //
+
+// GL tools for creating/manipulating meshes
+
+#include <string>
+#include "vmath.h"
+
+// forward declarations
+class GLMesh;
+class GLMaterial;
+
+
+namespace meshtools
+{
+    /// create a mesh reading from a file. return a NULL pointer in case of error
+    GLMesh* createMeshFromFile( const std::string &filename );
+    
+    /// create a prefab XZ plane in the origin
+    GLMesh* createPrefabPlane( float sideLen, unsigned int sideQuads, Vector4f color );
+    GLMesh* createPrefabPlane( float sideLen, unsigned int sideQuads, GLMaterial *mat );
+    /// create a prefab box in the origin
+    GLMesh* createPrefabBox( Vector3f size, Vector4f color );
+    GLMesh* createPrefabBox( Vector3f size, GLMaterial *mat );
+    
+}
+
+
+
+
+#endif //__GLMeshTools_H__
+

sources/opengl2_samples/test7c_cameramanipulator/GLRenderer.cpp

+#include <string>
+#include <vector>
+
+#include "glfw_utils.h" // just to retrieve opengl symbols without conflicting with the include order
+#include "stb_image.h"
+
+#include "logger.h"
+
+#include "GLShader.h"
+#include "GLMaterial.h"
+#include "GLCamera.h"
+
+#include "GLMaterialSystem.h"
+
+#include "GLRenderer.h"
+
+
+// ////////////// //
+// local function //
+// ////////////// //
+namespace 
+{
+    template <class T>
+    void append( std::vector<T> &to, const std::vector<T> &from )
+    {
+        to.insert(to.end(),from.begin(),from.end());
+    }
+
+
+
+
+
+    // /////////////////////// //
+    // opengl related function //
+    // /////////////////////// //
+
+    // initialize the vbo and corresponding ibo
+    VboIds createVBO(void)
+    {
+        GLint  vtxStride = sizeof(Vertex_t);
+
+        GLuint vboIds[2];
+        glGenBuffers(2, vboIds);
+
+        // define internal vbo structure
+        glEnableVertexAttribArray(VERTEX_POS_INDX); 
+        glEnableVertexAttribArray(VERTEX_NORMAL_INDX); 
+        glEnableVertexAttribArray(VERTEX_TANGENT_INDX);
+        glEnableVertexAttribArray(VERTEX_COLOR_INDX);
+        glEnableVertexAttribArray(VERTEX_TEXCOORD0_INDX);
+        
+        GLuint offset=0;
+        glVertexAttribPointer(VERTEX_POS_INDX,       VERTEX_POS_SIZE,       GL_FLOAT, GL_FALSE, vtxStride, (const void*)offset);
+        offset += VERTEX_POS_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_NORMAL_INDX,    VERTEX_NORMAL_SIZE,    GL_FLOAT, GL_FALSE, vtxStride, (const void*)offset);
+        offset += VERTEX_NORMAL_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_TANGENT_INDX,   VERTEX_TANGENT_SIZE,   GL_FLOAT, GL_FALSE, vtxStride, (const void*)offset);
+        offset += VERTEX_TANGENT_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_COLOR_INDX,     VERTEX_COLOR_SIZE,     GL_FLOAT, GL_FALSE, vtxStride, (const void*)offset);
+        offset += VERTEX_COLOR_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE, GL_FLOAT, GL_FALSE, vtxStride, (const void*)offset);
+
+        // set output
+        VboIds out;
+        out.dataId    = vboIds[0];
+        out.indicesId = vboIds[1];
+        return out;
+    }
+
+    
+
+    // draw a vbo
+    void drawVBO( const VboIds &vboIds, const std::vector<Vertex_t> &vertices, const std::vector<unsigned int> &indices)
+    {
+        GLuint vboid       = vboIds.dataId;
+        GLuint vboidxid    = vboIds.indicesId;
+        GLuint numVertices = vertices.size();
+        GLuint numIndices  = indices.size();
+
+        glBindBuffer(GL_ARRAY_BUFFER, vboid); 
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboidxid); 
+
+        glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);         // optimization: just tell the driver that the buffer will be completely replaced
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW); // optimization: just tell the driver that the buffer will be completely replaced
+
+        // update vertices positions
+        glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Vertex_t), &(vertices[0]), GL_DYNAMIC_DRAW);
+
+        GLuint offset=0;
+        glVertexAttribPointer(VERTEX_POS_INDX,       VERTEX_POS_SIZE,       GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset);
+        offset += VERTEX_POS_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_NORMAL_INDX,    VERTEX_NORMAL_SIZE,    GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset);
+        offset += VERTEX_NORMAL_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_TANGENT_INDX,   VERTEX_TANGENT_SIZE,   GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset);
+        offset += VERTEX_TANGENT_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_COLOR_INDX,     VERTEX_COLOR_SIZE,     GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset);
+        offset += VERTEX_COLOR_SIZE * sizeof(GLfloat); 
+        glVertexAttribPointer(VERTEX_TEXCOORD0_INDX, VERTEX_TEXCOORD0_SIZE, GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset);
+
+        // update indices
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*sizeof(GLuint),&(indices[0]), GL_DYNAMIC_DRAW);
+
+        // printf("CUBE: bind buffers: %u, %u\n", vboid, vboidxid);
+        glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);  
+
+        // std::cout << vboid << " - " << std::endl;
+        // std::cout << smvbo.vertices[0].pos << std::endl;
+    }
+
+
+    // get a list of all active uniforms in the shader
+    struct UniformData
+    {
+        std::string name;
+        int location;
+    };
+    std::vector<UniformData> getUniformList( GLShader *sh )
+    {
+        std::vector<UniformData> out;
+        int total = -1;
+        glGetProgramiv( sh->programId, GL_ACTIVE_UNIFORMS, &total ); 
+        for(int i=0; i<total; ++i) 
+        {
+            int name_len=-1, num=-1;
+            GLenum type = GL_ZERO;
+            char name[100];
+            glGetActiveUniform( sh->programId, GLuint(i), sizeof(name)-1,
+                &name_len, &num, &type, name );
+            name[name_len] = 0;
+            logInfo("Shader: found uniform '%s'\n",name);
+            GLint location = glGetUniformLocation( sh->programId, name );
+            UniformData ud;
+              ud.name = name;
+              ud.location = location;
+            out.push_back(ud);
+        }
+        return out;
+    }
+
+}
+
+
+
+
+
+GLBatch::GLBatch( GLRenderer *renderer)
+: _renderer(renderer)
+{
+    init();
+}
+
+
+GLBatch::GLBatch( GLRenderer *renderer, const BatchKey &key)
+: _renderer(renderer)
+{
+    init();
+    _key = key;
+    _shader   = materialsystem::getShader(_key.shader);
+    _material = materialsystem::getMaterial(_key.material);
+}
+
+
+GLBatch::~GLBatch()
+{
+    // nothing to do 
+}
+
+
+// add data to the batch
+bool GLBatch::addData( const std::vector<Vertex_t> &vert, const std::vector<unsigned int> &ind )
+{
+    int idx_offset = _vertices.size();
+	int idx_start  = _indices.size();
+    append(_vertices,vert);
+    append(_indices,ind);
+    // update indices
+    for (unsigned int i=idx_start; i<_indices.size(); i++)
+        _indices[i] += idx_offset;
+    return true;
+}
+
+
+void GLBatch::init( void )
+{
+    _key.shader = "";
+    _key.material = "";
+    _shader = NULL;
+    _material = NULL;
+    _vertices.clear();
+    _indices.clear();
+}
+
+
+
+
+
+
+// // //////////////////////////////// //
+// // shaders and materials management //
+// // //////////////////////////////// //