/* * * Copyright (C) 2004, 2006 Mekensleep * * Mekensleep * 24 rue vieille du temple * 75004 Paris * licensing@mekensleep.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: * Cedric PINSON * Igor Kravtchenko * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_NPROFILE #include #else // USE_NPROFILE #define NPROFILE_SAMPLE(a) #endif // USE_NPROFILE #include #include #include #include #include #include using namespace osgCal; SubMeshHardware::SubMeshHardware() { std::cerr << "SubMeshHardware::SubMeshHardware(): You should never call this constructor!" << std::endl; } SubMeshHardware::~SubMeshHardware() { } SubMeshHardware::SubMeshHardware(Model *model, int mesh) { mModel=model; mMeshId=mesh; mVertexProgram=true; _vbo=0; setUseDisplayList(false); setUseVertexBufferObjects(true); } void SubMeshHardware::InitHardwareMesh( int nbIdxs, osg::VertexProgram* vp, GlueCalHardwareModel* hardwareModel, unsigned int* vbo, unsigned int indexInVBO, int maxVertexIndex) { mHardwareModel = hardwareModel; mVp = vp; osg::StateSet *set = this->getOrCreateStateSet(); if (sizeof(CalIndex) == sizeof(unsigned int) ) indexInVBO = indexInVBO*sizeof(unsigned int); else if (sizeof(CalIndex) == sizeof(unsigned short)) indexInVBO = indexInVBO*sizeof(unsigned short); else assert(0 && "Invalid type for index"); _vbo = vbo; _indexVbo = indexInVBO; _nbIdxs = nbIdxs; _maxVertexIndex = maxVertexIndex; set->setAttributeAndModes( mVp, osg::StateAttribute::ON /*| osg::StateAttribute::PROTECTED*/); // | osg::StateAttribute::OVERRIDE /* | osg::StateAttribute::PROTECTED*/); } void SubMeshHardware::drawImplementation(osg::State& state) const { #ifdef USE_NPROFILE NPROFILE_SAMPLE("SubMeshHardware::drawImplementation"); #endif // return; // std::cout << "min " << _bbox._min << " max " << _bbox._max << std::endl; // no texture we don't draw mesh (for collision mesh) const osg::StateSet* set=getStateSet(); if (!set->getTextureAttribute(0, osg::StateAttribute::TEXTURE)) return; mHardwareModel->selectHardwareMesh(mMeshId); state.disableAllVertexArrays(); // fix flash color due to a bad state. // don't know why on ati we have color from another state const osg::Material* mt=(const osg::Material*)set->getAttribute(osg::StateAttribute::MATERIAL); glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); osg::Vec4 v=mt->getDiffuse(osg::Material::FRONT); glColor4fv(&v[0]); const Extensions* extensions = getExtensions(state.getContextID(),true); extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB, _vbo[MODEL_VBO_GEOMETRY]); state.setNormalPointer(GL_FLOAT, 88, (GLvoid*)12); state.setTexCoordPointer(0, 2, GL_FLOAT, 88, (GLvoid*)24); state.setTexCoordPointer(1, 2, GL_FLOAT, 88, (GLvoid*)32); state.setVertexAttribPointer(1, 4 , GL_FLOAT, false, 88, (GLvoid*)40); state.setVertexAttribPointer(6, 4 , GL_FLOAT, false, 88, (GLvoid*)56); state.setColorPointer(4, GL_FLOAT, 88, (GLvoid*) 72); state.setVertexPointer(3, GL_FLOAT, 88, 0); osg::VertexProgram::Extensions* vpExt = osg::VertexProgram::getExtensions(state.getContextID(),true); int boneId; for(boneId = 0; boneId < mHardwareModel->getBoneCount(); boneId++) { CalQuaternion rotationBoneSpace = mHardwareModel->getRotationBoneSpace(boneId, mModel->getCalModel()->getSkeleton()); CalVector translationBoneSpace = mHardwareModel->getTranslationBoneSpace(boneId, mModel->getCalModel()->getSkeleton()); CalMatrix rotationMatrix = rotationBoneSpace; float transformation[12]; transformation[0]=rotationMatrix.dxdx; transformation[1]=rotationMatrix.dxdy; transformation[2]=rotationMatrix.dxdz; transformation[3]=translationBoneSpace.x; transformation[4]=rotationMatrix.dydx; transformation[5]=rotationMatrix.dydy; transformation[6]=rotationMatrix.dydz; transformation[7]=translationBoneSpace.y; transformation[8]=rotationMatrix.dzdx; transformation[9]=rotationMatrix.dzdy; transformation[10]=rotationMatrix.dzdz; transformation[11]=translationBoneSpace.z; vpExt->glProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB,boneId*3+0,&transformation[0] ); vpExt->glProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB,boneId*3+1,&transformation[4] ); vpExt->glProgramLocalParameter4fv(GL_VERTEX_PROGRAM_ARB,boneId*3+2,&transformation[8] ); } extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, _vbo[MODEL_VBO_INDEX]); if ( sizeof(CalIndex) == sizeof(unsigned int)) { #ifndef OSG_GL_DRAWRANGELEMENTS glDrawElements(GL_TRIANGLES, _nbIdxs, GL_UNSIGNED_INT, (GLvoid*)_indexVbo); #else extensions->glDrawRangeElements(GL_TRIANGLES, 0, _maxVertexIndex, _nbIdxs, GL_UNSIGNED_INT, (GLvoid*) _indexVbo); #endif } else if (sizeof(CalIndex) == sizeof(unsigned short)) { #ifndef OSG_GL_DRAWRANGELEMENTS glDrawElements(GL_TRIANGLES, _nbIdxs, GL_UNSIGNED_SHORT, (GLvoid*)_indexVbo); #else extensions->glDrawRangeElements(GL_TRIANGLES, 0, _maxVertexIndex, _nbIdxs, GL_UNSIGNED_SHORT, (GLvoid*) _indexVbo); #endif } else { assert(0 && "invalid index size"); } state.disableVertexAttribPointer(1); state.disableVertexAttribPointer(6); extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); } osg::Object* SubMeshHardware::clone(const osg::CopyOp&) const { return new SubMeshHardware(mModel, mMeshId); } #if OSG_VERSION_RELEASE != 9 && OSG_VERSION_MAJOR != 1 bool SubMeshHardware::computeBound() const { _bbox=_staticbbox; // _bbox.init(); _bbox_computed = false; return true; } #else // OSG_VERSION_RELEASE != 9 && OSG_VERSION_MAJOR != 1 osg::BoundingBox SubMeshHardware::computeBound() const { _boundingBox = _staticbbox; _boundingBoxComputed = false; return _boundingBox; } #endif // OSG_VERSION_RELEASE != 9 && OSG_VERSION_MAJOR != 1