Finalized material system. Fixed texture coordinate transformation. Improvements to the ASE loaders, normals for the 3DS loader fixed. First try to load bones for MDL7 models (first try = failure ;-)).

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@54 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
aramis_acg
2008-06-03 21:50:53 +00:00
parent a3d2ff5f26
commit 8b2ca95419
18 changed files with 1601 additions and 698 deletions

View File

@@ -55,28 +55,90 @@ namespace Assimp
void TextureTransform::PreProcessUVTransform(
Dot3DS::Texture& rcIn)
{
if (rcIn.mOffsetU && 0.0f == fmodf(rcIn.mOffsetU, 1.0f ))
std::string s;
std::stringstream ss;
int iField;
if (rcIn.mOffsetU)
{
DefaultLogger::get()->warn("Texture coordinate offset in the x direction "
"is a multiple of 1. This is redundant ...");
rcIn.mOffsetU = 1.0f;
if (iField = (int)rcIn.mOffsetU)
{
if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{
float fNew = rcIn.mOffsetU-(float)iField;
ss << "[wrap] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetU = fNew;
}
else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
{
if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetU-(float)iField;
ss << "[mirror] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetU = fNew;
}
else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{
ss << "[clamp] Found texture coordinate U offset " << rcIn.mOffsetU << ". "
"This can be clamped to 1.0f";
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetU = 1.0f;
}
}
}
if (rcIn.mOffsetV && 0.0f == fmodf(rcIn.mOffsetV, 1.0f ))
if (rcIn.mOffsetV)
{
DefaultLogger::get()->warn("Texture coordinate offset in the y direction "
"is a multiple of 1. This is redundant ...");
rcIn.mOffsetV = 1.0f;
if (iField = (int)rcIn.mOffsetV)
{
if (aiTextureMapMode_Wrap == rcIn.mMapMode)
{
float fNew = rcIn.mOffsetV-(float)iField;
ss << "[wrap] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetV = fNew;
}
else if (aiTextureMapMode_Mirror == rcIn.mMapMode)
{
if (0 != (iField % 2))iField--;
float fNew = rcIn.mOffsetV-(float)iField;
ss << "[mirror] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be optimized to " << fNew;
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetV = fNew;
}
else if (aiTextureMapMode_Clamp == rcIn.mMapMode)
{
ss << "[clamp] Found texture coordinate V offset " << rcIn.mOffsetV << ". "
"This can be clamped to 1.0f";
ss >> s;
DefaultLogger::get()->info(s);
rcIn.mOffsetV = 1.0f;
}
}
}
if (rcIn.mRotation)
{
const float f = fmodf(rcIn.mRotation,2.0f * 3.141592653f );
if (f <= 0.05f && f >= -0.05f)
if (iField = (int)(rcIn.mRotation / 3.141592654f))
{
DefaultLogger::get()->warn("Texture coordinate rotation is a multiple "
"of 2 * PI. This is redundant");
rcIn.mRotation = 0.0f;
float fNew = rcIn.mRotation-(float)iField*3.141592654f;
ss << "[wrap] Found texture coordinate rotation " << rcIn.mRotation << ". "
"This can be optimized to " << fNew;
DefaultLogger::get()->info(s);
rcIn.mRotation = fNew;
}
}
return;
}
// ------------------------------------------------------------------------------------------------
void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
@@ -94,7 +156,8 @@ void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
(*i).fOffsetV == pcTex->mOffsetV &&
(*i).fScaleU == pcTex->mScaleU &&
(*i).fScaleV == pcTex->mScaleV &&
(*i).fRotation == pcTex->mRotation)
(*i).fRotation == pcTex->mRotation &&
(*i).iUVIndex == pcTex->iUVSrc)
{
(*i).pcTextures.push_back(pcTex);
return;
@@ -107,8 +170,12 @@ void TextureTransform::AddToList(std::vector<STransformVecInfo>& rasVec,
sInfo.fOffsetU = pcTex->mOffsetU;
sInfo.fOffsetV = pcTex->mOffsetV;
sInfo.fRotation = pcTex->mRotation;
sInfo.iUVIndex = pcTex->iUVSrc;
// add the texture to the list
sInfo.pcTextures.push_back(pcTex);
// and add the transformation itself to the second list
rasVec.push_back(sInfo);
}
// ------------------------------------------------------------------------------------------------
@@ -116,6 +183,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
{
unsigned int iCnt = 0;
Dot3DS::Texture* pcTexture = NULL;
// diffuse texture
if (material.sTexDiffuse.mMapName.length())
{
@@ -200,7 +268,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
// coordinate sets of all meshes referencing *this* material
// However, we can't do it now. We need to wait until
// everything is sorted by materials.
if (1 == iCnt)
if (1 == iCnt && 0 == pcTexture->iUVSrc)
{
material.iBakeUVTransform = 1;
material.pcSingleTexture = pcTexture;
@@ -213,7 +281,7 @@ void TextureTransform::ApplyScaleNOffset(Dot3DS::Material& material)
}
}
// ------------------------------------------------------------------------------------------------
void TextureTransform::ApplyScaleNOffset(std::vector<Dot3DS::Material> materials)
void TextureTransform::ApplyScaleNOffset(std::vector<Dot3DS::Material>& materials)
{
unsigned int iNum = 0;
for (std::vector<Dot3DS::Material>::iterator
@@ -234,15 +302,19 @@ void TextureTransform::BakeScaleNOffset(
if (!pcMesh->mTextureCoords[0])return;
if (1 == pcSrc->iBakeUVTransform)
{
std::string s;
std::stringstream ss(s);
ss << "Transforming existing UV channel. Source UV: " << 0
<< " OffsetU: " << pcSrc->pcSingleTexture->mOffsetU
<< " OffsetV: " << pcSrc->pcSingleTexture->mOffsetV
<< " ScaleU: " << pcSrc->pcSingleTexture->mScaleU
<< " ScaleV: " << pcSrc->pcSingleTexture->mScaleV
<< " Rotation (rad): " << pcSrc->pcSingleTexture->mRotation;
DefaultLogger::get()->info(s);
char szTemp[512];
sprintf(szTemp,"Transforming existing UV channel. Source UV: %i"
" OffsetU: %f"
" OffsetV: %f"
" ScaleU: %f"
" ScaleV: %f"
" Rotation (rad): %f",0,
pcSrc->pcSingleTexture->mOffsetU,
pcSrc->pcSingleTexture->mOffsetV,
pcSrc->pcSingleTexture->mScaleU,
pcSrc->pcSingleTexture->mScaleV,
pcSrc->pcSingleTexture->mRotation);
DefaultLogger::get()->info(std::string(szTemp));
if (!pcSrc->pcSingleTexture->mRotation)
{
@@ -279,6 +351,19 @@ void TextureTransform::BakeScaleNOffset(
}
else if (2 == pcSrc->iBakeUVTransform)
{
// first save all texture coordinate sets
aiVector3D* apvOriginalSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
{
apvOriginalSets[i] = pcMesh->mTextureCoords[i];
}
unsigned int iNextEmpty = 0;
while (pcMesh->mTextureCoords[++iNextEmpty]);
aiVector3D* apvOutputSets[AI_MAX_NUMBER_OF_TEXTURECOORDS];
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
apvOutputSets[i] = NULL;
// now we need to find all textures in the material
// which require scaling/offset operations
std::vector<STransformVecInfo> sOps;
@@ -290,108 +375,148 @@ void TextureTransform::BakeScaleNOffset(
AddToList(sOps,&pcSrc->sTexShininess);
AddToList(sOps,&pcSrc->sTexAmbient);
const aiVector3D* _pvBase;
if (0.0f == sOps[0].fOffsetU && 0.0f == sOps[0].fOffsetV &&
1.0f == sOps[0].fScaleU && 1.0f == sOps[0].fScaleV &&
0.0f == sOps[0].fRotation)
// check the list and find out how many we won't be able
// to generate.
std::vector<STransformVecInfo*> sFilteredOps;
unsigned int iNumUntransformed = 0;
sFilteredOps.reserve(sOps.size());
{
// we'll have an unmodified set, so we can use *this* one
_pvBase = pcMesh->mTextureCoords[0];
}
else
{
_pvBase = new aiVector3D[pcMesh->mNumVertices];
memcpy(const_cast<aiVector3D*>(_pvBase),pcMesh->mTextureCoords[0],
pcMesh->mNumVertices * sizeof(aiVector3D));
}
unsigned int iCnt = 0;
for (std::vector<STransformVecInfo>::iterator
i = sOps.begin();
i != sOps.end();++i,++iCnt)
{
if (!pcMesh->mTextureCoords[iCnt])
std::vector<STransformVecInfo*> sWishList;
sWishList.reserve(sOps.size());
for (unsigned int iUV = 0; iUV < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iUV)
{
pcMesh->mTextureCoords[iCnt] = new aiVector3D[pcMesh->mNumVertices];
}
// more than 4 UV texture channels are not available
if (iCnt >= AI_MAX_NUMBER_OF_TEXTURECOORDS)
{
for (std::vector<Dot3DS::Texture*>::iterator
a = (*i).pcTextures.begin();
a != (*i).pcTextures.end();++a)
for (std::vector<STransformVecInfo>::iterator
i = sOps.begin();
i != sOps.end();++i)
{
(*a)->iUVSrc = 0;
if (iUV != (*i).iUVIndex)continue;
if ((*i).IsUntransformed())
{
sFilteredOps.push_back(&(*i));
}
else sWishList.push_back(&(*i));
}
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;
}
// are we able to generate all?
const int iDiff = AI_MAX_NUMBER_OF_TEXTURECOORDS-(int)
(sWishList.size()+sFilteredOps.size());
std::string s;
std::stringstream ss(s);
ss << "Generating additional UV channel. Source UV: " << 0
<< " OffsetU: " << (*i).fOffsetU
<< " OffsetV: " << (*i).fOffsetV
<< " ScaleU: " << (*i).fScaleU
<< " ScaleV: " << (*i).fScaleV
<< " Rotation (rad): " << (*i).fRotation;
DefaultLogger::get()->info(s);
const aiVector3D* pvBase = _pvBase;
if (0.0f == (*i).fRotation)
iNumUntransformed = (unsigned int)sFilteredOps.size();
if (0 >= iDiff)
{
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
DefaultLogger::get()->warn("There are too many combinations of different "
"UV transformation operations to generate an own UV channel for each "
"(maximum is AI_MAX_NUMBER_OF_TEXTURECOORDS = 4 or 6). "
"An untransformed UV channel will be used for all remaining transformations");
std::vector<STransformVecInfo*>::const_iterator nash = sWishList.begin();
for (;nash != sWishList.end()-iDiff;++nash)
{
// scaling
pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
// offset
pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU;
pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV;
pvBase++;
sFilteredOps.push_back(*nash);
}
}
else
{
const float fSin = sinf((*i).fRotation);
const float fCos = cosf((*i).fRotation);
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{
// scaling
pcMesh->mTextureCoords[iCnt][n].x = pvBase->x * (*i).fScaleU;
pcMesh->mTextureCoords[iCnt][n].y = pvBase->y * (*i).fScaleV;
// rotation
pcMesh->mTextureCoords[iCnt][n].x *= fCos;
pcMesh->mTextureCoords[iCnt][n].y *= fSin;
// offset
pcMesh->mTextureCoords[iCnt][n].x += (*i).fOffsetU;
pcMesh->mTextureCoords[iCnt][n].y += (*i).fOffsetV;
pvBase++;
}
}
// setup the UV source index for each texture
for (std::vector<Dot3DS::Texture*>::iterator
a = (*i).pcTextures.begin();
a != (*i).pcTextures.end();++a)
{
(*a)->iUVSrc = iCnt;
for (std::vector<STransformVecInfo*>::const_iterator
nash = sWishList.begin();
nash != sWishList.end();++nash)sFilteredOps.push_back(*nash);
}
}
// release temporary storage
if (_pvBase != pcMesh->mTextureCoords[0])
delete[] _pvBase;
// now fill in all output IV indices
unsigned int iNum = 0;
for (std::vector<STransformVecInfo*>::iterator
bogart = sFilteredOps.begin();
bogart != sFilteredOps.end();++bogart,++iNum)
{
(**bogart).iUVIndex = iNum;
}
iNum = 0;
for (; iNum < iNumUntransformed; ++iNum)
pcMesh->mTextureCoords[iNum] = apvOriginalSets[iNum];
// now generate the texture coordinate sets
for (std::vector<STransformVecInfo*>::iterator
i = sFilteredOps.begin()+iNumUntransformed;
i != sFilteredOps.end();++i,++iNum)
{
const aiVector3D* _pvBase = apvOriginalSets[(**i).iUVIndex];
aiVector3D* _pvOut = new aiVector3D[pcMesh->mNumVertices];
pcMesh->mTextureCoords[iNum] = _pvOut;
char szTemp[512];
sprintf(szTemp,"Generating additional UV channel. Source UV: %i"
" OffsetU: %f"
" OffsetV: %f"
" ScaleU: %f"
" ScaleV: %f"
" Rotation (rad): %f",0,
(**i).fOffsetU,
(**i).fOffsetV,
(**i).fScaleU,
(**i).fScaleV,
(**i).fRotation);
DefaultLogger::get()->info(std::string(szTemp));
const aiVector3D* pvBase = _pvBase;
aiVector3D* pvOut = _pvOut;
if (0.0f == (**i).fRotation)
{
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{
// scaling
pvOut->x = pvBase->x * (**i).fScaleU;
pvOut->y = pvBase->y * (**i).fScaleV;
// offset
pvOut->x += (**i).fOffsetU;
pvOut->y += (**i).fOffsetV;
pvBase++;
pvOut++;
}
}
else
{
const float fSin = sinf((**i).fRotation);
const float fCos = cosf((**i).fRotation);
for (unsigned int n = 0; n < pcMesh->mNumVertices;++n)
{
// scaling
pvOut->x = pvBase->x * (**i).fScaleU;
pvOut->y = pvBase->y * (**i).fScaleV;
// rotation
pvOut->x *= fCos;
pvOut->y *= fSin;
// offset
pvOut->x += (**i).fOffsetU;
pvOut->y += (**i).fOffsetV;
pvBase++;
pvOut++;
}
}
}
// now check which source texture coordinate sets
// can be deleted because they're not anymore required
for (iNum = 0; iNum < AI_MAX_NUMBER_OF_TEXTURECOORDS;++iNum)
{
for (unsigned int z = 0; z < iNumUntransformed;++z)
{
if (apvOriginalSets[iNum] == pcMesh->mTextureCoords[z])
{
apvOriginalSets[iNum] = NULL;
break;
}
}
if (apvOriginalSets[iNum])delete[] apvOriginalSets[iNum];
}
}
return;
}
// ------------------------------------------------------------------------------------------------
void TextureTransform::SetupMatUVSrc (aiMaterial* pcMat, const Dot3DS::Material* pcMatIn)