- shaders are now processed
 - multi-part player models are handled correctly

Material system
 - added flags for 'usealpha' or 'ignorealpha' setting of textures

LWO
 - fixed texture assignment bug due to invalid tag list

3DS
 - improved handling of dummy nodes

Viewer:
 - lines&points are now displayed
 - improved animation control via slider (still some stuff missing)
 - skeleton is now displayed
 - some other minor fixes

Validator:
 - some material issues are warnings now (no errors anymore)

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@349 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-02-15 20:29:07 +00:00
parent ca337852bf
commit abe2d4834e
27 changed files with 902 additions and 584 deletions

View File

@ -438,11 +438,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
iArray.reserve(3);
aiMatrix4x4 abs;
if (pcIn->mName == "$$$DUMMY") {
/*if (pcIn->mName == "$$$DUMMY") {
// FIX: Append the "real" name of the dummy to the string
pcIn->mName = "Dummy." + pcIn->mDummyName;
}
else // if (pcIn->mName != "$$$DUMMY")
else*/ // if (pcIn->mName != "$$$DUMMY")
{
// Find all meshes with the same name as the node
for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)

View File

@ -669,14 +669,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
// This is the "real" name of a $$$DUMMY object
{
if (mCurrentNode->mName != "$$$DUMMY") {
DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
break;
}
const char* sz = (const char*) stream->GetPtr();
while (stream->GetI1());
mCurrentNode->mDummyName = std::string(sz);
// mCurrentNode->mDummyName = std::string(sz);
// FIX: if object name is DUMMY, take this one instead
if (mCurrentNode->mName == "$$$DUMMY") {
//DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
mCurrentNode->mName = std::string(sz);
break;
}
}
break;

View File

@ -76,10 +76,9 @@ bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
{
// get the current value of the property
this->configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,175.f);
this->configMaxAngle = std::max(std::min(this->configMaxAngle,175.0f),0.0f);
this->configMaxAngle = AI_DEG_TO_RAD(this->configMaxAngle);
// Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,175.f);
configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,175.0f),0.0f));
}
// ------------------------------------------------------------------------------------------------
@ -98,8 +97,7 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
bHas = true;
}
if (bHas)
{
if (bHas) {
DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
"Vertex normals have been calculated");
}
@ -154,8 +152,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
SpatialSort _vertexFinder;
float posEpsilon;
const float epsilon = 1e-5f;
if (shared)
{
if (shared) {
std::vector<std::pair<SpatialSort,float> >* avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
if (avf)
@ -165,8 +162,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
posEpsilon = blubb.second;
}
}
if (!vertexFinder)
{
if (!vertexFinder) {
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
vertexFinder = &_vertexFinder;
posEpsilon = ComputePositionEpsilon(pMesh);
@ -174,22 +170,19 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
std::vector<unsigned int> verticesFound;
aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];
if (configMaxAngle >= AI_DEG_TO_RAD( 175.f ))
{
if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) {
// There is no angle limit. Thus all vertices with positions close
// to each other will receive the same vertex normal. This allows us
// to optimize the whole algorithm a little bit ...
std::vector<bool> abHad(pMesh->mNumVertices,false);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
{
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
if (abHad[i])continue;
// Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);
aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a)
{
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
if (is_not_qnan(v.x))pcNor += v;
}
@ -204,17 +197,16 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
}
}
}
else
{
// Slower code path if a smooth angle is set. There are many ways to achieve
// the effect, this one is the most straightforward one.
else {
const float fLimit = ::cos(configMaxAngle);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
{
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
// Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
aiVector3D pcNor;
for (unsigned int a = 0; a < verticesFound.size(); ++a)
{
for (unsigned int a = 0; a < verticesFound.size(); ++a) {
const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
// check whether the angle between the two normals is not too large

View File

@ -39,7 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file Implementation of the LWO importer class */
/** @file LWOLoader.cpp
* @brief Implementation of the LWO importer class
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
@ -230,6 +232,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
mSurfaces->push_back(LWO::Surface());
LWO::Surface& surf = mSurfaces->back();
surf.mColor.r = surf.mColor.g = surf.mColor.b = 0.6f;
surf.mName = "LWODefaultSurface";
}
idx = iDefaultSurface;
}
@ -329,8 +332,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
}
// process normals (MODO extension)
if (nrm)
{
if (nrm) {
*nrm++ = ((aiVector3D*)&layer.mNormals.rawData[0])[idx];
}
@ -401,7 +403,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
}
// copy the meshes to the output structure
if (apcMeshes.size()) // shouldn't occur, just to be sure we don't crash
if (apcMeshes.size()) // shouldn't happen, just to be sure we don't crash
{
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ];
::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*));
@ -415,24 +417,23 @@ void LWOImporter::InternReadFile( const std::string& pFile,
void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups,
const LWO::Surface& surface)
{
// allocate output storage
// Allocate output storage
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
// First generate per-face normals
aiVector3D* out;
std::vector<aiVector3D> faceNormals;
// ... in some cases that's already enough
if (!surface.mMaximumSmoothAngle)
out = mesh->mNormals;
else
{
else {
faceNormals.resize(mesh->mNumVertices);
out = &faceNormals[0];
}
aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces;
for (; begin != end; ++begin)
{
for (; begin != end; ++begin) {
aiFace& face = *begin;
// LWO doc: "the normal is defined as the cross product of the first and last edges"
@ -447,7 +448,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
if (!surface.mMaximumSmoothAngle)return;
const float posEpsilon = ComputePositionEpsilon(mesh);
// now generate the spatial sort tree
// Now generate the spatial sort tree
SGSpatialSort sSort;
std::vector<unsigned int>::const_iterator it = smoothingGroups.begin();
for( begin = mesh->mFaces; begin != end; ++begin, ++it)
@ -459,70 +460,57 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
sSort.Add(mesh->mVertices[tt],tt,*it);
}
}
// sort everything - this takes O(nlogn) time
// Sort everything - this takes O(nlogn) time
sSort.Prepare();
std::vector<unsigned int> poResult;
poResult.reserve(20);
// generate vertex normals. We have O(logn) for the binary lookup, which we need
// Generate vertex normals. We have O(logn) for the binary lookup, which we need
// for n elements, thus the EXPECTED complexity is O(nlogn)
if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag)
{
if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) {
const float fLimit = cos(surface.mMaximumSmoothAngle);
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it)
{
register unsigned int sg = *it;
aiFace& face = *begin;
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
const aiFace& face = *begin;
unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
for (; beginIdx != endIdx; ++beginIdx)
{
register unsigned int idx = *beginIdx;
sSort.FindPositions(mesh->mVertices[idx],sg,posEpsilon,poResult,true);
sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
std::vector<unsigned int>::const_iterator a, end = poResult.end();
aiVector3D vNormals;
for (a = poResult.begin();a != end;++a)
{
for (a = poResult.begin();a != end;++a) {
const aiVector3D& v = faceNormals[*a];
if (v * faceNormals[idx] < fLimit)continue;
if (v * faceNormals[idx] < fLimit)
continue;
vNormals += v;
}
vNormals.Normalize();
mesh->mNormals[idx] = vNormals;
mesh->mNormals[idx] = vNormals.Normalize();
}
}
}
else // faster code path in case there is no smooth angle
{
// faster code path in case there is no smooth angle
else {
std::vector<bool> vertexDone(mesh->mNumVertices,false);
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it)
{
register unsigned int sg = *it;
aiFace& face = *begin;
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
const aiFace& face = *begin;
unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices;
for (; beginIdx != endIdx; ++beginIdx)
{
register unsigned int idx = *beginIdx;
if (vertexDone[idx])continue;
sSort.FindPositions(mesh->mVertices[idx],sg,posEpsilon,poResult,true);
if (vertexDone[idx])
continue;
sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true);
std::vector<unsigned int>::const_iterator a, end = poResult.end();
aiVector3D vNormals;
for (a = poResult.begin();a != end;++a)
{
for (a = poResult.begin();a != end;++a) {
const aiVector3D& v = faceNormals[*a];
vNormals += v;
}
vNormals.Normalize();
for (a = poResult.begin();a != end;++a)
{
for (a = poResult.begin();a != end;++a) {
mesh->mNormals[*a] = vNormals;
vertexDone[*a] = true;
}
@ -617,9 +605,9 @@ void LWOImporter::ResolveTags()
mMapping->resize(mTags->size(),0xffffffff);
for (unsigned int a = 0; a < mTags->size();++a)
{
const std::string& c = (*mTags)[a];
for (unsigned int i = 0; i < mSurfaces->size();++i)
{
const std::string& c = (*mTags)[a];
const std::string& d = (*mSurfaces)[i].mName;
if (!ASSIMP_stricmp(c,d))
{
@ -688,9 +676,11 @@ void LWOImporter::LoadLWOTags(unsigned int size)
{
if (!(*szCur))
{
const unsigned int len = (unsigned int)(szCur-szLast);
const size_t len = (size_t)(szCur-szLast);
// FIX: skip empty-sized tags
if (len)
mTags->push_back(std::string(szLast,len));
szCur += len & 1;
szCur += (len&0x1 ? 1 : 2);
szLast = szCur;
}
szCur++;
@ -881,7 +871,7 @@ inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx)
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead,
unsigned int idx, float* data)
{
ai_assert(NULL != data);
@ -897,7 +887,7 @@ void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRea
}
// ------------------------------------------------------------------------------------------------
void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx)
inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx)
{
if(0xffffffff == refList[srcIdx])
{

View File

@ -455,7 +455,7 @@ inline void LWOImporter::GetS0(std::string& out,unsigned int max)
}
++mFileBuffer;
}
unsigned int len = (unsigned int) ((const char*)mFileBuffer-sz);
size_t len = (size_t) ((const char*)mFileBuffer-sz);
out = std::string(sz,len);
mFileBuffer += (len&0x1 ? 1 : 2);
}

View File

@ -663,8 +663,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1;
it != end; ++it)
{
if ((*it).mName == derived)
{
if ((*it).mName == derived) {
// we have it ...
surf = *it;
derived.clear();

View File

@ -60,13 +60,36 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
// ------------------------------------------------------------------------------------------------
// Convert a Q3 shader blend function to the appropriate enum value
Q3Shader::BlendFunc StringToBlendFunc(const std::string& m)
{
if (m == "GL_ONE") {
return Q3Shader::BLEND_GL_ONE;
}
if (m == "GL_ZERO") {
return Q3Shader::BLEND_GL_ZERO;
}
if (m == "GL_SRC_ALPHA") {
return Q3Shader::BLEND_GL_SRC_ALPHA;
}
if (m == "GL_ONE_MINUS_SRC_ALPHA") {
return Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
}
if (m == "GL_ONE_MINUS_DST_COLOR") {
return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
}
DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m);
return Q3Shader::BLEND_NONE;
}
// ------------------------------------------------------------------------------------------------
// Load a Quake 3 shader
void Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io)
bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io)
{
boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt"));
if (!file.get())
return; // if we can't access the file, don't worry and return
return false; // if we can't access the file, don't worry and return
DefaultLogger::get()->info("Loading Quake3 shader file " + pFile);
@ -84,51 +107,80 @@ void Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
Q3Shader::ShaderMapBlock* curMap = NULL;
// read line per line
for (;;SkipLine(&buff)) {
if(!SkipSpacesAndLineEnd(&buff))
break;
for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
if (*buff == '{') {
++buff;
// append to last section, if any
if (!curData) {
DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'");
return;
return true; // still no failure, the file is there
}
// read this map section
for (;;SkipLine(&buff)) {
if(!SkipSpacesAndLineEnd(&buff))
break;
// read this data section
for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
if (*buff == '{') {
++buff;
// add new map section
curData->maps.push_back(Q3Shader::ShaderMapBlock());
curMap = &curData->maps.back();
}
else if (*buff == '}') {
// close this map section
if (curMap)
curMap = NULL;
else {
curData = NULL;
break;
}
}
for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) {
// 'map' - Specifies texture file name
else if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) {
if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) {
curMap->name = GetNextToken(buff);
}
// 'blendfunc' - Alpha blending mode
else if (TokenMatchI(buff,"blendfunc",9)) {
// fixme
const std::string blend_src = GetNextToken(buff);
if (blend_src == "add") {
curMap->blend_src = Q3Shader::BLEND_GL_ONE;
curMap->blend_dest = Q3Shader::BLEND_GL_ONE;
}
else if (blend_src == "filter") {
curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR;
curMap->blend_dest = Q3Shader::BLEND_GL_ZERO;
}
else if (blend_src == "blend") {
curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA;
curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA;
}
else {
curMap->blend_src = StringToBlendFunc(blend_src);
curMap->blend_dest = StringToBlendFunc(GetNextToken(buff));
}
}
// 'alphafunc' - Alpha testing mode
else if (TokenMatchI(buff,"alphafunc",9)) {
const std::string at = GetNextToken(buff);
if (at == "GT0") {
curMap->alpha_test = Q3Shader::AT_GT0;
}
else if (at == "LT128") {
curMap->alpha_test = Q3Shader::AT_LT128;
}
else if (at == "GE128") {
curMap->alpha_test = Q3Shader::AT_GE128;
}
}
else if (*buff == '}') {
++buff;
// close this map section
curMap = NULL;
break;
}
}
}
else if (*buff == '}') {
++buff;
curData = NULL;
break;
}
// 'cull' specifies culling behaviour for the model
else if (TokenMatch(buff,"cull",4)) {
else if (TokenMatchI(buff,"cull",4)) {
SkipSpaces(&buff);
if (!ASSIMP_strincmp(buff,"back",4)) {
curData->cull = Q3Shader::CULL_CCW;
@ -136,7 +188,12 @@ void Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
else if (!ASSIMP_strincmp(buff,"front",5)) {
curData->cull = Q3Shader::CULL_CW;
}
//else curData->cull = Q3Shader::CULL_NONE;
else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) {
curData->cull = Q3Shader::CULL_NONE;
}
else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode");
}
}
}
else {
@ -148,15 +205,16 @@ void Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
curData->name = GetNextToken(buff);
}
}
return true;
}
// ------------------------------------------------------------------------------------------------
// Load a Quake 3 skin
void Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
{
boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt"));
if (!file.get())
return; // if we can't access the file, don't worry and return
return false; // if we can't access the file, don't worry and return
DefaultLogger::get()->info("Loading Quake3 skin file " + pFile);
@ -177,7 +235,7 @@ void Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
std::string ss = GetNextToken(buff);
// ignore tokens starting with tag_
if (!::strncmp(&ss[0],"_tag",std::min((size_t)4, ss.length())))
if (!::strncmp(&ss[0],"tag_",std::min((size_t)4, ss.length())))
continue;
fill.textures.push_back(SkinData::TextureEntry());
@ -186,6 +244,90 @@ void Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
s.first = ss;
s.second = GetNextToken(buff);
}
return true;
}
// ------------------------------------------------------------------------------------------------
// Convert Q3Shader to material
void Q3Shader::ConvertShaderToMaterial(MaterialHelper* out, const ShaderDataBlock& shader)
{
ai_assert(NULL != out);
/* IMPORTANT: This is not a real conversion. Actually we're just guessing and
* hacking around to build an aiMaterial that looks nearly equal to the
* original Quake 3 shader. We're missing some important features like
* animatable material properties in our material system, but at least
* multiple textures should be handled correctly.
*/
// Two-sided material?
if (shader.cull == Q3Shader::CULL_NONE) {
const int twosided = 1;
out->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
}
unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm =0;
// Iterate through all textures
for (std::list< Q3Shader::ShaderMapBlock >::const_iterator it = shader.maps.begin(); it != shader.maps.end();++it) {
// CONVERSION BEHAVIOUR:
//
//
// If the texture is additive
// - if it is the first texture, assume additive blending for the whole material
// - otherwise register it as emissive texture.
//
// If the texture is using standard blend (or if the blend mode is unknown)
// - if first texture: assume default blending for material
// - in any case: set it as diffuse texture
//
// If the texture is using 'filter' blending
// - take as lightmap
//
// Textures with alpha funcs
// - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set)
aiString s((*it).name);
aiTextureType type; unsigned int index;
if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) {
if (it == shader.maps.begin()) {
const int additive = aiBlendMode_Additive;
out->AddProperty(&additive,1,AI_MATKEY_BLEND_FUNC);
index = cur_diffuse++;
type = aiTextureType_DIFFUSE;
}
else {
index = cur_emissive++;
type = aiTextureType_EMISSIVE;
}
}
else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && Q3Shader::BLEND_GL_ZERO) {
index = cur_lm++;
type = aiTextureType_LIGHTMAP;
}
else {
const int blend = aiBlendMode_Default;
out->AddProperty(&blend,1,AI_MATKEY_BLEND_FUNC);
index = cur_diffuse++;
type = aiTextureType_DIFFUSE;
}
// setup texture
out->AddProperty(&s,AI_MATKEY_TEXTURE(type,index));
// setup texture flags
const int use_alpha = ((*it).alpha_test != Q3Shader::AT_NONE ? aiTextureFlags_UseAlpha : aiTextureFlags_IgnoreAlpha);
out->AddProperty(&use_alpha,1,AI_MATKEY_TEXFLAGS(type,index));
}
// If at least one emissive texture was set, set the emissive base color to 1 to ensure
// the texture is actually displayed.
if (0 != cur_emissive) {
aiColor3D one(1.f,1.f,1.f);
out->AddProperty(&one,1,AI_MATKEY_COLOR_EMISSIVE);
}
}
// ------------------------------------------------------------------------------------------------
@ -291,11 +433,14 @@ void MD3Importer::SetupProperties(const Importer* pImp)
// AI_CONFIG_IMPORT_MD3_SKIN_NAME
configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME,"default"));
// AI_CONFIG_IMPORT_MD3_SHADER_SRC
configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC,""));
}
// ------------------------------------------------------------------------------------------------
// Try to read the skin for a MD3 file
void MD3Importer::ReadSkin(Q3Shader::SkinData& fill)
void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const
{
// skip any postfixes (e.g. lower_1.md3)
std::string::size_type s = filename.find_last_of('_');
@ -308,6 +453,39 @@ void MD3Importer::ReadSkin(Q3Shader::SkinData& fill)
Q3Shader::LoadSkin(fill,skin_file,mIOHandler);
}
// ------------------------------------------------------------------------------------------------
// Try to read the shader for a MD3 file
void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const
{
// Determine Q3 model name from given path
std::string::size_type s = path.find_last_of('\\',path.length()-2);
if (s == std::string::npos)
s = path.find_last_of('/',path.length()-2);
const std::string model_file = path.substr(s+1,path.length()-(s+2));
// If no specific dir or file is given, use our default search behaviour
if (!configShaderFile.length()) {
if(!Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + model_file + ".shader",mIOHandler)) {
Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + filename + ".shader",mIOHandler);
}
}
else {
// If the given string specifies a file, load this file.
// Otherwise it's a directory.
std::string::size_type st = configShaderFile.find_last_of('.');
if (st == std::string::npos) {
if(!Q3Shader::LoadShader(fill,configShaderFile + model_file + ".shader",mIOHandler)) {
Q3Shader::LoadShader(fill,configShaderFile + filename + ".shader",mIOHandler);
}
}
else {
Q3Shader::LoadShader(fill,configShaderFile,mIOHandler);
}
}
}
// ------------------------------------------------------------------------------------------------
// Read a multi-part Q3 player model
bool MD3Importer::ReadMultipartFile()
@ -416,6 +594,45 @@ error_cleanup:
return false;
}
// ------------------------------------------------------------------------------------------------
// Convert a MD3 path to a proper value
void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, std::string& out) const
{
// If the MD3's internal path itself and the given path are using
// the same directory, remove it completely to get right output paths.
const char* end1 = ::strrchr(header_name,'\\');
if (!end1)end1 = ::strrchr(header_name,'/');
const char* end2 = ::strrchr(texture_name,'\\');
if (!end2)end2 = ::strrchr(texture_name,'/');
// HACK: If the paths starts with "models", ignore the
// next two hierarchy levels, it specifies just the model name.
// Ignored by Q3, it might be not equal to the real model location.
if (end2) {
size_t len2;
const size_t len1 = (size_t)(end1 - header_name);
if (!ASSIMP_strincmp(texture_name,"models",6) && (texture_name[6] == '/' || texture_name[6] == '\\')) {
len2 = 6; // ignore the seventh - could be slash or backslash
if (!header_name[0]) {
// Use the file name only
out = end2+1;
return;
}
}
else len2 = std::min (len1, (size_t)(end2 - texture_name ));
if (!ASSIMP_strincmp(texture_name,header_name,len2)) {
// Use the file name only
out = end2+1;
return;
}
}
// Use the full path
out = texture_name;
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void MD3Importer::InternReadFile( const std::string& pFile,
@ -504,12 +721,27 @@ void MD3Importer::InternReadFile( const std::string& pFile,
Q3Shader::SkinData skins;
ReadSkin(skins);
// And check whether we can locate a shader file for this model
Q3Shader::ShaderData shaders;
ReadShader(shaders);
// Adjust all texture paths in the shader
const char* header_name = pcHeader->NAME;
if (shaders.blocks.size()) {
for (std::list< Q3Shader::ShaderDataBlock >::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) {
ConvertPath((*dit).name.c_str(),header_name,(*dit).name);
for (std::list< Q3Shader::ShaderMapBlock >::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) {
ConvertPath((*mit).name.c_str(),header_name,(*mit).name);
}
}
}
// Read all surfaces from the file
unsigned int iNum = pcHeader->NUM_SURFACES;
unsigned int iNumMaterials = 0;
unsigned int iDefaultMatIndex = 0xFFFFFFFF;
while (iNum-- > 0)
{
while (iNum-- > 0) {
// Ensure correct endianess
#ifdef AI_BUILD_BIG_ENDIAN
@ -555,6 +787,95 @@ void MD3Importer::InternReadFile( const std::string& pFile,
continue;
}
// Allocate output mesh
pScene->mMeshes[iNum] = new aiMesh();
aiMesh* pcMesh = pScene->mMeshes[iNum];
std::string _texture_name;
const char* texture_name = NULL;
// Check whether we have a texture record for this surface in the .skin file
std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find(
skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME );
if (it != skins.textures.end()) {
texture_name = &*( _texture_name = (*it).second).begin();
DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME);
(*it).resolved = true; // mark entry as resolved
}
// Get the first shader (= texture?) assigned to the surface
if (!texture_name && pcSurfaces->NUM_SHADER) {
texture_name = pcShaders->NAME;
}
std::string convertedPath;
if (texture_name) {
ConvertPath(texture_name,header_name,convertedPath);
}
const Q3Shader::ShaderDataBlock* shader = NULL;
// Now search the current shader for a record with this name (
// excluding texture file extension)
if (shaders.blocks.size()) {
std::string::size_type s = convertedPath.find_last_of('.');
if (s == std::string::npos)
s = convertedPath.length();
const std::string without_ext = convertedPath.substr(0,s);
std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext);
if (dit != shaders.blocks.end()) {
// Hurra, wir haben einen. Tolle Sache.
shader = &*dit;
DefaultLogger::get()->info("Found shader record for " +without_ext );
}
else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext );
}
MaterialHelper* pcHelper = new MaterialHelper();
const int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// Add a small ambient color value - Quake 3 seems to have one
aiColor3D clr;
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
// use surface name + skin_name as material name
aiString name;
name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]");
pcHelper->AddProperty(&name,AI_MATKEY_NAME);
if (!shader) {
// Setup dummy texture file name to ensure UV coordinates are kept during postprocessing
aiString szString;
if (convertedPath.length()) {
szString.Set(convertedPath);
}
else {
DefaultLogger::get()->warn("Texture file name has zero length. Using default name");
szString.Set("dummy_texture.bmp");
}
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
// prevent transparency by default
int no_alpha = aiTextureFlags_IgnoreAlpha;
pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0));
}
else {
Q3Shader::ConvertShaderToMaterial(pcHelper,*shader);
}
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++;
// Ensure correct endianess
#ifdef AI_BUILD_BIG_ENDIAN
@ -577,9 +898,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
#endif
// Allocate the output mesh
pScene->mMeshes[iNum] = new aiMesh();
aiMesh* pcMesh = pScene->mMeshes[iNum];
// Fill mesh information
pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3;
@ -600,6 +919,8 @@ void MD3Importer::InternReadFile( const std::string& pFile,
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*AI_MD3_XYZ_SCALE;
pcMesh->mVertices[iCurrent].y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE;
@ -613,101 +934,15 @@ void MD3Importer::InternReadFile( const std::string& pFile,
pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U;
pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V;
}
// FIX: flip the face ordering for use with OpenGL
// Flip face order if necessary
if (!shader || shader->cull == Q3Shader::CULL_CCW) {
pcMesh->mFaces[i].mIndices[0] = iTemp+2;
pcMesh->mFaces[i].mIndices[1] = iTemp+1;
pcMesh->mFaces[i].mIndices[2] = iTemp+0;
}
pcTriangles++;
}
std::string _texture_name;
const char* texture_name = NULL, *header_name = pcHeader->NAME;
// Check whether we have a texture record for this surface in the .skin file
std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find(
skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME );
if (it != skins.textures.end()) {
texture_name = &*( _texture_name = (*it).second).begin();
DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME);
(*it).resolved = true; // mark entry as resolved
}
// Get the first shader (= texture?) assigned to the surface
if (!texture_name && pcSurfaces->NUM_SHADER) {
texture_name = pcShaders->NAME;
}
const char* end2 = NULL;
if (texture_name) {
// If the MD3's internal path itself and the given path are using
// the same directory, remove it completely to get right output paths.
const char* end1 = ::strrchr(header_name,'\\');
if (!end1)end1 = ::strrchr(header_name,'/');
end2 = ::strrchr(texture_name,'\\');
if (!end2)end2 = ::strrchr(texture_name,'/');
// HACK: If the paths starts with "models/players", ignore the
// next hierarchy level, it specifies just the model name.
// Ignored by Q3, it might be not equal to the real model location.
if (end1 && end2) {
size_t len2;
const size_t len1 = (size_t)(end1 - header_name);
if (!ASSIMP_strincmp(header_name,"models/players/",15)) {
len2 = 15;
}
else len2 = std::min (len1, (size_t)(end2 - texture_name ));
if (!ASSIMP_strincmp(texture_name,header_name,len2)) {
// Use the file name only
end2++;
}
else {
// Use the full path
end2 = (const char*)texture_name;
}
}
}
MaterialHelper* pcHelper = new MaterialHelper();
// Setup dummy texture file name to ensure UV coordinates are kept during postprocessing
aiString szString;
if (end2 && end2[0]) {
const size_t iLen = ::strlen(end2);
::memcpy(szString.data,end2,iLen);
szString.data[iLen] = '\0';
szString.length = iLen;
}
else {
DefaultLogger::get()->warn("Texture file name has zero length. Using default name");
szString.Set("dummy_texture.bmp");
}
pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
const int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
// Add a small ambient color value - Quake 3 seems to have one
aiColor3D clr;
clr.b = clr.g = clr.r = 0.05f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
// use surface name + skin_name as material name
aiString name;
name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]");
pcHelper->AddProperty(&name,AI_MATKEY_NAME);
pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper;
pcMesh->mMaterialIndex = iNumMaterials++;
// Go to the next surface
pcSurfaces = (BE_NCONST MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END);
}

View File

@ -131,6 +131,12 @@ struct ShaderMapBlock
//! Blend and alpha test settings for texture
BlendFunc blend_src,blend_dest;
AlphaTestFunc alpha_test;
//! For std::find()
bool operator== (const std::string& o) const {
return !ASSIMP_stricmp(o,name);
}
};
// ---------------------------------------------------------------------------
@ -150,6 +156,12 @@ struct ShaderDataBlock
//! Maps defined in the shader
std::list<ShaderMapBlock> maps;
//! For std::find()
bool operator== (const std::string& o) const {
return !ASSIMP_stricmp(o,name);
}
};
// ---------------------------------------------------------------------------
@ -168,8 +180,18 @@ struct ShaderData
* @param fill Receives output data
* @param file File to be read.
* @param io IOSystem to be used for reading
* @return false if file is not accessible
*/
void LoadShader(ShaderData& fill, const std::string& file,IOSystem* io);
bool LoadShader(ShaderData& fill, const std::string& file,IOSystem* io);
// ---------------------------------------------------------------------------
/** @brief Convert a Q3Shader to an aiMaterial
*
* @param[out] out Material structure to be filled.
* @param[in] shader Input shader
*/
void ConvertShaderToMaterial(MaterialHelper* out, const ShaderDataBlock& shader);
// ---------------------------------------------------------------------------
/** @brief Load a skin file
@ -178,8 +200,9 @@ void LoadShader(ShaderData& fill, const std::string& file,IOSystem* io);
* @param fill Receives output data
* @param file File to be read.
* @param io IOSystem to be used for reading
* @return false if file is not accessible
*/
void LoadSkin(SkinData& fill, const std::string& file,IOSystem* io);
bool LoadSkin(SkinData& fill, const std::string& file,IOSystem* io);
} // ! namespace Q3SHader
@ -243,7 +266,22 @@ protected:
/** Try to read the skin for a MD3 file
* @param fill Receives output information
*/
void ReadSkin(Q3Shader::SkinData& fill);
void ReadSkin(Q3Shader::SkinData& fill) const;
// -------------------------------------------------------------------
/** Try to read the shader for a MD3 file
* @param fill Receives output information
*/
void ReadShader(Q3Shader::ShaderData& fill) const;
// -------------------------------------------------------------------
/** Convert a texture path in a MD3 file to a proper value
* @param[in] texture_name Path to be converted
* @param[in] header_path Base path specified in MD3 header
* @param[out] out Receives the converted output string
*/
void ConvertPath(const char* texture_name, const char* header_path,
std::string& out) const;
protected:
@ -256,6 +294,9 @@ protected:
/** Configuration option: name of skin file to be read */
std::string configSkinFile;
/** Configuration option: name or path of shader */
std::string configShaderFile;
/** Header of the MD3 file */
BE_NCONST MD3::Header* pcHeader;

View File

@ -288,24 +288,16 @@ uint32_t MaterialHelper::ComputeHash(bool includeMatName /*= false*/)
{
aiMaterialProperty* prop;
// If specified, exclude the material name from the hash
if ((prop = mProperties[i]) && (includeMatName || ::strcmp(prop->mKey.data,"$mat.name")))
// Exclude all properties whose first character is '?' from the hash
// See doc for aiMaterialProperty.
if ((prop = mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?'))
{
hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
// Combine the semantic and the index with the hash
// We print them to a string to make sure the quality
// of the hashing state isn't affected (our hashing
// procedure was originally intended for plaintest).
char buff[32];
unsigned int len;
len = ASSIMP_itoa10(buff,prop->mSemantic);
hash = SuperFastHash(buff,len-1,hash);
len = ASSIMP_itoa10(buff,prop->mIndex);
hash = SuperFastHash(buff,len-1,hash);
hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash);
hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash);
}
}
return hash;

View File

@ -131,8 +131,9 @@ public:
* proprty and call this method again, the resulting hash value will be
* different.
*
* @param includeMatName Set to 'true' to take the #AI_MATKEY_NAME property
* into account. The default value is false.
* @param includeMatName Set to 'true' to take all properties with
* '?' as initial character in their name into account.
* Currently #AI_MATKEY_NAME is the only example.
* @return Unique hash
*/
uint32_t ComputeHash(bool includeMatName = false);

View File

@ -201,7 +201,7 @@ void CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat,
// aiFace destructor ...
pcMesh->mFaces[planck].mIndices = NULL;
// FIX: update the mPrimitiveTypes member of the mesh
// Update the mPrimitiveTypes member of the mesh
switch (pcMesh->mFaces[planck].mNumIndices)
{
case 0x1:
@ -249,13 +249,11 @@ void GetVFormatList( aiScene* pcScene, unsigned int iMat,
// Compute the absolute transformation matrices of each node
void ComputeAbsoluteTransform( aiNode* pcNode )
{
if (pcNode->mParent)
{
if (pcNode->mParent) {
pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation;
}
for (unsigned int i = 0;i < pcNode->mNumChildren;++i)
{
for (unsigned int i = 0;i < pcNode->mNumChildren;++i) {
ComputeAbsoluteTransform(pcNode->mChildren[i]);
}
}
@ -291,17 +289,13 @@ void PretransformVertices::Execute( aiScene* pScene)
std::vector<aiMesh*> apcOutMeshes;
apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
std::list<unsigned int> aiVFormats;
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) {
// get the list of all vertex formats for this material
aiVFormats.clear();
GetVFormatList(pScene,i,aiVFormats);
aiVFormats.sort();
aiVFormats.unique();
for (std::list<unsigned int>::const_iterator
j = aiVFormats.begin();
j != aiVFormats.end();++j)
{
for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) {
unsigned int iVertices = 0;
unsigned int iFaces = 0;
CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices);

View File

@ -95,8 +95,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{
// if the material is not referenced ... remove it
if (!abReferenced[i])
{
if (!abReferenced[i]) {
++unreferenced;
continue;
}
@ -104,8 +103,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
for (unsigned int a = 0; a < i;++a)
{
if (me == aiHashes[a])
{
if (me == aiHashes[a]) {
++iCnt;
me = 0;
aiMappingTable[i] = aiMappingTable[a];
@ -113,27 +111,26 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
break;
}
}
if (me)
{
if (me) {
aiMappingTable[i] = iNewNum++;
}
}
if (iCnt)
{
if (iCnt) {
// build an output material list
aiMaterial** ppcMaterials = new aiMaterial*[iNewNum];
::memset(ppcMaterials,0,sizeof(void*)*iNewNum);
for (unsigned int p = 0; p < pScene->mNumMaterials;++p)
{
// if the material is not referenced ... remove it
if (!abReferenced[p])continue;
if (!abReferenced[p])
continue;
// generate new names for all modified materials
const unsigned int idx = aiMappingTable[p];
if (ppcMaterials[idx])
{
aiString sz;
sz.length = ::sprintf(sz.data,"aiMaterial #%i",p);
sz.length = ::sprintf(sz.data,"JoinedMaterial_#%i",p);
((MaterialHelper*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME);
}
else ppcMaterials[idx] = pScene->mMaterials[p];

View File

@ -635,17 +635,15 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{
aiMaterialProperty* prop = pMaterial->mProperties[i];
if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type)
{
if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type) {
iIndex = std::max(iIndex, (int) prop->mIndex);
++iNumIndices;
if (aiPTI_String != prop->mType)
this->ReportError("Material property %s is expected to be a string",prop->mKey.data);
ReportError("Material property %s is expected to be a string",prop->mKey.data);
}
}
if (iIndex +1 != iNumIndices)
{
if (iIndex +1 != iNumIndices) {
ReportError("%s #%i is set, but there are only %i %s textures",
szType,iIndex,iNumIndices,szType);
}
@ -666,8 +664,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
prop->mIndex, iNumIndices, szType);
}
if (!::strcmp(prop->mKey.data,"$tex.mapping"))
{
if (!::strcmp(prop->mKey.data,"$tex.mapping")) {
if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping))
{
ReportError("Material property %s%i is expected to be an integer (size is %i)",
@ -675,8 +672,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
}
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
}
else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo"))
{
else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) {
if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform))
{
ReportError("Material property %s%i is expected to be 5 floats large (size is %i)",
@ -684,8 +680,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
}
mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData);
}
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc"))
{
else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) {
if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength)
{
ReportError("Material property %s%i is expected to be an integer (size is %i)",
@ -709,7 +704,7 @@ void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial,
while (mesh->HasTextureCoords(iChannels))++iChannels;
if (iIndex >= iChannels)
{
ReportError("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels",
iIndex,prop->mKey.data,a,iChannels);
}
}
@ -742,42 +737,37 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
for (unsigned int i = 0; i < pMaterial->mNumProperties;++i)
{
const aiMaterialProperty* prop = pMaterial->mProperties[i];
if (!prop)
{
this->ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
if (!prop) {
ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)",
i,pMaterial->mNumProperties);
}
if (!prop->mDataLength || !prop->mData)
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength or "
if (!prop->mDataLength || !prop->mData) {
ReportError("aiMaterial::mProperties[%i].mDataLength or "
"aiMaterial::mProperties[%i].mData is 0",i,i);
}
// check all predefined types
if (aiPTI_String == prop->mType)
{
// FIX: strings are now stored in a less expensive way ...
if (prop->mDataLength < sizeof(size_t) + ((const aiString*)prop->mData)->length + 1)
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
if (prop->mDataLength < sizeof(size_t) + ((const aiString*)prop->mData)->length + 1) {
ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a string (%i, needed: %i)",
i,prop->mDataLength,sizeof(aiString));
}
this->Validate((const aiString*)prop->mData);
Validate((const aiString*)prop->mData);
}
else if (aiPTI_Float == prop->mType)
{
if (prop->mDataLength < sizeof(float))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
if (prop->mDataLength < sizeof(float)) {
ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain a float (%i, needed: %i)",
i,prop->mDataLength,sizeof(float));
}
}
else if (aiPTI_Integer == prop->mType)
{
if (prop->mDataLength < sizeof(int))
{
this->ReportError("aiMaterial::mProperties[%i].mDataLength is "
if (prop->mDataLength < sizeof(int)) {
ReportError("aiMaterial::mProperties[%i].mDataLength is "
"too small to contain an integer (%i, needed: %i)",
i,prop->mDataLength,sizeof(int));
}
@ -788,22 +778,19 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
// make some more specific tests
float fTemp;
int iShading;
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading))
{
if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) {
switch ((aiShadingMode)iShading)
{
case aiShadingMode_Blinn:
case aiShadingMode_CookTorrance:
case aiShadingMode_Phong:
if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp))
{
this->ReportWarning("A specular shading model is specified but there is no "
if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) {
ReportWarning("A specular shading model is specified but there is no "
"AI_MATKEY_SHININESS key");
}
if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp)
{
this->ReportWarning("A specular shading model is specified but the value of the "
if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) {
ReportWarning("A specular shading model is specified but the value of the "
"AI_MATKEY_SHININESS_STRENGTH key is 0.0");
}
break;
@ -811,13 +798,13 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
};
}
if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp))
{
if (!fTemp)
ReportWarning("Material is fully transparent ... are you sure you REALLY want this?");
if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01f)) {
ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)");
}
// check whether there are invalid texture keys
// Check whether there are invalid texture keys
// TODO: that's a relict of the past, where texture type and index were baked
// into the material string ... we could do that in one single pass.
SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE);
SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR);
SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT);
@ -826,6 +813,9 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS);
SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT);
SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS);
SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
}
// ------------------------------------------------------------------------------------------------

View File

@ -159,6 +159,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_CONFIG_IMPORT_MD3_SKIN_NAME \
"IMPORT_MD3_SKIN_NAME"
// ---------------------------------------------------------------------------
/** @brief Specify the Quake 3 shader file to be used for a particular
* MD3 file. This can also be a search path.
*
* By default Assimp's behaviour is as follows: If a MD3 file
* <tt><any_path>/models/<any_q3_subdir>/<model_name>/<file_name>.md3</tt> is
* loaded, the library tries to locate the corresponding shader file in
* <tt><any_path>/scripts/<model_name>.shader</tt>. This property overrides this
* behaviour. It can either specify a full path to the shader to be loaded
* or alternatively the path (relative or absolute) to the directory where
* the shaders for all MD3s to be loaded reside. Assimp attempts to open
* <tt><dir>/<model_name>.shader</tt> first, <tt><dir>/<file_name>.shader</tt>
* is the fallback file. Note that <dir> should have a terminal (back)slash.
* Property type: String. Default value: n/a.
*/
#define AI_CONFIG_IMPORT_MD3_SHADER_SRC \
"IMPORT_MD3_SHADER_SRC"
// ---------------------------------------------------------------------------
/** @brief Configures the LWO loader to load just one layer from the model.

View File

@ -97,7 +97,8 @@ enum aiPropertyTypeInfo
};
// ---------------------------------------------------------------------------
/** @brief Defines how the Nth texture is combined with the N-1th texture.
/** @brief Defines how the Nth texture of a specific type is combined with
* the result of all previous layers.
*
* Example (left: key, right: value): <br>
* @code
@ -418,8 +419,10 @@ enum aiShadingMode
// ---------------------------------------------------------------------------
/** @brief Defines some mixed flags for a particular texture.
*
* Usually you'll tell your artists how textures have to look like ...
* however, if you use Assimp for completely generic loadeing purposes you
* Usually you'll tell your cg artists how textures have to look like ...
* and hopefully the follow these rules. If they don't, restrict access
* to the coffee machine for them. That should help.
* However, if you use Assimp for completely generic loading purposes you
* might also need to process these flags in order to display as many
* 'unknown' 3D models as possible correctly.
*
@ -432,6 +435,25 @@ enum aiTextureFlags
aiTextureFlags_Invert = 0x1,
/** Explicit request to the application to process the alpha channel
* of the texture.
*
* Mutually exclusive with #aiTextureFlags_IgnoreAlpha. These
* flags are set if the library can say for sure that the alpha
* channel is used/is not used. If the model format does not
* define this, it is left to the application to decide whether
* the texture alpha channel - if any - is evaluated or not.
*/
aiTextureFlags_UseAlpha = 0x2,
/** Explicit request to the application to ignore the alpha channel
* of the texture.
*
* Mutually exclusive with #aiTextureFlags_IgnoreAlpha.
*/
aiTextureFlags_IgnoreAlpha = 0x4,
/** @cond never
* This value is not used. It forces the compiler to use at least
@ -539,6 +561,25 @@ struct aiUVTransform
// ---------------------------------------------------------------------------
/** @brief Data structure for a single material property
*
* As an user, you'll probably never need to deal with this data structure.
* Just use the provided aiGetMaterialXXX() or aiMaterial::Get() family
* of functions to query material properties easily. Processing them
* manually is faster, but it is not the recommended way. It isn't worth
* the effort. <br>
* Material property names follow a simple scheme:
* @code
* $<name>
* ?<name>
* A public property, there must be corresponding AI_MATKEY_XXX define
* 2nd: Public, but ignored by the #aiProcess_RemoveRedundantMaterials
* post-processing step.
* ~<name>
* A temporary property for internal use. If someone forgets to
* cleanup, some of these might still be contained in the output.
* Don't complain, if you understood what the first paragraph tried
* to tell you, you wouldn't even know.
* @endcode
* @see aiMaterial
*/
struct aiMaterialProperty
@ -710,7 +751,7 @@ extern "C" {
* <b>Type:</b> string (aiString)<br>
* <b>Default value:</b> <tt>none</tt> <br>
*/
#define AI_MATKEY_NAME "$mat.name",0,0
#define AI_MATKEY_NAME "?mat.name",0,0
// ---------------------------------------------------------------------------
/** @def AI_MATKEY_TWOSIDED

View File

@ -171,7 +171,6 @@ struct aiNode
*/
#define AI_SCENE_FLAGS_INCOMPLETE 0x1
/** @def AI_SCENE_FLAGS_VALIDATED
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
* if the validation is successful. In a validated scene you can be sure that
@ -179,7 +178,6 @@ struct aiNode
*/
#define AI_SCENE_FLAGS_VALIDATED 0x2
/** @def AI_SCENE_FLAGS_VALIDATION_WARNING
* This flag is set by the validation postprocess-step (aiPostProcess_ValidateDS)
* if the validation is successful but some issues have been found.
@ -190,7 +188,6 @@ struct aiNode
*/
#define AI_SCENE_FLAGS_VALIDATION_WARNING 0x4
/** @def AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
* This flag is currently only set by the aiProcess_JoinIdenticalVertices step.
* It indicates that the vertices of the output meshes aren't in the internal
@ -199,7 +196,6 @@ struct aiNode
*/
#define AI_SCENE_FLAGS_NON_VERBOSE_FORMAT 0x8
/** @def AI_SCENE_FLAGS_TERRAIN
* Denotes pure height-map terrain data. Pure terrains usually consist of quads,
* sometimes triangles, in a regular grid. The x,y coordinates of all vertex
@ -212,7 +208,8 @@ struct aiNode
* as long as possible (typically you'll do the triangulation when you actually
* need to render it).
*/
#define AI_SCENE_FLAGS_TERRAIN 0x16
#define AI_SCENE_FLAGS_TERRAIN 0x10
// -------------------------------------------------------------------------------
/** The root structure of the imported data.

View File

@ -150,7 +150,8 @@ class AssetHelper
piShininessTexture (NULL),
piLightmapTexture (NULL),
pvOriginalNormals (NULL),
bSharedFX(false) {}
bSharedFX(false),
twosided (false){}
~MeshHelper ()
{
@ -203,6 +204,9 @@ class AssetHelper
// strength of the specular highlight
float fSpecularStrength;
// two-sided?
bool twosided;
// Stores a pointer to the original normal set of the asset
aiVector3D* pvOriginalNormals;
};

View File

@ -45,6 +45,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace AssimpView {
struct SVertex
{
float x,y,z,w,u,v;
};
CDisplay CDisplay::s_cInstance;
@ -91,43 +95,40 @@ void GetNodeCount(aiNode* pcNode, unsigned int* piCnt)
}
//-------------------------------------------------------------------------------
int CDisplay::EnableAnimTools(BOOL hm)
{
EnableWindow(GetDlgItem(g_hDlg,IDC_PLAY),hm);
EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),hm);
return 1;
}
//-------------------------------------------------------------------------------
// Fill animation combo box
int CDisplay::FillAnimList(void)
{
if (0 == g_pcAsset->pcScene->mNumAnimations)
if (0 != g_pcAsset->pcScene->mNumAnimations)
{
// disable all UI components related to animations
EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),FALSE);
EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE);
}
else
{
// reenable all animation components if they have been
// disabled for a previous mesh
EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),TRUE);
EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),TRUE);
// now fill in all animation names
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i)
{
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i) {
SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data);
}
// also add a dummy - 'none'
SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,(LPARAM)"none");
// select first
SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_SETCURSEL,0,0);
EnableAnimTools(TRUE);
}
else // tools remain disabled
EnableAnimTools(FALSE);
return 1;
}
//-------------------------------------------------------------------------------
// Clear the list of animations
int CDisplay::ClearAnimList(void)
{
// clear the combo box
@ -135,6 +136,7 @@ int CDisplay::ClearAnimList(void)
return 1;
}
//-------------------------------------------------------------------------------
// Clear the tree view
int CDisplay::ClearDisplayList(void)
{
// clear the combo box
@ -143,6 +145,7 @@ int CDisplay::ClearDisplayList(void)
return 1;
}
//-------------------------------------------------------------------------------
// Add a specific node to the display list
int CDisplay::AddNodeToDisplayList(
unsigned int iIndex,
unsigned int iDepth,
@ -154,10 +157,8 @@ int CDisplay::AddNodeToDisplayList(
char chTemp[512];
if(0 == pcNode->mName.length)
{
if (iIndex >= 100)
{
if(0 == pcNode->mName.length) {
if (iIndex >= 100) {
iIndex += iDepth * 1000;
}
else if (iIndex >= 10)
@ -190,8 +191,7 @@ int CDisplay::AddNodeToDisplayList(
// recursively add all child nodes
++iDepth;
for (unsigned int i = 0; i< pcNode->mNumChildren;++i)
{
for (unsigned int i = 0; i< pcNode->mNumChildren;++i){
AddNodeToDisplayList(i,iDepth,pcNode->mChildren[i],hTexture);
}
@ -203,6 +203,7 @@ int CDisplay::AddNodeToDisplayList(
return 1;
}
//-------------------------------------------------------------------------------
// Replace the currently selected texture by another one
int CDisplay::ReplaceCurrentTexture(const char* szPath)
{
ai_assert(NULL != szPath);
@ -214,8 +215,7 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
szString.length = strlen(szPath);
CMaterialManager::Instance().LoadTexture(&piTexture,&szString);
if (!piTexture)
{
if (!piTexture) {
CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this texture",
D3DCOLOR_ARGB(0xFF,0xFF,0x0,0x0));
return 0;
@ -225,15 +225,15 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
// view item if the default texture was previously set
TVITEMEX tvi;
tvi.mask = TVIF_SELECTEDIMAGE | TVIF_IMAGE;
tvi.iImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
tvi.iSelectedImage = this->m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
tvi.iImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
tvi.iSelectedImage = m_aiImageList[AI_VIEW_IMGLIST_MATERIAL];
TreeView_SetItem(GetDlgItem(g_hDlg,IDC_TREE1),
this->m_pcCurrentTexture->hTreeItem);
m_pcCurrentTexture->hTreeItem);
// change this in the old aiMaterial structure, too
Assimp::MaterialHelper* pcMat = (Assimp::MaterialHelper*)
g_pcAsset->pcScene->mMaterials[this->m_pcCurrentTexture->iMatIndex];
g_pcAsset->pcScene->mMaterials[m_pcCurrentTexture->iMatIndex];
// update all meshes referencing this material
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
@ -242,137 +242,73 @@ int CDisplay::ReplaceCurrentTexture(const char* szPath)
continue;
AssetHelper::MeshHelper* pcMesh = g_pcAsset->apcMeshes[i];
IDirect3DTexture9** tex = NULL;
const char* tex_string = NULL;
switch (this->m_pcCurrentTexture->iType)
{
case aiTextureType_DIFFUSE:
if (pcMesh->piDiffuseTexture && pcMesh->piDiffuseTexture != piTexture)
{
pcMesh->piDiffuseTexture->Release();
pcMesh->piDiffuseTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piDiffuseTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",piTexture);
}
}
tex = &pcMesh->piDiffuseTexture;
tex_string = "DIFFUSE_TEXTURE";
break;
case aiTextureType_AMBIENT:
if (pcMesh->piAmbientTexture && pcMesh->piAmbientTexture != piTexture)
{
pcMesh->piAmbientTexture->Release();
pcMesh->piAmbientTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piAmbientTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",piTexture);
}
}
tex = &pcMesh->piAmbientTexture;
tex_string = "AMBIENT_TEXTURE";
break;
case aiTextureType_SPECULAR:
if (pcMesh->piSpecularTexture && pcMesh->piSpecularTexture != piTexture)
{
pcMesh->piSpecularTexture->Release();
pcMesh->piSpecularTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piSpecularTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",piTexture);
}
}
tex = &pcMesh->piSpecularTexture;
tex_string = "SPECULAR_TEXTURE";
break;
case aiTextureType_EMISSIVE:
if (pcMesh->piEmissiveTexture && pcMesh->piEmissiveTexture != piTexture)
{
pcMesh->piEmissiveTexture->Release();
pcMesh->piEmissiveTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piEmissiveTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",piTexture);
}
}
tex = &pcMesh->piEmissiveTexture;
tex_string = "EMISSIVE_TEXTURE";
break;
case aiTextureType_LIGHTMAP:
tex = &pcMesh->piLightmapTexture;
tex_string = "LIGHTMAP_TEXTURE";
break;
case aiTextureType_DISPLACEMENT:
case aiTextureType_REFLECTION:
case aiTextureType_UNKNOWN:
break;
case aiTextureType_SHININESS:
if (pcMesh->piShininessTexture && pcMesh->piShininessTexture != piTexture)
{
pcMesh->piShininessTexture->Release();
pcMesh->piShininessTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piShininessTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",piTexture);
}
}
tex = &pcMesh->piShininessTexture;
tex_string = "SHININESS_TEXTURE";
break;
case aiTextureType_NORMALS:
case aiTextureType_HEIGHT:
if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture)
{
// special handling here
if (pcMesh->piNormalTexture && pcMesh->piNormalTexture != piTexture) {
pcMesh->piNormalTexture->Release();
pcMesh->piNormalTexture = piTexture;
CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,
&pcMesh->piNormalTexture,true);
this->m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture;
CMaterialManager::Instance().HMtoNMIfNecessary(pcMesh->piNormalTexture,&pcMesh->piNormalTexture,true);
m_pcCurrentTexture->piTexture = &pcMesh->piNormalTexture;
if (!pcMesh->bSharedFX)
{
if (!pcMesh->bSharedFX) {
pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",piTexture);
}
}
break;
default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
if (pcMesh->piOpacityTexture && pcMesh->piOpacityTexture != piTexture)
{
pcMesh->piOpacityTexture->Release();
pcMesh->piOpacityTexture = piTexture;
this->m_pcCurrentTexture->piTexture = &pcMesh->piOpacityTexture;
if (!pcMesh->bSharedFX)
{
pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",piTexture);
}
}
tex = &pcMesh->piOpacityTexture;
tex_string = "OPACITY_TEXTURE";
break;
};
if (tex && *tex && *tex != piTexture)
{
(**tex).Release();
*tex = piTexture;
m_pcCurrentTexture->piTexture = tex;
if (!pcMesh->bSharedFX){
pcMesh->piEffect->SetTexture(tex_string,piTexture);
}
}
}
// now update the material itself
aiString szOld;
const char* szKey = NULL;
#if 0
switch (this->m_pcCurrentTexture->iType)
{
case aiTextureType_DIFFUSE:
szKey = AI_MATKEY_TEXTURE_DIFFUSE(0);
break;
case aiTextureType_AMBIENT:
szKey = AI_MATKEY_TEXTURE_AMBIENT(0);
break;
case aiTextureType_SPECULAR:
szKey = AI_MATKEY_TEXTURE_SPECULAR(0);
break;
case aiTextureType_EMISSIVE:
szKey = AI_MATKEY_TEXTURE_EMISSIVE(0);
break;
case aiTextureType_NORMALS:
szKey = AI_MATKEY_TEXTURE_NORMALS(0);
break;
case aiTextureType_HEIGHT:
szKey = AI_MATKEY_TEXTURE_HEIGHT(0);
break;
case aiTextureType_SHININESS:
szKey = AI_MATKEY_TEXTURE_SHININESS(0);
break;
default: //case aiTextureType_OPACITY && case aiTextureType_OPACITY | 0x40000000:
szKey = AI_MATKEY_TEXTURE_OPACITY(0);
break;
};
#endif
ai_assert(NULL != szKey);
aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0),&szOld);
pcMat->AddProperty(&szString,AI_MATKEY_TEXTURE(m_pcCurrentTexture->iType,0));
@ -478,8 +414,7 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType,
szType = "Opacity";
break;
};
if (bIsExtraOpacity)
{
if (bIsExtraOpacity) {
sprintf(chTemp,"%s %i (<copy of diffuse #1>)",szType,iIndex+1);
}
else
@ -494,8 +429,7 @@ int CDisplay::AddTextureToDisplayList(unsigned int iType,
// find out whether this is the default texture or not
if (piTexture && *piTexture)
{
if (piTexture && *piTexture) {
// {9785DA94-1D96-426b-B3CB-BADC36347F5E}
static const GUID guidPrivateData =
{ 0x9785da94, 0x1d96, 0x426b,
@ -651,6 +585,7 @@ int CDisplay::AddMaterialToDisplayList(HTREEITEM hRoot,
return 1;
}
//-------------------------------------------------------------------------------
// Expand all elements in the treeview
int CDisplay::ExpandTree()
{
// expand all materials
@ -671,6 +606,7 @@ int CDisplay::ExpandTree()
return 1;
}
//-------------------------------------------------------------------------------
// Get image list for tree view
int CDisplay::LoadImageList(void)
{
if (!m_hImageList)
@ -708,6 +644,7 @@ int CDisplay::LoadImageList(void)
return 1;
}
//-------------------------------------------------------------------------------
// Fill tree view
int CDisplay::FillDisplayList(void)
{
LoadImageList();
@ -750,6 +687,7 @@ int CDisplay::FillDisplayList(void)
return 1;
}
//-------------------------------------------------------------------------------
// Main render loop
int CDisplay::OnRender()
{
// update possible animation
@ -759,10 +697,17 @@ int CDisplay::OnRender()
ai_assert( g_pcAsset->mAnimator);
if (g_bPlay) {
g_dCurrent += clock()/ double( CLOCKS_PER_SEC) -lastPlaying;
g_pcAsset->mAnimator->Calculate( g_dCurrent );
double time = g_dCurrent;
aiAnimation* mAnim = g_pcAsset->mAnimator->CurrentAnim();
if( mAnim && mAnim->mDuration > 0.0) {
double tps = mAnim->mTicksPerSecond ? mAnim->mTicksPerSecond : 25.f;
time = fmod( time, mAnim->mDuration/tps);
SendDlgItemMessage(g_hDlg,IDC_SLIDERANIM,TBM_SETPOS,TRUE,LPARAM(10000 * (time/(mAnim->mDuration/tps))));
}
g_pcAsset->mAnimator->Calculate( time );
lastPlaying = g_dCurrent;
}
}
@ -795,6 +740,7 @@ int CDisplay::OnRender()
return 1;
}
//-------------------------------------------------------------------------------
// Update UI
void UpdateColorFieldsInUI()
{
InvalidateRect(GetDlgItem(g_hDlg,IDC_LCOLOR1),NULL,TRUE);
@ -806,6 +752,7 @@ void UpdateColorFieldsInUI()
UpdateWindow(GetDlgItem(g_hDlg,IDC_LCOLOR3));
}
//-------------------------------------------------------------------------------
// FIll statistics UI
int CDisplay::FillDefaultStatistics(void)
{
if (!g_pcAsset)
@ -858,6 +805,7 @@ int CDisplay::FillDefaultStatistics(void)
return 1;
}
//-------------------------------------------------------------------------------
// Reset UI
int CDisplay::Reset(void)
{
// clear all lists
@ -870,6 +818,7 @@ int CDisplay::Reset(void)
return OnSetupNormalView();
}
//-------------------------------------------------------------------------------
// reset to standard statistics view
void ShowNormalUIComponents()
{
ShowWindow(GetDlgItem(g_hDlg,IDC_NUMNODES),SW_SHOW);
@ -1089,60 +1038,45 @@ int CDisplay::OnSetupTextureView(TextureInfo* pcNew)
int CDisplay::OnSetup(HTREEITEM p_hTreeItem)
{
// search in our list for the item
union {
TextureInfo* pcNew;
NodeInfo* pcNew2;
MaterialInfo* pcNew3; };
MaterialInfo* pcNew3;
};
pcNew = NULL;
for (std::vector<TextureInfo>::iterator
i = this->m_asTextures.begin();
i != this->m_asTextures.end();++i)
{
if (p_hTreeItem == (*i).hTreeItem)
{
for (std::vector<TextureInfo>::iterator i = m_asTextures.begin();i != m_asTextures.end();++i){
if (p_hTreeItem == (*i).hTreeItem) {
pcNew = &(*i);
break;
}
}
if (pcNew)
{
return this->OnSetupTextureView(pcNew);
if (pcNew) {
return OnSetupTextureView(pcNew);
}
// seach the node list
for (std::vector<NodeInfo>::iterator
i = this->m_asNodes.begin();
i != this->m_asNodes.end();++i)
{
if (p_hTreeItem == (*i).hTreeItem)
{
for (std::vector<NodeInfo>::iterator i = m_asNodes.begin(); i != m_asNodes.end();++i){
if (p_hTreeItem == (*i).hTreeItem) {
pcNew2 = &(*i);
break;
}
}
if (pcNew2)
{
return this->OnSetupNodeView(pcNew2);
if (pcNew2) {
return OnSetupNodeView(pcNew2);
}
// seach the material list
for (std::vector<MaterialInfo>::iterator
i = this->m_asMaterials.begin();
i != this->m_asMaterials.end();++i)
{
if (p_hTreeItem == (*i).hTreeItem)
{
for (std::vector<MaterialInfo>::iterator i = m_asMaterials.begin();i != m_asMaterials.end();++i){
if (p_hTreeItem == (*i).hTreeItem){
pcNew3 = &(*i);
break;
}
}
if (pcNew3)
{
return this->OnSetupMaterialView(pcNew3);
if (pcNew3) {
return OnSetupMaterialView(pcNew3);
}
return this->OnSetupNormalView();
return OnSetupNormalView();
}
//-------------------------------------------------------------------------------
int CDisplay::ShowTreeViewContextMenu(HTREEITEM hItem)
@ -1499,6 +1433,7 @@ int CDisplay::HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam)
return 0;
}
//-------------------------------------------------------------------------------
// Setup stereo view
int CDisplay::SetupStereoView()
{
if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
@ -1515,6 +1450,7 @@ int CDisplay::SetupStereoView()
return 1;
}
//-------------------------------------------------------------------------------
// Do the actual rendering pass for the stereo view
int CDisplay::RenderStereoView(const aiMatrix4x4& m)
{
// and rerender the scene
@ -1550,6 +1486,7 @@ int CDisplay::RenderStereoView(const aiMatrix4x4& m)
return 1;
}
//-------------------------------------------------------------------------------
// Process input for the texture view
int CDisplay::HandleInputTextureView()
{
HandleMouseInputTextureView();
@ -1557,6 +1494,7 @@ int CDisplay::HandleInputTextureView()
return 1;
}
//-------------------------------------------------------------------------------
// Get input for the current state
int CDisplay::HandleInput()
{
if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
@ -1608,6 +1546,7 @@ int CDisplay::HandleInput()
return 1;
}
//-------------------------------------------------------------------------------
// Process input for an empty scen view to allow for skybox rotations
int CDisplay::HandleInputEmptyScene()
{
if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
@ -1630,6 +1569,7 @@ int CDisplay::HandleInputEmptyScene()
return 1;
}
//-------------------------------------------------------------------------------
// Draw the HUD on top of the scene
int CDisplay::DrawHUD()
{
// HACK: (thom) can't get the effect to work on non-shader cards, therefore deactivated for the moment
@ -1642,11 +1582,6 @@ int CDisplay::DrawHUD()
sRect.right -= sRect.left;
sRect.bottom -= sRect.top;
struct SVertex
{
float x,y,z,w,u,v;
};
// commit the texture to the shader
// FIX: Necessary because the texture view is also using this shader
g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture);
@ -1713,11 +1648,18 @@ int CDisplay::DrawHUD()
return 1;
}
//-------------------------------------------------------------------------------
// Render the full scene, all nodes
int CDisplay::RenderFullScene()
{
// reset the color index used for drawing normals
g_iCurrentColor = 0;
aiMatrix4x4 pcProj;
GetProjectionMatrix(pcProj);
vPos = GetCameraMatrix(mViewProjection);
mViewProjection = mViewProjection * pcProj;
// setup wireframe/solid rendering mode
if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
@ -1727,6 +1669,24 @@ int CDisplay::RenderFullScene()
g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
else g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
// for high-quality mode, enable anisotropic texture filtering
if (g_sOptions.bLowQuality) {
for (DWORD d = 0; d < 8;++d) {
g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
}
}
else {
for (DWORD d = 0; d < 8;++d) {
g_piDevice->SetSamplerState(d,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
g_piDevice->SetSamplerState(d,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
g_piDevice->SetSamplerState(d,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
g_piDevice->SetSamplerState(d,D3DSAMP_MAXANISOTROPY,g_sCaps.MaxAnisotropy);
}
}
// draw the scene background (clear and texture 2d)
CBackgroundPainter::Instance().OnPreRender();
@ -1764,6 +1724,34 @@ int CDisplay::RenderFullScene()
if (g_sOptions.bStereoView)
RenderStereoView(m);
// render the skeleton if necessary
if (g_sOptions.bSkeleton && NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode) {
// disable the z-buffer
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
if (g_sOptions.eDrawMode != RenderOptions::WIREFRAME) {
g_piDevice->SetRenderState(D3DRS_ZENABLE,FALSE);
}
g_piDevice->SetVertexDeclaration( gDefaultVertexDecl);
// this is very similar to the code in SetupMaterial()
ID3DXEffect* piEnd = g_piNormalsEffect;
aiMatrix4x4 pcProj = m * mViewProjection;
D3DXVECTOR4 vVector(1.f,0.f,0.f,1.f);
piEnd->SetVector("OUTPUT_COLOR",&vVector);
piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj);
UINT dwPasses = 0;
piEnd->Begin(&dwPasses,0);
piEnd->BeginPass(0);
RenderSkeleton(g_pcAsset->pcScene->mRootNode,m,m);
piEnd->EndPass();piEnd->End();
g_piDevice->SetRenderState(D3DRS_ZWRITEENABLE,TRUE);
g_piDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
}
// draw the HUD texture on top of the rendered scene using
// pre-projected vertices
@ -1778,6 +1766,37 @@ int CDisplay::RenderMaterialView()
return 1;
}
//-------------------------------------------------------------------------------
// Render animation skeleton
int CDisplay::RenderSkeleton (aiNode* piNode,const aiMatrix4x4& piMatrix, const aiMatrix4x4& parent)
{
aiMatrix4x4 me = g_pcAsset->mAnimator->GetGlobalTransform( piNode);
me.Transpose();
//me *= piMatrix;
if (piNode->mParent) {
AssetHelper::LineVertex data[2];
data[0].dColorDiffuse = data[1].dColorDiffuse = D3DCOLOR_ARGB(0xff,0xff,0,0);
data[0].vPosition.x = parent.d1;
data[0].vPosition.y = parent.d2;
data[0].vPosition.z = parent.d3;
data[1].vPosition.x = me.d1;
data[1].vPosition.y = me.d2;
data[1].vPosition.z = me.d3;
g_piDevice->DrawPrimitiveUP(D3DPT_LINELIST,1,&data,sizeof(AssetHelper::LineVertex));
}
// render all child nodes
for (unsigned int i = 0; i < piNode->mNumChildren;++i)
RenderSkeleton(piNode->mChildren[i],piMatrix, me );
return 1;
}
//-------------------------------------------------------------------------------
// Render a single node
int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
bool bAlpha /*= false*/)
{
@ -1801,14 +1820,9 @@ int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
bChangedVM = true;
}
aiMatrix4x4 pcProj;
GetProjectionMatrix(pcProj);
aiMatrix4x4 pcProj = aiMe * mViewProjection;
aiMatrix4x4 pcCam;
aiVector3D vPos = GetCameraMatrix(pcCam);
pcProj = (aiMe * pcCam) * pcProj;
pcCam = aiMe;
aiMatrix4x4 pcCam = aiMe;
pcCam.Inverse().Transpose();
// VERY UNOPTIMIZED, much stuff is redundant. Who cares?
@ -1911,11 +1925,6 @@ int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
const aiMesh* mesh = g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]];
AssetHelper::MeshHelper* helper = g_pcAsset->apcMeshes[piNode->mMeshes[i]];
// fix: Render triangle meshes only
if (mesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
continue;
// don't render the mesh if the render pass is incorrect
if (g_sOptions.bRenderMats && (helper->piOpacityTexture || helper->fOpacity != 1.0f) && !mesh->HasBones())
{
@ -1986,7 +1995,6 @@ int CDisplay::RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix,
ID3DXEffect* piEnd = g_piNormalsEffect;
piEnd->SetVector("OUTPUT_COLOR",&vVector);
piEnd->SetMatrix("WorldViewProjection", (const D3DXMATRIX*)&pcProj);
UINT dwPasses = 0;

View File

@ -295,6 +295,10 @@ public:
// Event handling for pop-up menus displayed by th tree view
int HandleTreeViewPopup(WPARAM wParam,LPARAM lParam);
//------------------------------------------------------------------
// Enable animation-related parts of the UI
int EnableAnimTools(BOOL hm) ;
//------------------------------------------------------------------
// setter for m_iViewMode
inline void SetViewMode(unsigned int p_iNew)
@ -444,6 +448,13 @@ private:
// Used by HandleTreeViewPopup().
int HandleTreeViewPopup2(WPARAM wParam,LPARAM lParam);
//------------------------------------------------------------------
// Render skeleton
int RenderSkeleton (aiNode* piNode,const aiMatrix4x4& piMatrix,
const aiMatrix4x4& parent);
private:
// view mode
@ -485,6 +496,10 @@ private:
// Colors used to draw the checker pattern (for the
// texture viewer as background )
D3DXVECTOR4 m_avCheckerColors[2];
// View projection matrix
aiMatrix4x4 mViewProjection;
aiVector3D vPos;
};
#endif // AV_DISPLAY_H_INCLUDE

View File

@ -825,9 +825,12 @@ int CMaterialManager::CreateMaterial(
}
else
{
int flags = 0;
aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags);
// try to find out whether the diffuse texture has any
// non-opaque pixels. If we find a few, use it as opacity texture
if (pcMesh->piDiffuseTexture && HasAlphaPixels(pcMesh->piDiffuseTexture))
if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture))
{
int iVal;
@ -911,11 +914,14 @@ int CMaterialManager::CreateMaterial(
// This is a workaround for some meshes in the DX SDK (e.g. tiny.x)
// FIX: Added this check to the x-loader, but the line remains to
// catch other loader doing the same ...
if (0.0f == pcMesh->fShininess)
{
if (0.0f == pcMesh->fShininess){
pcMesh->eShadingMode = aiShadingMode_Gouraud;
}
int two_sided = 0;
aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided);
pcMesh->twosided = (two_sided != 0);
// check whether we have already a material using the same
// shader. This will decrease loading time rapidly ...
for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
@ -969,7 +975,7 @@ int CMaterialManager::CreateMaterial(
return 2;
}
}
this->m_iShaderCount++;
m_iShaderCount++;
// build macros for the HLSL compiler
unsigned int iCurrent = 0;
@ -990,7 +996,6 @@ int CMaterialManager::CreateMaterial(
++iCurrent;
if (mapV == aiTextureMapMode_Wrap)
sMacro[iCurrent].Name = "AV_WRAPV";
else if (mapV == aiTextureMapMode_Mirror)
@ -1303,8 +1308,10 @@ int CMaterialManager::SetupMaterial (
}
}
// disable culling, if necessary
if (pcMesh->twosided && g_sOptions.bCulling) {
g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
}
// setup the correct shader technique to be used for drawing
if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0))
@ -1340,6 +1347,11 @@ int CMaterialManager::EndMaterial (AssetHelper::MeshHelper* pcMesh)
pcMesh->piEffect->EndPass();
pcMesh->piEffect->End();
// reenable culling if necessary
if (pcMesh->twosided && g_sOptions.bCulling) {
g_piDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
}
return 1;
}
}; // end namespace AssimpView

View File

@ -60,8 +60,17 @@ int CMeshRenderer::DrawUnsorted(unsigned int iIndex)
g_piDevice->SetIndices(g_pcAsset->apcMeshes[iIndex]->piIB);
D3DPRIMITIVETYPE type;
switch (g_pcAsset->pcScene->mMeshes[iIndex]->mPrimitiveTypes) {
case aiPrimitiveType_POINT:
type = D3DPT_POINTLIST;break;
case aiPrimitiveType_LINE:
type = D3DPT_LINELIST;break;
case aiPrimitiveType_TRIANGLE:
type = D3DPT_TRIANGLELIST;break;
}
// and draw the mesh
g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
g_piDevice->DrawIndexedPrimitive(type,
0,0,
g_pcAsset->pcScene->mMeshes[iIndex]->mNumVertices,0,
g_pcAsset->pcScene->mMeshes[iIndex]->mNumFaces);
@ -76,6 +85,8 @@ int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld)
AssetHelper::MeshHelper* pcHelper = g_pcAsset->apcMeshes[iIndex];
const aiMesh* pcMesh = g_pcAsset->pcScene->mMeshes[iIndex];
if (pcMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
return DrawUnsorted(iIndex);
if (pcMesh->HasBones())
return DrawUnsorted(iIndex);

View File

@ -1180,7 +1180,7 @@ INT_PTR CALLBACK SMMessageProc(HWND hwndDlg,UINT uMsg,
if (IDOK == LOWORD(wParam)) {
char s[30];
GetDlgItemText(hwndDlg,IDC_EDITSM,s,30);
g_smoothAngle = atof(s);
g_smoothAngle = (float)atof(s);
EndDialog(hwndDlg,0);
}
@ -1936,6 +1936,10 @@ __DRUNKEN_ALIEN_FROM_MARS:
{
g_bPlay = !g_bPlay;
SetDlgItemText(g_hDlg,IDC_PLAY,(g_bPlay ? "Stop" : "Play"));
if (g_bPlay)
EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),FALSE);
else EnableWindow(GetDlgItem(g_hDlg,IDC_SLIDERANIM),TRUE);
}
}
// check the file history

View File

@ -186,6 +186,13 @@ public:
return mCurrentAnimIndex;
}
// ----------------------------------------------------------------------------
/** @brief Get the current animation or NULL
*/
aiAnimation* CurrentAnim() const {
return mCurrentAnimIndex < mScene->mNumAnimations ? mScene->mAnimations[ mCurrentAnimIndex ] : NULL;
}
protected:
/** Recursively creates an internal node structure matching the

View File

@ -548,9 +548,6 @@ std::string g_szMaterialShader = std::string(
"#ifdef AV_CLAMPV\n"
"AddressV = CLAMP;\n"
"#endif\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_DIFFUSE_TEXTUR\n"
@ -559,9 +556,6 @@ std::string g_szMaterialShader = std::string(
"sampler DIFFUSE_SAMPLER2\n"
"{\n"
"Texture = <DIFFUSE_TEXTURE2>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_DIFFUSE_TEXTUR2\n"
@ -570,9 +564,6 @@ std::string g_szMaterialShader = std::string(
"sampler SPECULAR_SAMPLER\n"
"{\n"
"Texture = <SPECULAR_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_SPECULAR_TEXTUR\n"
@ -581,9 +572,6 @@ std::string g_szMaterialShader = std::string(
"sampler AMBIENT_SAMPLER\n"
"{\n"
"Texture = <AMBIENT_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_AMBIENT_TEXTUR\n"
@ -592,9 +580,6 @@ std::string g_szMaterialShader = std::string(
"sampler LIGHTMAP_SAMPLER\n"
"{\n"
"Texture = <LIGHTMAP_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_LIGHTMAP_TEXTURE\n"
@ -603,9 +588,6 @@ std::string g_szMaterialShader = std::string(
"sampler OPACITY_SAMPLER\n"
"{\n"
"Texture = <OPACITY_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_OPACITY_TEXTURE\n"
@ -614,9 +596,6 @@ std::string g_szMaterialShader = std::string(
"sampler EMISSIVE_SAMPLER\n"
"{\n"
"Texture = <EMISSIVE_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_EMISSIVE_TEXTUR\n"
@ -625,9 +604,6 @@ std::string g_szMaterialShader = std::string(
"sampler NORMAL_SAMPLER\n"
"{\n"
"Texture = <NORMAL_TEXTURE>;\n"
"MinFilter=LINEAR;\n"
"MagFilter=LINEAR;\n"
"MipFilter=LINEAR;\n"
"};\n"
"#endif // AV_NORMAL_TEXTURE\n"
@ -1278,6 +1254,8 @@ std::string g_szPassThroughShader = std::string(
"sampler TEXTURE_SAMPLER = sampler_state\n"
"{\n"
"Texture = (TEXTURE_2D);\n"
"MinFilter = POINT;\n"
"MagFilter = POINT;\n"
"};\n"
// Vertex Shader output for pixel shader usage

Binary file not shown.

View File

@ -128,10 +128,6 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
// get current time
double fCur = (double)timeGetTime();
// Remove all line and point meshes from the import
aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
aiPrimitiveType_LINE | aiPrimitiveType_POINT);
// Call ASSIMPs C-API to load the file
g_pcAsset->pcScene = (aiScene*)aiImportFile(g_szFileName,
aiProcess_CalcTangentSpace | // calculate tangents and bitangents if possible
@ -456,24 +452,17 @@ int CreateAssetData()
const aiMesh* mesh = g_pcAsset->pcScene->mMeshes[i];
// create the material for the mesh
if (!g_pcAsset->apcMeshes[i]->piEffect)
{
if (!g_pcAsset->apcMeshes[i]->piEffect) {
CMaterialManager::Instance().CreateMaterial(
g_pcAsset->apcMeshes[i],mesh);
}
if (mesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
{
continue;
}
// create vertex buffer
if(FAILED( g_piDevice->CreateVertexBuffer(sizeof(AssetHelper::Vertex) *
mesh->mNumVertices,
D3DUSAGE_WRITEONLY,
0,
D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piVB,NULL)))
{
D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piVB,NULL))) {
MessageBox(g_hDlg,"Failed to create vertex buffer",
"ASSIMP Viewer Utility",MB_OK);
return 2;
@ -483,12 +472,22 @@ int CreateAssetData()
if (g_pcAsset->apcMeshes[i]->piOpacityTexture || 1.0f != g_pcAsset->apcMeshes[i]->fOpacity)
dwUsage |= D3DUSAGE_DYNAMIC;
unsigned int nidx;
switch (mesh->mPrimitiveTypes) {
case aiPrimitiveType_POINT:
nidx = 1;break;
case aiPrimitiveType_LINE:
nidx = 2;break;
case aiPrimitiveType_TRIANGLE:
nidx = 3;break;
default: assert(false);
};
// check whether we can use 16 bit indices
if (mesh->mNumFaces * 3 >= 65536)
{
if (mesh->mNumFaces * 3 >= 65536) {
// create 32 bit index buffer
if(FAILED( g_piDevice->CreateIndexBuffer( 4 *
mesh->mNumFaces * 3,
mesh->mNumFaces * nidx,
D3DUSAGE_WRITEONLY | dwUsage,
D3DFMT_INDEX32,
D3DPOOL_DEFAULT,
@ -505,17 +504,16 @@ int CreateAssetData()
g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
for (unsigned int x = 0; x < mesh->mNumFaces;++x)
{
for (unsigned int a = 0; a < 3;++a)
for (unsigned int a = 0; a < nidx;++a)
{
*pbData++ = mesh->mFaces[x].mIndices[a];
}
}
}
else
{
else {
// create 16 bit index buffer
if(FAILED( g_piDevice->CreateIndexBuffer( 2 *
mesh->mNumFaces * 3,
mesh->mNumFaces * nidx,
D3DUSAGE_WRITEONLY | dwUsage,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
@ -532,7 +530,7 @@ int CreateAssetData()
g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
for (unsigned int x = 0; x < mesh->mNumFaces;++x)
{
for (unsigned int a = 0; a < 3;++a)
for (unsigned int a = 0; a < nidx;++a)
{
*pbData++ = (uint16_t)mesh->mFaces[x].mIndices[a];
}
@ -542,8 +540,7 @@ int CreateAssetData()
// collect weights on all vertices. Quick and careless
std::vector<std::vector<aiVertexWeight> > weightsPerVertex( mesh->mNumVertices);
for( unsigned int a = 0; a < mesh->mNumBones; a++)
{
for( unsigned int a = 0; a < mesh->mNumBones; a++) {
const aiBone* bone = mesh->mBones[a];
for( unsigned int b = 0; b < bone->mNumWeights; b++)
weightsPerVertex[bone->mWeights[b].mVertexId].push_back( aiVertexWeight( a, bone->mWeights[b].mWeight));
@ -560,19 +557,16 @@ int CreateAssetData()
pbData2->vNormal = aiVector3D(0.0f,0.0f,0.0f);
else pbData2->vNormal = mesh->mNormals[x];
if (NULL == mesh->mTangents)
{
if (NULL == mesh->mTangents) {
pbData2->vTangent = aiVector3D(0.0f,0.0f,0.0f);
pbData2->vBitangent = aiVector3D(0.0f,0.0f,0.0f);
}
else
{
else {
pbData2->vTangent = mesh->mTangents[x];
pbData2->vBitangent = mesh->mBitangents[x];
}
if (mesh->HasVertexColors( 0))
{
if (mesh->HasVertexColors( 0)) {
pbData2->dColorDiffuse = D3DCOLOR_ARGB(
((unsigned char)std::max( std::min( mesh->mColors[0][x].a * 255.0f, 255.0f),0.0f)),
((unsigned char)std::max( std::min( mesh->mColors[0][x].r * 255.0f, 255.0f),0.0f)),
@ -582,16 +576,14 @@ int CreateAssetData()
else pbData2->dColorDiffuse = D3DCOLOR_ARGB(0xFF,0xff,0xff,0xff);
// ignore a third texture coordinate component
if (mesh->HasTextureCoords( 0))
{
if (mesh->HasTextureCoords( 0)) {
pbData2->vTextureUV = aiVector2D(
mesh->mTextureCoords[0][x].x,
mesh->mTextureCoords[0][x].y);
}
else pbData2->vTextureUV = aiVector2D(0.5f,0.5f);
if (mesh->HasTextureCoords( 1))
{
if (mesh->HasTextureCoords( 1)) {
pbData2->vTextureUV2 = aiVector2D(
mesh->mTextureCoords[1][x].x,
mesh->mTextureCoords[1][x].y);
@ -599,8 +591,7 @@ int CreateAssetData()
else pbData2->vTextureUV2 = aiVector2D(0.5f,0.5f);
// Bone indices and weights
if( mesh->HasBones())
{
if( mesh->HasBones()) {
unsigned char boneIndices[4] = { 0, 0, 0, 0 };
unsigned char boneWeights[4] = { 0, 0, 0, 0 };
ai_assert( weightsPerVertex[x].size() <= 4);
@ -623,8 +614,7 @@ int CreateAssetData()
g_pcAsset->apcMeshes[i]->piVB->Unlock();
// now generate the second vertex buffer, holding all normals
if (!g_pcAsset->apcMeshes[i]->piVBNormals)
{
if (!g_pcAsset->apcMeshes[i]->piVBNormals) {
GenerateNormalsAsLineList(g_pcAsset->apcMeshes[i],mesh);
}
}

View File

@ -96,7 +96,7 @@ BEGIN
LTEXT "[A]",IDC_STATIC,552,348,11,8
LTEXT "[Z]",IDC_STATIC,552,358,11,8
LTEXT "[R]",IDC_STATIC,552,368,11,8
COMBOBOX IDC_COMBO1,353,361,84,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO1,353,361,84,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
CONTROL 149,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,0,114,9
CONTROL 148,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,229,114,9
CONTROL 147,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE,470,336,114,9