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}/RigTransform
|
||||||
${HEADER_PATH}/RigTransformHardware
|
${HEADER_PATH}/RigTransformHardware
|
||||||
${HEADER_PATH}/RigTransformSoftware
|
${HEADER_PATH}/RigTransformSoftware
|
||||||
|
${HEADER_PATH}/MorphTransformHardware
|
||||||
${HEADER_PATH}/MorphTransformSoftware
|
${HEADER_PATH}/MorphTransformSoftware
|
||||||
${HEADER_PATH}/Sampler
|
${HEADER_PATH}/Sampler
|
||||||
${HEADER_PATH}/Skeleton
|
${HEADER_PATH}/Skeleton
|
||||||
@ -76,6 +77,7 @@ SET(TARGET_SRC
|
|||||||
RigGeometry.cpp
|
RigGeometry.cpp
|
||||||
RigTransformHardware.cpp
|
RigTransformHardware.cpp
|
||||||
RigTransformSoftware.cpp
|
RigTransformSoftware.cpp
|
||||||
|
MorphTransformHardware.cpp
|
||||||
MorphTransformSoftware.cpp
|
MorphTransformSoftware.cpp
|
||||||
Skeleton.cpp
|
Skeleton.cpp
|
||||||
StackedMatrixElement.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