rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file FindDegenerates.cpp
|
nuclear@0
|
43 * @brief Implementation of the FindDegenerates post-process step.
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47
|
nuclear@0
|
48 // internal headers
|
nuclear@0
|
49 #include "ProcessHelper.h"
|
nuclear@0
|
50 #include "FindDegenerates.h"
|
nuclear@0
|
51
|
nuclear@0
|
52 using namespace Assimp;
|
nuclear@0
|
53
|
nuclear@0
|
54 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
55 // Constructor to be privately used by Importer
|
nuclear@0
|
56 FindDegeneratesProcess::FindDegeneratesProcess()
|
nuclear@0
|
57 : configRemoveDegenerates (false)
|
nuclear@0
|
58 {}
|
nuclear@0
|
59
|
nuclear@0
|
60 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
61 // Destructor, private as well
|
nuclear@0
|
62 FindDegeneratesProcess::~FindDegeneratesProcess()
|
nuclear@0
|
63 {
|
nuclear@0
|
64 // nothing to do here
|
nuclear@0
|
65 }
|
nuclear@0
|
66
|
nuclear@0
|
67 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
68 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
69 bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
70 {
|
nuclear@0
|
71 return 0 != (pFlags & aiProcess_FindDegenerates);
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
75 // Setup import configuration
|
nuclear@0
|
76 void FindDegeneratesProcess::SetupProperties(const Importer* pImp)
|
nuclear@0
|
77 {
|
nuclear@0
|
78 // Get the current value of AI_CONFIG_PP_FD_REMOVE
|
nuclear@0
|
79 configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0));
|
nuclear@0
|
80 }
|
nuclear@0
|
81
|
nuclear@0
|
82 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
83 // Executes the post processing step on the given imported data.
|
nuclear@0
|
84 void FindDegeneratesProcess::Execute( aiScene* pScene)
|
nuclear@0
|
85 {
|
nuclear@0
|
86 DefaultLogger::get()->debug("FindDegeneratesProcess begin");
|
nuclear@0
|
87 for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
|
nuclear@0
|
88 ExecuteOnMesh( pScene->mMeshes[i]);
|
nuclear@0
|
89 }
|
nuclear@0
|
90 DefaultLogger::get()->debug("FindDegeneratesProcess finished");
|
nuclear@0
|
91 }
|
nuclear@0
|
92
|
nuclear@0
|
93 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
94 // Executes the post processing step on the given imported mesh
|
nuclear@0
|
95 void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh)
|
nuclear@0
|
96 {
|
nuclear@0
|
97 mesh->mPrimitiveTypes = 0;
|
nuclear@0
|
98
|
nuclear@0
|
99 std::vector<bool> remove_me;
|
nuclear@0
|
100 if (configRemoveDegenerates)
|
nuclear@0
|
101 remove_me.resize(mesh->mNumFaces,false);
|
nuclear@0
|
102
|
nuclear@0
|
103 unsigned int deg = 0, limit;
|
nuclear@0
|
104 for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
nuclear@0
|
105 {
|
nuclear@0
|
106 aiFace& face = mesh->mFaces[a];
|
nuclear@0
|
107 bool first = true;
|
nuclear@0
|
108
|
nuclear@0
|
109 // check whether the face contains degenerated entries
|
nuclear@0
|
110 for (register unsigned int i = 0; i < face.mNumIndices; ++i)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 // Polygons with more than 4 points are allowed to have double points, that is
|
nuclear@0
|
113 // simulating polygons with holes just with concave polygons. However,
|
nuclear@0
|
114 // double points may not come directly after another.
|
nuclear@0
|
115 limit = face.mNumIndices;
|
nuclear@0
|
116 if (face.mNumIndices > 4)
|
nuclear@0
|
117 limit = std::min(limit,i+2);
|
nuclear@0
|
118
|
nuclear@0
|
119 for (register unsigned int t = i+1; t < limit; ++t)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]])
|
nuclear@0
|
122 {
|
nuclear@0
|
123 // we have found a matching vertex position
|
nuclear@0
|
124 // remove the corresponding index from the array
|
nuclear@0
|
125 --face.mNumIndices;--limit;
|
nuclear@0
|
126 for (unsigned int m = t; m < face.mNumIndices; ++m)
|
nuclear@0
|
127 {
|
nuclear@0
|
128 face.mIndices[m] = face.mIndices[m+1];
|
nuclear@0
|
129 }
|
nuclear@0
|
130 --t;
|
nuclear@0
|
131
|
nuclear@0
|
132 // NOTE: we set the removed vertex index to an unique value
|
nuclear@0
|
133 // to make sure the developer gets notified when his
|
nuclear@0
|
134 // application attemps to access this data.
|
nuclear@0
|
135 face.mIndices[face.mNumIndices] = 0xdeadbeef;
|
nuclear@0
|
136
|
nuclear@0
|
137 if(first)
|
nuclear@0
|
138 {
|
nuclear@0
|
139 ++deg;
|
nuclear@0
|
140 first = false;
|
nuclear@0
|
141 }
|
nuclear@0
|
142
|
nuclear@0
|
143 if (configRemoveDegenerates) {
|
nuclear@0
|
144 remove_me[a] = true;
|
nuclear@0
|
145 goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby!
|
nuclear@0
|
146 }
|
nuclear@0
|
147 }
|
nuclear@0
|
148 }
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 // We need to update the primitive flags array of the mesh.
|
nuclear@0
|
152 switch (face.mNumIndices)
|
nuclear@0
|
153 {
|
nuclear@0
|
154 case 1u:
|
nuclear@0
|
155 mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
nuclear@0
|
156 break;
|
nuclear@0
|
157 case 2u:
|
nuclear@0
|
158 mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
nuclear@0
|
159 break;
|
nuclear@0
|
160 case 3u:
|
nuclear@0
|
161 mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
nuclear@0
|
162 break;
|
nuclear@0
|
163 default:
|
nuclear@0
|
164 mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
nuclear@0
|
165 break;
|
nuclear@0
|
166 };
|
nuclear@0
|
167 evil_jump_outside:
|
nuclear@0
|
168 continue;
|
nuclear@0
|
169 }
|
nuclear@0
|
170
|
nuclear@0
|
171 // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import
|
nuclear@0
|
172 if (configRemoveDegenerates && deg) {
|
nuclear@0
|
173 unsigned int n = 0;
|
nuclear@0
|
174 for (unsigned int a = 0; a < mesh->mNumFaces; ++a)
|
nuclear@0
|
175 {
|
nuclear@0
|
176 aiFace& face_src = mesh->mFaces[a];
|
nuclear@0
|
177 if (!remove_me[a]) {
|
nuclear@0
|
178 aiFace& face_dest = mesh->mFaces[n++];
|
nuclear@0
|
179
|
nuclear@0
|
180 // Do a manual copy, keep the index array
|
nuclear@0
|
181 face_dest.mNumIndices = face_src.mNumIndices;
|
nuclear@0
|
182 face_dest.mIndices = face_src.mIndices;
|
nuclear@0
|
183
|
nuclear@0
|
184 if (&face_src != &face_dest) {
|
nuclear@0
|
185 // clear source
|
nuclear@0
|
186 face_src.mNumIndices = 0;
|
nuclear@0
|
187 face_src.mIndices = NULL;
|
nuclear@0
|
188 }
|
nuclear@0
|
189 }
|
nuclear@0
|
190 else {
|
nuclear@0
|
191 // Otherwise delete it if we don't need this face
|
nuclear@0
|
192 delete[] face_src.mIndices;
|
nuclear@0
|
193 face_src.mIndices = NULL;
|
nuclear@0
|
194 face_src.mNumIndices = 0;
|
nuclear@0
|
195 }
|
nuclear@0
|
196 }
|
nuclear@0
|
197 // Just leave the rest of the array unreferenced, we don't care for now
|
nuclear@0
|
198 mesh->mNumFaces = n;
|
nuclear@0
|
199 if (!mesh->mNumFaces) {
|
nuclear@0
|
200 // WTF!?
|
nuclear@0
|
201 // OK ... for completeness and because I'm not yet tired,
|
nuclear@0
|
202 // let's write code that willl hopefully never be called
|
nuclear@0
|
203 // (famous last words)
|
nuclear@0
|
204
|
nuclear@0
|
205 // OK ... bad idea.
|
nuclear@0
|
206 throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
|
nuclear@0
|
207 }
|
nuclear@0
|
208 }
|
nuclear@0
|
209
|
nuclear@0
|
210 if (deg && !DefaultLogger::isNullLogger())
|
nuclear@0
|
211 {
|
nuclear@0
|
212 char s[64];
|
nuclear@0
|
213 ASSIMP_itoa10(s,deg);
|
nuclear@0
|
214 DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
|
nuclear@0
|
215 }
|
nuclear@0
|
216 }
|