1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2006 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include <OSGConfig.h>
48 #include "OSGGPUSkinningAlgorithm.h"
49 #include "OSGGPUSkinningDataAttachment.h"
50 #include "OSGSkeleton.h"
51 #include "OSGShaderProgram.h"
53 #include <boost/cast.hpp>
57 // Documentation for this class is emitted in the
58 // OSGGPUSkinningAlgorithmBase.cpp file.
59 // To modify it, please change the .fcd file (OSGGPUSkinningAlgorithm.fcd) and
60 // regenerate the base file.
62 /***************************************************************************\
64 \***************************************************************************/
66 const std::string
GPUSkinningAlgorithm::_vpVertexSkinning(
69 "uniform mat4 matBindShape;\n"
70 "uniform mat4 matJoints[70];\n"
72 "void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
73 " in vec4 jointIdx, in vec4 jointWeight)\n"
75 " float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
76 " vec4 inNorm = vec4(vertNorm, 0.);\n"
77 " vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
78 " vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
80 " for(int i = 0; i < 4; ++i)\n"
82 " int idxJ = int(jointIdx[i]);\n"
86 " mat4 matJ = matJoints[idxJ] * matBindShape;\n"
88 " tmpPos += jointWeight[i] * (matJ * vertPos);\n"
89 " tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
93 " vertPos = sumWinv * tmpPos;\n"
94 " vertNorm = sumWinv * tmpNorm.xyz;\n"
97 "void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
98 " inout vec3 vertTangent,\n"
99 " in vec4 jointIdx, in vec4 jointWeight )\n"
101 " float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
102 " vec4 inNorm = vec4(vertNorm, 0.);\n"
103 " vec4 inTangent = vec4(vertTangent, 0.);\n"
104 " vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
105 " vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
106 " vec4 tmpTangent = vec4(0., 0., 0., 0.);\n"
108 " for(int i = 0; i < 4; ++i)\n"
110 " int idxJ = int(jointIdx[i]);\n"
114 " mat4 matJ = matJoints[idxJ] * matBindShape;\n"
116 " tmpPos += jointWeight[i] * (matJ * vertPos);\n"
117 " tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
118 " tmpTangent += jointWeight[i] * (matJ * inTangent);\n"
122 " vertPos = sumWinv * tmpPos;\n"
123 " vertNorm = sumWinv * tmpNorm.xyz;\n"
124 " vertTangent = sumWinv * tmpTangent.xyz;\n"
127 "void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
128 " inout vec3 vertTangent, inout vec3 vertBinormal,\n"
129 " in vec4 jointIdx, in vec4 jointWeight )\n"
131 " float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
132 " vec4 inNorm = vec4(vertNorm, 0.);\n"
133 " vec4 inTangent = vec4(vertTangent, 0.);\n"
134 " vec4 inBinormal = vec4(vertBinormal, 0.);\n"
135 " vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
136 " vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
137 " vec4 tmpTangent = vec4(0., 0., 0., 0.);\n"
138 " vec4 tmpBinormal = vec4(0., 0., 0., 0.);\n"
140 " for(int i = 0; i < 4; ++i)\n"
142 " int idxJ = int(jointIdx[i]);\n"
146 " mat4 matJ = matJoints[idxJ] * matBindShape;\n"
148 " tmpPos += jointWeight[i] * (matJ * vertPos);\n"
149 " tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
150 " tmpTangent += jointWeight[i] * (matJ * inTangent);\n"
151 " tmpBinormal += jointWeight[i] * (matJ * inBinormal);\n"
155 " vertPos = sumWinv * tmpPos;\n"
156 " vertNorm = sumWinv * tmpNorm.xyz;\n"
157 " vertTangent = sumWinv * tmpTangent.xyz;\n"
158 " vertBinormal = sumWinv * tmpBinormal.xyz;\n"
162 /***************************************************************************\
164 \***************************************************************************/
166 void GPUSkinningAlgorithm::initMethod(InitPhase ePhase
)
168 Inherited::initMethod(ePhase
);
170 if(ePhase
== TypeObject::SystemPost
)
176 /***************************************************************************\
178 \***************************************************************************/
180 /*-------------------------------------------------------------------------*\
182 \*-------------------------------------------------------------------------*/
184 /*----------------------- constructors & destructors ----------------------*/
186 GPUSkinningAlgorithm::GPUSkinningAlgorithm(void) :
191 GPUSkinningAlgorithm::GPUSkinningAlgorithm(const GPUSkinningAlgorithm
&source
) :
196 GPUSkinningAlgorithm::~GPUSkinningAlgorithm(void)
200 /*----------------------------- class specific ----------------------------*/
203 GPUSkinningAlgorithm::adjustVolume(Volume
&volume
)
205 if(_sfSkeleton
.getValue() != NULL
)
206 _sfSkeleton
.getValue()->adjustVolume(volume
);
210 GPUSkinningAlgorithm::renderEnter(Action
*action
)
212 Action::ResultE res
= Action::Continue
;
213 SkinnedGeometry
*skinGeo
= getSkin ();
214 Skeleton
*skel
= getSkeleton();
216 boost::polymorphic_downcast
<RenderAction
*>(action
);
218 OSG_ASSERT(skinGeo
!= NULL
);
219 OSG_ASSERT(skel
!= NULL
);
221 GPUSkinningDataAttachmentUnrecPtr data
= getGPUSkinningData(skel
);
225 data
= GPUSkinningDataAttachment::create();
226 skel
->addAttachment(data
);
229 skel
->renderEnter(action
, skinGeo
);
231 ShaderProgramChunkUnrecPtr shCode
= data
->getShaderCode();
235 shCode
= ShaderProgramChunk::create();
236 data
->setShaderCode(shCode
);
238 ShaderProgramUnrecPtr vp
= ShaderProgram::createVertexShader();
239 vp
->setProgram(_vpVertexSkinning
);
241 shCode
->addShader(vp
);
243 vp
->addUniformVariable(
244 "matJoints", (*skel
->getMFJointMatrices()));
245 vp
->addUniformVariable(
246 "matBindShape", skinGeo
->getBindShapeMatrix());
248 else if(data
->getDataValid() == false)
250 ShaderProgram
*vp
= shCode
->getVertexShader(0);
251 OSG_ASSERT(vp
!= NULL
);
253 vp
->updateUniformVariable(
254 "matJoints", (*skel
->getMFJointMatrices()));
255 vp
->updateUniformVariable(
256 "matBindShape", skinGeo
->getBindShapeMatrix());
258 data
->setDataValid(true);
264 ract
->addOverride(ShaderProgramChunk::getStaticClassId(),
267 res
= skinGeo
->SkinnedGeometry::Inherited::renderEnter(ract
);
275 GPUSkinningAlgorithm::renderLeave(Action
*action
)
277 Action::ResultE res
= Action::Continue
;
278 SkinnedGeometry
*skinGeo
= getSkin();
279 Skeleton
*skel
= getSkeleton();
281 skel
->renderLeave(action
, skinGeo
);
283 res
= skinGeo
->SkinnedGeometry::Inherited::renderLeave(action
);
289 GPUSkinningAlgorithm::intersectEnter(Action
*action
)
291 SkinnedGeometry
*skinGeo
= getSkin();
293 return skinGeo
->SkinnedGeometry::Inherited::intersectEnter(action
);
296 GPUSkinningAlgorithm::RenderModeE
297 GPUSkinningAlgorithm::getRenderMode(void) const
299 return SkinnedGeometry::RMSkinnedGPU
;
302 void GPUSkinningAlgorithm::changed(ConstFieldMaskArg whichField
,
306 if((SkeletonFieldMask
& whichField
) != 0 &&
307 _sfSkeleton
.getValue() != NULL
)
309 if(_sfSkeleton
.getValue()->hasChangedFunctor(boost::bind(
310 &GPUSkinningAlgorithm::skeletonChanged
,
311 this, _1
, _2
, _3
)) == false)
313 _sfSkeleton
.getValue()->addChangedFunctor(boost::bind(
314 &GPUSkinningAlgorithm::skeletonChanged
,
316 "GPUSkinningAlgorithm::skeletonChanged");
320 Inherited::changed(whichField
, origin
, details
);
323 void GPUSkinningAlgorithm::dump( UInt32
,
324 const BitVector
) const
326 SLOG
<< "Dump GPUSkinningAlgorithm NI" << std::endl
;
330 GPUSkinningAlgorithm::skeletonChanged(FieldContainer
*fc
,
331 ConstFieldMaskArg whichField
,
334 // if the skeleton was changed by a sync we don't invalidate
335 // the data - it either is updated by the same sync or
336 // the sync marks it as invalid.
338 if(//origin != ChangedOrigin::Sync &&
339 ((Skeleton::JointMatricesFieldMask
|
340 Skeleton::JointsChangedFieldMask
|
341 Skeleton::JointNormalMatricesFieldMask
) & whichField
) != 0)
343 OSG_ASSERT(fc
== _sfSkeleton
.getValue());
345 GPUSkinningDataAttachment
*data
=
346 getGPUSkinningData(_sfSkeleton
.getValue());
349 data
->setDataValid(false);
354 GPUSkinningAlgorithm::resolveLinks(void)
356 if(_sfSkeleton
.getValue() != NULL
)
358 _sfSkeleton
.getValue()->subChangedFunctor(boost::bind(
359 &GPUSkinningAlgorithm::skeletonChanged
,
363 Inherited::resolveLinks();
367 // renderEnter code that does not work because of problems with the
368 // way ProgVars are handled and how uniform locations are invalidated
370 ShaderProgramChunkUnrecPtr shCode
= getShaderCode();
371 ShaderProgramVariableChunkUnrecPtr shData
= getShaderData();
375 shCode
= ShaderProgramChunk::create();
376 setShaderCode(shCode
);
378 ShaderProgramUnrecPtr vp
= ShaderProgram::createVertexShader();
379 vp
->setProgram(_vpVertexSkinning
);
381 shCode
->addShader(vp
);
383 vp
->addUniformVariable(
384 "matBindShape", skinGeo
->getBindShapeMatrix());
385 vp
->addUniformVariable(
386 "matJoints", (*skel
->getMFJointMatrices()));
390 ShaderProgram
*vp
= shCode
->getVertexShader(0);
392 vp
->updateUniformVariable(
393 "matBindShape", skinGeo
->getBindShapeMatrix());
394 vp
->updateUniformVariable(
395 "matJoints", (*skel
->getMFJointMatrices()));
401 shData
= ShaderProgramVariableChunk::create();
402 setShaderData(shData
);
404 shData
->addUniformVariable(
405 "matBindShape", skinGeo
->getBindShapeMatrix());
406 shData
->addUniformVariable(
407 "matJoints", (*skel
->getMFJointMatrices()));
411 shData
->updateUniformVariable(
412 "matBindShape", skinGeo
->getBindShapeMatrix());
413 shData
->updateUniformVariable(
414 "matJoints", (*skel
->getMFJointMatrices()));