1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2013, assimp team |
6 | All rights reserved. |
7 | |
8 | Redistribution and use of this software in source and binary forms, |
9 | with or without modification, are permitted provided that the |
10 | following conditions are met: |
11 | |
12 | * Redistributions of source code must retain the above |
13 | copyright notice, this list of conditions and the |
14 | following disclaimer. |
15 | |
16 | * Redistributions in binary form must reproduce the above |
17 | copyright notice, this list of conditions and the |
18 | following disclaimer in the documentation and/or other |
19 | materials provided with the distribution. |
20 | |
21 | * Neither the name of the assimp team, nor the names of its |
22 | contributors may be used to endorse or promote products |
23 | derived from this software without specific prior |
24 | written permission of the assimp team. |
25 | |
26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
27 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
30 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
31 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
32 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
33 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
34 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
35 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
36 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | |
38 | ---------------------------------------------------------------------- |
39 | */ |
40 | |
41 | /** @file BlenderBMesh.cpp |
42 | * @brief Conversion of Blender's new BMesh stuff |
43 | */ |
44 | |
45 | |
46 | #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER |
47 | |
48 | #include "BlenderDNA.h" |
49 | #include "BlenderScene.h" |
50 | #include "BlenderBMesh.h" |
51 | #include "BlenderTessellator.h" |
52 | |
53 | namespace Assimp |
54 | { |
55 | template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix() |
56 | { |
57 | static auto prefix = "BLEND_BMESH: " ; |
58 | return prefix; |
59 | } |
60 | } |
61 | |
62 | using namespace Assimp; |
63 | using namespace Assimp::Blender; |
64 | using namespace Assimp::Formatter; |
65 | |
66 | // ------------------------------------------------------------------------------------------------ |
67 | BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ): |
68 | BMesh( mesh ), |
69 | triMesh( NULL ) |
70 | { |
71 | } |
72 | |
73 | // ------------------------------------------------------------------------------------------------ |
74 | BlenderBMeshConverter::~BlenderBMeshConverter( ) |
75 | { |
76 | DestroyTriMesh( ); |
77 | } |
78 | |
79 | // ------------------------------------------------------------------------------------------------ |
80 | bool BlenderBMeshConverter::ContainsBMesh( ) const |
81 | { |
82 | // TODO - Should probably do some additional verification here |
83 | return BMesh->totpoly && BMesh->totloop && BMesh->totvert; |
84 | } |
85 | |
86 | // ------------------------------------------------------------------------------------------------ |
87 | const Mesh* BlenderBMeshConverter::TriangulateBMesh( ) |
88 | { |
89 | AssertValidMesh( ); |
90 | AssertValidSizes( ); |
91 | PrepareTriMesh( ); |
92 | |
93 | for ( int i = 0; i < BMesh->totpoly; ++i ) |
94 | { |
95 | const MPoly& poly = BMesh->mpoly[ i ]; |
96 | ConvertPolyToFaces( poly ); |
97 | } |
98 | |
99 | return triMesh; |
100 | } |
101 | |
102 | // ------------------------------------------------------------------------------------------------ |
103 | void BlenderBMeshConverter::AssertValidMesh( ) |
104 | { |
105 | if ( !ContainsBMesh( ) ) |
106 | { |
107 | ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" ); |
108 | } |
109 | } |
110 | |
111 | // ------------------------------------------------------------------------------------------------ |
112 | void BlenderBMeshConverter::AssertValidSizes( ) |
113 | { |
114 | if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) ) |
115 | { |
116 | ThrowException( "BMesh poly array has incorrect size" ); |
117 | } |
118 | if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) ) |
119 | { |
120 | ThrowException( "BMesh loop array has incorrect size" ); |
121 | } |
122 | } |
123 | |
124 | // ------------------------------------------------------------------------------------------------ |
125 | void BlenderBMeshConverter::PrepareTriMesh( ) |
126 | { |
127 | if ( triMesh ) |
128 | { |
129 | DestroyTriMesh( ); |
130 | } |
131 | |
132 | triMesh = new Mesh( *BMesh ); |
133 | triMesh->totface = 0; |
134 | triMesh->mface.clear( ); |
135 | } |
136 | |
137 | // ------------------------------------------------------------------------------------------------ |
138 | void BlenderBMeshConverter::DestroyTriMesh( ) |
139 | { |
140 | delete triMesh; |
141 | triMesh = NULL; |
142 | } |
143 | |
144 | // ------------------------------------------------------------------------------------------------ |
145 | void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly ) |
146 | { |
147 | const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ]; |
148 | |
149 | if ( poly.totloop == 3 || poly.totloop == 4 ) |
150 | { |
151 | AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 ); |
152 | |
153 | // UVs are optional, so only convert when present. |
154 | if ( BMesh->mloopuv.size() ) |
155 | { |
156 | if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) ) |
157 | { |
158 | ThrowException( "BMesh uv loop array has incorrect size" ); |
159 | } |
160 | const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ]; |
161 | AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 ); |
162 | } |
163 | } |
164 | else if ( poly.totloop > 4 ) |
165 | { |
166 | #if ASSIMP_BLEND_WITH_GLU_TESSELLATE |
167 | BlenderTessellatorGL tessGL( *this ); |
168 | tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); |
169 | #elif ASSIMP_BLEND_WITH_POLY_2_TRI |
170 | BlenderTessellatorP2T tessP2T( *this ); |
171 | tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); |
172 | #endif |
173 | } |
174 | } |
175 | |
176 | // ------------------------------------------------------------------------------------------------ |
177 | void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) |
178 | { |
179 | MFace face; |
180 | face.v1 = v1; |
181 | face.v2 = v2; |
182 | face.v3 = v3; |
183 | face.v4 = v4; |
184 | // TODO - Work out how materials work |
185 | face.mat_nr = 0; |
186 | triMesh->mface.push_back( face ); |
187 | triMesh->totface = static_cast<int>(triMesh->mface.size( )); |
188 | } |
189 | |
190 | // ------------------------------------------------------------------------------------------------ |
191 | void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 ) |
192 | { |
193 | MTFace mtface; |
194 | memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 ); |
195 | memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 ); |
196 | memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 ); |
197 | |
198 | if ( uv4 ) |
199 | { |
200 | memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 ); |
201 | } |
202 | |
203 | triMesh->mtface.push_back( mtface ); |
204 | } |
205 | |
206 | #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER |
207 | |