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 //------------------------------------------------------------------------------