Exemple #1
0
/*!
The SLRefGroup::shapeInit checks the validity of the referenced node. To avoid 
endless loops a refShape node is not allowed to refShape its ancestors. An 
ancestor of a refShape node is group node followed along the previous pointers 
with lower depth than the depth of the refShape node.
*/
void SLRefGroup::shapeInit(SLSceneView* sv)
{  
   // cummulate wm with referenced wm
   SLShape* ref = (SLShape*)_refGroup; 
   _wm *= ref->m();
   _wmI.setMatrix(_wm.inverse());
   _wmN.setMatrix(_wmI.mat3());
   _wmN.transpose();
   
   // check circular references
   SLNode* parent = this->parent();
   while (parent)
   {  if (parent==_refGroup)
         SL_EXIT_MSG("Reference node produces a never ending loop.");
      parent = parent->parent();
   }
   
   // set transparency flag
   _aabb.hasAlpha(((SLShape*)_refGroup)->aabb()->hasAlpha());
   
   // delete all child references
   if (_first) deleteAll();
      
   // loop through the referenced group and add a SLRefShape or SLRefGroup
   SLNode* current = ((SLGroup*)_refGroup)->first();
   while (current)
   {  if (typeid(*current)==typeid(SLGroup))
           addNode(new SLRefGroup((SLGroup*)current, name()+"_"+current->name()));
      else addNode(new SLRefShape((SLShape*)current, name()+"_"+current->name()));
      ((SLShape*)_last)->wm(_wm);
      ((SLShape*)_last)->depth(depth()+1);
      ((SLShape*)_last)->shapeInit(sv);
      current = current->next();
   }
}
//----------------------------------------------------------------------------- 
//! SLGLShader::createAndCompile creates & compiles the OpenGL shader object
SLbool SLGLShader::createAndCompile()
{  
    // delete if object already exits
    if (_objectGL) glDeleteShader(_objectGL);

    if (_code!="")
    {  
        switch (_type)
        {   case VertexShader:
                _objectGL = glCreateShader(GL_VERTEX_SHADER); break;
            case FragmentShader:
                _objectGL = glCreateShader(GL_FRAGMENT_SHADER); break;
            default:
                SL_EXIT_MSG("SLGLShader::load: Unknown shader type.");
        }
      
        //SLstring verGLSL = SLGLState::getInstance()->glSLVersionNO();
        //SLstring srcVersion = "#version " + verGLSL + "\n";

        //if (verGLSL > "120")
        //{   if (_type == VertexShader)
        //    {   SLUtils::replaceString(_code, "attribute", "in");
        //        SLUtils::replaceString(_code, "varying", "out");
        //    }
        //    if (_type == FragmentShader)
        //    {   SLUtils::replaceString(_code, "varying", "in");
        //    }
        //}
        //SLstring scrComplete = srcVersion + _code;

        SLstring scrComplete = _code;

        const char* src = scrComplete.c_str();
        glShaderSource(_objectGL, 1, &src, 0);
        glCompileShader(_objectGL);

        // Check compiler log
        SLint compileSuccess = 0;
        glGetShaderiv(_objectGL, GL_COMPILE_STATUS, &compileSuccess);
        if (compileSuccess == GL_FALSE) 
        {   GLchar log[256];
            glGetShaderInfoLog(_objectGL, sizeof(log), 0, &log[0]);
            SL_LOG("*** COMPILER ERROR ***\n");
            SL_LOG("Source file: %s\n", _file.c_str());
            SL_LOG("%s\n\n", log);
            return false;
        }
        return true;
    } else SL_WARN_MSG("SLGLShader::createAndCompile: Nothing to compile!");
    return false;
}
Exemple #3
0
/*!
SLGroup::shapeInit loops over all child nodes and calls their init method with
an incremented depth. While looping it must be checked that all child nodes
have a depth equal the groups depth + 1.
*/
void SLGroup::shapeInit(SLSceneView* sv)
{  SLNode* current = _first;
   while (current)
   {  if (current->depth() && current->depth() != depth()+1) 
      {  SL_EXIT_MSG("Scenegraph is not directed acyclic. There is a loop.");
      }
      current->init(sv, depth()+1);
      
      // Set transparent flags of the group
      if (!_aabb.hasAlpha() && ((SLShape*)current)->aabb()->hasAlpha())
         _aabb.hasAlpha(true); 
         
      current = current->next();
   }
}
Exemple #4
0
/*!
The SLRefShape::shapeInit checks the validity of the referenced node. To avoid 
endless loops a refShape node is not allowed to refShape its ancestors. An 
ancestor of a refShape node is group node followed along the previous pointers 
with lower depth than the depth of the refShape node.
Do not initialize the referenced shape twice.
*/
void SLRefShape::shapeInit(SLSceneView* sv)
{  (void)sv; // avoid unused parameter warning

   // cummulate my wm with referenced object transform (m)
   SLShape* ref = (SLShape*)_refShape;
   _wm *= ref->m();
   _wmI.setMatrix(_wm.inverse());
   _wmN.setMatrix(_wmI.mat3());
   _wmN.transpose();
   
   // set transparency flag
   _aabb.hasAlpha(((SLShape*)_refShape)->aabb()->hasAlpha());
   
   // check circular references
   SLNode* parent = this->parent();
   while (parent)
   {  if (parent==_refShape)
         SL_EXIT_MSG("Reference node produces a never ending loop.");
      parent = parent->parent();
   }
}
/*! 
SLLightRect::init sets the light id, the light states & creates an 
emissive mat.
@todo properly remove this function and find a clean way to init lights in a scene
*/
void SLLightRect::init()
{  
    // Check if OpenGL lights are available
    if (SLScene::current->lights().size() >= SL_MAX_LIGHTS) 
        SL_EXIT_MSG("Max. NO. of lights is exceeded!");

    // Add the light to the lights array of the scene
    if (_id==-1)
    {   _id = (SLint)SLScene::current->lights().size();
        SLScene::current->lights().push_back(this);
    }
   
    // Set the OpenGL light states
    setState();
    _stateGL->numLightsUsed = (SLint)SLScene::current->lights().size();
   
    // Set emissive light material to the lights diffuse color
    if (_meshes.size() > 0)
        if (_meshes[0]->mat)
            _meshes[0]->mat->emission(_on ? diffuse() : SLCol4f::BLACK);   
}
Exemple #6
0
/*! 
SLMesh::shapeDraw does the OpenGL rendering of the mesh. The triangle 
primitives are rendered per material (SLMatFaces) with the vertex array P, 
the normal array N, the array Tc and the face vertex index array F. 
Optionally you can draw the normals and/or the uniform grid voxels.
*/
void SLMesh::shapeDraw(SLSceneView* sv)
{  
   if (P && N)
   {     
      ////////////////////////
      // 1: Check drawing bits
      ////////////////////////
            
      // Return if hidden
      if (sv->drawBits()->get(SL_DB_HIDDEN) || _drawBits.get(SL_DB_HIDDEN)) 
         return;
              
      // Set polygon mode
      SLPrimitive primitiveType = SL_TRIANGLES;
      if (sv->drawBits()->get(SL_DB_POLYGONLINE) || 
         _drawBits.get(SL_DB_POLYGONLINE))
      	primitiveType = SL_LINE_LOOP;
         
      // Set face culling      
      stateGL->cullFace(!(sv->drawBits()->get(SL_DB_CULLOFF) || 
                         _drawBits.get(SL_DB_CULLOFF)));
      
      // check if texture exists
      SLbool useTexture = Tc && !(sv->drawBits()->get(SL_DB_TEXOFF) || 
                                     _drawBits.get(SL_DB_TEXOFF));
                                     
      // enable polygonoffset if voxels are drawn to avoid stitching
      if (sv->drawBits()->get(SL_DB_VOXELS) || _drawBits.get(SL_DB_VOXELS))
      {  stateGL->polygonOffset(true, 1.0f, 1.0f);
      }


      //////////////////////
      // 2: Build VBO's once
      //////////////////////

      if (!_bufP.id()) _bufP.generate(P, numV, 3);
      if (!_bufN.id()) _bufN.generate(N, numV, 3);
      if (!_bufTc.id() && Tc) _bufTc.generate(Tc, numV, 2);
      if (!_bufT.id() && T) _bufT.generate(T, numV, 4);
      if (!_bufF.id() && F) _bufF.generate(F, numF, 3, SL_UNSIGNED_SHORT, SL_ELEMENT_ARRAY_BUFFER);    
       
      
      ////////////////////////////////
      // 3: Draw elements per material
      ////////////////////////////////

      for (SLuint m = 0; m < numM; ++m)
      {  
         // Opaque materials only in 1st non-blended pass
         // Transparent materials only in 2nd blended pass
         if ((!stateGL->blend() && !M[m].mat->hasAlpha()) || 
             ( stateGL->blend() &&  M[m].mat->hasAlpha()))
         {
            // 3.a: Apply mesh material if exists & differs from current
             if (M[m].mat != SLMaterial::current || SLMaterial::current->shaderProg()==0)
               M[m].mat->activate(stateGL, this);
            
            // 3.b: Pass the matrices to the shader program
            SLGLShaderProg* sp = SLMaterial::current->shaderProg();
            sp->uniformMatrix4fv("u_mvMatrix",    1, (SLfloat*)&stateGL->modelViewMatrix);
            sp->uniformMatrix4fv("u_mvpMatrix",   1, (SLfloat*)stateGL->mvpMatrix());
            sp->uniformMatrix3fv("u_nMatrix",     1, (SLfloat*)stateGL->normalMatrix());
            sp->uniformMatrix4fv("u_invMvMatrix", 1, (SLfloat*)stateGL->invModelViewMatrix());
                              
            // 3.c: Enable attribute pointers
            _bufP.bindAndEnableAttrib(sp->getAttribLocation("a_position"));
            _bufN.bindAndEnableAttrib(sp->getAttribLocation("a_normal"));
            if (_bufTc.id() && useTexture) 
               _bufTc.bindAndEnableAttrib(sp->getAttribLocation("a_texCoord"));
            if (_bufT.id())  
               _bufT.bindAndEnableAttrib(sp->getAttribLocation("a_tangent"));
   
            // 3.d: Finally draw elements
            _bufF.bindAndDrawElementsAs(primitiveType, M[m].numF*3, 
                                        M[m].startF*3*sizeof(SLushort));

            // 3.e: Disable attribute pointers
            _bufP.disableAttribArray();
            _bufN.disableAttribArray();
            if (_bufTc.id()) _bufTc.disableAttribArray();
            if (_bufT.id())  _bufT.disableAttribArray();
         }
      }
      
      //////////////////////////////////////
      // 4: Draw optional normals & tangents
      //////////////////////////////////////

      if (sv->drawBits()->get(SL_DB_NORMALS) || _drawBits.get(SL_DB_NORMALS))
      {  
         // scale the normals to 5% of the surounding sphere
         float r = _aabb.radiusOS() * 0.05f;
         SLVec3f* V2;
         
         if (!_bufN2.id())
         {  // scalefactor r from scaled radius for normals & tangents
            // build array between vertex and normal target point
            V2 = new SLVec3f[numV*2]; 
            for (SLuint i=0; i < numV; ++i)
            {  V2[i<<1] = P[i];
               V2[(i<<1)+1].set(P[i] + N[i]*r);
            }
            
            // Create buffer object for normals
            _bufN2.generate(V2, numV*2, 3);
            
            if (T)
            {  if (!_bufT2.id())
               {  for (SLuint i=0; i < numV; ++i)
                  {  V2[(i<<1)+1].set(P[i].x+T[i].x*r, 
                                      P[i].y+T[i].y*r, 
                                      P[i].z+T[i].z*r);
                  }
               
                  // Create buffer object for tangents
                  _bufT2.generate(V2, numV*2, 3);
               }
            } 
            delete[] V2;

         }
         _bufN2.drawArrayAsConstantColorLines(SLCol3f::BLUE);
         if (T) _bufT2.drawArrayAsConstantColorLines(SLCol3f::RED);
      } 
      else
      {  
         // release buffer objects for normal & tangent rendering
         if (_bufN2.id()) _bufN2.dispose();
         if (_bufT2.id()) _bufT2.dispose();
      }

      //////////////////////////////////////////
      // 5: Draw optional acceleration structure
      //////////////////////////////////////////

      if (_accelStruct) 
      {  if (sv->drawBits()->get(SL_DB_VOXELS) || _drawBits.get(SL_DB_VOXELS))
         {  _accelStruct->draw(sv);
            stateGL->polygonOffset(false);
         } else
         {  // Delete the visualization VBO if not rendered anymore
            _accelStruct->disposeBuffers();
         }
      }
            
      GET_GL_ERROR;
   } else
   {  SL_EXIT_MSG("SLMesh::shapeDraw: Arrays P or/and N empty");
   }
}
//-----------------------------------------------------------------------------
//! SLRectangle::buildMesh fills in the underlying arrays from the SLMesh object
void SLRectangle::buildMesh(SLMaterial* material)
{  
    deleteData();
   
    // Check max. allowed no. of verts
    SLuint uIntNumV64 = (_resX+1) * (_resY+1);
    if (uIntNumV64 > UINT_MAX)
        SL_EXIT_MSG("SLMesh supports max. 2^32 vertices.");

    // allocate new arrays of SLMesh
    numV = (_resX+1) * (_resY+1);
    numI = _resX * _resY * 2 * 3;
    P = new SLVec3f[numV];
    N = new SLVec3f[numV];
    Tc = new SLVec2f[numV];

    if (uIntNumV64 < 65535)
         I16 = new SLushort[numI];
    else I32 = new SLuint[numI];
   
    // Calculate normal from the first 3 corners
    SLVec3f maxmin(_max.x, _min.y, 0);
    SLVec3f minmax(_min.x, _max.y, 0);
    SLVec3f e1(maxmin - _min);
    SLVec3f e2(minmax - _min);
    SLVec3f curN(e1^e2);
    curN.normalize();
   
    //Set one default material index
    mat = material;
   
    // define delta vectors dX & dY and deltas for texCoord dS,dT
    SLVec3f dX = e1 / (SLfloat)_resX;
    SLVec3f dY = e2 / (SLfloat)_resY;
    SLfloat dS = (_tmax.x - _tmin.x) / (SLfloat)_resX;
    SLfloat dT = (_tmax.y - _tmin.y) / (SLfloat)_resY;

    // Build vertex data
    SLuint i = 0;
    for (SLuint y=0; y<=_resY; ++y)
    {  
        SLVec3f curV = _min;
        SLVec2f curT = _tmin;
        curV   += (SLfloat)y*dY;
        curT.y += (SLfloat)y*dT;

        for (SLuint x=0; x<=_resX; ++x, ++i)
        {  
            P[i]  = curV;
            Tc[i] = curT;
            N[i]  = curN;
            curV   += dX;
            curT.x += dS;
        }      
    }
   
    // Build face vertex indexes
    if (I16)
    {
        SLuint v = 0, i = 0; //index for vertices and indexes
        for (SLuint y=0; y<_resY; ++y)
        {  
            for (SLuint x=0; x<_resX; ++x, ++v)
            {  // triangle 1
                I16[i++] = v;
                I16[i++] = v+_resX+2;
                I16[i++] = v+_resX+1;

                // triangle 2
                I16[i++] = v;
                I16[i++] = v+1;
                I16[i++] = v+_resX+2;
            }      
            v++;
        }
    } else
    {
        SLuint v = 0, i = 0; //index for vertices and indexes
        for (SLuint y=0; y<_resY; ++y)
        {  
            for (SLuint x=0; x<_resX; ++x, ++v)
            {  // triangle 1
                I32[i++] = v;
                I32[i++] = v+_resX+2;
                I32[i++] = v+_resX+1;

                // triangle 2
                I32[i++] = v;
                I32[i++] = v+1;
                I32[i++] = v+_resX+2;
            }      
            v++;
        }
    }
}
Exemple #8
0
/*! SLGLShaderProg::init creates the OpenGL shaderprogram object, compiles all
shader objects and attaches them to the shaderprogram. At the end all shaders
are linked. If a shader fails to compile a simple texture only shader is
compiled that shows an error message in the texture.
*/
void SLGLShaderProg::init()
{     
   // create program object if it doesn't exist
   if(!_programObjectGL) _programObjectGL = glCreateProgram();
   
   // if already linked, detach, recreate and compile shaders
   if (_isLinked)
   {  for (SLuint i=0; i<_shaderList.size(); i++)
      {  if (_isLinked)
         {  glDetachShader(_programObjectGL, _shaderList[i]->_shaderObjectGL);
            GET_GL_ERROR;
         }
      }
      _isLinked = false;
   }
   
   // compile all shader objects
   SLbool allSuccuessfullyCompiled = true;
   for (SLuint i=0; i<_shaderList.size(); i++)
   {  if (!_shaderList[i]->createAndCompile())
      {  allSuccuessfullyCompiled = false;
         break;
      }
      GET_GL_ERROR;
   }

   // try to compile alternative per vertex lighting shaders
   if (!allSuccuessfullyCompiled)
   {        
      // delete all shaders and uniforms that where attached
      for (SLuint i=0; i<_shaderList.size();    i++) delete _shaderList[i]; 
      for (SLuint i=0; i<_uniform1fList.size(); ++i) delete _uniform1fList[i];
      for (SLuint i=0; i<_uniform1iList.size(); ++i) delete _uniform1iList[i];
      _shaderList.clear();
      _uniform1fList.clear();
      _uniform1iList.clear();

      addShader(new SLGLShader(defaultPath+"ErrorTex.vert", SLVertexShader));
      addShader(new SLGLShader(defaultPath+"ErrorTex.frag", SLFragmentShader));

      allSuccuessfullyCompiled = true;
      for (SLuint i=0; i<_shaderList.size(); i++)
      {  if (!_shaderList[i]->createAndCompile())
         {  allSuccuessfullyCompiled = false;
            break;
         }
         GET_GL_ERROR;
      }
   }

   // attach all shader objects
   if (allSuccuessfullyCompiled)
   {  for (SLuint i=0; i<_shaderList.size(); i++)
      {  glAttachShader(_programObjectGL, _shaderList[i]->_shaderObjectGL);
         GET_GL_ERROR;
      }
   } else SL_EXIT_MSG("No successufully compiled shaders attached!");
    
   int linked;
   glLinkProgram(_programObjectGL);
   GET_GL_ERROR;
   glGetProgramiv(_programObjectGL, GL_LINK_STATUS, &linked);
   GET_GL_ERROR;

   if (linked)
   {  _isLinked = true;
      for (SLuint i=0; i<_shaderList.size(); i++) 
         _name += "+"+_shaderList[i]->name();
      //SL_LOG("Linked: %s", _name.c_str());
   } else
   {  SLchar log[256];
      glGetProgramInfoLog(_programObjectGL, sizeof(log), 0, &log[0]);
      SL_LOG("*** LINKER ERROR ***\n");
      SL_LOG("Source files: \n");
      for (SLuint i=0; i<_shaderList.size(); i++) 
         SL_LOG("%s\n", _shaderList[i]->name().c_str());
      SL_LOG("%s\n", log);
      SL_EXIT_MSG("GLSL linker error");
   }
}