diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 92a1905c7..1ac58c6ef 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the 3ds importer class */ #include "3DSLoader.h" #include "MaterialSystem.h" +#include "DefaultLogger.h" #include "../include/IOStream.h" #include "../include/IOSystem.h" @@ -98,11 +99,18 @@ void Dot3DSImporter::ReplaceDefaultMaterial() { // NOTE: The additional check seems to be necessary, // some exporters seem to generate invalid data here - if (0xcdcdcdcd == (*a) || (*a) >= this->mScene->mMaterials.size()) + if (0xcdcdcdcd == (*a)) { (*a) = iIndex; ++iCnt; } + else if ( (*a) >= this->mScene->mMaterials.size()) + { + (*a) = iIndex; + ++iCnt; + DefaultLogger::get()->warn("Material index overflow in 3DS file. Assigning " + "default material ..."); + } } } if (0 != iCnt && iIndex == this->mScene->mMaterials.size()) @@ -125,14 +133,17 @@ void Dot3DSImporter::CheckIndices(Dot3DS::Mesh* sMesh) // check whether all indices are in range if ((*i).i1 >= sMesh->mPositions.size()) { + DefaultLogger::get()->warn("Face index overflow in 3DS file (#1)"); (*i).i1 = sMesh->mPositions.size()-1; } if ((*i).i2 >= sMesh->mPositions.size()) { + DefaultLogger::get()->warn("Face index overflow in 3DS file (#2)"); (*i).i2 = sMesh->mPositions.size()-1; } if ((*i).i3 >= sMesh->mPositions.size()) { + DefaultLogger::get()->warn("Face index overflow in 3DS file (#3)"); (*i).i3 = sMesh->mPositions.size()-1; } } @@ -155,31 +166,55 @@ void Dot3DSImporter::MakeUnique(Dot3DS::Mesh* sMesh) vNew2.resize(sMesh->mFaces.size() * 3); for (unsigned int i = 0; i < sMesh->mFaces.size();++i) { + uint32_t iTemp1,iTemp2; + // position and texture coordinates - vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1]; - vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i1]; - sMesh->mFaces[i].i1 = iBase++; + vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3]; + vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i3]; + iTemp1 = iBase++; vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2]; vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i2]; - sMesh->mFaces[i].i2 = iBase++; + iTemp2 = iBase++; - vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3]; - vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i3]; + vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1]; + vNew2[iBase] = sMesh->mTexCoords[sMesh->mFaces[i].i1]; sMesh->mFaces[i].i3 = iBase++; + + sMesh->mFaces[i].i1 = iTemp1; + sMesh->mFaces[i].i2 = iTemp2; + + // handle the face order ... + /*if (iTemp1 > iTemp2) + { + sMesh->mFaces[i].bFlipped = true; + }*/ } } else { for (unsigned int i = 0; i < sMesh->mFaces.size();++i) { + uint32_t iTemp1,iTemp2; + // position only - vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1]; - sMesh->mFaces[i].i1 = iBase++; - vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2]; - sMesh->mFaces[i].i2 = iBase++; vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i3]; + iTemp1 = iBase++; + + vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i2]; + iTemp2 = iBase++; + + vNew[iBase] = sMesh->mPositions[sMesh->mFaces[i].i1]; sMesh->mFaces[i].i3 = iBase++; + + sMesh->mFaces[i].i1 = iTemp1; + sMesh->mFaces[i].i2 = iTemp2; + + // handle the face order ... + /*if (iTemp1 > iTemp2) + { + sMesh->mFaces[i].bFlipped = true; + }*/ } } sMesh->mPositions = vNew; @@ -216,9 +251,16 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + // phong shininess and shininess strength + if (Dot3DS::Dot3DSFile::Phong == oldMat.mShading || + Dot3DS::Dot3DSFile::Metal == oldMat.mShading) + { + mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); + mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); + } + // opacity mat.AddProperty( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); @@ -231,8 +273,6 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, { case Dot3DS::Dot3DSFile::Flat: eShading = aiShadingMode_Flat; break; - case Dot3DS::Dot3DSFile::Phong : - eShading = aiShadingMode_Phong; break; // I don't know what "Wire" shading should be, // assume it is simple lambertian diffuse (L dot N) shading @@ -243,6 +283,9 @@ void Dot3DSImporter::ConvertMaterial(Dot3DS::Material& oldMat, // assume cook-torrance shading for metals. // NOTE: I assume the real shader inside 3ds max is an anisotropic // Phong-Blinn shader, but this is a good approximation too + case Dot3DS::Dot3DSFile::Phong : + eShading = aiShadingMode_Phong; break; + case Dot3DS::Dot3DSFile::Metal : eShading = aiShadingMode_CookTorrance; break; } @@ -361,9 +404,8 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) else aiSplit[*a].push_back(iNum); } // now generate submeshes -#if 0 + bool bFirst = true; -#endif for (unsigned int p = 0; p < this->mScene->mMaterials.size();++p) { if (aiSplit[p].size() != 0) @@ -377,7 +419,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName); avOutMeshes.push_back(p_pcOut); -#if 0 + if (bFirst) { p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4(); @@ -385,7 +427,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) *((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat; bFirst = false; } -#endif + // convert vertices p_pcOut->mNumVertices = aiSplit[p].size()*3; @@ -408,7 +450,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) p_pcOut->mFaces[q].mIndices = new unsigned int[3]; p_pcOut->mFaces[q].mNumIndices = 3; - p_pcOut->mFaces[q].mIndices[0] = iBase; + p_pcOut->mFaces[q].mIndices[2] = iBase; p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i1]; p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i1]; @@ -416,7 +458,7 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut) p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i2]; p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i2]; - p_pcOut->mFaces[q].mIndices[2] = iBase; + p_pcOut->mFaces[q].mIndices[0] = iBase; p_pcOut->mVertices[iBase] = (*i).mPositions[(*i).mFaces[iIndex].i3]; p_pcOut->mNormals[iBase++] = (*i).mNormals[(*i).mFaces[iIndex].i3]; } @@ -505,7 +547,7 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* for (unsigned int i = 0;i < iArray.size();++i) { const unsigned int iIndex = iArray[i]; -#if 0 + if (NULL != pcSOut->mMeshes[iIndex]->mColors[1]) { pcOut->mTransformation = *((aiMatrix4x4*) @@ -514,13 +556,11 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1]; pcSOut->mMeshes[iIndex]->mColors[1] = NULL; } -#endif + pcOut->mMeshes[i] = iIndex; } - // NOTE: Not necessary. We can use the given transformation matrix. - // However, we'd need it if we wanted to implement keyframe animation - + // (code for keyframe animation. however, this is currently not supported by Assimp) #if 0 // build the scaling matrix. Toggle y and z axis aiMatrix4x4 mS; @@ -536,11 +576,34 @@ void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* // build the pivot matrix. Toggle y and z axis aiMatrix4x4 mP; - mP.a4 = pcIn->vPivot.x; - mP.b4 = pcIn->vPivot.z; - mP.c4 = pcIn->vPivot.y; + mP.a4 = -pcIn->vPivot.x; + mP.b4 = -pcIn->vPivot.z; + mP.c4 = -pcIn->vPivot.y; + + +#endif + // build a matrix to flip the z coordinate of the vertices + aiMatrix4x4 mF; + mF.c3 = -1.0f; + + + // build the final matrix + // NOTE: This should be the identity. Theoretically. In reality + // there are many models with very funny local matrices and + // very different keyframe values ... this is the only reason + // why we extract the data from the first keyframe. + pcOut->mTransformation = mF; /* mF * mT * pcIn->mRotation * mS * mP * + pcOut->mTransformation.Inverse(); */ + + // (code for keyframe animation. however, this is currently not supported by Assimp) +#if 0 + if (pcOut->mTransformation != mF) + { + DefaultLogger::get()->warn("The local transformation matrix of the " + "3ds file does not match the first keyframe. Using the " + "information from the keyframe."); + } #endif - pcOut->mTransformation = aiMatrix4x4(); // mT * pcIn->mRotation * mS * mP * pcOut->mTransformation.Inverse(); pcOut->mNumChildren = pcIn->mChildren.size(); pcOut->mChildren = new aiNode*[pcIn->mChildren.size()]; @@ -748,6 +811,10 @@ void Dot3DSImporter::BakeScaleNOffset( { (*a)->iUVSrc = 0; } + DefaultLogger::get()->error("There are too many " + "combinations of different UV scaling/offset/rotation operations " + "to generate an UV channel for each (maximum is 4). Using the " + "first UV channel ..."); continue; } const aiVector3D* pvBase = _pvBase; @@ -815,6 +882,9 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut) // unsigned int iCnt = 0; + DefaultLogger::get()->warn("No hierarchy information has been " + "found in the file. A flat hierarchy tree is built ..."); + pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes; pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mNumMeshes ]; @@ -827,7 +897,12 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut) pcNode->mMeshes = new unsigned int[1]; pcNode->mMeshes[0] = i; pcNode->mNumMeshes = 1; - pcNode->mName.Set("UNNAMED"); + + std::string s; + std::stringstream ss(s); + ss << "UNNAMED[" << i << + "]"; + + pcNode->mName.Set(s); // add the new child to the parent node pcOut->mRootNode->mChildren[i] = pcNode; @@ -860,6 +935,7 @@ void Dot3DSImporter::ConvertScene(aiScene* pcOut) this->ConvertMeshes(pcOut); return; } +#if 0 // ------------------------------------------------------------------------------------------------ void Dot3DSImporter::GenTexCoord (Dot3DS::Texture* pcTexture, const std::vector& p_vIn, @@ -886,4 +962,5 @@ void Dot3DSImporter::GenTexCoord (Dot3DS::Texture* pcTexture, (*a).y += pcTexture->mOffsetV; } return; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/code/3DSGenNormals.cpp b/code/3DSGenNormals.cpp index 57c09160a..075872070 100644 --- a/code/3DSGenNormals.cpp +++ b/code/3DSGenNormals.cpp @@ -59,7 +59,7 @@ void Dot3DSImporter::GenNormals(Dot3DS::Mesh* sMesh) sMesh->mNormals.resize(sMesh->mPositions.size(),aiVector3D()); for( unsigned int a = 0; a < sMesh->mFaces.size(); a++) { - const Dot3DS::Face& face = sMesh->mFaces[a]; + Dot3DS::Face& face = sMesh->mFaces[a]; // assume it is a triangle aiVector3D* pV1 = &sMesh->mPositions[face.i1]; diff --git a/code/3DSHelper.h b/code/3DSHelper.h index 5adc9fa00..b56364323 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -199,6 +199,7 @@ public: // Specifies the shininess of the material // followed by percentage chunk CHUNK_MAT_SHININESS = 0xA040, + CHUNK_MAT_SHININESS_PERCENT = 0xA041 , // Specifies the shading mode to be used // followed by a short @@ -304,7 +305,7 @@ public: /** Helper structure representing a 3ds mesh face */ struct Face { - Face() : iSmoothGroup(0), bDirection(true), i1(0), i2(0), i3(0) + Face() : iSmoothGroup(0), i1(0), i2(0), i3(0), bFlipped(false) { // let the rest uninitialized for performance } @@ -327,9 +328,8 @@ struct Face //! specifies to which smoothing group the face belongs to uint32_t iSmoothGroup; - //! Direction the normal vector of the face - //! will be pointing to - bool bDirection; + //! Specifies that the face normal must be flipped + bool bFlipped; }; // --------------------------------------------------------------------------- /** Helper structure representing a texture */ @@ -376,7 +376,8 @@ struct Material mTransparency (1.0f), mBumpHeight (1.0f), iBakeUVTransform (0), - pcSingleTexture (NULL) + pcSingleTexture (NULL), + mShininessStrength (1.0f) { static int iCnt = 0; std::stringstream ss(mName); @@ -389,6 +390,8 @@ struct Material aiColor3D mDiffuse; //! Specular exponent float mSpecularExponent; + //! Shininess strength, in percent + float mShininessStrength; //! Specular color of the material aiColor3D mSpecular; //! Ambient color of the material @@ -462,9 +465,12 @@ struct Mesh struct Node { Node() + + // (code for keyframe animation. however, this is currently not supported by Assimp) #if 0 : vScaling(1.0f,1.0f,1.0f) #endif + { static int iCnt = 0; std::stringstream ss(mName); @@ -489,6 +495,7 @@ struct Node //! Index of the node int16_t mHierarchyIndex; +// (code for keyframe animation. however, this is currently not supported by Assimp) #if 0 aiVector3D vPivot; aiVector3D vScaling; @@ -502,7 +509,7 @@ struct Node { mChildren.push_back(pc); pc->mParent = this; - pc->mHierarchyPos = this->mHierarchyPos+1; + //pc->mHierarchyPos = this->mHierarchyPos+1; return *this; } }; diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index 239a07701..3c00f9102 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Implementation of the 3ds importer class */ #include "3DSLoader.h" #include "MaterialSystem.h" +#include "DefaultLogger.h" #include "../include/IOStream.h" #include "../include/IOSystem.h" @@ -59,7 +60,6 @@ using namespace Assimp; "specified in the higher-level chunk header." \ - // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer Dot3DSImporter::Dot3DSImporter() @@ -145,6 +145,7 @@ void Dot3DSImporter::InternReadFile( this->mMasterScale = 1.0f; this->mBackgroundImage = ""; this->bHasBG = false; + this->mErrorText = ""; int iRemaining = (unsigned int)fileSize; this->ParseMainChunk(&iRemaining); @@ -170,31 +171,10 @@ void Dot3DSImporter::InternReadFile( // Generate it if no material containing DEFAULT in its name has been // found in the file this->ReplaceDefaultMaterial(); - - try - { - // Convert the scene from our internal representation to an aiScene object - this->ConvertScene(pScene); - } - catch (ImportErrorException ex) - { - // delete the scene itself - if (pScene->mMeshes) - { - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - delete pScene->mMeshes[i]; - delete[] pScene->mMeshes; - } - if (pScene->mMaterials) - { - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - delete pScene->mMaterials[i]; - delete[] pScene->mMaterials; - } - // there are no animations - if (pScene->mRootNode)DeleteNodeRecursively(pScene->mRootNode); - throw ex; - } + + // Convert the scene from our internal representation to an aiScene object + this->ConvertScene(pScene); + // Generate the node graph for the scene. This is a little bit // tricky since we'll need to split some meshes into submeshes @@ -205,6 +185,12 @@ void Dot3DSImporter::InternReadFile( delete[] this->mBuffer; delete this->mScene; + + // check whether an error occured during reading ... set it as warning + if ("" != this->mErrorText) + { + DefaultLogger::get()->warn(this->mErrorText); + } return; } // ------------------------------------------------------------------------------------------------ @@ -532,7 +518,7 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining) const unsigned char* sz = (unsigned char*)this->mCurrent; unsigned int iCnt = 0; uint16_t iHierarchy; - //uint16_t iTemp; +// uint16_t iTemp; Dot3DS::Node* pcNode; switch (psChunk->Flag) { @@ -554,20 +540,28 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining) iHierarchy++; pcNode->mHierarchyPos = iHierarchy; pcNode->mHierarchyIndex = this->mLastNodeIndex; - if (iHierarchy > this->mLastNodeIndex) + if (this->mCurrentNode && this->mCurrentNode->mHierarchyPos == iHierarchy) + { + // add to the parent of the last touched node + this->mCurrentNode->mParent->push_back(pcNode); + this->mLastNodeIndex++; + } + else if(iHierarchy >= this->mLastNodeIndex) { // place it at the current position in the hierarchy this->mCurrentNode->push_back(pcNode); + this->mLastNodeIndex = iHierarchy; } else { // need to go back to the specified position in the hierarchy. this->InverseNodeSearch(pcNode,this->mCurrentNode); + this->mLastNodeIndex++; } - this->mLastNodeIndex++; this->mCurrentNode = pcNode; break; + // (code for keyframe animation. however, this is currently not supported by Assimp) #if 0 case Dot3DSFile::CHUNK_TRACKPIVOT: @@ -651,42 +645,33 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining) if (0.0f != fRadians) { - // if the radians go beyond PI then the rotations - // thereafter must be inversed -#if 0 - if (neg)fRadians *= -1.0f; - if ((fRadians >= 3.1415926f || fRadians <= -3.1415926f)) - { - neg = !neg; - } -#endif - - // get the rotation matrix around the axis const float fSin = sinf(-fRadians); const float fCos = cosf(-fRadians); const float fOneMinusCos = 1.0f - fCos; std::swap(vAxis.z,vAxis.y); - vAxis.Normalize(); + //vAxis.z *= -1.0f; + //vAxis.Normalize(); aiMatrix4x4 mRot = aiMatrix4x4( (vAxis.x * vAxis.x) * fOneMinusCos + fCos, - (vAxis.x * vAxis.y) * fOneMinusCos - (vAxis.z * fSin), - (vAxis.x * vAxis.z) * fOneMinusCos + (vAxis.y * fSin), + (vAxis.x * vAxis.y) * fOneMinusCos /*-*/- (vAxis.z * fSin), + (vAxis.x * vAxis.z) * fOneMinusCos /*+*/+ (vAxis.y * fSin), 0.0f, - (vAxis.y * vAxis.x) * fOneMinusCos + (vAxis.z * fSin), + (vAxis.y * vAxis.x) * fOneMinusCos /*+*/+ (vAxis.z * fSin), (vAxis.y * vAxis.y) * fOneMinusCos + fCos, - (vAxis.y * vAxis.z) * fOneMinusCos - (vAxis.x * fSin), + (vAxis.y * vAxis.z) * fOneMinusCos /*-*/- (vAxis.x * fSin), 0.0f, - (vAxis.z * vAxis.x) * fOneMinusCos - (vAxis.y * fSin), - (vAxis.z * vAxis.y) * fOneMinusCos + (vAxis.x * fSin), + (vAxis.z * vAxis.x) * fOneMinusCos /*-*/- (vAxis.y * fSin), + (vAxis.z * vAxis.y) * fOneMinusCos /*+*/+ (vAxis.x * fSin), (vAxis.z * vAxis.z) * fOneMinusCos + fCos, 0.0f,0.0f,0.0f,0.0f,1.0f); - //mRot.Transpose(); + mRot.Transpose(); // build a chain of concatenated rotation matrix' // if there are multiple track chunks for the same frame + // (there are some silly files usinf this ...) if (0 != iNum0) { this->mCurrentNode->mRotation = this->mCurrentNode->mRotation * mRot; @@ -739,14 +724,19 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining) this->mCurrentNode->vScaling.y *= vMe.y; this->mCurrentNode->vScaling.z *= vMe.z; } + else + { + DefaultLogger::get()->warn("Found zero scaling factors. " + "This will be ignored."); + } this->mCurrent += sizeof(aiVector3D); } else this->mCurrent += sizeof(uint32_t) + sizeof(aiVector3D); } } break; +#endif // end keyframe animation code -#endif // 0 }; if ((unsigned int)pcCurNext < (unsigned int)this->mCurrent) { @@ -790,13 +780,6 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining) { // nth bit is set for nth smoothing group (*i).iSmoothGroup = *((uint32_t*)this->mCurrent); -#if 0 - for (unsigned int x = 0, a = 1; x < 32;++x,a <<= 1) - { - if ((*i).iSmoothGroup & a) - mMesh.bSmoothGroupRequired[x] = true; - } -#endif this->mCurrent += sizeof(uint32_t); } break; @@ -955,10 +938,10 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining) aiMatrix4x4 mMe = mMesh.mMat; mMe.a1 *= -1.0f; - mMe.a2 *= -1.0f; - mMe.a3 *= -1.0f; - mMe.a4 *= -1.0f; - mInv = mMe * mInv; + mMe.b1 *= -1.0f; + mMe.c1 *= -1.0f; + mMe.d1 *= -1.0f; + mInv = mInv * mMe; for (register unsigned int i = 0; i < mMesh.mPositions.size();++i) { aiVector3D a,c; @@ -1007,8 +990,6 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining) sFace.i3 = *((uint16_t*)this->mCurrent); this->mCurrent += 2*sizeof(uint16_t); mMesh.mFaces.push_back(sFace); - - //if (sFace.i1 < sFace.i2)sFace.bDirection = false; } // resize the material array (0xcdcdcdcd marks the @@ -1131,6 +1112,14 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining) else *pcf *= (float)0xFFFF; break; + case Dot3DSFile::CHUNK_MAT_SHININESS_PERCENT: + pcf = &this->mScene->mMaterials.back().mShininessStrength; + *pcf = this->ParsePercentageChunk(); + if (is_qnan(*pcf)) + *pcf = 0.0f; + else *pcf *= (float)0xffff / 100.0f; + break; + case Dot3DSFile::CHUNK_MAT_SELF_ILPCT: pcf = &this->mScene->mMaterials.back().sTexEmissive.mTextureBlend; *pcf = this->ParsePercentageChunk(); diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index eb4866c91..430bb0ded 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -507,10 +507,12 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, aiScene* pcScene) for (unsigned int t = 0; t < 3;++t) { - p_pcOut->mFaces[q].mIndices[t] = iBase; p_pcOut->mVertices[iBase] = mesh.mPositions[mesh.mFaces[iIndex].mIndices[t]]; p_pcOut->mNormals[iBase++] = mesh.mNormals[mesh.mFaces[iIndex].mIndices[t]]; } + p_pcOut->mFaces[q].mIndices[0] = iBase-2; + p_pcOut->mFaces[q].mIndices[1] = iBase-1; + p_pcOut->mFaces[q].mIndices[2] = iBase; } } // convert texture coordinates diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index 76eb04b2e..4172d9915 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -81,24 +81,39 @@ void CalcTangentsProcess::Execute( aiScene* pScene) { DefaultLogger::get()->debug("CalcTangentsProcess begin"); + bool bHas = false; for( unsigned int a = 0; a < pScene->mNumMeshes; a++) - ProcessMesh( pScene->mMeshes[a]); + if(ProcessMesh( pScene->mMeshes[a]))bHas = true; - DefaultLogger::get()->debug("CalcTangentsProcess finished"); + if (bHas)DefaultLogger::get()->debug("CalcTangentsProcess finished. There was much work to do ..."); + else DefaultLogger::get()->debug("CalcTangentsProcess finished"); } // ------------------------------------------------------------------------------------------------ // Calculates tangents and bitangents for the given mesh -void CalcTangentsProcess::ProcessMesh( aiMesh* pMesh) +bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh) { // we assume that the mesh is still in the verbose vertex format where each face has its own set // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to // assert() it here. //assert( must be verbose, dammit); + // TODO (Aramis) + // If we had a model format in the lib which has native support for + // tangents and bitangents, it would be necessary to add a + // "KillTangentsAndBitangents" flag ... + if (pMesh->mTangents && pMesh->mBitangents) + { + return false; + } + // what we can check, though, is if the mesh has normals and texture coord. That's a requirement if( pMesh->mNormals == NULL || pMesh->mTextureCoords[0] == NULL) - return; + { + DefaultLogger::get()->error("Normal vectors and at least one " + "texture coordinate set are required to calculate tangents. "); + return false; + } // calculate the position bounds so we have a reliable epsilon to check position differences against aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f); @@ -229,4 +244,5 @@ void CalcTangentsProcess::ProcessMesh( aiMesh* pMesh) meshBitang[ closeVertices[b] ] = smoothBitangent; } } + return true; } diff --git a/code/CalcTangentsProcess.h b/code/CalcTangentsProcess.h index 1621ba822..bcaf3c026 100644 --- a/code/CalcTangentsProcess.h +++ b/code/CalcTangentsProcess.h @@ -89,7 +89,7 @@ protected: /** Calculates tangents and bitangents for the given mesh * @param pMesh The mesh to process. */ - void ProcessMesh( aiMesh* pMesh); + bool ProcessMesh( aiMesh* pMesh); }; } // end of namespace Assimp diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index 8971cedf5..151f213af 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -51,7 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { // --------------------------------------------------------------------------- -DefaultLogger *DefaultLogger::m_pLogger = NULL; +NullLogger DefaultLogger::s_pNullLogger; +Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger; // --------------------------------------------------------------------------- // @@ -72,17 +73,29 @@ struct LogStreamInfo // Creates the only singleton instance Logger *DefaultLogger::create(const std::string &name, LogSeverity severity) { - ai_assert (NULL == m_pLogger); m_pLogger = new DefaultLogger( name, severity ); return m_pLogger; } - +// --------------------------------------------------------------------------- +void DefaultLogger::set (Logger *logger) +{ + if (!logger) + { + DefaultLogger::m_pLogger = &s_pNullLogger; + return; + } + DefaultLogger::m_pLogger = logger; +} +// --------------------------------------------------------------------------- +bool DefaultLogger::isNullLogger() +{ + return m_pLogger == &s_pNullLogger; +} // --------------------------------------------------------------------------- // Singleton getter Logger *DefaultLogger::get() { - ai_assert (NULL != m_pLogger); return m_pLogger; } @@ -92,7 +105,7 @@ void DefaultLogger::kill() { ai_assert (NULL != m_pLogger); delete m_pLogger; - m_pLogger = NULL; + m_pLogger = &s_pNullLogger; } // --------------------------------------------------------------------------- @@ -142,6 +155,22 @@ void DefaultLogger::setLogSeverity( LogSeverity log_severity ) void DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) { ai_assert ( NULL != pStream ); + + // fix (Aramis) + if (0 == severity) + { + severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING; + } + + for ( StreamIt it = m_StreamArray.begin(); + it != m_StreamArray.end(); + ++it ) + { + if ( (*it)->m_pStream == pStream ) + { + (*it)->m_uiErrorSeverity |= severity; + } + } LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream ); m_StreamArray.push_back( pInfo ); @@ -152,6 +181,12 @@ void DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) { ai_assert ( NULL != pStream ); + + // fix (Aramis) + if (0 == severity) + { + severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING; + } for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); @@ -166,6 +201,9 @@ void DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) uiSev &= ( ~Logger::WARN ); if ( severity & Logger::ERR ) uiSev &= ( ~Logger::ERR ); + // fix (Aramis) + if ( severity & Logger::DEBUGGING ) + uiSev &= ( ~Logger::DEBUGGING ); (*it)->m_uiErrorSeverity = uiSev; diff --git a/code/DefaultLogger.h b/code/DefaultLogger.h index 1ae2cdbfc..6cdd5e850 100644 --- a/code/DefaultLogger.h +++ b/code/DefaultLogger.h @@ -38,6 +38,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ +#if (!defined AI_DEFAULTLOGGER_H_INCLUDED) +#define AI_DEFAULTLOGGER_H_INCLUDED + #include "../include/Logger.h" #include @@ -47,6 +50,39 @@ namespace Assimp class IOStream; struct LogStreamInfo; + +// --------------------------------------------------------------------------- +/** @class NullLogger + * @brief Empty logging implementation. Does nothing. Used by default + * if the application hasn't specified a custom logger (or DefaultLogger) + * via DefaultLogger::set() or DefaultLogger::create(); + */ +class NullLogger : public Logger +{ +public: + /** @brief Logs a debug message */ + void debug(const std::string &message) {} + + /** @brief Logs an info message */ + void info(const std::string &message) {} + + /** @brief Logs a warning message */ + void warn(const std::string &message) {} + + /** @brief Logs an error message */ + void error(const std::string &message) {} + + /** @brief Log severity setter */ + void setLogSeverity(LogSeverity log_severity) {} + + /** @brief Detach a still attached stream from logger */ + void attachStream(LogStream *pStream, unsigned int severity) {} + + /** @brief Detach a still attached stream from logger */ + void detatchStream(LogStream *pStream, unsigned int severity) {} +}; + + // --------------------------------------------------------------------------- /** @class DefaultLogger * @brief Default logging implementation. The logger writes into a file. @@ -57,18 +93,39 @@ class DefaultLogger : public Logger { public: - /** @brief Creates the only logging instance + /** @brief Creates a custom logging instance (DefaultLogger) * @param name Name for logfile * @param severity Log severity, VERBOSE will activate debug messages + * + * This replaces the default NullLogger with a DefaultLogger instance. */ static Logger *create(const std::string &name, LogSeverity severity); + + /** @brief Setup a custom implementation of the Logger interface as + * default logger. + * + * Use this if the provided DefaultLogger class doesn't fit into + * your needs. If the provided message formatting is OK for you, + * it is easier to use create() to create a DefaultLogger and to attach + * your own custom output streams to it than using this method. + * @param logger Pass NULL to setup a default NullLogger + */ + static void set (Logger *logger); /** @brief Getter for singleton instance - * @return Only instance + * @return Only instance. This is never null, but it could be a + * NullLogger. Use isNullLogger to check this. */ static Logger *get(); + + /** @brief Return whether a default NullLogger is currently active + * @return true if the current logger id a NullLogger. + * Use create() or set() to setup a custom logger. + */ + static bool isNullLogger(); - /** @brief Will kill the singleton instance */ + /** @brief Will kill the singleton instance and setup a NullLogger as + logger */ static void kill(); /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ @@ -112,7 +169,9 @@ private: typedef std::vector::const_iterator ConstStreamIt; //! only logging instance - static DefaultLogger *m_pLogger; + static Logger *m_pLogger; + static NullLogger s_pNullLogger; + //! Logger severity LogSeverity m_Severity; //! Attached streams @@ -123,3 +182,5 @@ private: // --------------------------------------------------------------------------- } // Namespace Assimp + +#endif // !! AI_DEFAULTLOGGER_H_INCLUDED diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index 79cb74166..22f89919a 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -109,6 +109,9 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) aiVector3D pDelta2 = *pV3 - *pV1; aiVector3D vNor = pDelta1 ^ pDelta2; + if (face.mIndices[1] > face.mIndices[2]) + vNor *= -1.0f; + for (unsigned int i = 0;i < face.mNumIndices;++i) { pMesh->mNormals[face.mIndices[i]] = vNor; diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index c605cef4f..f3d21d557 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -110,6 +110,9 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh) aiVector3D pDelta2 = *pV3 - *pV1; aiVector3D vNor = pDelta1 ^ pDelta2; + if (face.mIndices[1] > face.mIndices[2]) + vNor *= -1.0f; + for (unsigned int i = 0;i < face.mNumIndices;++i) { pMesh->mNormals[face.mIndices[i]] = vNor; diff --git a/code/Importer.cpp b/code/Importer.cpp index 578814073..94be22acf 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -99,10 +99,6 @@ Importer::Importer() : mScene(NULL), mErrorString("") { - // construct a new logger - /*DefaultLogger::create( "test.log", DefaultLogger::VERBOSE ); - DefaultLogger::get()->info("Start logging");*/ - // allocate a default IO handler mIOHandler = new DefaultIOSystem; diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index c2f6301c1..5d5438cbf 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -244,6 +244,7 @@ void MD2Importer::InternReadFile( unsigned int iCurrent = 0; if (0 != this->m_pcHeader->numTexCoords) { + for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->numTriangles;++i) { // allocate the face @@ -253,10 +254,9 @@ void MD2Importer::InternReadFile( // copy texture coordinates // check whether they are different from the previous value at this index. // In this case, create a full separate set of vertices/normals/texcoords + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; - // validate vertex indices if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; @@ -295,6 +295,9 @@ void MD2Importer::InternReadFile( pcOut->x = u; pcOut->y = v; } + pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2; + pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1; + pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0; } } else @@ -308,10 +311,9 @@ void MD2Importer::InternReadFile( // copy texture coordinates // check whether they are different from the previous value at this index. // In this case, create a full separate set of vertices/normals/texcoords + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; - // validate vertex indices if (pcTriangles[i].vertexIndices[c] >= this->m_pcHeader->numVertices) pcTriangles[i].vertexIndices[c] = this->m_pcHeader->numVertices-1; @@ -343,6 +345,9 @@ void MD2Importer::InternReadFile( pcOut->x = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].s / this->m_pcHeader->skinWidth; pcOut->y = (float)pcTexCoords[pcTriangles[i].textureIndices[c]].t / this->m_pcHeader->skinHeight; } + pScene->mMeshes[0]->mFaces[i].mIndices[0] = iTemp+2; + pScene->mMeshes[0]->mFaces[i].mIndices[1] = iTemp+1; + pScene->mMeshes[0]->mFaces[i].mIndices[2] = iTemp+0; } } diff --git a/code/MD3FileData.h b/code/MD3FileData.h index 398198ac2..646bfe9ef 100644 --- a/code/MD3FileData.h +++ b/code/MD3FileData.h @@ -254,7 +254,7 @@ struct Vertex * \note This has been taken from q3 source (misc_model.c) */ // --------------------------------------------------------------------------- -inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut) +inline void LatLngNormalToVec3(int16_t p_iNormal, float* p_afOut) { float lat = (float)(( p_iNormal >> 8 ) & 0xff); float lng = (float)(( p_iNormal & 0xff )); diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 2c4d6d5ab..e6ef92693 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -201,25 +201,28 @@ void MD3Importer::InternReadFile( pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pcMesh->mFaces[i].mIndices[c] = iCurrent; - // read vertices pcMesh->mVertices[iCurrent].x = pcVertices[ pcTriangles->INDEXES[c]].X; pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y; - pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z * -1.0f; + pcMesh->mVertices[iCurrent].z = pcVertices[ pcTriangles->INDEXES[c]].Z*-1.0f; // convert the normal vector to uncompressed float3 format LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL, (float*)&pcMesh->mNormals[iCurrent]); - std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z ); + //std::swap(pcMesh->mNormals[iCurrent].z,pcMesh->mNormals[iCurrent].y); + pcMesh->mNormals[iCurrent].z *= -1.0f; // read texture coordinates pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[ pcTriangles->INDEXES[c]].V; } + pcMesh->mFaces[i].mIndices[0] = iTemp+2; + pcMesh->mFaces[i].mIndices[1] = iTemp+1; + pcMesh->mFaces[i].mIndices[2] = iTemp+0; pcTriangles++; } diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index e47254575..43f22fd8f 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -654,6 +654,7 @@ void MDLImporter::InternReadFile_Quake1( ) pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { pcMesh->mFaces[i].mIndices[c] = iCurrent; @@ -705,6 +706,9 @@ void MDLImporter::InternReadFile_Quake1( ) pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight; } + pcMesh->mFaces[i].mIndices[0] = iTemp+2; + pcMesh->mFaces[i].mIndices[1] = iTemp+1; + pcMesh->mFaces[i].mIndices[2] = iTemp+0; pcTriangles++; } return; @@ -824,10 +828,9 @@ void MDLImporter::InternReadFile_GameStudio( ) pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pcMesh->mFaces[i].mIndices[c] = iCurrent; - // read vertices unsigned int iIndex = pcTriangles->index_xyz[c]; if (iIndex >= (unsigned int)this->m_pcHeader->num_verts) @@ -879,6 +882,9 @@ void MDLImporter::InternReadFile_GameStudio( ) vTexCoords[iCurrent].x = s; vTexCoords[iCurrent].y = t; } + pcMesh->mFaces[i].mIndices[0] = iTemp+2; + pcMesh->mFaces[i].mIndices[1] = iTemp+1; + pcMesh->mFaces[i].mIndices[2] = iTemp+0; pcTriangles++; } @@ -901,10 +907,9 @@ void MDLImporter::InternReadFile_GameStudio( ) pcMesh->mFaces[i].mIndices = new unsigned int[3]; pcMesh->mFaces[i].mNumIndices = 3; + unsigned int iTemp = iCurrent; for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pcMesh->mFaces[i].mIndices[c] = iCurrent; - // read vertices unsigned int iIndex = pcTriangles->index_xyz[c]; if (iIndex >= (unsigned int)this->m_pcHeader->num_verts) @@ -956,6 +961,9 @@ void MDLImporter::InternReadFile_GameStudio( ) vTexCoords[iCurrent].x = s; vTexCoords[iCurrent].y = t; } + pcMesh->mFaces[i].mIndices[0] = iTemp+2; + pcMesh->mFaces[i].mIndices[1] = iTemp+1; + pcMesh->mFaces[i].mIndices[2] = iTemp+0; pcTriangles++; } } @@ -1384,7 +1392,7 @@ void MDLImporter::InternReadFile_GameStudioA7( ) unsigned int iOutIndex = iTriangle * 3 + c; // write the output face index - pcFaces[iTriangle].mIndices[c] = iOutIndex; + pcFaces[iTriangle].mIndices[c] = iTriangle * 3 + (2-c); // swap z and y axis vPositions[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x; diff --git a/code/MakeVerboseFormat.cpp b/code/MakeVerboseFormat.cpp new file mode 100644 index 000000000..62473e547 --- /dev/null +++ b/code/MakeVerboseFormat.cpp @@ -0,0 +1,221 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +/** @file Implementation of the post processing step "MakeVerboseFormat" +*/ +#include "MakeVerboseFormat.h" +#include "DefaultLogger.h" + +#include "../include/aiMesh.h" +#include "../include/aiScene.h" +#include "../include/aiAssert.h" + +using namespace Assimp; + + +MakeVerboseFormatProcess::MakeVerboseFormatProcess() +{ + // nothing to do here +} + +MakeVerboseFormatProcess::~MakeVerboseFormatProcess() +{ + // nothing to do here +} +// ------------------------------------------------------------------- +// Executes the post processing step on the given imported data. +void MakeVerboseFormatProcess::Execute( aiScene* pScene) +{ + ai_assert(NULL != pScene); + DefaultLogger::get()->debug("MakeVerboseFormatProcess begin"); + + bool bHas = false; + for( unsigned int a = 0; a < pScene->mNumMeshes; a++) + { + if( this->MakeVerboseFormat( pScene->mMeshes[a])) + bHas = true; + } + if (bHas)DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ..."); + else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do."); + +} + +// ------------------------------------------------------------------- +// Executes the post processing step on the given imported data. +bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) +{ + ai_assert(NULL != pcMesh); + + unsigned int iOldNumVertices = pcMesh->mNumVertices; + const unsigned int iNumVerts = pcMesh->mNumFaces*3; + + aiVector3D* pvPositions = new aiVector3D[iNumVerts]; + + aiVector3D* pvNormals; + if (pcMesh->HasNormals()) + { + pvNormals = new aiVector3D[iNumVerts]; + } + aiVector3D* pvTangents, *pvBitangents; + if (pcMesh->HasTangentsAndBitangents()) + { + pvTangents = new aiVector3D[iNumVerts]; + pvBitangents = new aiVector3D[iNumVerts]; + } + + ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); + ai_assert(AI_MAX_NUMBER_OF_COLOR_SETS == 4); + + aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {NULL,NULL,NULL,NULL}; + aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {NULL,NULL,NULL,NULL}; + + unsigned int p = 0; + while (pcMesh->HasTextureCoords(p)) + apvTextureCoords[p++] = new aiVector3D[iNumVerts]; + + p = 0; + while (pcMesh->HasVertexColors(p)) + apvColorSets[p++] = new aiColor4D[iNumVerts]; + + // allocate enough memory to hold output bones and vertex weights ... + std::vector* newWeights = new std::vector[pcMesh->mNumBones]; + for (unsigned int i = 0;i < pcMesh->mNumBones;++i) + { + newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3); + } + + // iterate through all faces and build a clean list + unsigned int iIndex = 0; + for (unsigned int a = 0; a< pcMesh->mNumFaces;++a) + { + aiFace* pcFace = &pcMesh->mFaces[a]; + for (unsigned int q = 0; q < 3;++q,++iIndex) + { + // need to build a clean list of bones, too + for (unsigned int i = 0;i < pcMesh->mNumBones;++i) + { + for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++) + { + const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a]; + if(pcFace->mIndices[q] == w.mVertexId) + { + aiVertexWeight wNew; + wNew.mVertexId = iIndex; + wNew.mWeight = w.mWeight; + newWeights[i].push_back(wNew); + } + } + } + + pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]]; + + if (pcMesh->HasNormals()) + { + pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]]; + } + if (pcMesh->HasTangentsAndBitangents()) + { + pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]]; + pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]]; + } + + unsigned int p = 0; + while (pcMesh->HasTextureCoords(p)) + { + apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]]; + ++p; + } + p = 0; + while (pcMesh->HasVertexColors(p)) + { + apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]]; + ++p; + } + pcFace->mIndices[q] = iIndex; + } + } + + // build output vertex weights + for (unsigned int i = 0;i < pcMesh->mNumBones;++i) + { + delete pcMesh->mBones[i]->mWeights; + if (!newWeights[i].empty()) + { + pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()]; + memcpy(pcMesh->mBones[i]->mWeights,&newWeights[i][0], + sizeof(aiVertexWeight) * newWeights[i].size()); + } + else pcMesh->mBones[i]->mWeights = NULL; + } + + // delete the old members + delete[] pcMesh->mVertices; + pcMesh->mVertices = pvPositions; + + p = 0; + while (pcMesh->HasTextureCoords(p)) + { + delete pcMesh->mTextureCoords[p]; + pcMesh->mTextureCoords[p] = apvTextureCoords[p]; + ++p; + } + p = 0; + while (pcMesh->HasVertexColors(p)) + { + delete pcMesh->mColors[p]; + pcMesh->mColors[p] = apvColorSets[p]; + ++p; + } + pcMesh->mNumVertices = iNumVerts; + + if (pcMesh->HasNormals()) + { + delete[] pcMesh->mNormals; + pcMesh->mNormals = pvNormals; + } + if (pcMesh->HasTangentsAndBitangents()) + { + delete[] pcMesh->mTangents; + pcMesh->mTangents = pvTangents; + delete[] pcMesh->mBitangents; + pcMesh->mBitangents = pvBitangents; + } + return (pcMesh->mNumVertices != iOldNumVertices); +} \ No newline at end of file diff --git a/code/MakeVerboseFormat.h b/code/MakeVerboseFormat.h new file mode 100644 index 000000000..b76a3e602 --- /dev/null +++ b/code/MakeVerboseFormat.h @@ -0,0 +1,106 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Defines a post processing step to bring a given scene + into the verbose format that is expected by most postprocess steps. + This is the inverse of the "JoinIdenticalVertices" steps */ +#ifndef AI_MAKEVERBOSEFORMAT_H_INC +#define AI_MAKEVERBOSEFORMAT_H_INC + +#include "BaseProcess.h" +#include "../include/aiMesh.h" +namespace Assimp + { + +// --------------------------------------------------------------------------- +/** MakeVerboseFormatProcess: Class to convert an asset to the verbose + * format which is expected by most postprocess steps. + * + * This is the inverse of what the "JoinIdenticalVertices" step is doing. + * This step has no official flag (since it wouldn't make sense to run it + * during import). It is intended for applications intending to modify the + * returned aiScene. After this step has been executed, they can execute + * other postprocess steps on the data. + * The step has been added because it was required by the viewer, however + * it has been moved to the main library since others might find it + * useful, too. +*/ +class MakeVerboseFormatProcess : public BaseProcess +{ + friend class Importer; + +public: + /** Constructor to be privately used by Importer, or by applications + which know what they are doing if they modify the aiScene object */ + MakeVerboseFormatProcess(); + + /** Destructor, private as well */ + ~MakeVerboseFormatProcess(); + +public: + // ------------------------------------------------------------------- + /** Returns whether the processing step is present in the given flag field. + * @param pFlags The processing flags the importer was called with. A bitwise + * combination of #aiPostProcessSteps. + * @return true if the process is present in this flag fields, false if not. + */ + bool IsActive( unsigned int pFlags) const + { + // NOTE: There is no direct flag that corresponds to + // this postprocess step. + return false; + } + + // ------------------------------------------------------------------- + /** Executes the post processing step on the given imported data. + * At the moment a process is not supposed to fail. + * @param pScene The imported data to work at. + */ + void Execute( aiScene* pScene); + + +private: + + //! Apply the postprocess step to a given submesh + bool MakeVerboseFormat (aiMesh* pcMesh); +}; +}; // end of namespace Assimp + +#endif // !!AI_KILLNORMALPROCESS_H_INC \ No newline at end of file diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index 89de99778..042de6c13 100644 --- a/code/SplitLargeMeshes.cpp +++ b/code/SplitLargeMeshes.cpp @@ -64,7 +64,7 @@ aiReturn aiSetVertexSplitLimit(unsigned int pLimit) } SplitLargeMeshesProcess_Vertex::LIMIT = pLimit; - //DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed"); + DefaultLogger::get()->debug("aiSetVertexSplitLimit() - vertex split limit was changed"); return AI_SUCCESS; } // ------------------------------------------------------------------------------------------------ @@ -77,7 +77,7 @@ aiReturn aiSetTriangleSplitLimit(unsigned int pLimit) } SplitLargeMeshesProcess_Triangle::LIMIT = pLimit; - //DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed"); + DefaultLogger::get()->debug("aiSetTriangleSplitLimit() - triangle split limit was changed"); return AI_SUCCESS; } }; //! extern "C" diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index e57edcec0..c15e3ab3f 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -570,7 +570,8 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vectorAddProperty( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours - mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + // FIX: Setup this as ambient not as emissive color + mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_AMBIENT); mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); diff --git a/code/jAssimp/JNILogger.cpp b/code/jAssimp/JNILogger.cpp new file mode 100644 index 000000000..d566e2189 --- /dev/null +++ b/code/jAssimp/JNILogger.cpp @@ -0,0 +1,134 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Implementation of the JNI API for jAssimp */ + +#if (defined ASSIMP_JNI_EXPORT) + + +// include assimp +#include "../../include/aiTypes.h" +#include "../../include/aiMesh.h" +#include "../../include/aiAnim.h" +#include "../../include/aiScene.h" +#include "../../include/aiAssert.h" +#include "../../include/aiPostProcess.h" +#include "../../include/assimp.hpp" + +#include "../DefaultLogger.h" + +#include "JNILogger.h" + +using namespace Assimp; + + +namespace Assimp { +namespace JNIBridge { + + +// ------------------------------------------------------------------------------------------------ +void JNILogDispatcher::SetJNIEnvironment(JNIEnv* ptr) +{ + // there is much error handling code in this function. + // However, it is not impossible that the jAssimp package + // loaded by the JVM is incomplete ... + + jclass java_lang_Exception = this->GetJNIEnv()->FindClass("java.lang.Exception"); + + // get a handle to the assimp.DefaultLogger class + this->m_pcJNIEnv = ptr; + if( NULL == (this->m_pcClass = this->GetJNIEnv()->FindClass("assimp.DefaultLogger"))) + { + this->GetJNIEnv()->ThrowNew(java_lang_Exception, + "Unable to get class handle to assimp.DefaultLogger"); + return; + } + // get handles to the logging functions + if( NULL == (this->m_pcMethodError = this->GetJNIEnv()->GetStaticMethodID( + this->m_pcClass,"_NativeCallWriteError","(Ljava/lang/String;)V"))) + { + this->GetJNIEnv()->ThrowNew(java_lang_Exception, + "Unable to get class handle to assimp.DefaultLogger._NativeCallWriteError()"); + return; + } + if( NULL == (this->m_pcMethodWarn = this->GetJNIEnv()->GetStaticMethodID( + this->m_pcClass,"_NativeCallWriteWarn","(Ljava/lang/String;)V"))) + { + this->GetJNIEnv()->ThrowNew(java_lang_Exception, + "Unable to get class handle to assimp.DefaultLogger._NativeCallWriteWarn()"); + return; + } + if( NULL == (this->m_pcMethodInfo = this->GetJNIEnv()->GetStaticMethodID( + this->m_pcClass,"_NativeCallWriteInfo","(Ljava/lang/String;)V"))) + { + this->GetJNIEnv()->ThrowNew(java_lang_Exception, + "Unable to get class handle to assimp.DefaultLogger._NativeCallWriteInfo()"); + return; + } + if( NULL == (this->m_pcMethodDebug = this->GetJNIEnv()->GetStaticMethodID( + this->m_pcClass,"_NativeCallWriteDebug","(Ljava/lang/String;)V"))) + { + this->GetJNIEnv()->ThrowNew(java_lang_Exception, + "Unable to get class handle to assimp.DefaultLogger._NativeCallWriteDebug()"); + } +} +// ------------------------------------------------------------------------------------------------ +void JNILogDispatcher::debug(const std::string &message) +{ + +} +// ------------------------------------------------------------------------------------------------ +void JNILogDispatcher::info(const std::string &message) +{ +} +// ------------------------------------------------------------------------------------------------ +void JNILogDispatcher::warn(const std::string &message) +{ +} +// ------------------------------------------------------------------------------------------------ +void JNILogDispatcher::error(const std::string &message) +{ +} + + +};}; + +#endif // jni \ No newline at end of file diff --git a/code/jAssimp/JNILogger.h b/code/jAssimp/JNILogger.h new file mode 100644 index 000000000..c04e25dc1 --- /dev/null +++ b/code/jAssimp/JNILogger.h @@ -0,0 +1,122 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#if (!defined AI_JNILOGGER_H_INCLUDED) +#define AI_JNILOGGER_H_INCLUDED + + +#include "../../include/Logger.h" +#include + +#include + +namespace Assimp { +namespace JNIBridge { + +// --------------------------------------------------------------------------- +class IOStream; +struct LogStreamInfo; + + +// --------------------------------------------------------------------------- +/** @class JNILogDispatcher + * @brief Logging system implementation that is used to send all + * log messages generated by native code to the Java logging system. + */ +class JNILogDispatcher : public Logger +{ +public: + /** @brief Logs a debug message */ + void debug(const std::string &message); + + /** @brief Logs an info message */ + void info(const std::string &message); + + /** @brief Logs a warning message */ + void warn(const std::string &message); + + /** @brief Logs an error message */ + void error(const std::string &message); + + /** @brief Log severity setter */ + void setLogSeverity(LogSeverity log_severity) {} + + /** @brief Detach a still attached stream from logger */ + void attachStream(LogStream *pStream, unsigned int severity) {} + + /** @brief Detach a still attached stream from logger */ + void detatchStream(LogStream *pStream, unsigned int severity) {} + + //! Setup the JNI environment to use + //! (must be attached to the thread) + //! \param ptr Java environment to be used. != 0 + void SetJNIEnvironment(JNIEnv* ptr); + + //! Get the current JNI environment + inline JNIEnv* GetJNIEnv() + { + ai_assert(NULL != m_pcJNIEnv); + return m_pcJNIEnv; + } + +private: + + //! JNI environment pointer + JNIEnv* m_pcJNIEnv; + + //! Handle to assimp.DefaultLogger class + jclass m_pcClass; + + //! Handle to the static assimp.DefaultLogger._NativeCallWriteError() method + jmethodID m_pcMethodError; + + //! Handle to the static assimp.DefaultLogger._NativeCallWriteInfo() method + jmethodID m_pcMethodInfo; + + //! Handle to the static assimp.DefaultLogger._NativeCallWriteDebug() method + jmethodID m_pcMethodDebug; + + //! Handle to the static assimp.DefaultLogger._NativeCallWriteWarn() method + jmethodID m_pcMethodWarn; +}; + +};}; + +#endif // AI_JNILOGGER_H_INCLUDED \ No newline at end of file diff --git a/include/aiMaterial.h b/include/aiMaterial.h index 64e3889ef..09aacb994 100644 --- a/include/aiMaterial.h +++ b/include/aiMaterial.h @@ -269,9 +269,15 @@ public: /** @def AI_MATKEY_SHININESS * Defines the base shininess of the material +* This is the exponent of the phong shading equation. */ #define AI_MATKEY_SHININESS "$mat.shininess" +/** @def AI_MATKEY_SHININESS_STRENGTH +* Defines the strength of the specular highlight. +*/ +#define AI_MATKEY_SHININESS_STRENGTH "$mat.shinpercent" + /** @def AI_MATKEY_COLOR_DIFFUSE * Defines the diffuse base color of the material */ diff --git a/port/jAssimp/src/assimp/Animation.java b/port/jAssimp/src/assimp/Animation.java index b932c62e5..2328b0da0 100644 --- a/port/jAssimp/src/assimp/Animation.java +++ b/port/jAssimp/src/assimp/Animation.java @@ -50,7 +50,7 @@ package assimp; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Animation extends IMappable { +public class Animation extends Mappable { /** * Construction from a given object and array index * diff --git a/port/jAssimp/src/assimp/CompressedTexture.java b/port/jAssimp/src/assimp/CompressedTexture.java new file mode 100644 index 000000000..36e05779c --- /dev/null +++ b/port/jAssimp/src/assimp/CompressedTexture.java @@ -0,0 +1,135 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp; + +import java.awt.*; + +/** + * Represents an embedded compressed texture that is stored in a format + * like JPEG or PNG. See the documentation of Texture + * for more details on this class. Use instanceof to + * determine whether a particular Texture in the list + * returned by Scene.getTextures() is a compressed texture. + *

+ * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class CompressedTexture extends Texture { + + private String m_format = ""; + private byte[] m_data; + private int m_length = 0; + + + /** + * Construction from a given parent object and array index + * + * @param parent Must be valid, null is not allowed + * @param index Valied index in the parent's list + */ + public CompressedTexture(Object parent, int index) throws NativeError { + super(parent, index); + } + + /** + * Retrieves the format of the texture data. This is + * the most common file extension of the format (without a + * dot at the beginning). Examples include dds, png, jpg ... + * @return Extension string or null if the format of the texture + * data is not known to ASSIMP. + */ + public String getFormat() { + return m_format; + } + + public byte[] getData() { + return m_data; + } + + /** + * Retrieve the height of the texture image + * + * @return Height, in pixels + */ + public int getHeight() { + DefaultLogger.get() + return height; + } + + /** + * Retrieve the width of the texture image + * + * @return Width, in pixels + */ + public int getWidth() { + return width; + } + + /** + * Internal helper function to map the native texture data into + * a byte array in the memory of the JVM + */ + @Override + protected void OnMap() throws NativeError { + + // first allocate the output array + data = new Color[iNumPixels]; + + // now allocate a temporary output array + byte[] temp = new byte[(iNumPixels) << 2]; + + // and copy the native color data to it + if (0xffffffff == this._NativeMapColorData(((Scene)this.getParent()).getImporter().getContext(), + this.getArrayIndex(),temp)) { + throw new NativeError("Unable to map aiTexture into the Java-VM"); + } + + // now convert the temporary representation to a Color array + // (data is given in BGRA order, we need RGBA) + for (int i = 0, iBase = 0; i < iNumPixels; ++i, iBase += 4) { + data[i] = new Color(temp[iBase + 2], temp[iBase + 1], temp[iBase], temp[iBase + 3]); + } + return; + } +} diff --git a/port/jAssimp/src/assimp/DefaultLogger.java b/port/jAssimp/src/assimp/DefaultLogger.java new file mode 100644 index 000000000..847c3f47f --- /dev/null +++ b/port/jAssimp/src/assimp/DefaultLogger.java @@ -0,0 +1,403 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp; + +import java.util.Vector; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Default implementation of a logger. When writing to the log, + * jASSIMP uses the Logger instance returned by + * DefaultLogger.get() + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public class DefaultLogger implements Logger { + + + /** + * Helper class to combine a logstream with an error severity + */ + private static class LogStreamInfo { + public LogStream stream; + public int severity; + + public LogStreamInfo(LogStream stream, int severity) { + this.stream = stream; + this.severity = severity; + } + } + + /** + * NULL logger class. Does nothing ... + */ + private static class NullLogger implements Logger { + + + public void debug(String message) { + } // nothing to do here ... + + + public void error(String message) { + } // nothing to do here ... + + + public void warn(String message) { + } // nothing to do here ... + + + public void info(String message) { + } // nothing to do here ... + + + public void attachStream(LogStream stream, int severity) { + } // nothing to do here ... + + + public void detachStream(LogStream stream, int severity) { + } // nothing to do here ... + } + + + /** + * Implementation of LogStream that can be used to use a + * java.io.OutputStream object directly as log stream. + */ + public static class StreamWrapper implements LogStream { + + private OutputStream stream; + + /** + * Construction from an existing java.io.OutputStream object + * + * @param stream May not be null + */ + public StreamWrapper(OutputStream stream) { + assert(null != stream); + this.stream = stream; + } + + public void write(String message) { + try { + stream.write(message.getBytes(), 0, message.length()); + } catch (IOException e) { + // .... should't care + } + } + + public OutputStream getStream() { + return stream; + } + } + + /** + * Implementation of LogStream that can be used to use a + * java.io.FileWriter object directly as log stream. + */ + public static class FileStreamWrapper implements LogStream { + + private FileWriter stream; + + /** + * Construction from an existing java.io.FileWriter object + * + * @param stream May not be null + */ + public FileStreamWrapper(FileWriter stream) { + assert(null != stream); + this.stream = stream; + } + + public void write(String message) { + try { + stream.write(message); + } catch (IOException e) { + // .... should't care + } + } + + public FileWriter getStream() { + return stream; + } + } + + + /** + * Normal granlality of logging + */ + public static final int LOGSEVERITY_NORMAL = 0x0; + + /** + * Debug infos will be logged, too + */ + public static final int LOGSEVERITY_VERBOSE = 0x1; + + /** + * Default logger. It does nothing and is used if the + * application hasn't allocated a default logger + */ + private static NullLogger s_nullLogger = new NullLogger(); + + /** + * The logger that is used by ASSIMP for logging + */ + private static Logger s_logger = s_nullLogger; + + /** + * List of logstreams to output to + */ + private Vector m_avStreams; + + /** + * One of the LOGSEVERITY_XXX constants. + */ + private int m_iLogSeverity = LOGSEVERITY_NORMAL; + + + private DefaultLogger() { + } + + + /** + * Create the default logger + * + * @param file Output log file. If != null this will + * automatically add a file log stream to the logger + * @param bErrOut If this is true an additional logstream which + * outputs all log messages via System.err.println() + * will be added to the logger. + */ + public static void create(String file, boolean bErrOut) throws IOException { + + s_logger = new DefaultLogger(); + + if (null != file) { + FileWriter stream = new FileWriter(file); + s_logger.attachStream(new FileStreamWrapper(stream), 0); + } + if (bErrOut) { + s_logger.attachStream(new StreamWrapper(System.err), 0); + } + } + + /** + * Create the default logger, no default log streams will be + * attached to it. + */ + public static void create() throws IOException { + create(null, false); + } + + /** + * Supply your own implementation of Logger to the + * logging system. Use this if you want to override the default + * formatting behaviour of DefaultLogger. You can + * access your logger as normal, via get(). + * + * @param logger + */ + public static void set(Logger logger) { + s_logger = logger; + } + + /** + * Kill the logger ... a null logger will be used instead + */ + public static void kill() { + s_logger = s_nullLogger; + } + + /** + * Get access to the Singleton instance of the logger. This will + * never be null. If no logger has been explicitly created via + * create() this is a NULLLogger instance. + * Use isNullLogger() to check whether the returned logger + * is a null logger. + * + * @return Never null ... + */ + public static Logger get() { + return s_logger; + } + + + /** + * Check whether the current logger is a null logger, which + * doesn't log anything. Use create() or set() + * to setup another logger. + * + * @return true if the curent logger is a null logger (true by default) + */ + public static boolean isNullLogger() { + return (s_logger instanceof NullLogger); + } + + + /** + * Write a debug message to the log + * + * @param message Message to be logged + */ + public void debug(String message) { + this.writeToStreams("Debug:" + message + "\n", ERRORSEVERITY_DEBUGGING); + } + + /** + * Write an error message to the log + * + * @param message Message to be logged + */ + public void error(String message) { + this.writeToStreams("Debug:" + message + "\n", ERRORSEVERITY_ERR); + } + + /** + * Write a warn message to the log + * + * @param message Message to be logged + */ + public void warn(String message) { + this.writeToStreams("Debug:" + message + "\n", ERRORSEVERITY_WARN); + } + + /** + * Write an info message to the log + * + * @param message Message to be logged + */ + public void info(String message) { + this.writeToStreams("Debug:" + message + "\n", ERRORSEVERITY_INFO); + } + + /** + * Attach a logstream to the logger + * + * @param stream Log stream instance + * @param severity Error severity. Bitwise combination of the + * ERRORSEVERITY_XXX constants. Specify 0 to attach the + * stream to all types of log messages. + */ + public void attachStream(LogStream stream, int severity) { + + if (0 == severity) { + severity = ERRORSEVERITY_DEBUGGING | ERRORSEVERITY_WARN | + ERRORSEVERITY_ERR | ERRORSEVERITY_INFO; + } + + for (LogStreamInfo info : this.m_avStreams) { + + if (info.stream != stream) continue; + info.severity |= severity; + severity = 0xcdcdcdcd; + } + if (0xcdcdcdcd != severity) + this.m_avStreams.add(new LogStreamInfo(stream, severity)); + } + + /** + * Detach a logstream from the logger + * + * @param stream Log stream instance + * @param severity Error severities to detach the stream from. + * Bitwise combination of the ERRORSEVERITY_XXX constants. + * Specify 0 to detach the stream from all types of log messages. + */ + public void detachStream(LogStream stream, int severity) { + + if (0 == severity) { + severity = ERRORSEVERITY_DEBUGGING | ERRORSEVERITY_WARN | + ERRORSEVERITY_ERR | ERRORSEVERITY_INFO; + } + + for (LogStreamInfo info : this.m_avStreams) { + + if (info.stream != stream) continue; + + if (0 != (severity & ERRORSEVERITY_DEBUGGING)) { + info.severity &= (~ERRORSEVERITY_DEBUGGING); + } + if (0 != (severity & ERRORSEVERITY_ERR)) { + info.severity &= (~ERRORSEVERITY_ERR); + } + if (0 != (severity & ERRORSEVERITY_INFO)) { + info.severity &= (~ERRORSEVERITY_INFO); + } + if (0 != (severity & ERRORSEVERITY_WARN)) { + info.severity &= (~ERRORSEVERITY_WARN); + } + if (0 == info.severity) { + this.m_avStreams.remove(info); + } + break; + } + } + + private void writeToStreams(String message, int severity) { + + for (LogStreamInfo info : this.m_avStreams) { + + if (0 == (info.severity & severity)) continue; + + info.stream.write(message); + } + } + + // Helpers to make the access to the logging system easier + // for native code + public static void _NativeCallWriteError(String message) { + DefaultLogger.get().error(message); + } + public static void _NativeCallWriteWarn(String message) { + DefaultLogger.get().warn(message); + } + public static void _NativeCallWriteInfo(String message) { + DefaultLogger.get().info(message); + } + public static void _NativeCallWriteDebug(String message) { + DefaultLogger.get().debug(message); + } + +} diff --git a/port/jAssimp/src/assimp/LogStream.java b/port/jAssimp/src/assimp/LogStream.java new file mode 100644 index 000000000..21d18c442 --- /dev/null +++ b/port/jAssimp/src/assimp/LogStream.java @@ -0,0 +1,62 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp; + +/** + * Output stream for the logger. Directly corresponding with the native + * LoggStream interface + *
+ * For direct output to a java.io.Stream you can use the + * DefaultLogStream class. + * + * @author Aramis (Alexander Gessler) + * @version 1.0 + */ +public interface LogStream { + + /** + * Override this for your own output implementations + * @param message Message to be written to the log stream + */ + public void write(String message); +} diff --git a/port/jAssimp/src/assimp/Logger.java b/port/jAssimp/src/assimp/Logger.java index 8650ab38a..b2e4e363c 100644 --- a/port/jAssimp/src/assimp/Logger.java +++ b/port/jAssimp/src/assimp/Logger.java @@ -1,11 +1,116 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + package assimp; /** - * Created by IntelliJ IDEA. - * User: Alex - * Date: 21.05.2008 - * Time: 19:31:28 - * To change this template use File | Settings | File Templates. + * Base logging interface. Directly corresponding with the native + * Logger interface + * + * @author Aramis (Alexander Gessler) + * @version 1.0 */ public interface Logger { + + /** + * Debug log message + */ + public static final int ERRORSEVERITY_DEBUGGING = 0x1; + + /** + * Information log message + */ + public static final int ERRORSEVERITY_INFO = 0x2; + + /** + * Warn log message + */ + public static final int ERRORSEVERITY_WARN = 0x4; + + /** + * Error log message + */ + public static final int ERRORSEVERITY_ERR = 0x8; + + + /** + * Write a debug message to the log + * @param message Message to be logged + */ + public void debug(String message); + + /** + * Write an error message to the log + * @param message Message to be logged + */ + public void error(String message); + + /** + * Write a warn message to the log + * @param message Message to be logged + */ + public void warn(String message); + + /** + * Write an info message to the log + * @param message Message to be logged + */ + public void info(String message); + + /** + * Attach a logstream to the logger + * @param stream Log stream instance + * @param severity Error severity. Bitwise combination of the + * ERRORSEVERITY_XXX constants. Specify 0 to attach the + * stream to all types of log messages. + */ + public void attachStream(LogStream stream, int severity); + + /** + * Detach a logstream from the logger + * @param stream Log stream instance + * @param severity Error severities to detach the stream from. + * Bitwise combination of the ERRORSEVERITY_XXX constants. + * Specify 0 to detach the stream from all types of log messages. + */ + public void detachStream(LogStream stream, int severity); } diff --git a/port/jAssimp/src/assimp/IMappable.java b/port/jAssimp/src/assimp/Mappable.java similarity index 100% rename from port/jAssimp/src/assimp/IMappable.java rename to port/jAssimp/src/assimp/Mappable.java diff --git a/port/jAssimp/src/assimp/Material.java b/port/jAssimp/src/assimp/Material.java index a783ec9fe..811e2a1f5 100644 --- a/port/jAssimp/src/assimp/Material.java +++ b/port/jAssimp/src/assimp/Material.java @@ -51,7 +51,7 @@ package assimp; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Material extends IMappable { +public class Material extends Mappable { /** * Construction from a given parent object and array index * diff --git a/port/jAssimp/src/assimp/Mesh.java b/port/jAssimp/src/assimp/Mesh.java index 50340128e..1be19f052 100644 --- a/port/jAssimp/src/assimp/Mesh.java +++ b/port/jAssimp/src/assimp/Mesh.java @@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package assimp; -import java.lang.ref.Reference; import java.awt.*; @@ -61,7 +60,7 @@ import java.awt.*; * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Mesh extends IMappable { +public class Mesh extends Mappable { /** * Defines the maximum number of UV(W) channels that are available diff --git a/port/jAssimp/src/assimp/Texture.java b/port/jAssimp/src/assimp/Texture.java index dd5453380..015bc68b0 100644 --- a/port/jAssimp/src/assimp/Texture.java +++ b/port/jAssimp/src/assimp/Texture.java @@ -50,18 +50,18 @@ import java.awt.*; * Example file formats doing this include MDL3, MDL5 and MDL7 (3D GameStudio). * Embedded textures are converted to an array of color values (RGBA). *

- * Embedded textures in compressed file formats, such as JPEG or DDS - * are NOT supported by jAssimp. + * Compressed textures (textures that are stored in a format like png or jpg) + * are represented by the class. * * @author Aramis (Alexander Gessler) * @version 1.0 */ -public class Texture extends IMappable { +public class Texture extends Mappable { - private int width = 0; - private int height = 0; + protected int width = 0; + protected int height = 0; - private Color[] data = null; + protected Color[] data = null; /** * Construction from a given parent object and array index diff --git a/port/jAssimp/src/assimp/test/DumpToFile.java b/port/jAssimp/src/assimp/test/DumpToFile.java new file mode 100644 index 000000000..3a01db3b7 --- /dev/null +++ b/port/jAssimp/src/assimp/test/DumpToFile.java @@ -0,0 +1,183 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (ASSIMP) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2008, ASSIMP Development Team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the ASSIMP team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the ASSIMP Development Team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + + +package assimp.test; + +import assimp.*; + + +import java.io.FileWriter; +import java.io.IOException; + + +/** + * Example class to demonstrate how to use jAssimp to load an asset from + * a file. The Main() method expects two parameters, the first being + * the path to the file to be opened, the second being the output path. + * The class writes a text file with the asset data inside. + */ +public class DumpToFile { + + public static void Main(String[] arguments) throws IOException { + + /* Use output.txt as default output file if none was specified + * However, at least one parameter is expected + */ + if (1 == arguments.length) { + String s = arguments[0]; + arguments = new String[2]; + arguments[0] = s; + arguments[1] = "output.txt"; + } + else if (2 != arguments.length)return; + + FileWriter stream; + try { + stream = new FileWriter(arguments[1]); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Unable to open output file"); + throw e; + } + + /* Try to create an instance of class assimp.Importer. + * The constructor throws an assimp.NativeError exception + * if the native jAssimp library is not available.It must + * be placed in the jar/class directory of the application + */ + Importer imp; + try { + imp = new Importer(); + } catch (NativeError nativeError) { + nativeError.printStackTrace(); + System.out.println("NativeError exception [#1]: " + nativeError.getMessage()); + return; + } + + /* Now setup the correct postprocess steps. Triangulation is + * automatically performed, DX conversion is not necessary, + * However, a few steps are normally useful. Especially + * JoinVertices since it will dramantically reduce the size + * of the output file + */ + imp.addPostProcessStep(PostProcessStep.CalcTangentSpace); + imp.addPostProcessStep(PostProcessStep.GenSmoothNormals); + imp.addPostProcessStep(PostProcessStep.JoinIdenticalVertices); + + /* Load the asset into memory. Again, a NativeError exception + * could be thrown if an unexpected errors occurs in the + * native interface. If assimp is just unable to load the asset + * null is the return value and no exception is thrown + */ + Scene scene; + try { + scene = imp.readFile(arguments[0]); + } catch (NativeError nativeError) { + nativeError.printStackTrace(); + System.out.println("NativeError exception [#2] :" + nativeError.getMessage()); + return; + } + if (null == scene) { + System.out.println("Unable to load asset: " + arguments[0]); + return; + } + + /* Now iterate through all meshes that have been loaded + */ + int iMesh = 0; + for (Mesh mesh : scene.getMeshes()) { + + stream.write("Mesh " + iMesh + "\n"); + stream.write("\tNum Vertices: " + mesh.getNumVertices() + "\n"); + stream.write("\tNum Faces: " + mesh.getNumFaces() + "\n"); + stream.write("\tNum Bones: " + mesh.getNumBones() + "\n\n"); + + /* Output all vertices. First get direct access to jAssimp's buffers + * UV coords and colors could also be there, but we don't output them + * at the moment! + */ + float[] positions = mesh.getPositionArray(); + float[] normals = mesh.getNormalArray(); + float[] tangents = mesh.getTangentArray(); + float[] bitangents = mesh.getBitangentArray(); + for (int i = 0;i < mesh.getNumVertices();++i) { + + // format: "Vertex pos(x|y|z) nor(x|y|z) tan(x|y|) bit(x|y|z)" + // great that this IDE is automatically able to replace + with append ... ;-) + stream.write(new StringBuilder(). + append("\tVertex: pos("). + append(positions[i * 3]).append("|"). + append(positions[i * 3 + 1]).append("|"). + append(positions[i * 3 + 2]).append(")\t"). + append("nor("). + append(normals[i * 3]).append("|"). + append(normals[i * 3 + 1]).append("|"). + append(normals[i * 3 + 2]).append(")\t"). + append("tan("). + append(tangents[i * 3]).append("|"). + append(tangents[i * 3 + 1]).append("|"). + append(tangents[i * 3 + 2]).append(")\t"). + append("bit("). + append(bitangents[i * 3]).append("|"). + append(bitangents[i * 3 + 1]).append("|"). + append(bitangents[i * 3 + 2]).append(")\n").toString()); + + } + stream.write("\n\n"); + + /* Now write a list of all faces in this model + */ + int[] faces = mesh.getFaceArray(); + for (int i = 0; i < mesh.getNumFaces();++i) { + stream.write(new StringBuilder().append("\tFace ("). + append(faces[i * 3]).append("|"). + append(faces[i * 3 + 1]).append("|"). + append(faces[i * 3 + 2]).append(")\n").toString()); + } + + ++iMesh; + } + + + stream.close(); + } +} diff --git a/tools/assimp_view/AssetHelper.h b/tools/assimp_view/AssetHelper.h index cc815d036..2e80881e5 100644 --- a/tools/assimp_view/AssetHelper.h +++ b/tools/assimp_view/AssetHelper.h @@ -178,6 +178,9 @@ class AssetHelper // shininess for the material float fShininess; + // strength of the specular highlight + float fSpecularStrength; + // Stores a pointer to the original normal set of the asset aiVector3D* pvOriginalNormals; }; diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index e3ca984de..9d2b608e1 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -235,7 +235,6 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex]; // update all meshes referencing this material - this->m_pcCurrentTexture->piTexture = piTexture; for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { if (this->m_pcCurrentTexture->iMatIndex != g_pcAsset->pcScene->mMeshes[i]->mMaterialIndex) @@ -249,6 +248,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piDiffuseTexture->Release(); pcMesh->piDiffuseTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piDiffuseTexture; if (!pcMesh->bSharedFX) { @@ -261,6 +261,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piAmbientTexture->Release(); pcMesh->piAmbientTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piAmbientTexture; if (!pcMesh->bSharedFX) { @@ -273,6 +274,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piSpecularTexture->Release(); pcMesh->piSpecularTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piSpecularTexture; if (!pcMesh->bSharedFX) { @@ -285,6 +287,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piEmissiveTexture->Release(); pcMesh->piEmissiveTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piEmissiveTexture; if (!pcMesh->bSharedFX) { @@ -297,6 +300,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piShininessTexture->Release(); pcMesh->piShininessTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piShininessTexture; if (!pcMesh->bSharedFX) { @@ -310,6 +314,9 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piNormalTexture->Release(); pcMesh->piNormalTexture = piTexture; + CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture, + &pcMesh->piNormalTexture,true); + this->m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture; if (!pcMesh->bSharedFX) { @@ -322,6 +329,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath) { pcMesh->piOpacityTexture->Release(); pcMesh->piOpacityTexture = piTexture; + this->m_pcCurrentTexture->piTexture = &pcMesh->piOpacityTexture; if (!pcMesh->bSharedFX) { @@ -414,32 +422,32 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType, bool bIsExtraOpacity = 0 != (iType & 0x40000000); const char* szType; - IDirect3DTexture9* piTexture; + IDirect3DTexture9** piTexture; switch (iType) { case AI_TEXTYPE_DIFFUSE: - piTexture = g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piDiffuseTexture; szType = "Diffuse";break; case AI_TEXTYPE_SPECULAR: - piTexture = g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piSpecularTexture; szType = "Specular";break; case AI_TEXTYPE_AMBIENT: - piTexture = g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piAmbientTexture; szType = "Ambient";break; case AI_TEXTYPE_EMISSIVE: - piTexture = g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piEmissiveTexture; szType = "Emissive";break; case AI_TEXTYPE_HEIGHT: - piTexture = g_pcAsset->apcMeshes[iMesh]->piNormalTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; szType = "HeightMap";break; case AI_TEXTYPE_NORMALS: - piTexture = g_pcAsset->apcMeshes[iMesh]->piNormalTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piNormalTexture; szType = "NormalMap";break; case AI_TEXTYPE_SHININESS: - piTexture = g_pcAsset->apcMeshes[iMesh]->piShininessTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piShininessTexture; szType = "Shininess";break; default: // opacity + opacity | mask - piTexture = g_pcAsset->apcMeshes[iMesh]->piOpacityTexture; + piTexture = &g_pcAsset->apcMeshes[iMesh]->piOpacityTexture; szType = "Opacity";break; }; if (bIsExtraOpacity) @@ -466,7 +474,7 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType, uint32_t iData = 0; DWORD dwSize = 4; - piTexture->GetPrivateData(guidPrivateData,&iData,&dwSize); + (*piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize); if (0xFFFFFFFF == iData) { @@ -583,13 +591,27 @@ int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot, } } - AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iIndex]; + AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[iMesh]; + if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture == pcMesh->piOpacityTexture && bNoOpacity) { - // seems the diffuse texture contains alpha, therefore it has been - // added to the opacity channel, too. Add a special value ... - AddTextureToDisplayList(AI_TEXTYPE_OPACITY | 0x40000000, - 0,&szPath,hTexture,iUV,fBlend,eOp,iMesh); + // check whether the diffuse texture is not a default texture + + // {9785DA94-1D96-426b-B3CB-BADC36347F5E} + static const GUID guidPrivateData = + { 0x9785da94, 0x1d96, 0x426b, + { 0xb3, 0xcb, 0xba, 0xdc, 0x36, 0x34, 0x7f, 0x5e } }; + + uint32_t iData = 0; + DWORD dwSize = 4; + if(FAILED( pcMesh->piDiffuseTexture->GetPrivateData(guidPrivateData,&iData,&dwSize) || + 0xffffffff == iData)) + { + // seems the diffuse texture contains alpha, therefore it has been + // added to the opacity channel, too. Add a special value ... + AddTextureToDisplayList(AI_TEXTYPE_OPACITY | 0x40000000, + 0,&szPath,hTexture,iUV,fBlend,eOp,iMesh); + } } // add the material to the list @@ -785,6 +807,17 @@ int CDisplay::Reset(void) return this->OnSetupNormalView(); } //------------------------------------------------------------------------------- +void UpdateColorFieldsInUI() +{ + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); + InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); + + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); + UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); +} +//------------------------------------------------------------------------------- int CDisplay::OnSetupNormalView() { // now ... change the meaning of the statistics fields back @@ -804,6 +837,8 @@ int CDisplay::OnSetupNormalView() this->m_pcCurrentTexture = NULL; this->m_pcCurrentNode = NULL; + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); UpdateWindow(g_hDlg); return 1; } @@ -829,6 +864,10 @@ int CDisplay::OnSetupMaterialView(MaterialInfo* pcNew) this->m_pcCurrentMaterial = pcNew; this->SetViewMode(VIEWMODE_MATERIAL); + + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); + UpdateWindow(g_hDlg); return 1; } //------------------------------------------------------------------------------- @@ -846,6 +885,14 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) "diffuse texture",D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0)); } + // check whether the pattern background effect is supported + if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0)) + { + CLogDisplay::Instance().AddEntry("[WARN] The background shader won't work " + "on your system, it required PS 3.0 hardware. A default color is used ...", + D3DCOLOR_ARGB(0xFF,0xFF,0x00,0)); + } + this->m_fTextureZoom = 1000.0f; this->m_vTextureOffset.x = this->m_vTextureOffset.y = 0.0f; @@ -863,7 +910,7 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) // and fill them with data D3DSURFACE_DESC sDesc; - pcNew->piTexture->GetLevelDesc(0,&sDesc); + (*pcNew->piTexture)->GetLevelDesc(0,&sDesc); char szTemp[128]; sprintf(szTemp,"%i",sDesc.Width); @@ -872,7 +919,7 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) sprintf(szTemp,"%i",sDesc.Height); SetWindowText(GetDlgItem(g_hDlg,IDC_ENODEWND),szTemp); - sprintf(szTemp,"%i",pcNew->piTexture->GetLevelCount()); + sprintf(szTemp,"%i",(*pcNew->piTexture)->GetLevelCount()); SetWindowText(GetDlgItem(g_hDlg,IDC_ESHADER),szTemp); sprintf(szTemp,"%i",pcNew->iUV); @@ -899,7 +946,7 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) SetWindowText(GetDlgItem(g_hDlg,IDC_ELOAD),szOp); // NOTE: Format is always ARGB8888 since other formats are - // convert to this format ... + // converted to this format ... SetWindowText(GetDlgItem(g_hDlg,IDC_EFACE),"ARGB8"); // check whether this is the default texture @@ -912,7 +959,7 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) uint32_t iData = 0; DWORD dwSize = 4; - pcNew->piTexture->GetPrivateData(guidPrivateData,&iData,&dwSize); + (*pcNew->piTexture)->GetPrivateData(guidPrivateData,&iData,&dwSize); if (0xFFFFFFFF == iData) { @@ -922,6 +969,8 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew) return 0; } } + // redraw the color fields in the UI --- their purpose has possibly changed + UpdateColorFieldsInUI(); UpdateWindow(g_hDlg); return 1; } @@ -1047,14 +1096,6 @@ int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem) return 1; } //------------------------------------------------------------------------------- -template -type clamp(intype in) -{ - // for unsigned types only ... - intype mask = (0x1u << (sizeof(type)*8))-1; - return (type)std::max((intype)0,std::min(in,mask)); -} -//------------------------------------------------------------------------------- int CDisplay::HandleTreeViewPopup(WPARAM wParam,LPARAM lParam) { // get the current selected material @@ -1259,7 +1300,7 @@ int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam) // get a pointer to the first surface of the current texture IDirect3DSurface9* pi = NULL; - this->m_pcCurrentTexture->piTexture->GetSurfaceLevel(0,&pi); + (*this->m_pcCurrentTexture->piTexture)->GetSurfaceLevel(0,&pi); if(!pi || FAILED(D3DXSaveSurfaceToFile(szFileName,eFormat,pi,NULL,NULL))) { CLogDisplay::Instance().AddEntry("[ERROR] Unable to export texture", @@ -1880,39 +1921,52 @@ int CDisplay::RenderPatternBG() { if (!g_piPatternEffect) { - // seems we have not yet compiled this shader. - // and NOW is the best time to do that ... - ID3DXBuffer* piBuffer = NULL; - if(FAILED( D3DXCreateEffect(g_piDevice, - g_szCheckerBackgroundShader.c_str(), - (UINT)g_szCheckerBackgroundShader.length(), - NULL, - NULL, - D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, - NULL, - &g_piPatternEffect,&piBuffer))) + // the pattern effect won't work on ps_2_0 cards + if (g_sCaps.PixelShaderVersion >= D3DPS_VERSION(3,0)) { + // seems we have not yet compiled this shader. + // and NOW is the best time to do that ... + ID3DXBuffer* piBuffer = NULL; + if(FAILED( D3DXCreateEffect(g_piDevice, + g_szCheckerBackgroundShader.c_str(), + (UINT)g_szCheckerBackgroundShader.length(), + NULL, + NULL, + D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, + NULL, + &g_piPatternEffect,&piBuffer))) + { + if( piBuffer) + { + MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); + piBuffer->Release(); + } + return 0; + } if( piBuffer) { - MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); + piBuffer = NULL; } - return 0; } - if( piBuffer) + else { - piBuffer->Release(); - piBuffer = NULL; + // clear the color buffer in magenta + // (hopefully this is ugly enough that every ps_2_0 cards owner + // runs to the next shop to buy himself a new card ...) + g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, + D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); + return 1; } } - // clear the color buffer in magenta - g_piDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, + + // clear the depth buffer only + g_piDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0xFF,0xFF,0,0xFF), 1.0f,0 ); - if (!g_piPatternEffect) - { - return 0; - } + // setup the colors to be used ... + g_piPatternEffect->SetVector("COLOR_ONE",&this->m_avCheckerColors[0]); + g_piPatternEffect->SetVector("COLOR_TWO",&this->m_avCheckerColors[1]); // setup the shader UINT dw; @@ -1990,7 +2044,7 @@ int CDisplay::RenderTextureView() sRect.bottom -= sRect.top; // commit the texture to the shader - g_piPassThroughEffect->SetTexture("TEXTURE_2D",this->m_pcCurrentTexture->piTexture); + g_piPassThroughEffect->SetTexture("TEXTURE_2D",*this->m_pcCurrentTexture->piTexture); if (AI_TEXTYPE_OPACITY == this->m_pcCurrentTexture->iType) { @@ -2016,7 +2070,7 @@ int CDisplay::RenderTextureView() // build a rectangle which centers the texture // scaling is OK, but no stretching D3DSURFACE_DESC sDesc; - this->m_pcCurrentTexture->piTexture->GetLevelDesc(0,&sDesc); + (*this->m_pcCurrentTexture->piTexture)->GetLevelDesc(0,&sDesc); struct SVertex{float x,y,z,w,u,v;}; SVertex as[4]; diff --git a/tools/assimp_view/Display.h b/tools/assimp_view/Display.h index e8eea94a5..a254450ff 100644 --- a/tools/assimp_view/Display.h +++ b/tools/assimp_view/Display.h @@ -85,6 +85,9 @@ private: this->m_aiImageList[2] = 2; this->m_aiImageList[3] = 3; this->m_aiImageList[4] = 4; + + this->m_avCheckerColors[0].x = this->m_avCheckerColors[0].y = this->m_avCheckerColors[0].z = 0.4f; + this->m_avCheckerColors[0].x = this->m_avCheckerColors[1].y = this->m_avCheckerColors[2].z = 0.6f; } public: @@ -112,7 +115,7 @@ public: struct TextureInfo { // texture info - IDirect3DTexture9* piTexture; + IDirect3DTexture9** piTexture; // Blend factor of the texture float fBlend; @@ -350,6 +353,34 @@ public: this->m_asMaterials.push_back(info); } + //------------------------------------------------------------------ + // set the primary color of the checker pattern background + inline void SetFirstCheckerColor(D3DXVECTOR4 c) + { + this->m_avCheckerColors[0] = c; + } + + //------------------------------------------------------------------ + // set the secondary color of the checker pattern background + inline void SetSecondCheckerColor(D3DXVECTOR4 c) + { + this->m_avCheckerColors[1] = c; + } + + //------------------------------------------------------------------ + // get the primary color of the checker pattern background + inline const D3DXVECTOR4* GetFirstCheckerColor() const + { + return &this->m_avCheckerColors[0]; + } + + //------------------------------------------------------------------ + // get the secondary color of the checker pattern background + inline const D3DXVECTOR4* GetSecondCheckerColor() const + { + return &this->m_avCheckerColors[1]; + } + private: //------------------------------------------------------------------ @@ -450,6 +481,10 @@ private: // Current offset (in pixels) of the texture viewer aiVector2D m_vTextureOffset; + + // Colors used to draw the checker pattern (for the + // texture viewer as background ) + D3DXVECTOR4 m_avCheckerColors[2]; }; #endif // AV_DISPLAY_H_INCLUDE \ No newline at end of file diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index c30b0c167..cbf3c2c25 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/tools/assimp_view/LogWindow.cpp @@ -198,7 +198,10 @@ void CLogWindow::WriteLine(const std::string& message) this->szPlainText.append(message); this->szPlainText.append("\r\n"); - this->szText.resize(this->szText.length()-1); + if (0 != this->szText.length()) + { + this->szText.resize(this->szText.length()-1); + } switch (message.c_str()[0]) { diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 52e892846..a810f8d7f 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -471,6 +471,11 @@ void CMaterialManager::DeleteMaterial(AssetHelper::MeshHelper* pcIn) pcIn->piNormalTexture->Release(); pcIn->piNormalTexture = NULL; } + if (pcIn->piShininessTexture) + { + pcIn->piShininessTexture->Release(); + pcIn->piShininessTexture = NULL; + } } //------------------------------------------------------------------------------- void CMaterialManager::HMtoNMIfNecessary( @@ -790,6 +795,16 @@ int CMaterialManager::CreateMaterial( } else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; + + // + // Shininess strength ------------------------------------------------------ + // + if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) + { + // assume 1.0 as default shininess strength + pcMesh->fSpecularStrength = 1.0f; + } + aiString szPath; // @@ -1073,7 +1088,10 @@ int CMaterialManager::CreateMaterial( if (1.0f != pcMesh->fOpacity) pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) + { pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); + pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor); pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor); @@ -1176,7 +1194,10 @@ int CMaterialManager::SetupMaterial ( if (1.0f != pcMesh->fOpacity) pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); if (pcMesh->eShadingMode != aiShadingMode_Gouraud) + { pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); + pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); + } pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor); pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor); diff --git a/tools/assimp_view/MaterialManager.h b/tools/assimp_view/MaterialManager.h index 363d632fb..c4b267940 100644 --- a/tools/assimp_view/MaterialManager.h +++ b/tools/assimp_view/MaterialManager.h @@ -50,6 +50,8 @@ class CMaterialManager { private: + friend class CDisplay; + // default constructor CMaterialManager() : m_iShaderCount (0) {} diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 221e96ea7..9bb83dcf1 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -237,6 +237,35 @@ void SaveLightColors() RegSetValueExA(g_hRegistry,"LightColor2",0,REG_DWORD,(const BYTE*)&g_avLightColors[2],4); } + +//------------------------------------------------------------------------------- +// Save the checker pattern colors to the registry +//------------------------------------------------------------------------------- +void SaveCheckerPatternColors() +{ + // we have it as float4. save it as binary value --. + RegSetValueExA(g_hRegistry,"CheckerPattern0",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetFirstCheckerColor(), + sizeof(D3DXVECTOR3)); + + RegSetValueExA(g_hRegistry,"CheckerPattern1",0,REG_BINARY, + (const BYTE*)CDisplay::Instance().GetSecondCheckerColor(), + sizeof(D3DXVECTOR3)); +} + +//------------------------------------------------------------------------------- +// Load the checker pattern colors from the registry +//------------------------------------------------------------------------------- +void LoadCheckerPatternColors() +{ + DWORD dwTemp = sizeof(D3DXVECTOR3); + RegQueryValueEx(g_hRegistry,"CheckerPattern0",NULL,NULL, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetFirstCheckerColor(),&dwTemp); + + RegQueryValueEx(g_hRegistry,"CheckerPattern1",NULL,NULL, + (BYTE*) /* jep, this is evil */ CDisplay::Instance().GetSecondCheckerColor(),&dwTemp); +} + //------------------------------------------------------------------------------- // Toggle the "Display Normals" state //------------------------------------------------------------------------------- @@ -515,7 +544,7 @@ void DisplayColorDialog(D3DCOLOR* pclrResult) clr.lStructSize = sizeof(CHOOSECOLOR); clr.hwndOwner = g_hDlg; clr.Flags = CC_RGBINIT | CC_FULLOPEN; - clr.rgbResult = RGB(100,100,100); + clr.rgbResult = RGB((*pclrResult >> 16) & 0xff,(*pclrResult >> 8) & 0xff,*pclrResult & 0xff); clr.lpCustColors = g_aclCustomColors; clr.lpfnHook = NULL; clr.lpTemplateName = NULL; @@ -530,6 +559,32 @@ void DisplayColorDialog(D3DCOLOR* pclrResult) return; } + +//------------------------------------------------------------------------------- +// Let the user choose a color in a windows standard color dialog +//------------------------------------------------------------------------------- +void DisplayColorDialog(D3DXVECTOR4* pclrResult) +{ + CHOOSECOLOR clr; + clr.lStructSize = sizeof(CHOOSECOLOR); + clr.hwndOwner = g_hDlg; + clr.Flags = CC_RGBINIT | CC_FULLOPEN; + clr.rgbResult = RGB(clamp(pclrResult->x * 255.0f), + clamp(pclrResult->y * 255.0f), + clamp(pclrResult->z * 255.0f)); + clr.lpCustColors = g_aclCustomColors; + clr.lpfnHook = NULL; + clr.lpTemplateName = NULL; + clr.lCustData = NULL; + + ChooseColor(&clr); + + pclrResult->x = GetRValue(clr.rgbResult) / 255.0f; + pclrResult->y = GetGValue(clr.rgbResult) / 255.0f; + pclrResult->z = GetBValue(clr.rgbResult) / 255.0f; + return; +} + //------------------------------------------------------------------------------- // Let the user choose the baclground color for the viewer //------------------------------------------------------------------------------- @@ -961,7 +1016,7 @@ void InitUI() SetDlgItemText(g_hDlg,IDC_EFACE,"0"); SetDlgItemText(g_hDlg,IDC_EMAT,"0"); SetDlgItemText(g_hDlg,IDC_ESHADER,"0"); - SetDlgItemText(g_hDlg,IDC_ENODE,"0"); + SetDlgItemText(g_hDlg,IDC_ENODEWND,"0"); SetDlgItemText(g_hDlg,IDC_ETEX,"0"); SetDlgItemText(g_hDlg,IDC_EMESH,"0"); @@ -1143,6 +1198,7 @@ void InitUI() g_sOptions.eDrawMode = RenderOptions::WIREFRAME; CheckDlgButton(g_hDlg,IDC_TOGGLEWIRE,BST_CHECKED); } + LoadCheckerPatternColors(); return; } @@ -1263,9 +1319,23 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, if(IDC_LCOLOR1 == pcStruct->CtlID) { - unsigned char r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); - unsigned char g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); - unsigned char b = (unsigned char)((g_avLightColors[0]) & 0xFF); + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetFirstCheckerColor()->z * 255.0f); + szText = "B0"; + } + else + { + r = (unsigned char)((g_avLightColors[0] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[0] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[0]) & 0xFF); + szText = "L0"; + } HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); FillRect(pcStruct->hDC,&sRect,hbr); @@ -1273,34 +1343,59 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); SetBkMode(pcStruct->hDC,TRANSPARENT); - TextOut(pcStruct->hDC,4,1,"L0",2); + TextOut(pcStruct->hDC,4,1,szText,2); bDraw = true; } else if(IDC_LCOLOR2 == pcStruct->CtlID) { - unsigned char r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); - unsigned char g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); - unsigned char b = (unsigned char)((g_avLightColors[1]) & 0xFF); + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->x * 255.0f); + g = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->y * 255.0f); + b = (unsigned char)(CDisplay::Instance().GetSecondCheckerColor()->z * 255.0f); + szText = "B1"; + } + else + { + r = (unsigned char)((g_avLightColors[1] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[1] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[1]) & 0xFF); + szText = "L1"; + } HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); FillRect(pcStruct->hDC,&sRect,hbr); SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); SetBkMode(pcStruct->hDC,TRANSPARENT); - TextOut(pcStruct->hDC,4,1,"L1",2); + TextOut(pcStruct->hDC,4,1,szText,2); bDraw = true; } else if(IDC_LCOLOR3 == pcStruct->CtlID) { - unsigned char r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); - unsigned char g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); - unsigned char b = (unsigned char)((g_avLightColors[2]) & 0xFF); + unsigned char r,g,b; + const char* szText; + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + r = g = b = 0; + szText = "-"; + } + else + { + r = (unsigned char)((g_avLightColors[2] >> 16) & 0xFF); + g = (unsigned char)((g_avLightColors[2] >> 8) & 0xFF); + b = (unsigned char)((g_avLightColors[2]) & 0xFF); + szText = "A0"; + } HBRUSH hbr = CreateSolidBrush(RGB(r,g,b)); - FillRect(pcStruct->hDC,&sRect,hbr); SetTextColor(pcStruct->hDC,RGB(0xFF-r,0xFF-g,0xFF-b)); SetBkMode(pcStruct->hDC,TRANSPARENT); - TextOut(pcStruct->hDC,4,1,"A0",2); + TextOut(pcStruct->hDC,4,1,szText,2); bDraw = true; } // draw the black border around the rects @@ -1460,14 +1555,8 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, char szFile[MAX_PATH]; DragQueryFile(hDrop,0,szFile,sizeof(szFile)); - if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) - { - // replace the selected texture with the new one ... - CDisplay::Instance().ReplaceCurrentTexture(szFile); - } - else - { - const char* sz = strrchr(szFile,'.'); + + const char* sz = strrchr(szFile,'.'); if (sz && 0 != aiIsExtensionSupported(sz)) { strcpy(g_szFileName,szFile); @@ -1477,6 +1566,11 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, UpdateHistory(); SaveHistory(); } + else if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode()) + { + // replace the selected texture with the new one ... + CDisplay::Instance().ReplaceCurrentTexture(szFile); + } else { if (!sz) goto __DRUNKEN_ALIEN_FROM_MARS; @@ -1535,13 +1629,12 @@ INT_PTR CALLBACK MessageProc(HWND hwndDlg,UINT uMsg, else { __DRUNKEN_ALIEN_FROM_MARS: - CLogDisplay::Instance().AddEntry( - "[ERROR] File extension is not supported. E.T. can read this.", - D3DCOLOR_ARGB(0xFF,0xFF,0,0)); + CLogDisplay::Instance().AddEntry( + "[ERROR] File extension is not supported. E.T. can read this.", + D3DCOLOR_ARGB(0xFF,0xFF,0,0)); } } - } - DragFinish(hDrop); + DragFinish(hDrop); } return TRUE; @@ -1713,17 +1806,38 @@ __DRUNKEN_ALIEN_FROM_MARS: } else if (IDC_LCOLOR1 == LOWORD(wParam)) { - DisplayColorDialog(&g_avLightColors[0]); + + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast(CDisplay::Instance().GetFirstCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[0]); + SaveLightColors(); + } InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); - SaveLightColors(); } else if (IDC_LCOLOR2 == LOWORD(wParam)) { - DisplayColorDialog(&g_avLightColors[1]); + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + // hey, I'm tired and yes, I KNOW IT IS EVIL! + DisplayColorDialog(const_cast(CDisplay::Instance().GetSecondCheckerColor())); + SaveCheckerPatternColors(); + } + else + { + DisplayColorDialog(&g_avLightColors[1]); + SaveLightColors(); + } InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR2),NULL,TRUE); UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); - SaveLightColors(); } else if (IDC_LCOLOR3 == LOWORD(wParam)) { @@ -1734,9 +1848,20 @@ __DRUNKEN_ALIEN_FROM_MARS: } else if (IDC_LRESET == LOWORD(wParam)) { - g_avLightColors[0] = D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF); - g_avLightColors[1] = D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00); - g_avLightColors[2] = D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05); + if (CDisplay::VIEWMODE_TEXTURE == CDisplay::Instance().GetViewMode() || + CDisplay::VIEWMODE_MATERIAL == CDisplay::Instance().GetViewMode()) + { + CDisplay::Instance().SetFirstCheckerColor(D3DXVECTOR4(0.4f,0.4f,0.4f,1.0f)); + CDisplay::Instance().SetSecondCheckerColor(D3DXVECTOR4(0.6f,0.6f,0.6f,1.0f)); + SaveCheckerPatternColors(); + } + else + { + g_avLightColors[0] = D3DCOLOR_ARGB(0xFF,0xFF,0xFF,0xFF); + g_avLightColors[1] = D3DCOLOR_ARGB(0xFF,0xFF,0x00,0x00); + g_avLightColors[2] = D3DCOLOR_ARGB(0xFF,0x05,0x05,0x05); + SaveLightColors(); + } InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE); UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR1)); @@ -1744,7 +1869,6 @@ __DRUNKEN_ALIEN_FROM_MARS: UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR2)); InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR3),NULL,TRUE); UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3)); - SaveLightColors(); } else if (IDC_NOSPECULAR == LOWORD(wParam)) { diff --git a/tools/assimp_view/Normals.cpp b/tools/assimp_view/Normals.cpp index 78a612813..7b50aed6f 100644 --- a/tools/assimp_view/Normals.cpp +++ b/tools/assimp_view/Normals.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "GenVertexNormalsProcess.h" #include "JoinVerticesProcess.h" #include "CalcTangentsProcess.h" +#include "MakeVerboseFormat.h" namespace AssimpView { @@ -81,83 +82,25 @@ void AssetHelper::SetNormalSet(unsigned int iSet) if (this->iNormalSet == iSet)return; // we need to build an unique set of vertices for this ... - for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) { - aiMesh* pcMesh = this->pcScene->mMeshes[i]; - const unsigned int iNumVerts = pcMesh->mNumFaces*3; + Assimp::MakeVerboseFormatProcess* pcProcess = new Assimp::MakeVerboseFormatProcess(); + pcProcess->Execute(this->pcScene); + delete pcProcess; - aiVector3D* pvPositions = new aiVector3D[iNumVerts]; - aiVector3D* pvNormals = new aiVector3D[iNumVerts]; - aiVector3D* pvTangents(NULL), *pvBitangents(NULL); - - ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); - ai_assert(AI_MAX_NUMBER_OF_COLOR_SETS == 4); - aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {NULL,NULL,NULL,NULL}; - aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {NULL,NULL,NULL,NULL}; - - - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - apvTextureCoords[p++] = new aiVector3D[iNumVerts]; - - p = 0; - while (pcMesh->HasVertexColors(p)) - apvColorSets[p++] = new aiColor4D[iNumVerts]; - - // iterate through all faces and build a clean list - unsigned int iIndex = 0; - for (unsigned int a = 0; a< pcMesh->mNumFaces;++a) + for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) { - aiFace* pcFace = &pcMesh->mFaces[a]; - for (unsigned int q = 0; q < 3;++q,++iIndex) + if (!this->apcMeshes[i]->pvOriginalNormals) { - pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]]; - pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]]; - - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - { - apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]]; - ++p; - } - p = 0; - while (pcMesh->HasVertexColors(p)) - { - apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]]; - ++p; - } - pcFace->mIndices[q] = iIndex; + this->apcMeshes[i]->pvOriginalNormals = new aiVector3D[this->pcScene->mMeshes[i]->mNumVertices]; + memcpy( this->apcMeshes[i]->pvOriginalNormals,this->pcScene->mMeshes[i]->mNormals, + this->pcScene->mMeshes[i]->mNumVertices * sizeof(aiVector3D)); } + delete[] this->pcScene->mMeshes[i]->mNormals; + this->pcScene->mMeshes[i]->mNormals = NULL; } - - // delete the old members - delete[] pcMesh->mVertices; - pcMesh->mVertices = pvPositions; - - p = 0; - while (pcMesh->HasTextureCoords(p)) - { - delete pcMesh->mTextureCoords[p]; - pcMesh->mTextureCoords[p] = apvTextureCoords[p]; - ++p; - } - p = 0; - while (pcMesh->HasVertexColors(p)) - { - delete pcMesh->mColors[p]; - pcMesh->mColors[p] = apvColorSets[p]; - ++p; - } - pcMesh->mNumVertices = iNumVerts; - - // keep the pointer to the normals - delete[] pcMesh->mNormals; - pcMesh->mNormals = NULL; - - if (!this->apcMeshes[i]->pvOriginalNormals) - this->apcMeshes[i]->pvOriginalNormals = pvNormals; } + // now we can start to calculate a new set of normals if (HARD == iSet) { @@ -175,7 +118,12 @@ void AssetHelper::SetNormalSet(unsigned int iSet) { for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) { - this->pcScene->mMeshes[i]->mNormals = this->apcMeshes[i]->pvOriginalNormals; + if (this->apcMeshes[i]->pvOriginalNormals) + { + delete[] this->pcScene->mMeshes[i]->mNormals; + this->pcScene->mMeshes[i]->mNormals = this->apcMeshes[i]->pvOriginalNormals; + this->apcMeshes[i]->pvOriginalNormals = NULL; + } } } @@ -191,7 +139,7 @@ void AssetHelper::SetNormalSet(unsigned int iSet) this->iNormalSet = iSet; - if (g_bWasFlipped && ORIGINAL != iSet) + if (g_bWasFlipped) { // invert all normal vectors for (unsigned int i = 0; i < this->pcScene->mNumMeshes;++i) diff --git a/tools/assimp_view/Shaders.cpp b/tools/assimp_view/Shaders.cpp index 69350c073..4cb3dc6f2 100644 --- a/tools/assimp_view/Shaders.cpp +++ b/tools/assimp_view/Shaders.cpp @@ -473,6 +473,7 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "float SPECULARITY;\n" + "float SPECULAR_STRENGTH;\n" "#endif\n" "#ifdef AV_OPACITY\n" "float TRANSPARENCY;\n" @@ -746,15 +747,15 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifndef AV_SKYBOX_LOOKUP\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#else\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SKYBOX_LOOKUP\n" "#endif // !AV_SPECULAR_COMPONENT\n" @@ -817,15 +818,15 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifndef AV_SKYBOX_LOOKUP\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#else\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_0),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SKYBOX_LOOKUP\n" "#endif // !AV_SPECULAR_COMPONENT\n" @@ -858,15 +859,15 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifndef AV_SKYBOX_LOOKUP\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#else\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * GetSSSCubeMap(Reflect) * (saturate(fHalfLambert * 2.0f) * pow(dot(Reflect,AV_LIGHT_1),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SKYBOX_LOOKUP\n" "#endif // !AV_SPECULAR_COMPONENT\n" @@ -921,9 +922,9 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SPECULAR_COMPONENT\n" "#ifdef AV_AMBIENT_TEXTURE\n" @@ -976,9 +977,9 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[0].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SPECULAR_COMPONENT\n" "#ifdef AV_AMBIENT_TEXTURE\n" @@ -1008,9 +1009,9 @@ std::string g_szMaterialShader = std::string( "#ifdef AV_SPECULAR_COMPONENT\n" "#ifdef AV_SPECULAR_TEXTURE\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * tex2D(SPECULAR_SAMPLER,IN.TexCoord0).rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#else\n" - "SPECULAR_COLOR.rgb * afLightColor[1].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" + "SPECULAR_COLOR.rgb * SPECULAR_STRENGTH * afLightColor[1].rgb * (saturate(L1 * 4.0f) * pow(dot(Reflect,ViewDir),SPECULARITY)) + \n" "#endif // !AV_SPECULAR_TEXTURE\n" "#endif // !AV_SPECULAR_COMPONENT\n" "#ifdef AV_AMBIENT_TEXTURE\n" diff --git a/tools/assimp_view/assimp_view.aps b/tools/assimp_view/assimp_view.aps index 0620bea84..2c2ad83f5 100644 Binary files a/tools/assimp_view/assimp_view.aps and b/tools/assimp_view/assimp_view.aps differ diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index e5c4bdbcc..6064acb33 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -590,9 +590,10 @@ int DeleteAssetData(bool bNoMaterials) g_pcAsset->apcMeshes[i]->piIB = NULL; } - //// delete storage eventually allocated to hold a copy - //// of the original vertex normals - //if (AssetHelper::ORIGINAL != g_pcAsset->iNormalSet) + // TODO ... unfixed memory leak + // delete storage eventually allocated to hold a copy + // of the original vertex normals + //if (g_pcAsset->apcMeshes[i]->pvOriginalNormals) //{ // delete[] g_pcAsset->apcMeshes[i]->pvOriginalNormals; //} @@ -629,6 +630,11 @@ int DeleteAssetData(bool bNoMaterials) g_pcAsset->apcMeshes[i]->piEmissiveTexture->Release(); g_pcAsset->apcMeshes[i]->piEmissiveTexture = NULL; } + if(g_pcAsset->apcMeshes[i]->piOpacityTexture) + { + g_pcAsset->apcMeshes[i]->piOpacityTexture->Release(); + g_pcAsset->apcMeshes[i]->piOpacityTexture = NULL; + } if(g_pcAsset->apcMeshes[i]->piShininessTexture) { g_pcAsset->apcMeshes[i]->piShininessTexture->Release(); diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 8681838d4..1a4323f5e 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -160,6 +160,16 @@ INT_PTR CALLBACK HelpDialogProc(HWND hwndDlg,UINT uMsg, void HandleCommandLine(char* p_szCommand); +//------------------------------------------------------------------------------- +template +type clamp(intype in) +{ + // for unsigned types only ... + intype mask = (0x1u << (sizeof(type)*8))-1; + return (type)std::max((intype)0,std::min(in,mask)); +} + + //------------------------------------------------------------------------------- // Position of the cursor relative to the 3ds max' like control circle //------------------------------------------------------------------------------- diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index 77fa9f9e6..31707e204 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -584,6 +584,10 @@ RelativePath="..\..\code\KillNormalsProcess.h" > + + @@ -791,6 +795,10 @@ RelativePath="..\..\code\jAssimp\assimp_Texture.h" > + + + + @@ -979,6 +991,10 @@ RelativePath="..\..\code\jAssimp\JNICalls.cpp" > + +