/src/assimp/code/AssetLib/Ogre/OgreMaterial.cpp
Line | Count | Source |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2025, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution. |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER |
43 | | |
44 | | #include "OgreImporter.h" |
45 | | #include <assimp/StringUtils.h> |
46 | | #include <assimp/TinyFormatter.h> |
47 | | #include <assimp/fast_atof.h> |
48 | | #include <assimp/material.h> |
49 | | #include <assimp/scene.h> |
50 | | #include <assimp/DefaultLogger.hpp> |
51 | | |
52 | | #include <memory> |
53 | | #include <sstream> |
54 | | #include <vector> |
55 | | |
56 | | using namespace std; |
57 | | |
58 | | namespace Assimp { |
59 | | namespace Ogre { |
60 | | |
61 | | static const string partComment = "//"; |
62 | | static const string partBlockStart = "{"; |
63 | | static const string partBlockEnd = "}"; |
64 | | |
65 | 0 | void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, Mesh *mesh) { |
66 | 0 | std::vector<aiMaterial *> materials; |
67 | | |
68 | | // Create materials that can be found and parsed via the IOSystem. |
69 | 0 | for (size_t i = 0, len = mesh->NumSubMeshes(); i < len; ++i) { |
70 | 0 | SubMesh *submesh = mesh->GetSubMesh(i); |
71 | 0 | if (submesh && !submesh->materialRef.empty()) { |
72 | 0 | aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef); |
73 | 0 | if (material) { |
74 | 0 | submesh->materialIndex = static_cast<int>(materials.size()); |
75 | 0 | materials.push_back(material); |
76 | 0 | } |
77 | 0 | } |
78 | 0 | } |
79 | |
|
80 | 0 | AssignMaterials(pScene, materials); |
81 | 0 | } |
82 | | |
83 | 0 | void OgreImporter::ReadMaterials(const std::string &pFile, Assimp::IOSystem *pIOHandler, aiScene *pScene, MeshXml *mesh) { |
84 | 0 | std::vector<aiMaterial *> materials; |
85 | | |
86 | | // Create materials that can be found and parsed via the IOSystem. |
87 | 0 | for (size_t i = 0, len = mesh->NumSubMeshes(); i < len; ++i) { |
88 | 0 | SubMeshXml *submesh = mesh->GetSubMesh(static_cast<uint16_t>(i)); |
89 | 0 | if (submesh && !submesh->materialRef.empty()) { |
90 | 0 | aiMaterial *material = ReadMaterial(pFile, pIOHandler, submesh->materialRef); |
91 | 0 | if (material) { |
92 | 0 | submesh->materialIndex = static_cast<int>(materials.size()); |
93 | 0 | materials.push_back(material); |
94 | 0 | } |
95 | 0 | } |
96 | 0 | } |
97 | |
|
98 | 0 | AssignMaterials(pScene, materials); |
99 | 0 | } |
100 | | |
101 | 0 | void OgreImporter::AssignMaterials(aiScene *pScene, std::vector<aiMaterial *> &materials) { |
102 | 0 | pScene->mNumMaterials = static_cast<unsigned int>(materials.size()); |
103 | 0 | if (pScene->mNumMaterials > 0) { |
104 | 0 | pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; |
105 | 0 | for (size_t i = 0; i < pScene->mNumMaterials; ++i) { |
106 | 0 | pScene->mMaterials[i] = materials[i]; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | } |
110 | | |
111 | 0 | aiMaterial *OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSystem *pIOHandler, const std::string &materialName) { |
112 | 0 | if (materialName.empty()) { |
113 | 0 | return nullptr; |
114 | 0 | } |
115 | | |
116 | | // Full reference and examples of Ogre Material Script |
117 | | // can be found from http://www.ogre3d.org/docs/manual/manual_14.html |
118 | | |
119 | | /*and here is another one: |
120 | | |
121 | | import * from abstract_base_passes_depth.material |
122 | | import * from abstract_base.material |
123 | | import * from mat_shadow_caster.material |
124 | | import * from mat_character_singlepass.material |
125 | | |
126 | | material hero/hair/caster : mat_shadow_caster_skin_areject |
127 | | { |
128 | | set $diffuse_map "hero_hair_alpha_c.dds" |
129 | | } |
130 | | |
131 | | material hero/hair_alpha : mat_char_cns_singlepass_areject_4weights |
132 | | { |
133 | | set $diffuse_map "hero_hair_alpha_c.dds" |
134 | | set $specular_map "hero_hair_alpha_s.dds" |
135 | | set $normal_map "hero_hair_alpha_n.dds" |
136 | | set $light_map "black_lightmap.dds" |
137 | | |
138 | | set $shadow_caster_material "hero/hair/caster" |
139 | | } |
140 | | */ |
141 | | |
142 | 0 | stringstream ss; |
143 | | |
144 | | // Scope for scopre_ptr auto release |
145 | 0 | { |
146 | | /* There are three .material options in priority order: |
147 | | 1) File with the material name (materialName) |
148 | | 2) File with the mesh files base name (pFile) |
149 | | 3) Optional user defined material library file (m_userDefinedMaterialLibFile) */ |
150 | 0 | std::vector<string> potentialFiles; |
151 | 0 | potentialFiles.push_back(materialName + ".material"); |
152 | 0 | potentialFiles.push_back(pFile.substr(0, pFile.rfind(".mesh")) + ".material"); |
153 | 0 | if (!m_userDefinedMaterialLibFile.empty()) |
154 | 0 | potentialFiles.push_back(m_userDefinedMaterialLibFile); |
155 | |
|
156 | 0 | IOStream *materialFile = nullptr; |
157 | 0 | for (size_t i = 0; i < potentialFiles.size(); ++i) { |
158 | 0 | materialFile = pIOHandler->Open(potentialFiles[i]); |
159 | 0 | if (materialFile) { |
160 | 0 | break; |
161 | 0 | } |
162 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); |
163 | 0 | } |
164 | 0 | if (!materialFile) { |
165 | 0 | ASSIMP_LOG_ERROR("Failed to find source file for material '", materialName, "'"); |
166 | 0 | return nullptr; |
167 | 0 | } |
168 | | |
169 | 0 | std::unique_ptr<IOStream> stream(materialFile); |
170 | 0 | if (stream->FileSize() == 0) { |
171 | 0 | ASSIMP_LOG_WARN("Source file for material '", materialName, "' is empty (size is 0 bytes)"); |
172 | 0 | return nullptr; |
173 | 0 | } |
174 | | |
175 | | // Read bytes |
176 | 0 | vector<char> data(stream->FileSize()); |
177 | 0 | stream->Read(&data[0], stream->FileSize(), 1); |
178 | | |
179 | | // Convert to UTF-8 and terminate the string for ss |
180 | 0 | BaseImporter::ConvertToUTF8(data); |
181 | 0 | data.push_back('\0'); |
182 | |
|
183 | 0 | ss << &data[0]; |
184 | 0 | } |
185 | | |
186 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("Reading material '", materialName, "'"); |
187 | |
|
188 | 0 | aiMaterial *material = new aiMaterial(); |
189 | 0 | m_textures.clear(); |
190 | |
|
191 | 0 | aiString matName(materialName); |
192 | 0 | material->AddProperty(&matName, AI_MATKEY_NAME); |
193 | | |
194 | | // The stringstream will push words from a line until newline. |
195 | | // It will also trim whitespace from line start and between words. |
196 | 0 | string linePart; |
197 | 0 | ss >> linePart; |
198 | |
|
199 | 0 | const string partMaterial = "material"; |
200 | 0 | const string partTechnique = "technique"; |
201 | |
|
202 | 0 | while (!ss.eof()) { |
203 | | // Skip commented lines |
204 | 0 | if (linePart == partComment) { |
205 | 0 | NextAfterNewLine(ss, linePart); |
206 | 0 | continue; |
207 | 0 | } |
208 | 0 | if (linePart != partMaterial) { |
209 | 0 | ss >> linePart; |
210 | 0 | continue; |
211 | 0 | } |
212 | | |
213 | 0 | ss >> linePart; |
214 | 0 | if (linePart != materialName) { |
215 | 0 | ss >> linePart; |
216 | 0 | continue; |
217 | 0 | } |
218 | | |
219 | 0 | NextAfterNewLine(ss, linePart); |
220 | 0 | if (linePart != partBlockStart) { |
221 | 0 | ASSIMP_LOG_ERROR("Invalid material: block start missing near index ", ss.tellg()); |
222 | 0 | return material; |
223 | 0 | } |
224 | | |
225 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("material '", materialName, "'"); |
226 | |
|
227 | 0 | while (linePart != partBlockEnd) { |
228 | | // Proceed to the first technique |
229 | 0 | ss >> linePart; |
230 | |
|
231 | 0 | if (linePart == partTechnique) { |
232 | 0 | std::string techniqueName = SkipLine(ss); |
233 | 0 | ReadTechnique(ai_trim(techniqueName), ss, material); |
234 | 0 | } |
235 | | |
236 | | // Read information from a custom material |
237 | | /** @todo This "set $x y" does not seem to be a official Ogre material system feature. |
238 | | Materials can inherit other materials and override texture units by using the (unique) |
239 | | parent texture unit name in your cloned material. |
240 | | This is not yet supported and below code is probably some hack from the original |
241 | | author of this Ogre importer. Should be removed? */ |
242 | 0 | if (linePart == "set") { |
243 | 0 | ss >> linePart; |
244 | 0 | if (linePart == "$specular") //todo load this values: |
245 | 0 | { |
246 | 0 | } else if (linePart == "$diffuse") { |
247 | 0 | } else if (linePart == "$ambient") { |
248 | 0 | } else if (linePart == "$colormap") { |
249 | 0 | ss >> linePart; |
250 | 0 | aiString cm(linePart); |
251 | 0 | material->AddProperty(&cm, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); |
252 | 0 | } else if (linePart == "$normalmap") { |
253 | 0 | ss >> linePart; |
254 | 0 | aiString nm(linePart); |
255 | 0 | material->AddProperty(&nm, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); |
256 | 0 | } else if (linePart == "$shininess_strength") { |
257 | 0 | ss >> linePart; |
258 | 0 | float Shininess = fast_atof(linePart.c_str()); |
259 | 0 | material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS_STRENGTH); |
260 | 0 | } else if (linePart == "$shininess_exponent") { |
261 | 0 | ss >> linePart; |
262 | 0 | float Shininess = fast_atof(linePart.c_str()); |
263 | 0 | material->AddProperty(&Shininess, 1, AI_MATKEY_SHININESS); |
264 | 0 | } |
265 | | //Properties from Venetica: |
266 | 0 | else if (linePart == "$diffuse_map") { |
267 | 0 | ss >> linePart; |
268 | 0 | if (linePart[0] == '"') // "file" -> file |
269 | 0 | linePart = linePart.substr(1, linePart.size() - 2); |
270 | 0 | aiString ts(linePart); |
271 | 0 | material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); |
272 | 0 | } else if (linePart == "$specular_map") { |
273 | 0 | ss >> linePart; |
274 | 0 | if (linePart[0] == '"') // "file" -> file |
275 | 0 | linePart = linePart.substr(1, linePart.size() - 2); |
276 | 0 | aiString ts(linePart); |
277 | 0 | material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0)); |
278 | 0 | } else if (linePart == "$normal_map") { |
279 | 0 | ss >> linePart; |
280 | 0 | if (linePart[0] == '"') // "file" -> file |
281 | 0 | linePart = linePart.substr(1, linePart.size() - 2); |
282 | 0 | aiString ts(linePart); |
283 | 0 | material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); |
284 | 0 | } else if (linePart == "$light_map") { |
285 | 0 | ss >> linePart; |
286 | 0 | if (linePart[0] == '"') { |
287 | 0 | linePart = linePart.substr(1, linePart.size() - 2); |
288 | 0 | } |
289 | 0 | aiString ts(linePart); |
290 | 0 | material->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_LIGHTMAP, 0)); |
291 | 0 | } |
292 | 0 | } |
293 | 0 | } |
294 | 0 | ss >> linePart; |
295 | 0 | } |
296 | | |
297 | 0 | return material; |
298 | 0 | } |
299 | | |
300 | 0 | bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream &ss, aiMaterial *material) { |
301 | 0 | string linePart; |
302 | 0 | ss >> linePart; |
303 | |
|
304 | 0 | if (linePart != partBlockStart) { |
305 | 0 | ASSIMP_LOG_ERROR("Invalid material: Technique block start missing near index ", ss.tellg()); |
306 | 0 | return false; |
307 | 0 | } |
308 | | |
309 | 0 | ASSIMP_LOG_VERBOSE_DEBUG(" technique '", techniqueName, "'"); |
310 | |
|
311 | 0 | const string partPass = "pass"; |
312 | |
|
313 | 0 | while (linePart != partBlockEnd) { |
314 | 0 | ss >> linePart; |
315 | | |
316 | | // Skip commented lines |
317 | 0 | if (linePart == partComment) { |
318 | 0 | SkipLine(ss); |
319 | 0 | continue; |
320 | 0 | } |
321 | | |
322 | | /// @todo Techniques have other attributes than just passes. |
323 | 0 | if (linePart == partPass) { |
324 | 0 | string passName = SkipLine(ss); |
325 | 0 | ReadPass(ai_trim(passName), ss, material); |
326 | 0 | } |
327 | 0 | } |
328 | 0 | return true; |
329 | 0 | } |
330 | | |
331 | 0 | bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMaterial *material) { |
332 | 0 | string linePart; |
333 | 0 | ss >> linePart; |
334 | |
|
335 | 0 | if (linePart != partBlockStart) { |
336 | 0 | ASSIMP_LOG_ERROR("Invalid material: Pass block start missing near index ", ss.tellg()); |
337 | 0 | return false; |
338 | 0 | } |
339 | | |
340 | 0 | ASSIMP_LOG_VERBOSE_DEBUG(" pass '", passName, "'"); |
341 | |
|
342 | 0 | const string partAmbient = "ambient"; |
343 | 0 | const string partDiffuse = "diffuse"; |
344 | 0 | const string partSpecular = "specular"; |
345 | 0 | const string partEmissive = "emissive"; |
346 | 0 | const string partTextureUnit = "texture_unit"; |
347 | |
|
348 | 0 | while (linePart != partBlockEnd) { |
349 | 0 | ss >> linePart; |
350 | | |
351 | | // Skip commented lines |
352 | 0 | if (linePart == partComment) { |
353 | 0 | SkipLine(ss); |
354 | 0 | continue; |
355 | 0 | } |
356 | | |
357 | | // Colors |
358 | | /// @todo Support alpha via aiColor4D. |
359 | 0 | if (linePart == partAmbient || linePart == partDiffuse || linePart == partSpecular || linePart == partEmissive) { |
360 | 0 | float r, g, b; |
361 | 0 | ss >> r >> g >> b; |
362 | 0 | const aiColor3D color(r, g, b); |
363 | |
|
364 | 0 | ASSIMP_LOG_VERBOSE_DEBUG(" ", linePart, " ", r, " ", g, " ", b); |
365 | |
|
366 | 0 | if (linePart == partAmbient) { |
367 | 0 | material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT); |
368 | 0 | } else if (linePart == partDiffuse) { |
369 | 0 | material->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE); |
370 | 0 | } else if (linePart == partSpecular) { |
371 | 0 | material->AddProperty(&color, 1, AI_MATKEY_COLOR_SPECULAR); |
372 | 0 | } else if (linePart == partEmissive) { |
373 | 0 | material->AddProperty(&color, 1, AI_MATKEY_COLOR_EMISSIVE); |
374 | 0 | } |
375 | 0 | } else if (linePart == partTextureUnit) { |
376 | 0 | string textureUnitName = SkipLine(ss); |
377 | 0 | ReadTextureUnit(ai_trim(textureUnitName), ss, material); |
378 | 0 | } |
379 | 0 | } |
380 | 0 | return true; |
381 | 0 | } |
382 | | |
383 | 0 | bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstream &ss, aiMaterial *material) { |
384 | 0 | string linePart; |
385 | 0 | ss >> linePart; |
386 | |
|
387 | 0 | if (linePart != partBlockStart) { |
388 | 0 | ASSIMP_LOG_ERROR("Invalid material: Texture unit block start missing near index ", ss.tellg()); |
389 | 0 | return false; |
390 | 0 | } |
391 | | |
392 | 0 | ASSIMP_LOG_VERBOSE_DEBUG(" texture_unit '", textureUnitName, "'"); |
393 | |
|
394 | 0 | const string partTexture = "texture"; |
395 | 0 | const string partTextCoordSet = "tex_coord_set"; |
396 | 0 | const string partColorOp = "colour_op"; |
397 | |
|
398 | 0 | aiTextureType textureType = aiTextureType_NONE; |
399 | 0 | std::string textureRef; |
400 | 0 | int uvCoord = 0; |
401 | |
|
402 | 0 | while (linePart != partBlockEnd) { |
403 | 0 | ss >> linePart; |
404 | | |
405 | | // Skip commented lines |
406 | 0 | if (linePart == partComment) { |
407 | 0 | SkipLine(ss); |
408 | 0 | continue; |
409 | 0 | } |
410 | | |
411 | 0 | if (linePart == partTexture) { |
412 | 0 | ss >> linePart; |
413 | 0 | textureRef = linePart; |
414 | | |
415 | | // User defined Assimp config property to detect texture type from filename. |
416 | 0 | if (m_detectTextureTypeFromFilename) { |
417 | 0 | size_t posSuffix = textureRef.find_last_of('.'); |
418 | 0 | size_t posUnderscore = textureRef.find_last_of('_'); |
419 | |
|
420 | 0 | if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { |
421 | 0 | string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); |
422 | 0 | ASSIMP_LOG_VERBOSE_DEBUG("Detecting texture type from filename postfix '", identifier, "'"); |
423 | |
|
424 | 0 | if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { |
425 | 0 | textureType = aiTextureType_NORMALS; |
426 | 0 | } else if (identifier == "_s" || identifier == "_spec" || identifier == "_specular" || identifier == "_specularmap") { |
427 | 0 | textureType = aiTextureType_SPECULAR; |
428 | 0 | } else if (identifier == "_l" || identifier == "_light" || identifier == "_lightmap" || identifier == "_occ" || identifier == "_occlusion") { |
429 | 0 | textureType = aiTextureType_LIGHTMAP; |
430 | 0 | } else if (identifier == "_disp" || identifier == "_displacement") { |
431 | 0 | textureType = aiTextureType_DISPLACEMENT; |
432 | 0 | } else { |
433 | 0 | textureType = aiTextureType_DIFFUSE; |
434 | 0 | } |
435 | 0 | } else { |
436 | 0 | textureType = aiTextureType_DIFFUSE; |
437 | 0 | } |
438 | 0 | } |
439 | | // Detect from texture unit name. This cannot be too broad as |
440 | | // authors might give names like "LightSaber" or "NormalNinja". |
441 | 0 | else { |
442 | 0 | string unitNameLower = ai_tolower(textureUnitName); |
443 | 0 | if (unitNameLower.find("normalmap") != string::npos) { |
444 | 0 | textureType = aiTextureType_NORMALS; |
445 | 0 | } else if (unitNameLower.find("specularmap") != string::npos) { |
446 | 0 | textureType = aiTextureType_SPECULAR; |
447 | 0 | } else if (unitNameLower.find("lightmap") != string::npos) { |
448 | 0 | textureType = aiTextureType_LIGHTMAP; |
449 | 0 | } else if (unitNameLower.find("displacementmap") != string::npos) { |
450 | 0 | textureType = aiTextureType_DISPLACEMENT; |
451 | 0 | } else { |
452 | 0 | textureType = aiTextureType_DIFFUSE; |
453 | 0 | } |
454 | 0 | } |
455 | 0 | } else if (linePart == partTextCoordSet) { |
456 | 0 | ss >> uvCoord; |
457 | 0 | } |
458 | | /// @todo Implement |
459 | 0 | else if (linePart == partColorOp) { |
460 | | /* |
461 | | ss >> linePart; |
462 | | if("replace"==linePart)//I don't think, assimp has something for this... |
463 | | { |
464 | | } |
465 | | else if("modulate"==linePart) |
466 | | { |
467 | | //TODO: set value |
468 | | //material->AddProperty(aiTextureOp_Multiply) |
469 | | } |
470 | | */ |
471 | 0 | } |
472 | 0 | } |
473 | |
|
474 | 0 | if (textureRef.empty()) { |
475 | 0 | ASSIMP_LOG_WARN("Texture reference is empty, ignoring texture_unit."); |
476 | 0 | return false; |
477 | 0 | } |
478 | 0 | if (textureType == aiTextureType_NONE) { |
479 | 0 | ASSIMP_LOG_WARN("Failed to detect texture type for '", textureRef, "', ignoring texture_unit."); |
480 | 0 | return false; |
481 | 0 | } |
482 | | |
483 | 0 | unsigned int textureTypeIndex = m_textures[textureType]; |
484 | 0 | m_textures[textureType]++; |
485 | |
|
486 | 0 | ASSIMP_LOG_VERBOSE_DEBUG(" texture '", textureRef, "' type ", textureType, |
487 | 0 | " index ", textureTypeIndex, " UV ", uvCoord); |
488 | |
|
489 | 0 | aiString assimpTextureRef(textureRef); |
490 | 0 | material->AddProperty(&assimpTextureRef, AI_MATKEY_TEXTURE(textureType, textureTypeIndex)); |
491 | 0 | material->AddProperty(&uvCoord, 1, AI_MATKEY_UVWSRC(textureType, textureTypeIndex)); |
492 | |
|
493 | 0 | return true; |
494 | 0 | } |
495 | | |
496 | | } // namespace Ogre |
497 | | } // namespace Assimp |
498 | | |
499 | | #endif // ASSIMP_BUILD_NO_OGRE_IMPORTER |