1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2013, assimp team
6All rights reserved.
7
8Redistribution and use of this software in source and binary forms,
9with or without modification, are permitted provided that the
10following 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
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36OF 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
53namespace Assimp
54{
55 template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix()
56 {
57 static auto prefix = "BLEND_BMESH: ";
58 return prefix;
59 }
60}
61
62using namespace Assimp;
63using namespace Assimp::Blender;
64using namespace Assimp::Formatter;
65
66// ------------------------------------------------------------------------------------------------
67BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
68 BMesh( mesh ),
69 triMesh( NULL )
70{
71}
72
73// ------------------------------------------------------------------------------------------------
74BlenderBMeshConverter::~BlenderBMeshConverter( )
75{
76 DestroyTriMesh( );
77}
78
79// ------------------------------------------------------------------------------------------------
80bool BlenderBMeshConverter::ContainsBMesh( ) const
81{
82 // TODO - Should probably do some additional verification here
83 return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
84}
85
86// ------------------------------------------------------------------------------------------------
87const 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// ------------------------------------------------------------------------------------------------
103void 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// ------------------------------------------------------------------------------------------------
112void 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// ------------------------------------------------------------------------------------------------
125void 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// ------------------------------------------------------------------------------------------------
138void BlenderBMeshConverter::DestroyTriMesh( )
139{
140 delete triMesh;
141 triMesh = NULL;
142}
143
144// ------------------------------------------------------------------------------------------------
145void 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// ------------------------------------------------------------------------------------------------
177void 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// ------------------------------------------------------------------------------------------------
191void 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