Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

CharacterMesh.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * キャラクタメッシュ実装
00022  * @author Junpee
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 // 一度VertexBufferが作られた後にMeshDataの頂点フォーマットに変更があるとおかしくなる
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     // 変形した位置と法線を使用し、WeightとBoneIndexを使用しない
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     // ソフトウェアでキャラクタ変形を行うのでWeightとBoneIndexを0にする
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 } // End of namespace Lamp
00395 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:29 2005 for Lamp by doxygen 1.3.2