vrshoot

diff libs/assimp/ComputeUVMappingProcess.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/ComputeUVMappingProcess.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,504 @@
     1.4 +/*
     1.5 +Open Asset Import Library (assimp)
     1.6 +----------------------------------------------------------------------
     1.7 +
     1.8 +Copyright (c) 2006-2012, assimp team
     1.9 +All rights reserved.
    1.10 +
    1.11 +Redistribution and use of this software in source and binary forms, 
    1.12 +with or without modification, are permitted provided that the 
    1.13 +following conditions are met:
    1.14 +
    1.15 +* Redistributions of source code must retain the above
    1.16 +  copyright notice, this list of conditions and the
    1.17 +  following disclaimer.
    1.18 +
    1.19 +* Redistributions in binary form must reproduce the above
    1.20 +  copyright notice, this list of conditions and the
    1.21 +  following disclaimer in the documentation and/or other
    1.22 +  materials provided with the distribution.
    1.23 +
    1.24 +* Neither the name of the assimp team, nor the names of its
    1.25 +  contributors may be used to endorse or promote products
    1.26 +  derived from this software without specific prior
    1.27 +  written permission of the assimp team.
    1.28 +
    1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
    1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.40 +
    1.41 +----------------------------------------------------------------------
    1.42 +*/
    1.43 +
    1.44 +/** @file GenUVCoords step */
    1.45 +
    1.46 +
    1.47 +#include "AssimpPCH.h"
    1.48 +#include "ComputeUVMappingProcess.h"
    1.49 +#include "ProcessHelper.h"
    1.50 +
    1.51 +using namespace Assimp;
    1.52 +
    1.53 +namespace {
    1.54 +
    1.55 +	const static aiVector3D base_axis_y(0.f,1.f,0.f);
    1.56 +	const static aiVector3D base_axis_x(1.f,0.f,0.f);
    1.57 +	const static aiVector3D base_axis_z(0.f,0.f,1.f);
    1.58 +	const static float angle_epsilon = 0.95f;
    1.59 +}
    1.60 +
    1.61 +// ------------------------------------------------------------------------------------------------
    1.62 +// Constructor to be privately used by Importer
    1.63 +ComputeUVMappingProcess::ComputeUVMappingProcess()
    1.64 +{
    1.65 +	// nothing to do here
    1.66 +}
    1.67 +
    1.68 +// ------------------------------------------------------------------------------------------------
    1.69 +// Destructor, private as well
    1.70 +ComputeUVMappingProcess::~ComputeUVMappingProcess()
    1.71 +{
    1.72 +	// nothing to do here
    1.73 +}
    1.74 +
    1.75 +// ------------------------------------------------------------------------------------------------
    1.76 +// Returns whether the processing step is present in the given flag field.
    1.77 +bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
    1.78 +{
    1.79 +	return	(pFlags & aiProcess_GenUVCoords) != 0;
    1.80 +}
    1.81 +
    1.82 +// ------------------------------------------------------------------------------------------------
    1.83 +// Check whether a ray intersects a plane and find the intersection point
    1.84 +inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
    1.85 +	const aiVector3D& planeNormal, aiVector3D& pos)
    1.86 +{
    1.87 +	const float b = planeNormal * (planePos - ray.pos);
    1.88 +	float h = ray.dir * planeNormal;
    1.89 +    if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0)
    1.90 +		return false;
    1.91 +
    1.92 +    pos = ray.pos + (ray.dir * h);
    1.93 +    return true;
    1.94 +}
    1.95 +
    1.96 +// ------------------------------------------------------------------------------------------------
    1.97 +// Find the first empty UV channel in a mesh
    1.98 +inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
    1.99 +{
   1.100 +	for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
   1.101 +		if (!mesh->mTextureCoords[m])return m;
   1.102 +	
   1.103 +	DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
   1.104 +	return UINT_MAX;
   1.105 +}
   1.106 +
   1.107 +// ------------------------------------------------------------------------------------------------
   1.108 +// Try to remove UV seams
   1.109 +void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
   1.110 +{
   1.111 +	// TODO: just a very rough algorithm. I think it could be done
   1.112 +	// much easier, but I don't know how and am currently too tired to 
   1.113 +	// to think about a better solution. 
   1.114 +
   1.115 +	const static float LOWER_LIMIT = 0.1f;
   1.116 +	const static float UPPER_LIMIT = 0.9f;
   1.117 +
   1.118 +	const static float LOWER_EPSILON = 10e-3f;
   1.119 +	const static float UPPER_EPSILON = 1.f-10e-3f;
   1.120 +
   1.121 +	for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
   1.122 +	{
   1.123 +		const aiFace& face = mesh->mFaces[fidx];
   1.124 +		if (face.mNumIndices < 3) continue; // triangles and polygons only, please
   1.125 +
   1.126 +		unsigned int small = face.mNumIndices, large = small;
   1.127 +		bool zero = false, one = false, round_to_zero = false;
   1.128 +
   1.129 +		// Check whether this face lies on a UV seam. We can just guess,
   1.130 +		// but the assumption that a face with at least one very small
   1.131 +		// on the one side and one very large U coord on the other side 
   1.132 +		// lies on a UV seam should work for most cases.
   1.133 +		for (unsigned int n = 0; n < face.mNumIndices;++n)
   1.134 +		{
   1.135 +			if (out[face.mIndices[n]].x < LOWER_LIMIT)
   1.136 +			{
   1.137 +				small = n;
   1.138 +
   1.139 +				// If we have a U value very close to 0 we can't
   1.140 +				// round the others to 0, too.
   1.141 +				if (out[face.mIndices[n]].x <= LOWER_EPSILON)
   1.142 +					zero = true;
   1.143 +				else round_to_zero = true;
   1.144 +			}
   1.145 +			if (out[face.mIndices[n]].x > UPPER_LIMIT)
   1.146 +			{
   1.147 +				large = n;
   1.148 +
   1.149 +				// If we have a U value very close to 1 we can't
   1.150 +				// round the others to 1, too.
   1.151 +				if (out[face.mIndices[n]].x >= UPPER_EPSILON)
   1.152 +					one = true;
   1.153 +			}
   1.154 +		}
   1.155 +		if (small != face.mNumIndices && large != face.mNumIndices)
   1.156 +		{
   1.157 +			for (unsigned int n = 0; n < face.mNumIndices;++n)
   1.158 +			{
   1.159 +				// If the u value is over the upper limit and no other u 
   1.160 +				// value of that face is 0, round it to 0
   1.161 +				if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
   1.162 +					out[face.mIndices[n]].x = 0.f;
   1.163 +
   1.164 +				// If the u value is below the lower limit and no other u 
   1.165 +				// value of that face is 1, round it to 1
   1.166 +				else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
   1.167 +					out[face.mIndices[n]].x = 1.f;
   1.168 +
   1.169 +				// The face contains both 0 and 1 as UV coords. This can occur
   1.170 +				// for faces which have an edge that lies directly on the seam.
   1.171 +				// Due to numerical inaccuracies one U coord becomes 0, the
   1.172 +				// other 1. But we do still have a third UV coord to determine 
   1.173 +				// to which side we must round to.
   1.174 +				else if (one && zero)
   1.175 +				{
   1.176 +					if (round_to_zero && out[face.mIndices[n]].x >=  UPPER_EPSILON)
   1.177 +						out[face.mIndices[n]].x = 0.f;
   1.178 +					else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
   1.179 +						out[face.mIndices[n]].x = 1.f;
   1.180 +				}
   1.181 +			}
   1.182 +		}
   1.183 +	}
   1.184 +}
   1.185 +
   1.186 +// ------------------------------------------------------------------------------------------------
   1.187 +void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
   1.188 +{
   1.189 +	aiVector3D center, min, max;
   1.190 +	FindMeshCenter(mesh, center, min, max);
   1.191 +
   1.192 +	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
   1.193 +	// currently the mapping axis will always be one of x,y,z, except if the
   1.194 +	// PretransformVertices step is used (it transforms the meshes into worldspace, 
   1.195 +	// thus changing the mapping axis)
   1.196 +	if (axis * base_axis_x >= angle_epsilon)	{
   1.197 +
   1.198 +		// For each point get a normalized projection vector in the sphere,
   1.199 +		// get its longitude and latitude and map them to their respective
   1.200 +		// UV axes. Problems occur around the poles ... unsolvable.
   1.201 +		//
   1.202 +		// The spherical coordinate system looks like this:
   1.203 +		// x = cos(lon)*cos(lat)
   1.204 +		// y = sin(lon)*cos(lat)
   1.205 +		// z = sin(lat)
   1.206 +		// 
   1.207 +		// Thus we can derive:
   1.208 +		// lat  = arcsin (z)
   1.209 +		// lon  = arctan (y/x)
   1.210 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.211 +			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
   1.212 +			out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
   1.213 +				(asin  (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
   1.214 +		}
   1.215 +	}
   1.216 +	else if (axis * base_axis_y >= angle_epsilon)	{
   1.217 +		// ... just the same again
   1.218 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.219 +			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
   1.220 +			out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
   1.221 +				(asin  (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
   1.222 +		}
   1.223 +	}
   1.224 +	else if (axis * base_axis_z >= angle_epsilon)	{
   1.225 +		// ... just the same again
   1.226 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.227 +			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
   1.228 +			out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
   1.229 +				(asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
   1.230 +		}
   1.231 +	}
   1.232 +	// slower code path in case the mapping axis is not one of the coordinate system axes
   1.233 +	else	{
   1.234 +		aiMatrix4x4 mTrafo;
   1.235 +		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
   1.236 +
   1.237 +		// again the same, except we're applying a transformation now
   1.238 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.239 +			const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
   1.240 +			out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
   1.241 +				(asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
   1.242 +		}
   1.243 +	}
   1.244 +	
   1.245 +	
   1.246 +	// Now find and remove UV seams. A seam occurs if a face has a tcoord
   1.247 +	// close to zero on the one side, and a tcoord close to one on the
   1.248 +	// other side.
   1.249 +	RemoveUVSeams(mesh,out);
   1.250 +}
   1.251 +
   1.252 +// ------------------------------------------------------------------------------------------------
   1.253 +void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
   1.254 +{
   1.255 +	aiVector3D center, min, max;
   1.256 +
   1.257 +	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
   1.258 +	// currently the mapping axis will always be one of x,y,z, except if the
   1.259 +	// PretransformVertices step is used (it transforms the meshes into worldspace, 
   1.260 +	// thus changing the mapping axis)
   1.261 +	if (axis * base_axis_x >= angle_epsilon)	{
   1.262 +		FindMeshCenter(mesh, center, min, max);
   1.263 +		const float diff = max.x - min.x;
   1.264 +
   1.265 +		// If the main axis is 'z', the z coordinate of a point 'p' is mapped 
   1.266 +		// directly to the texture V axis. The other axis is derived from
   1.267 +		// the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
   1.268 +		// 'c' is the center point of the mesh.
   1.269 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.270 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.271 +			aiVector3D& uv  = out[pnt];
   1.272 +
   1.273 +			uv.y = (pos.x - min.x) / diff;
   1.274 +			uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
   1.275 +		}
   1.276 +	}
   1.277 +	else if (axis * base_axis_y >= angle_epsilon)	{
   1.278 +		FindMeshCenter(mesh, center, min, max);
   1.279 +		const float diff = max.y - min.y;
   1.280 +
   1.281 +		// just the same ...
   1.282 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.283 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.284 +			aiVector3D& uv  = out[pnt];
   1.285 +
   1.286 +			uv.y = (pos.y - min.y) / diff;
   1.287 +			uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
   1.288 +		}
   1.289 +	}
   1.290 +	else if (axis * base_axis_z >= angle_epsilon)	{
   1.291 +		FindMeshCenter(mesh, center, min, max);
   1.292 +		const float diff = max.z - min.z;
   1.293 +
   1.294 +		// just the same ...
   1.295 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.296 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.297 +			aiVector3D& uv  = out[pnt];
   1.298 +
   1.299 +			uv.y = (pos.z - min.z) / diff;
   1.300 +			uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
   1.301 +		}
   1.302 +	}
   1.303 +	// slower code path in case the mapping axis is not one of the coordinate system axes
   1.304 +	else {
   1.305 +		aiMatrix4x4 mTrafo;
   1.306 +		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
   1.307 +		FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
   1.308 +		const float diff = max.y - min.y;
   1.309 +
   1.310 +		// again the same, except we're applying a transformation now
   1.311 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
   1.312 +			const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
   1.313 +			aiVector3D& uv  = out[pnt];
   1.314 +
   1.315 +			uv.y = (pos.y - min.y) / diff;
   1.316 +			uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
   1.317 +		}
   1.318 +	}
   1.319 +
   1.320 +	// Now find and remove UV seams. A seam occurs if a face has a tcoord
   1.321 +	// close to zero on the one side, and a tcoord close to one on the
   1.322 +	// other side.
   1.323 +	RemoveUVSeams(mesh,out);
   1.324 +}
   1.325 +
   1.326 +// ------------------------------------------------------------------------------------------------
   1.327 +void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
   1.328 +{
   1.329 +	float diffu,diffv;
   1.330 +	aiVector3D center, min, max;
   1.331 +
   1.332 +	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
   1.333 +	// currently the mapping axis will always be one of x,y,z, except if the
   1.334 +	// PretransformVertices step is used (it transforms the meshes into worldspace, 
   1.335 +	// thus changing the mapping axis)
   1.336 +	if (axis * base_axis_x >= angle_epsilon)	{
   1.337 +		FindMeshCenter(mesh, center, min, max);
   1.338 +		diffu = max.z - min.z;
   1.339 +		diffv = max.y - min.y;
   1.340 +
   1.341 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.342 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.343 +			out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f);
   1.344 +		}
   1.345 +	}
   1.346 +	else if (axis * base_axis_y >= angle_epsilon)	{
   1.347 +		FindMeshCenter(mesh, center, min, max);
   1.348 +		diffu = max.x - min.x;
   1.349 +		diffv = max.z - min.z;
   1.350 +
   1.351 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.352 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.353 +			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
   1.354 +		}
   1.355 +	}
   1.356 +	else if (axis * base_axis_z >= angle_epsilon)	{
   1.357 +		FindMeshCenter(mesh, center, min, max);
   1.358 +		diffu = max.y - min.y;
   1.359 +		diffv = max.z - min.z;
   1.360 +
   1.361 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.362 +			const aiVector3D& pos = mesh->mVertices[pnt];
   1.363 +			out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
   1.364 +		}
   1.365 +	}
   1.366 +	// slower code path in case the mapping axis is not one of the coordinate system axes
   1.367 +	else
   1.368 +	{
   1.369 +		aiMatrix4x4 mTrafo;
   1.370 +		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
   1.371 +		FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
   1.372 +		diffu = max.x - min.x;
   1.373 +		diffv = max.z - min.z;
   1.374 +
   1.375 +		// again the same, except we're applying a transformation now
   1.376 +		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
   1.377 +			const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
   1.378 +			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
   1.379 +		}
   1.380 +	}
   1.381 +
   1.382 +	// shouldn't be necessary to remove UV seams ...
   1.383 +}
   1.384 +
   1.385 +// ------------------------------------------------------------------------------------------------
   1.386 +void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh* /*mesh*/, aiVector3D* /*out*/)
   1.387 +{
   1.388 +	DefaultLogger::get()->error("Mapping type currently not implemented");
   1.389 +}
   1.390 +
   1.391 +// ------------------------------------------------------------------------------------------------
   1.392 +void ComputeUVMappingProcess::Execute( aiScene* pScene) 
   1.393 +{
   1.394 +	DefaultLogger::get()->debug("GenUVCoordsProcess begin");
   1.395 +	char buffer[1024];
   1.396 +
   1.397 +	if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
   1.398 +		throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
   1.399 +
   1.400 +	std::list<MappingInfo> mappingStack;
   1.401 +
   1.402 +	/*  Iterate through all materials and search for non-UV mapped textures
   1.403 +	 */
   1.404 +	for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
   1.405 +	{
   1.406 +		mappingStack.clear();
   1.407 +		aiMaterial* mat = pScene->mMaterials[i];
   1.408 +		for (unsigned int a = 0; a < mat->mNumProperties;++a)
   1.409 +		{
   1.410 +			aiMaterialProperty* prop = mat->mProperties[a];
   1.411 +			if (!::strcmp( prop->mKey.data, "$tex.mapping"))
   1.412 +			{
   1.413 +				aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
   1.414 +				if (aiTextureMapping_UV != mapping)
   1.415 +				{
   1.416 +					if (!DefaultLogger::isNullLogger())
   1.417 +					{
   1.418 +						sprintf(buffer, "Found non-UV mapped texture (%s,%i). Mapping type: %s",
   1.419 +							TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
   1.420 +							MappingTypeToString(mapping));
   1.421 +
   1.422 +						DefaultLogger::get()->info(buffer);
   1.423 +					}
   1.424 +
   1.425 +					if (aiTextureMapping_OTHER == mapping)
   1.426 +						continue;
   1.427 +
   1.428 +					MappingInfo info (mapping);
   1.429 +
   1.430 +					// Get further properties - currently only the major axis
   1.431 +					for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
   1.432 +					{
   1.433 +						aiMaterialProperty* prop2 = mat->mProperties[a2];
   1.434 +						if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
   1.435 +							continue;
   1.436 +
   1.437 +						if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))	{
   1.438 +							info.axis = *((aiVector3D*)prop2->mData);
   1.439 +							break;
   1.440 +						}
   1.441 +					}
   1.442 +
   1.443 +					unsigned int idx;
   1.444 +
   1.445 +					// Check whether we have this mapping mode already
   1.446 +					std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
   1.447 +					if (mappingStack.end() != it)
   1.448 +					{
   1.449 +						idx = (*it).uv;
   1.450 +					}
   1.451 +					else
   1.452 +					{
   1.453 +						/*  We have found a non-UV mapped texture. Now
   1.454 +						*   we need to find all meshes using this material
   1.455 +						*   that we can compute UV channels for them.
   1.456 +						*/
   1.457 +						for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
   1.458 +						{
   1.459 +							aiMesh* mesh = pScene->mMeshes[m];
   1.460 +							unsigned int outIdx;
   1.461 +							if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
   1.462 +								!mesh->mNumVertices)
   1.463 +							{
   1.464 +								continue;
   1.465 +							}
   1.466 +
   1.467 +							// Allocate output storage
   1.468 +							aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
   1.469 +
   1.470 +							switch (mapping)
   1.471 +							{
   1.472 +							case aiTextureMapping_SPHERE:
   1.473 +								ComputeSphereMapping(mesh,info.axis,p);
   1.474 +								break;
   1.475 +							case aiTextureMapping_CYLINDER:
   1.476 +								ComputeCylinderMapping(mesh,info.axis,p);
   1.477 +								break;
   1.478 +							case aiTextureMapping_PLANE:
   1.479 +								ComputePlaneMapping(mesh,info.axis,p);
   1.480 +								break;
   1.481 +							case aiTextureMapping_BOX:
   1.482 +								ComputeBoxMapping(mesh,p);
   1.483 +								break;
   1.484 +							default:
   1.485 +								ai_assert(false);
   1.486 +							}
   1.487 +							if (m && idx != outIdx)
   1.488 +							{
   1.489 +								DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
   1.490 +									"this material have equal numbers of UV channels. The UV index stored in  "
   1.491 +									"the material structure does therefore not apply for all meshes. ");
   1.492 +							}
   1.493 +							idx = outIdx;
   1.494 +						}
   1.495 +						info.uv = idx;
   1.496 +						mappingStack.push_back(info);
   1.497 +					}
   1.498 +
   1.499 +					// Update the material property list
   1.500 +					mapping = aiTextureMapping_UV;
   1.501 +					((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
   1.502 +				}
   1.503 +			}
   1.504 +		}
   1.505 +	}
   1.506 +	DefaultLogger::get()->debug("GenUVCoordsProcess finished");
   1.507 +}