00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "LampBasic.h"
00026 #include "Graphics/Mesh/CharacterMesh.h"
00027 #include "Graphics/Renderer/RenderingDevice.h"
00028 #include "Graphics/Scene/Scene.h"
00029 #include "Graphics/Mesh/MeshManager.h"
00030 #include "Graphics/Model/CharacterModel.h"
00031 #include "Graphics/MeshData/MeshData.h"
00032
00033 namespace Lamp{
00034
00035
00036
00037 CharacterMesh::CharacterMesh(const String& name, Scene* scene) :
00038 Mesh(name, scene), vertexBuffer_(NULL), vertexDeclaration_(NULL),
00039 vertexSize_(0), deformedVertexCount_(0), deformedPosition_(NULL),
00040 deformedNormal_(NULL){
00041 }
00042
00043
00044 CharacterMesh::~CharacterMesh(){
00045 SafeArrayDelete(deformedNormal_);
00046 SafeArrayDelete(deformedPosition_);
00047 SafeRelease(vertexBuffer_);
00048 SafeRelease(vertexDeclaration_);
00049 }
00050
00051
00052 CharacterMesh* CharacterMesh::copyCharacterMesh(u_int copyMask) const{
00053 MeshManager* manager = scene_->getMeshManager();
00054 CharacterMesh* copyMesh =
00055 manager->createCharacterMesh(manager->rename(name_));
00056
00057 copyMeshValue(copyMesh, copyMask);
00058 return copyMesh;
00059 }
00060
00061
00062 void CharacterMesh::traverse(const Matrix34& parentMatrix,
00063 bool parentEnabled, bool parentScaled, bool parentChanged){
00064 Mesh::traverse(parentMatrix, parentEnabled, parentScaled, parentChanged);
00065 if(!isGlobalEnabled()){ SafeRelease(vertexBuffer_); }
00066 }
00067
00068
00069
00070
00071 bool CharacterMesh::characterDeform(){
00072
00073
00074
00075
00076 if(vertexDeclaration_ == NULL){ createVertexDeclaration(); }
00077 if(vertexBuffer_ == NULL){ createVertexBuffer(); }
00078
00079 deform();
00080
00081 setupVertexBuffer();
00082 return true;
00083 }
00084
00085
00086 void CharacterMesh::deform(){
00087
00088 CharacterModel* characterModel = getParent()->castCharacterModel();
00089 Assert(characterModel != NULL);
00090
00091 characterModel->buildBoneMatrix();
00092 const Matrix34* positionDeformMatrixArray =
00093 characterModel->getPositionDeformMatrixArray();
00094
00095
00096 int vertexCount = getVertexCount();
00097 if((deformedPosition_ == NULL) || (deformedVertexCount_ != vertexCount)){
00098 SafeArrayDelete(deformedNormal_);
00099 SafeArrayDelete(deformedPosition_);
00100 deformedVertexCount_ = vertexCount;
00101 deformedPosition_ = new Vector3[deformedVertexCount_];
00102 if(hasNormal()){ deformedNormal_ = new Vector3[deformedVertexCount_]; }
00103 }
00104
00105
00106 if(!hasNormal()){
00107
00108 if(getBonesPerVertex() == 1){
00109 stitchingDeformP(positionDeformMatrixArray);
00110 }else{
00111 skinningDeformP(positionDeformMatrixArray);
00112 }
00113 }else if(!characterModel->isBoneScaled()){
00114
00115 if(getBonesPerVertex() == 1){
00116 stitchingDeformPN(positionDeformMatrixArray);
00117 }else{
00118 skinningDeformPN(positionDeformMatrixArray);
00119 }
00120 }else{
00121
00122 const Matrix33* normalDeformMatrixArray =
00123 characterModel->getNormalDeformMatrixArray();
00124 if(getBonesPerVertex() == 1){
00125 stitchingDeformPN(
00126 positionDeformMatrixArray, normalDeformMatrixArray);
00127 }else{
00128 skinningDeformPN(
00129 positionDeformMatrixArray, normalDeformMatrixArray);
00130 }
00131 }
00132 }
00133
00134
00135
00136
00137 void CharacterMesh::skinningDeformP(const Matrix34* positionDeformMatrixArray){
00138 int vertexCount = getVertexCount();
00139 int weightsPerVertex = getWeightsPerVertex();
00140 int bonesPerVertex = getBonesPerVertex();
00141 const float* weightArray = getWeightArray();
00142 const u_char* boneIndexArray = getBoneIndexArray();
00143 const Vector3* readPosition = getPositionArray();
00144 Vector3* writePosition = deformedPosition_;
00145 for(int i = 0; i < vertexCount; i++){
00146 int weightOffset = i * weightsPerVertex;
00147 int boneOffset = i * bonesPerVertex;
00148 Vector3 accumulatePosition(Vector3::zero);
00149 Vector3 accumulateNormal(Vector3::zero);
00150 float lastWeight = 1.f;
00151 for(int j = 0; j < weightsPerVertex; j++){
00152
00153 float weight = weightArray[weightOffset + j];
00154 lastWeight -= weight;
00155 if(weight <= Math::epsilon){ continue; }
00156 const Matrix34& positionDeformMatrix =
00157 positionDeformMatrixArray[boneIndexArray[boneOffset + j]];
00158
00159 accumulatePosition +=
00160 positionDeformMatrix * (*readPosition) * weight;
00161 }
00162
00163 if(lastWeight > Math::epsilon){
00164 const Matrix34& positionDeformMatrix = positionDeformMatrixArray[
00165 boneIndexArray[boneOffset + weightsPerVertex]];
00166
00167 accumulatePosition +=
00168 positionDeformMatrix * (*readPosition) * lastWeight;
00169 }
00170 (*writePosition) = accumulatePosition;
00171 readPosition++;
00172 writePosition++;
00173 }
00174 }
00175
00176
00177 void CharacterMesh::skinningDeformPN(const Matrix34* positionDeformMatrixArray){
00178 int vertexCount = getVertexCount();
00179 int weightsPerVertex = getWeightsPerVertex();
00180 int bonesPerVertex = getBonesPerVertex();
00181 const float* weightArray = getWeightArray();
00182 const u_char* boneIndexArray = getBoneIndexArray();
00183 const Vector3* readPosition = getPositionArray();
00184 const Vector3* readNormal = getNormalArray();
00185 Vector3* writePosition = deformedPosition_;
00186 Vector3* writeNormal = deformedNormal_;
00187 for(int i = 0; i < vertexCount; i++){
00188 int weightOffset = i * weightsPerVertex;
00189 int boneOffset = i * bonesPerVertex;
00190 Vector3 accumulatePosition(Vector3::zero);
00191 Vector3 accumulateNormal(Vector3::zero);
00192 float lastWeight = 1.f;
00193 for(int j = 0; j < weightsPerVertex; j++){
00194
00195 float weight = weightArray[weightOffset + j];
00196 lastWeight -= weight;
00197 if(weight <= Math::epsilon){ continue; }
00198 const Matrix34& positionDeformMatrix =
00199 positionDeformMatrixArray[boneIndexArray[boneOffset + j]];
00200
00201 accumulatePosition +=
00202 positionDeformMatrix * (*readPosition) * weight;
00203
00204 accumulateNormal +=
00205 positionDeformMatrix.multiply33(*readNormal) * weight;
00206 }
00207
00208 if(lastWeight > Math::epsilon){
00209 const Matrix34& positionDeformMatrix = positionDeformMatrixArray[
00210 boneIndexArray[boneOffset + weightsPerVertex]];
00211
00212 accumulatePosition +=
00213 positionDeformMatrix * (*readPosition) * lastWeight;
00214
00215 accumulateNormal +=
00216 positionDeformMatrix.multiply33(*readNormal) * lastWeight;
00217 }
00218 (*writePosition) = accumulatePosition;
00219 readPosition++;
00220 writePosition++;
00221 (*writeNormal) = accumulateNormal;
00222 readNormal++;
00223 writeNormal++;
00224 }
00225 }
00226
00227
00228 void CharacterMesh::skinningDeformPN(const Matrix34* positionDeformMatrixArray,
00229 const Matrix33* normalDeformMatrixArray){
00230 int vertexCount = getVertexCount();
00231 int weightsPerVertex = getWeightsPerVertex();
00232 int bonesPerVertex = getBonesPerVertex();
00233 const float* weightArray = getWeightArray();
00234 const u_char* boneIndexArray = getBoneIndexArray();
00235 const Vector3* readPosition = getPositionArray();
00236 const Vector3* readNormal = getNormalArray();
00237 bool calcNormal = hasNormal();
00238 Vector3* writePosition = deformedPosition_;
00239 Vector3* writeNormal = deformedNormal_;
00240 for(int i = 0; i < vertexCount; i++){
00241 int weightOffset = i * weightsPerVertex;
00242 int boneOffset = i * bonesPerVertex;
00243 Vector3 accumulatePosition(Vector3::zero);
00244 Vector3 accumulateNormal(Vector3::zero);
00245 float lastWeight = 1.f;
00246 for(int j = 0; j < weightsPerVertex; j++){
00247
00248 float weight = weightArray[weightOffset + j];
00249 lastWeight -= weight;
00250 if(weight <= Math::epsilon){ continue; }
00251
00252 const Matrix34& positionDeformMatrix =
00253 positionDeformMatrixArray[boneIndexArray[boneOffset + j]];
00254 accumulatePosition +=
00255 positionDeformMatrix * (*readPosition) * weight;
00256
00257 const Matrix33& normalDeformMatrix =
00258 normalDeformMatrixArray[boneIndexArray[boneOffset + j]];
00259 accumulateNormal += normalDeformMatrix * (*readNormal) * weight;
00260 }
00261
00262 if(lastWeight > Math::epsilon){
00263
00264 const Matrix34& positionDeformMatrix = positionDeformMatrixArray[
00265 boneIndexArray[boneOffset + weightsPerVertex]];
00266 accumulatePosition +=
00267 positionDeformMatrix * (*readPosition) * lastWeight;
00268
00269 const Matrix33& normalDeformMatrix = normalDeformMatrixArray[
00270 boneIndexArray[boneOffset + weightsPerVertex]];
00271 accumulateNormal +=
00272 normalDeformMatrix * (*readNormal) * lastWeight;
00273 }
00274 (*writePosition) = accumulatePosition;
00275 readPosition++;
00276 writePosition++;
00277 (*writeNormal) = accumulateNormal;
00278 readNormal++;
00279 writeNormal++;
00280 }
00281 }
00282
00283
00284
00285
00286 void CharacterMesh::stitchingDeformP(const Matrix34* positionDeformMatrixArray){
00287 int vertexCount = getVertexCount();
00288 const u_char* boneIndexArray = getBoneIndexArray();
00289 const Vector3* readPosition = getPositionArray();
00290 Vector3* writePosition = deformedPosition_;
00291 for(int i = 0; i < vertexCount; i++){
00292 const Matrix34& positionDeformMatrix =
00293 positionDeformMatrixArray[boneIndexArray[i]];
00294
00295 (*writePosition) = positionDeformMatrix * (*readPosition);
00296 readPosition++;
00297 writePosition++;
00298 }
00299 }
00300
00301
00302 void CharacterMesh::stitchingDeformPN(
00303 const Matrix34* positionDeformMatrixArray){
00304 int vertexCount = getVertexCount();
00305 const u_char* boneIndexArray = getBoneIndexArray();
00306 const Vector3* readPosition = getPositionArray();
00307 const Vector3* readNormal = getNormalArray();
00308 Vector3* writePosition = deformedPosition_;
00309 Vector3* writeNormal = deformedNormal_;
00310 for(int i = 0; i < vertexCount; i++){
00311 const Matrix34& positionDeformMatrix =
00312 positionDeformMatrixArray[boneIndexArray[i]];
00313
00314 (*writePosition) = positionDeformMatrix * (*readPosition);
00315 readPosition++;
00316 writePosition++;
00317
00318 (*writeNormal) = positionDeformMatrix.multiply33(*readNormal);
00319 readNormal++;
00320 writeNormal++;
00321 }
00322 }
00323
00324
00325 void CharacterMesh::stitchingDeformPN(const Matrix34* positionDeformMatrixArray,
00326 const Matrix33* normalDeformMatrixArray){
00327 int vertexCount = getVertexCount();
00328 const u_char* boneIndexArray = getBoneIndexArray();
00329 const Vector3* readPosition = getPositionArray();
00330 const Vector3* readNormal = getNormalArray();
00331 Vector3* writePosition = deformedPosition_;
00332 Vector3* writeNormal = deformedNormal_;
00333 for(int i = 0; i < vertexCount; i++){
00334 const Matrix34& positionDeformMatrix =
00335 positionDeformMatrixArray[boneIndexArray[i]];
00336 const Matrix33& normalDeformMatrix =
00337 normalDeformMatrixArray[boneIndexArray[i]];
00338
00339 (*writePosition) = positionDeformMatrix * (*readPosition);
00340 readPosition++;
00341 writePosition++;
00342
00343 (*writeNormal) = normalDeformMatrix * (*readNormal);
00344 readNormal++;
00345 writeNormal++;
00346 }
00347 }
00348
00349
00350
00351
00352 bool CharacterMesh::setupVertexBuffer(){
00353
00354 Assert(vertexDeclaration_ != NULL);
00355 Assert(vertexBuffer_ != NULL);
00356 RenderingDevice* device = RenderingDevice::getInstance();
00357 int vertexCount = getVertexCount();
00358
00359 device->writeDynamicVertexBuffer(vertexBuffer_, vertexSize_ * vertexCount,
00360 vertexCount, deformedPosition_, 0, NULL, 0, NULL, deformedNormal_,
00361 getColorArray(), getTexCoordSetCount(), getTexCoordTypeArray(),
00362 getTexCoordArray());
00363 return true;
00364 }
00365
00366
00367
00368
00369 bool CharacterMesh::createVertexDeclaration(){
00370 Assert(vertexDeclaration_ == NULL);
00371 Assert(vertexSize_ == 0);
00372
00373 RenderingDevice* device = RenderingDevice::getInstance();
00374 vertexSize_ = device->createVertexDeclaration(
00375 &vertexDeclaration_, true, 0, 0, hasNormal(), hasColor(),
00376 getTexCoordSetCount(), getTexCoordTypeArray());
00377 return true;
00378 }
00379
00380
00381 bool CharacterMesh::createVertexBuffer(){
00382 Assert(vertexBuffer_ == NULL);
00383
00384 if(vertexDeclaration_ == NULL){ createVertexDeclaration(); }
00385 Assert(vertexDeclaration_ != NULL);
00386
00387 RenderingDevice* device = RenderingDevice::getInstance();
00388 int vertexCount = getVertexCount();
00389 u_int bufferSize = vertexSize_ * vertexCount;
00390 vertexBuffer_ = device->createDynamicVertexBuffer(bufferSize);
00391 return true;
00392 }
00393
00394 }
00395