/*! * Returns true if the \a m_nodetypeList contains the type of the element defined with \a sourceRow and \a sourceParent */ bool NodesFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { SceneModel* sceneModel = dynamic_cast< SceneModel* > ( sourceModel() ); QModelIndex index = sceneModel->index(sourceRow, 0, sourceParent); InstanceNode* nodeInstance = sceneModel->NodeFromIndex( index ); if( !nodeInstance ) return false; SoNode* node = nodeInstance->GetNode(); if( !node ) return false; if( node->getTypeId().isDerivedFrom( TSeparatorKit::getClassTypeId() ) ) return ( true ); if( node->getTypeId().isDerivedFrom( TShapeKit::getClassTypeId() ) ) { if( m_shapeTypeList.count() < 1 ) return ( true ); TShapeKit* shapeKit = static_cast< TShapeKit* >( node ); if(!shapeKit) return ( false ); TShape* shape = static_cast< TShape* >( shapeKit->getPart( "shape", false ) ); if( shape && m_shapeTypeList.contains( shape->getTypeId().getName().getString() ) ) return ( true ); } return ( false ); }
/** * Creates a new group node insert command that adds a \a separatorKit to \a parentIndex node in the \a model. * * If \a parent is not null, this command is appended to parent's child list and then owns this command. */ CmdInsertSeparatorKit::CmdInsertSeparatorKit( TSeparatorKit* separatorKit, const QModelIndex& parentIndex, SceneModel* model, QUndoCommand* parent ) : QUndoCommand("InsertSeparatorKit", parent), m_separatorKit ( separatorKit ), m_coinParent( 0 ), m_pModel( model ), m_row( -1 ) { if( !m_separatorKit ) gf::SevereError( "CmdInsertSeparatorKit Null separatorKit." ); m_separatorKit->ref(); if( !parentIndex.isValid() ) gf::SevereError( "CmdInsertSeparatorKit called with invalid ModelIndex." ); InstanceNode* instanceParent = m_pModel->NodeFromIndex( parentIndex ); m_coinParent = static_cast< SoBaseKit* > ( instanceParent->GetNode() ); }
/** * Creates a new tracker insert command that adds a \a tracker to a parent node with \a parentIndex in the \a model. * * If \a parent is not null, this command is appended to parent's child list and then owns this command. */ CmdInsertTracker::CmdInsertTracker( TTracker* tracker, const QModelIndex& parentIndex, SoSceneKit* scene, SceneModel* model, QUndoCommand* parent ) : QUndoCommand("Insert Tracker", parent), m_tracker ( tracker ), m_coinParent( 0 ), m_scene( scene ), m_pModel( model ), m_row( 0 ) { if( !m_tracker ) gf::SevereError( "CmdInsertTracker Null tracker." ); m_tracker->ref(); if( !parentIndex.isValid() ) gf::SevereError( "CmdInsertTracker called with invalid ModelIndex." ); InstanceNode* instanceParent = m_pModel->NodeFromIndex( parentIndex ); if( !instanceParent->GetNode() ) gf::SevereError( "CmdInsertTracker called with NULL parent node." ); m_coinParent = static_cast< SoBaseKit* > ( instanceParent->GetNode() ); }
/** * Creates a new cut command that represents the cut the node located with \a index from the \a model. * The node is stored at the \a clipborad. * * If \a parent is not null, this command is appended to parent's child list and then owns this command. */ CmdCut::CmdCut( const QModelIndex& selectedIndex, SoNode*& clipboard, SceneModel* model, QUndoCommand* parent ) : QUndoCommand("Cut", parent), m_pClipboard ( clipboard ), m_previousNode ( 0 ), m_coinNode( 0 ), m_coinParent( 0 ), m_pModel( model ), m_row ( -1 ) { InstanceNode* instanceNode = m_pModel->NodeFromIndex( selectedIndex ); m_coinNode = instanceNode->GetNode(); m_coinNode->ref(); m_coinParent = static_cast< SoBaseKit* > (instanceNode->GetParent()->GetNode() ); m_previousNode = clipboard ; m_row = instanceNode->GetParent()->children.indexOf( instanceNode ); }
/** * Creates a new analyzerkit insert command that adds a \a analyzerkit node to a node given with the \a parentIndex node in the \a model. * * If \a parent is not null, this command is appended to parent's child list and then owns this command. */ CmdInsertAnalyzerKit::CmdInsertAnalyzerKit( const QModelIndex& parentIndex, TAnalyzerKit* analyzerKit, SceneModel* model, QUndoCommand* parent ) : QUndoCommand("InsertAnalyzerKit", parent), m_coinParent( 0 ), m_analyzerKit(analyzerKit), m_pModel(model), m_row( -1 ) { if( m_analyzerKit == 0 ) gf::SevereError( "CmdInsertAnalyzerKit called with NULL TAnalyzerKit*" ); m_analyzerKit->ref(); if( !parentIndex.isValid() ) gf::SevereError( "CmdInsertAnalyzerKit called with invalid ModelIndex." ); InstanceNode* instanceParent = m_pModel->NodeFromIndex( parentIndex ); if( !instanceParent->GetNode() ) gf::SevereError( "CmdInsertAnalyzerKit called with NULL parent node." ); m_coinParent = static_cast< SoBaseKit* > ( instanceParent->GetNode() ); }
/* * Returns the type of the surface */ QString FluxAnalysis::GetSurfaceType( QString nodeURL ) { QModelIndex nodeIndex = m_pCurrentSceneModel->IndexFromNodeUrl( nodeURL ); if( !nodeIndex.isValid() ) return QLatin1String( "" ); InstanceNode* instanceNode = m_pCurrentSceneModel->NodeFromIndex( nodeIndex ); if( !instanceNode || instanceNode == 0 ) return QLatin1String( "" ); TShapeKit* shapeKit = static_cast< TShapeKit* > ( instanceNode->GetNode() ); if( !shapeKit || shapeKit == 0 ) return QLatin1String( "" ); TShape* shape = static_cast< TShape* >( shapeKit->getPart( "shape", false ) ); if( !shape || shape == 0 ) return QLatin1String( "" ); return ( shape->getTypeId().getName().getString() ); }
/* * Fun flux analysis */ void FluxAnalysis::RunFluxAnalysis( QString nodeURL, QString surfaceSide, unsigned long nOfRays, bool increasePhotonMap, int heightDivisions, int widthDivisions ) { m_surfaceURL = nodeURL; m_surfaceSide = surfaceSide; //Delete a photonCounts if( m_photonCounts && m_photonCounts != 0 ) { for( int h = 0; h < m_heightDivisions; h++ ) { delete[] m_photonCounts[h]; } delete[] m_photonCounts; } m_photonCounts = 0; m_heightDivisions = heightDivisions; m_widthDivisions = widthDivisions; //Check if there is a scene if ( !m_pCurrentScene ) return; //Check if there is a transmissivity defined TTransmissivity* transmissivity = 0; if ( !m_pCurrentScene->getPart( "transmissivity", false ) ) transmissivity = 0; else transmissivity = static_cast< TTransmissivity* > ( m_pCurrentScene->getPart( "transmissivity", false ) ); //Check if there is a rootSeparator InstanceNode if( !m_pRootSeparatorInstance ) return; InstanceNode* sceneInstance = m_pRootSeparatorInstance->GetParent(); if ( !sceneInstance ) return; //Check if there is a light and is properly configured if ( !m_pCurrentScene->getPart( "lightList[0]", false ) )return; TLightKit* lightKit = static_cast< TLightKit* >( m_pCurrentScene->getPart( "lightList[0]", false ) ); InstanceNode* lightInstance = sceneInstance->children[0]; if ( !lightInstance ) return; if( !lightKit->getPart( "tsunshape", false ) ) return; TSunShape* sunShape = static_cast< TSunShape * >( lightKit->getPart( "tsunshape", false ) ); if( !lightKit->getPart( "icon", false ) ) return; TLightShape* raycastingSurface = static_cast< TLightShape * >( lightKit->getPart( "icon", false ) ); if( !lightKit->getPart( "transform" ,false ) ) return; SoTransform* lightTransform = static_cast< SoTransform * >( lightKit->getPart( "transform" ,false ) ); //Check if there is a random generator is defined. if( !m_pRandomDeviate || m_pRandomDeviate== 0 ) return; //Check if the surface and the surface side defined is suitable if( CheckSurface() == false || CheckSurfaceSide() == false ) return; //Create the photon map where photons are going to be stored if( !m_pPhotonMap || !increasePhotonMap ) { if( m_pPhotonMap ) m_pPhotonMap->EndStore( -1 ); delete m_pPhotonMap; m_pPhotonMap = new TPhotonMap(); m_pPhotonMap->SetBufferSize( HUGE_VAL ); m_tracedRays = 0; m_wPhoton = 0; m_totalPower = 0; } QVector< InstanceNode* > exportSuraceList; QModelIndex nodeIndex = m_pCurrentSceneModel->IndexFromNodeUrl( m_surfaceURL ); if( !nodeIndex.isValid() ) return; InstanceNode* surfaceNode = m_pCurrentSceneModel->NodeFromIndex( nodeIndex ); if( !surfaceNode || surfaceNode == 0 ) return; exportSuraceList.push_back( surfaceNode ); //UpdateLightSize(); TSeparatorKit* concentratorRoot = static_cast< TSeparatorKit* >( m_pCurrentScene->getPart( "childList[0]", false ) ); if ( !concentratorRoot ) return; SoGetBoundingBoxAction* bbAction = new SoGetBoundingBoxAction( SbViewportRegion() ) ; concentratorRoot->getBoundingBox( bbAction ); SbBox3f box = bbAction->getXfBoundingBox().project(); delete bbAction; bbAction = 0; BBox sceneBox; if( !box.isEmpty() ) { sceneBox.pMin = Point3D( box.getMin()[0], box.getMin()[1], box.getMin()[2] ); sceneBox.pMax = Point3D( box.getMax()[0], box.getMax()[1], box.getMax()[2] ); if( lightKit ) lightKit->Update( sceneBox ); } m_pCurrentSceneModel->UpdateSceneModel(); //Compute bounding boxes and world to object transforms trf::ComputeSceneTreeMap( m_pRootSeparatorInstance, Transform( new Matrix4x4 ), true ); m_pPhotonMap->SetConcentratorToWorld( m_pRootSeparatorInstance->GetIntersectionTransform() ); QStringList disabledNodes = QString( lightKit->disabledNodes.getValue().getString() ).split( ";", QString::SkipEmptyParts ); QVector< QPair< TShapeKit*, Transform > > surfacesList; trf::ComputeFistStageSurfaceList( m_pRootSeparatorInstance, disabledNodes, &surfacesList ); lightKit->ComputeLightSourceArea( m_sunWidthDivisions, m_sunHeightDivisions, surfacesList ); if( surfacesList.count() < 1 ) return; QVector< long > raysPerThread; int maximumValueProgressScale = 100; unsigned long t1 = nOfRays/ maximumValueProgressScale; for( int progressCount = 0; progressCount < maximumValueProgressScale; ++ progressCount ) raysPerThread<< t1; if( ( t1 * maximumValueProgressScale ) < nOfRays ) raysPerThread<< ( nOfRays - ( t1* maximumValueProgressScale) ); Transform lightToWorld = tgf::TransformFromSoTransform( lightTransform ); lightInstance->SetIntersectionTransform( lightToWorld.GetInverse() ); // Create a progress dialog. QProgressDialog dialog; dialog.setLabelText( QString("Progressing using %1 thread(s)..." ).arg( QThread::idealThreadCount() ) ); // Create a QFutureWatcher and conncect signals and slots. QFutureWatcher< void > futureWatcher; QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); QMutex mutex; QMutex mutexPhotonMap; QFuture< void > photonMap; if( transmissivity ) photonMap = QtConcurrent::map( raysPerThread, RayTracer( m_pRootSeparatorInstance, lightInstance, raycastingSurface, sunShape, lightToWorld, transmissivity, *m_pRandomDeviate, &mutex, m_pPhotonMap, &mutexPhotonMap, exportSuraceList ) ); else photonMap = QtConcurrent::map( raysPerThread, RayTracerNoTr( m_pRootSeparatorInstance, lightInstance, raycastingSurface, sunShape, lightToWorld, *m_pRandomDeviate, &mutex, m_pPhotonMap, &mutexPhotonMap, exportSuraceList ) ); futureWatcher.setFuture( photonMap ); // Display the dialog and start the event loop. dialog.exec(); futureWatcher.waitForFinished(); m_tracedRays += nOfRays; double irradiance = sunShape->GetIrradiance(); double inputAperture = raycastingSurface->GetValidArea(); m_wPhoton = double ( inputAperture * irradiance ) / m_tracedRays; UpdatePhotonCounts(); }
void ModelEntity::renderNode(const Node& node, const InstanceNode& instanceNode, float time, int32_t animStackIndex, int32_t animLayerIndex) const { enum RenderFilter renderFilter = Entity::getRenderFilter(); bool finalTransparent = (instanceNode.isTransparentActive() && instanceNode.isTransparent()) || (!instanceNode.isTransparentActive() && node.isTransparent()); bool renderMesh = (renderFilter == RENDER_ALL) || (finalTransparent && renderFilter == RENDER_TRANSPARENT) || (!finalTransparent && renderFilter == RENDER_OPAQUE); if (isDebug()) { if (node.getCamera().get()) { node.getCamera()->debugDraw(instanceNode.getPosition(), instanceNode.getRotation(), true); } if (node.getLight().get()) { node.getLight()->debugDraw(instanceNode.getPosition(), instanceNode.getRotation()); } } if (isWireframe()) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } if (node.getMesh().get() && renderMesh) { VAOSP currentVAO; ProgramSP currentProgram; SubMeshSP currentSubMesh; SurfaceMaterialSP currentSurfaceMaterial; const std::vector<std::shared_ptr<AnimationStack> >& allAnimStacks = node.getAllAnimStacks(); for (uint32_t subMeshIndex = 0; subMeshIndex < node.getMesh()->getSubMeshesCount(); subMeshIndex++) { currentSubMesh = node.getMesh()->getSubMeshAt(subMeshIndex); if (subMeshIndex >= node.getMesh()->getSurfaceMaterialsCount()) { break; } currentSurfaceMaterial = node.getMesh()->getSurfaceMaterialAt(subMeshIndex); float currentEmissive[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentAmbient[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentDiffuse[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentSpecular[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentReflection[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentRefraction[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; float currentShininess = 0.0f; float currentTransparency = 0.0f; for (int32_t i = 0; i < 4; i++) { currentEmissive[i] = currentSurfaceMaterial->getEmissive().getRGBA()[i]; currentAmbient[i] = currentSurfaceMaterial->getAmbient().getRGBA()[i]; currentDiffuse[i] = currentSurfaceMaterial->getDiffuse().getRGBA()[i]; currentSpecular[i] = currentSurfaceMaterial->getSpecular().getRGBA()[i]; currentReflection[i] = currentSurfaceMaterial->getReflection().getRGBA()[i]; currentRefraction[i] = currentSurfaceMaterial->getRefraction().getRGBA()[i]; } currentShininess = currentSurfaceMaterial->getShininess(); currentTransparency = currentSurfaceMaterial->getTransparency(); if (animStackIndex >= 0 && animLayerIndex >= 0 && static_cast<decltype(allAnimStacks.size())>(animStackIndex) < allAnimStacks.size() && animLayerIndex < allAnimStacks[animStackIndex]->getAnimationLayersCount()) { // Animate values depending on time const AnimationLayerSP& animLayer = allAnimStacks[animStackIndex]->getAnimationLayer(animLayerIndex); for (enum AnimationLayer::eCHANNELS_RGBA i = AnimationLayer::R; i <= AnimationLayer::A; i = static_cast<enum AnimationLayer::eCHANNELS_RGBA>(i + 1)) { if (animLayer->hasEmissiveColorValue(i)) { currentEmissive[i] = animLayer->getEmissiveColorValue(i, time); } if (animLayer->hasAmbientColorValue(i)) { currentAmbient[i] = animLayer->getAmbientColorValue(i, time); } if (animLayer->hasDiffuseColorValue(i)) { currentDiffuse[i] = animLayer->getDiffuseColorValue(i, time); } if (animLayer->hasSpecularColorValue(i)) { currentSpecular[i] = animLayer->getSpecularColorValue(i, time); } if (animLayer->hasReflectionColorValue(i)) { currentReflection[i] = animLayer->getReflectionColorValue(i, time); } if (animLayer->hasRefractionColorValue(i)) { currentRefraction[i] = animLayer->getRefractionColorValue(i, time); } } if (animLayer->hasShininessValue(AnimationLayer::S)) { currentShininess = animLayer->getShininessValue(AnimationLayer::S, time); } if (animLayer->hasTransparencyValue(AnimationLayer::S)) { currentTransparency = animLayer->getTransparencyValue(AnimationLayer::S, time); } } currentVAO = currentSubMesh->getVAOByProgramType(getCurrentProgramType()); currentProgram = currentVAO->getProgram(); currentProgram->use(); glUniformMatrix4fv(currentProgram->getUniformLocation(u_modelMatrix), 1, GL_FALSE, instanceNode.getModelMatrix().getM()); // We have the inverse and transpose by setting the matrix glUniformMatrix3fv(currentProgram->getUniformLocation(u_normalModelMatrix), 1, GL_TRUE, instanceNode.getNormalModelMatrix().getM()); currentVAO->bind(); glUniform4fv(currentProgram->getUniformLocation(u_emissiveColor), 1, currentEmissive); glUniform4fv(currentProgram->getUniformLocation(u_ambientColor), 1, currentAmbient); if (currentSurfaceMaterial->getDiffuseTextureName() != 0) { glUniform1i(currentProgram->getUniformLocation(u_hasDiffuseTexture), 1); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, currentSurfaceMaterial->getDiffuseTextureName()); glUniform1i(currentProgram->getUniformLocation(u_diffuseTexture), 0); } else { glUniform1i(currentProgram->getUniformLocation(u_hasDiffuseTexture), 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); glUniform1i(currentProgram->getUniformLocation(u_diffuseTexture), 0); } glUniform4fv(currentProgram->getUniformLocation(u_diffuseColor), 1, currentDiffuse); if (currentSurfaceMaterial->getSpecularTextureName() != 0) { glUniform1i(currentProgram->getUniformLocation(u_hasSpecularTexture), 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, currentSurfaceMaterial->getSpecularTextureName()); glUniform1i(currentProgram->getUniformLocation(u_specularTexture), 1); } else { glUniform1i(currentProgram->getUniformLocation(u_hasSpecularTexture), 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glUniform1i(currentProgram->getUniformLocation(u_specularTexture), 0); } glUniform4fv(currentProgram->getUniformLocation(u_specularColor), 1, currentSpecular); glUniform1f(currentProgram->getUniformLocation(u_shininess), currentShininess); glUniform1f(currentProgram->getUniformLocation(u_transparency), currentTransparency); if (currentSurfaceMaterial->getNormalMapTextureName() != 0) { glUniform1i(currentProgram->getUniformLocation(u_hasNormalMapTexture), 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, currentSurfaceMaterial->getNormalMapTextureName()); glUniform1i(currentProgram->getUniformLocation(u_normalMapTexture), 2); glActiveTexture(GL_TEXTURE0); } else { glUniform1i(currentProgram->getUniformLocation(u_hasNormalMapTexture), 0); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); glUniform1i(currentProgram->getUniformLocation(u_normalMapTexture), 2); glActiveTexture(GL_TEXTURE0); } glUniform1i(currentProgram->getUniformLocation(u_convertDirectX), currentSurfaceMaterial->isConvertDirectX()); glUniform4fv(currentProgram->getUniformLocation(u_reflectionColor), 1, currentReflection); glUniform4fv(currentProgram->getUniformLocation(u_refractionColor), 1, currentRefraction); float environmentRefractiveIndex = refractiveIndex; if (environmentRefractiveIndex != RI_NOTHING) { float materialRefractiveIndex = currentSurfaceMaterial->getRefractiveIndex(); float eta = environmentRefractiveIndex / materialRefractiveIndex; float reflectanceNormalIncidence = ((environmentRefractiveIndex - materialRefractiveIndex) * (environmentRefractiveIndex - materialRefractiveIndex)) / ((environmentRefractiveIndex + materialRefractiveIndex) * (environmentRefractiveIndex + materialRefractiveIndex)); glUniform1f(currentProgram->getUniformLocation(u_eta), eta); glUniform1f(currentProgram->getUniformLocation(u_reflectanceNormalIncidence), reflectanceNormalIncidence); } else { glUniform1f(currentProgram->getUniformLocation(u_eta), 0.0f); glUniform1f(currentProgram->getUniformLocation(u_reflectanceNormalIncidence), 0.0f); } if (SkyManager::getInstance()->hasActiveSky()) { glUniform1i(currentProgram->getUniformLocation(u_hasCubeMapTexture), 1); SkySP activeSky = SkyManager::getInstance()->getActiveSky(); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_CUBE_MAP, activeSky->getSkyTextureName()); glUniform1i(currentProgram->getUniformLocation(u_cubemap), 3); glActiveTexture(GL_TEXTURE0); } else { glUniform1i(currentProgram->getUniformLocation(u_hasCubeMapTexture), 0); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glUniform1i(currentProgram->getUniformLocation(u_cubemap), 3); glActiveTexture(GL_TEXTURE0); } // Only allow dynamic cube map, if also a sky cube map is available if (Entity::getDynamicCubeMaps() && currentSurfaceMaterial->getDynamicCubeMapTextureName() != 0 && SkyManager::getInstance()->hasActiveSky()) { glUniform1i(currentProgram->getUniformLocation(u_hasDynamicCubeMapTexture), 1); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_CUBE_MAP, currentSurfaceMaterial->getDynamicCubeMapTextureName()); glUniform1i(currentProgram->getUniformLocation(u_dynamicCubeMapTexture), 4); glActiveTexture(GL_TEXTURE0); } else { glUniform1i(currentProgram->getUniformLocation(u_hasDynamicCubeMapTexture), 0); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glUniform1i(currentProgram->getUniformLocation(u_dynamicCubeMapTexture), 4); glActiveTexture(GL_TEXTURE0); } if (!Entity::getDynamicCubeMaps()) { glUniformMatrix4fv(currentProgram->getUniformLocation(u_cubeMapViewMatrix), 6, GL_FALSE, Entity::getCubeMapViewMatrices()[0].getM()); glUniformMatrix4fv(currentProgram->getUniformLocation(u_cubeMapProjectionMatrix), 1, GL_FALSE, Entity::getCubeMapProjectionMatrix().getM()); } // Skinning if (node.getMesh()->hasSkinning()) { glUniform1i(currentProgram->getUniformLocation(u_hasSkinning), 1); glUniformMatrix4fv(currentProgram->getUniformLocation(u_bindMatrix), model->getNumberJoints(), GL_FALSE, bindMatrices[0].getM()); glUniformMatrix3fv(currentProgram->getUniformLocation(u_bindNormalMatrix), model->getNumberJoints(), GL_TRUE, bindNormalMatrices[0].getM()); glUniformMatrix4fv(currentProgram->getUniformLocation(u_inverseBindMatrix), model->getNumberJoints(), GL_FALSE, inverseBindMatrices[0].getM()); glUniformMatrix3fv(currentProgram->getUniformLocation(u_inverseBindNormalMatrix), model->getNumberJoints(), GL_TRUE, inverseBindNormalMatrices[0].getM()); } else { glUniform1i(currentProgram->getUniformLocation(u_hasSkinning), 0); glUniformMatrix4fv(currentProgram->getUniformLocation(u_bindMatrix), model->getNumberJoints(), GL_FALSE, Matrix4x4().getM()); glUniformMatrix3fv(currentProgram->getUniformLocation(u_bindNormalMatrix), model->getNumberJoints(), GL_TRUE, Matrix3x3().getM()); glUniformMatrix4fv(currentProgram->getUniformLocation(u_inverseBindMatrix), model->getNumberJoints(), GL_FALSE, Matrix4x4().getM()); glUniformMatrix3fv(currentProgram->getUniformLocation(u_inverseBindNormalMatrix), model->getNumberJoints(), GL_TRUE, Matrix3x3().getM()); } // Write bright color glUniform1i(currentProgram->getUniformLocation(u_writeBrightColor), writeBrightColor); glUniform1f(currentProgram->getUniformLocation(u_brightColorLimit), brightColorLimit); if (finalTransparent) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glDrawElements(GL_TRIANGLES, currentSubMesh->getTriangleCount() * 3, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(currentSubMesh->getIndicesOffset() * sizeof(uint32_t))); if (finalTransparent) { glDisable(GL_BLEND); } if (currentSurfaceMaterial->getDiffuseTextureName() != 0) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); } if (currentSurfaceMaterial->getSpecularTextureName() != 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); } if (currentSurfaceMaterial->getNormalMapTextureName() != 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); } if (SkyManager::getInstance()->hasActiveSky()) { glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } if (currentSurfaceMaterial->getDynamicCubeMapTexture() != 0) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } glActiveTexture(GL_TEXTURE0); currentVAO->unbind(); } } if (isWireframe()) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } }