MorphTransformHardware using TBO added
This commit is contained in:
parent
ed04e2735e
commit
2b2a8f3d2e
60
include/osgAnimation/MorphTransformHardware
Normal file
60
include/osgAnimation/MorphTransformHardware
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_MORPH_TRANSFORM_HARDWARE
|
||||
#define OSGANIMATION_MORPH_TRANSFORM_HARDWARE 1
|
||||
|
||||
#include <osgAnimation/Export>
|
||||
#include <osgAnimation/RigTransform>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Array>
|
||||
|
||||
namespace osgAnimation
|
||||
{
|
||||
class MorphGeometry;
|
||||
|
||||
/// This class manage format for hardware morphing
|
||||
class OSGANIMATION_EXPORT MorphTransformHardware : public MorphTransform
|
||||
{
|
||||
public:
|
||||
|
||||
MorphTransformHardware();
|
||||
|
||||
MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop);
|
||||
|
||||
META_Object(osgAnimation,MorphTransformHardware);
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void operator()(MorphGeometry&);
|
||||
void setShader(osg::Shader*);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool init(MorphGeometry&);
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Uniform> _uniformTargetsWeight;
|
||||
osg::ref_ptr<osg::Shader> _shader;
|
||||
|
||||
bool _needInit;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -34,6 +34,7 @@ SET(TARGET_H
|
||||
${HEADER_PATH}/RigTransform
|
||||
${HEADER_PATH}/RigTransformHardware
|
||||
${HEADER_PATH}/RigTransformSoftware
|
||||
${HEADER_PATH}/MorphTransformHardware
|
||||
${HEADER_PATH}/MorphTransformSoftware
|
||||
${HEADER_PATH}/Sampler
|
||||
${HEADER_PATH}/Skeleton
|
||||
@ -76,6 +77,7 @@ SET(TARGET_SRC
|
||||
RigGeometry.cpp
|
||||
RigTransformHardware.cpp
|
||||
RigTransformSoftware.cpp
|
||||
MorphTransformHardware.cpp
|
||||
MorphTransformSoftware.cpp
|
||||
Skeleton.cpp
|
||||
StackedMatrixElement.cpp
|
||||
|
197
src/osgAnimation/MorphTransformHardware.cpp
Normal file
197
src/osgAnimation/MorphTransformHardware.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/* -*-c++-*-
|
||||
* Copyleft 2016 Valentin Julien
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library 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
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#include <osgAnimation/MorphTransformHardware>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
#include <osgAnimation/BoneMapVisitor>
|
||||
#include <osg/TextureBuffer>
|
||||
#include <sstream>
|
||||
|
||||
///texture unit reserved for morphtarget TBO
|
||||
#define MORPHTEXTUREUNIT 7
|
||||
|
||||
using namespace osgAnimation;
|
||||
|
||||
MorphTransformHardware::MorphTransformHardware()
|
||||
{
|
||||
_needInit = true;
|
||||
|
||||
}
|
||||
|
||||
MorphTransformHardware::MorphTransformHardware(const MorphTransformHardware& rth, const osg::CopyOp& copyop):
|
||||
MorphTransform(rth, copyop),
|
||||
_uniformTargetsWeight(rth._uniformTargetsWeight),
|
||||
_shader(rth._shader),
|
||||
_needInit(rth._needInit)
|
||||
{
|
||||
}
|
||||
|
||||
void MorphTransformHardware::setShader(osg::Shader* shader)
|
||||
{
|
||||
_shader = shader;
|
||||
}
|
||||
|
||||
bool MorphTransformHardware::init(MorphGeometry& morphGeometry)
|
||||
{
|
||||
osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(morphGeometry.getVertexArray());
|
||||
|
||||
osg::Vec3Array * vertexSource = (morphGeometry.getVertexSource());
|
||||
osg::Vec3Array * normalSource = (morphGeometry.getNormalSource());
|
||||
morphGeometry.setDataVariance(osg::Object::STATIC);
|
||||
///check for correct morph configuration
|
||||
///(blender osgexport doesn't set sources so assume morphgeom arrays are sources)
|
||||
if(pos)
|
||||
{
|
||||
///check if source is setted correctly
|
||||
if (!vertexSource|| vertexSource->size() != pos->size())
|
||||
{
|
||||
vertexSource =(static_cast<osg::Vec3Array*>( pos->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(pos->begin(),pos->end());
|
||||
pos->setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(morphGeometry.getNormalArray());
|
||||
bool normalmorphable = morphGeometry.getMorphNormals() && normal;
|
||||
if(!normalmorphable) {
|
||||
OSG_WARN << "MorphTransformHardware::morph geometry "<<morphGeometry.getName()<<" without normal morphing not supported! " << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (normalmorphable && (!normalSource || normalSource->size() != normal->size()))
|
||||
{
|
||||
normalSource =(static_cast<osg::Vec3Array*>( normal->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));//osg::Vec3Array(normal->begin(),normal->end());
|
||||
normal->setDataVariance(osg::Object::DYNAMIC);
|
||||
}
|
||||
}
|
||||
///end check
|
||||
morphGeometry.setVertexArray(morphGeometry.getVertexSource());
|
||||
morphGeometry.setNormalArray(morphGeometry.getNormalSource(),osg::Array::BIND_PER_VERTEX);
|
||||
morphGeometry.setDataVariance(osg::Object::STATIC);
|
||||
|
||||
//create one TBO for all morphtargets (pack vertex/normal)
|
||||
osg::Vec3Array * morphTargets=new osg::Vec3Array ;
|
||||
MorphGeometry::MorphTargetList & morphlist=morphGeometry.getMorphTargetList();
|
||||
for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph) {
|
||||
const osg::Geometry * morphtargetgeom= curmorph->getGeometry() ;
|
||||
const osg::Vec3Array *varray=(osg::Vec3Array*)morphtargetgeom->getVertexArray();
|
||||
const osg::Vec3Array *narray=(osg::Vec3Array*)morphtargetgeom->getNormalArray();
|
||||
if(morphGeometry.getMethod()==MorphGeometry::RELATIVE){
|
||||
for(unsigned int i=0; i<morphGeometry.getVertexArray()->getNumElements(); ++i) {
|
||||
morphTargets->push_back( (*varray)[i]);
|
||||
morphTargets->push_back( (*narray)[i]);
|
||||
}
|
||||
}else{
|
||||
//convert to RELATIVE as it involve less math in the VS than NORMALIZED
|
||||
const osg::Vec3Array *ovarray=(osg::Vec3Array*)morphGeometry.getVertexArray();
|
||||
const osg::Vec3Array *onarray=(osg::Vec3Array*)morphGeometry.getNormalArray();
|
||||
for(unsigned int i=0; i<morphGeometry.getVertexArray()->getNumElements(); ++i) {
|
||||
morphTargets->push_back( (*varray)[i]- (*ovarray)[i] );
|
||||
morphTargets->push_back( (*narray)[i]- (*onarray)[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
osg::TextureBuffer * morphTargetsTBO=new osg::TextureBuffer();
|
||||
morphTargetsTBO->setBufferData(morphTargets);
|
||||
morphTargetsTBO->setInternalFormat( GL_RGB32F_ARB );
|
||||
|
||||
//create TBO Texture handle
|
||||
osg::Uniform * morphTBOHandle=new osg::Uniform(osg::Uniform::SAMPLER_BUFFER,"morphTargets");
|
||||
morphTBOHandle->set(MORPHTEXTUREUNIT);
|
||||
|
||||
//create dynamic uniform for morphtargets animation weights
|
||||
_uniformTargetsWeight=new osg::Uniform(osg::Uniform::FLOAT,"morphWeights",morphlist.size());
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Program> program ;
|
||||
osg::ref_ptr<osg::Shader> vertexshader;
|
||||
osg::ref_ptr<osg::StateSet> stateset = morphGeometry.getOrCreateStateSet();
|
||||
//grab geom source program and vertex shader if _shader is not setted
|
||||
if(!_shader.valid() && (program = (osg::Program*)stateset->getAttribute(osg::StateAttribute::PROGRAM)))
|
||||
{
|
||||
for(unsigned int i=0;i<program->getNumShaders();++i)
|
||||
if(program->getShader(i)->getType()==osg::Shader::VERTEX){
|
||||
// vertexshader=program->getShader(i);
|
||||
program->removeShader(vertexshader);
|
||||
}
|
||||
}else {
|
||||
|
||||
} program = new osg::Program;
|
||||
program->setName("HardwareMorphing");
|
||||
//set default source if _shader is not user setted
|
||||
if (!vertexshader.valid()){
|
||||
if (!_shader.valid())
|
||||
vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert");
|
||||
else vertexshader=_shader;
|
||||
}
|
||||
|
||||
|
||||
if (!vertexshader.valid()) {
|
||||
OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// replace max matrix by the value from uniform
|
||||
{
|
||||
std::string str = vertexshader->getShaderSource();
|
||||
std::string toreplace = std::string("MAX_MORPHWEIGHT");
|
||||
std::size_t start = str.find(toreplace);
|
||||
if (std::string::npos == start){
|
||||
///perhaps remanance from previous init (if saved after init) so reload shader
|
||||
|
||||
vertexshader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"morphing.vert");
|
||||
if (!vertexshader.valid()) {
|
||||
OSG_WARN << "RigTransformHardware can't load VertexShader" << std::endl;
|
||||
return false;
|
||||
}
|
||||
str = vertexshader->getShaderSource();
|
||||
start = str.find(toreplace);
|
||||
}
|
||||
if (std::string::npos != start) {
|
||||
std::stringstream ss;
|
||||
ss << _uniformTargetsWeight->getNumElements();
|
||||
str.replace(start, toreplace.size(), ss.str());
|
||||
vertexshader->setShaderSource(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_WARN << "MAX_MORPHWEIGHT not found in Shader! " << str << std::endl;
|
||||
}
|
||||
OSG_INFO << "Shader " << str << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
program->addShader(vertexshader.get());
|
||||
//morphGeometry.setStateSet((osg::StateSet *) osg::CopyOp()(source.getOrCreateStateSet()));
|
||||
|
||||
osg::ref_ptr<osg::StateSet> ss = morphGeometry.getOrCreateStateSet();
|
||||
ss->addUniform(_uniformTargetsWeight);
|
||||
ss->setTextureAttribute(MORPHTEXTUREUNIT,morphTargetsTBO);
|
||||
ss->addUniform( morphTBOHandle);
|
||||
ss->addUniform(new osg::Uniform("nbMorphVertex", morphGeometry.getVertexArray()->getNumElements()));
|
||||
|
||||
ss->setAttributeAndModes(program.get());
|
||||
_needInit = false;
|
||||
return true;
|
||||
}
|
||||
void MorphTransformHardware::operator()(MorphGeometry& geom)
|
||||
{
|
||||
if (_needInit)
|
||||
if (!init(geom))
|
||||
return;
|
||||
|
||||
///upload new morph weights each update via uniform
|
||||
int curimorph=0;
|
||||
MorphGeometry::MorphTargetList & morphlist=geom.getMorphTargetList();
|
||||
for(MorphGeometry::MorphTargetList::const_iterator curmorph=morphlist.begin(); curmorph!=morphlist.end(); ++curmorph)
|
||||
_uniformTargetsWeight->setElement(curimorph++, curmorph->getWeight());
|
||||
_uniformTargetsWeight->dirty();
|
||||
}
|
Loading…
Reference in New Issue
Block a user