View difference between Paste ID: vz51v8E9 and nxgJ3VG4
SHOW: | | - or go back to the newest paste.
1
#include <iostream>
2
#include <vector>
3
#include <fstream>
4
#include <limits>
5
#include <stdint.h> 
6
7
#include <assimp/Importer.hpp>      // C++ importer interface
8
#include <assimp/scene.h>           // Output data structure
9
#include <assimp/postprocess.h>     // Post processing flags
10
#include <assimp/ai_assert.h>
11
12
#pragma comment (lib, "assimp.lib")
13
14
// One instance per aiMesh in the globally loaded asset
15
MeshHelper** apcMeshes;
16
17
const aiScene* scene;
18
19
////////////////////////////////////////////////////////////
20
// Load
21
////////////////////////////////////////////////////////////
22
bool Load(const std::string& pFile)
23
{
24
	// Create an instance of the Importer class
25
	Assimp::Importer importer;
26
	// And have it read the given file with some example postprocessing
27
	// Usually - if speed is not the most important aspect for you - you'll 
28
	// propably to request more postprocessing than we do in this example.
29
	scene = importer.ReadFile(pFile, 
30
							aiProcess_CalcTangentSpace       | 
31
							aiProcess_Triangulate            |
32
							aiProcess_JoinIdenticalVertices  |
33
							aiProcess_FlipUVs);
34
  
35
	// If the import failed, report it
36
	if(!scene)
37
	{
38
		std::string s = "Error in load the " + pFile;
39
		MessageBoxA(NULL, s.c_str(), "Error mesh", MB_OK);
40
		return false;
41
	}
42
43
	// allocate a new MeshHelper array and build a new instance
44
	// for each mesh in the original asset
45
	apcMeshes = new MeshHelper*[scene->mNumMeshes]();
46
	for (unsigned int i = 0; i < scene->mNumMeshes;++i)
47
		apcMeshes[i] = new MeshHelper();
48
49
	for (unsigned int i = 0; i < scene->mNumMeshes;++i)
50
	{
51
		const aiMesh* mesh = scene->mMeshes[i];
52
53
		/*
54
		// create the material for the mesh
55
		if (!apcMeshes[i]->piEffect)	{
56
			CMaterialManager::Instance().CreateMaterial(apcMeshes[i], mesh);
57
		}
58
		*/
59
60
		// create vertex buffer
61
		if(FAILED( devices.d3ddev->CreateVertexBuffer(sizeof(Vertex) *
62
														mesh->mNumVertices,
63
														D3DUSAGE_WRITEONLY,
64
														0,
65
														D3DPOOL_DEFAULT, &apcMeshes[i]->piVB,NULL)))	
66
		{
67
			MessageBoxA(NULL, "Failed to create vertex buffer", "Error Model", MB_OK);
68
			return false;
69
		}
70
71
		DWORD dwUsage = 0;
72
		if (apcMeshes[i]->piOpacityTexture || 1.0f != apcMeshes[i]->fOpacity)
73
			dwUsage |= D3DUSAGE_DYNAMIC;
74
75
		unsigned int nidx;
76
		switch (mesh->mPrimitiveTypes) 
77
		{
78
			case aiPrimitiveType_POINT:
79
				nidx = 1;
80
				break;
81
			case aiPrimitiveType_LINE:
82
				nidx = 2;
83
				break;
84
			case aiPrimitiveType_TRIANGLE:
85
				nidx = 3;
86
				break;
87
			default: 
88
				ai_assert(false);
89
		};
90
91
92
		// check whether we can use 16 bit indices
93
		if (mesh->mNumFaces * 3 >= 65536)	{
94
			// create 32 bit index buffer
95
			if(FAILED( devices.d3ddev->CreateIndexBuffer( 4 * mesh->mNumFaces * nidx,
96
														D3DUSAGE_WRITEONLY | dwUsage,
97
														D3DFMT_INDEX32,
98
														D3DPOOL_DEFAULT, 
99
														&apcMeshes[i]->piIB,
100
														NULL)))
101
			{
102
				MessageBoxA(NULL, "Failed to create 32 Bit index buffer", "Error model", MB_OK);
103
				return false;
104
			}
105
106
			// now fill the index buffer
107
			unsigned int* pbData;
108
			apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
109
			for (unsigned int x = 0; x < mesh->mNumFaces;++x)
110
			{
111
				for (unsigned int a = 0; a < nidx;++a)
112
				{
113
					*pbData++ = mesh->mFaces[x].mIndices[a];
114
				}
115
			}
116
		}
117
		else	{
118
			// create 16 bit index buffer
119
			if(FAILED( devices.d3ddev->CreateIndexBuffer( 2 * mesh->mNumFaces * nidx,
120
														D3DUSAGE_WRITEONLY | dwUsage,
121
														D3DFMT_INDEX16,
122
														D3DPOOL_DEFAULT,
123
														&apcMeshes[i]->piIB,
124
														NULL)))
125
			{
126
				MessageBoxA(NULL, "Failed to create 16 Bit index buffer", "Error model", MB_OK);
127
				return false;
128
			}
129
130
			// now fill the index buffer
131
			uint16_t* pbData;
132
			apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
133
			for (unsigned int x = 0; x < mesh->mNumFaces;++x)
134
			{
135
				for (unsigned int a = 0; a < nidx;++a)
136
				{
137
					*pbData++ = (uint16_t)mesh->mFaces[x].mIndices[a];
138
				}
139
			}
140
		}
141
		apcMeshes[i]->piIB->Unlock();
142
143
		// collect weights on all vertices. Quick and careless
144
		std::vector<std::vector<aiVertexWeight>> weightsPerVertex( mesh->mNumVertices);
145
		for( unsigned int a = 0; a < mesh->mNumBones; a++)	{
146
			const aiBone* bone = mesh->mBones[a];
147
			for( unsigned int b = 0; b < bone->mNumWeights; b++)
148
				weightsPerVertex[bone->mWeights[b].mVertexId].push_back( aiVertexWeight( a, bone->mWeights[b].mWeight));
149
		}
150
151
		// now fill the vertex buffer
152
		Vertex* pbData2;
153
		apcMeshes[i]->piVB->Lock(0,0,(void**)&pbData2,0);
154
		for (unsigned int x = 0; x < mesh->mNumVertices;++x)
155
		{
156
			pbData2->vPosition = mesh->mVertices[x];
157
158
			if (NULL == mesh->mNormals)
159
				pbData2->vNormal = aiVector3D(0.0f,0.0f,0.0f);
160
			else pbData2->vNormal = mesh->mNormals[x];
161
162
			if (NULL == mesh->mTangents)	{
163
				pbData2->vTangent = aiVector3D(0.0f,0.0f,0.0f);
164
				pbData2->vBitangent = aiVector3D(0.0f,0.0f,0.0f);
165
			}
166
			else	{
167
				pbData2->vTangent = mesh->mTangents[x];
168
				pbData2->vBitangent = mesh->mBitangents[x];
169
			}
170
171
			if (mesh->HasVertexColors( 0 ))	{
172
				using std::min;
173
				using std::max;
174
				unsigned char m_argb[4];
175
				m_argb[0] = (unsigned char)max( min( mesh->mColors[0][x].a * 255.0f, 255.0f), 0.0f);
176
				m_argb[1] = (unsigned char)max( min( mesh->mColors[0][x].r * 255.0f, 255.0f), 0.0f);
177
				m_argb[2] = (unsigned char)max( min( mesh->mColors[0][x].g * 255.0f, 255.0f), 0.0f);
178
				m_argb[3] = (unsigned char)max( min( mesh->mColors[0][x].b * 255.0f, 255.0f), 0.0f);
179
180
				pbData2->dColorDiffuse = D3DCOLOR_ARGB(m_argb[0],m_argb[1],m_argb[2],m_argb[3]);
181
			}
182
			else pbData2->dColorDiffuse = D3DCOLOR_ARGB(0xFF,0xff,0xff,0xff);
183
184
			// ignore a third texture coordinate component
185
			if (mesh->HasTextureCoords( 0))	{
186
				pbData2->vTextureUV = aiVector2D(
187
					mesh->mTextureCoords[0][x].x,
188
					mesh->mTextureCoords[0][x].y);
189
			}
190
			else pbData2->vTextureUV = aiVector2D(0.5f,0.5f);
191
192
			if (mesh->HasTextureCoords( 1))	{
193
				pbData2->vTextureUV2 = aiVector2D(
194
					mesh->mTextureCoords[1][x].x,
195
					mesh->mTextureCoords[1][x].y);
196
			}
197
			else pbData2->vTextureUV2 = aiVector2D(0.5f,0.5f);
198
199
			// Bone indices and weights
200
			if( mesh->HasBones())	{
201
				unsigned char boneIndices[4] = { 0, 0, 0, 0 };
202
				unsigned char boneWeights[4] = { 0, 0, 0, 0 };
203
				ai_assert( weightsPerVertex[x].size() <= 4);
204
				for( unsigned int a = 0; a < weightsPerVertex[x].size(); a++)
205
				{
206
					boneIndices[a] = weightsPerVertex[x][a].mVertexId;
207
					boneWeights[a] = (unsigned char) (weightsPerVertex[x][a].mWeight * 255.0f);
208
				}
209
210
				memcpy( pbData2->mBoneIndices, boneIndices, sizeof( boneIndices));
211
				memcpy( pbData2->mBoneWeights, boneWeights, sizeof( boneWeights));
212
			} else
213
			{
214
				memset( pbData2->mBoneIndices, 0, sizeof( pbData2->mBoneIndices));
215
				memset( pbData2->mBoneWeights, 0, sizeof( pbData2->mBoneWeights));
216
			}
217
218
			++pbData2;
219
		}
220
		apcMeshes[i]->piVB->Unlock();
221
222
		// now generate the second vertex buffer, holding all normals
223
		if (!apcMeshes[i]->piVBNormals)	{
224
			//GenerateNormalsAsLineList(apcMeshes[i],mesh);
225
226
			ai_assert(NULL != apcMeshes[i]);
227
			ai_assert(NULL != mesh);
228
229
			if (!mesh->mNormals)return 0;
230
231
			// create vertex buffer
232
			if(FAILED( devices.d3ddev->CreateVertexBuffer(sizeof(LineVertex) *
233
														mesh->mNumVertices * 2,
234
														D3DUSAGE_WRITEONLY,
235
														LineVertex::GetFVF(),
236
														D3DPOOL_DEFAULT, &apcMeshes[i]->piVBNormals,NULL)))
237
			{
238
				MessageBoxA(NULL,"Failed to create vertex buffer for the normal list", "Error model", MB_OK);
239
				return false;
240
			}
241
242
			// now fill the vertex buffer with data
243
			LineVertex* pbData2;
244
			apcMeshes[i]->piVBNormals->Lock(0,0,(void**)&pbData2,0);
245
			for (unsigned int x = 0; x < mesh->mNumVertices;++x)
246
			{
247
				pbData2->vPosition = mesh->mVertices[x];
248
249
				++pbData2;
250
251
				aiVector3D vNormal = mesh->mNormals[x];
252
				vNormal.Normalize();
253
254
				// scalo with the inverse of the world scaling to make sure
255
				// the normals have equal length in each case
256
				// TODO: Check whether this works in every case, I don't think so
257
				//vNormal.x /= g_mWorld.a1*4;
258
				//vNormal.y /= g_mWorld.b2*4;
259
				//vNormal.z /= g_mWorld.c3*4;
260
261
				pbData2->vPosition = mesh->mVertices[x] + vNormal;
262
263
				++pbData2;
264
			}
265
			apcMeshes[i]->piVBNormals->Unlock();
266
		}
267
	}
268
269
	// get the number of vertices/faces in the model
270
	unsigned int iNumVert = 0;
271
	unsigned int iNumFaces = 0;
272
	for (unsigned int i = 0; i < scene->mNumMeshes;++i)
273
	{
274
		iNumVert += scene->mMeshes[i]->mNumVertices;
275
		iNumFaces += scene->mMeshes[i]->mNumFaces;
276
	}
277
278
	meshrender = new MeshRender(devices, scene, apcMeshes);
279
280
	return true;
281
}
282
283
////////////////////////////////////////////////////////////
284
// Render
285
////////////////////////////////////////////////////////////
286
void Render(bool wireframe)
287
{
288
	if(wireframe) 
289
	{
290
		devices.d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
291
	}
292
293
	aiMatrix4x4 m;
294
	RenderNode(scene->mRootNode, true);
295
	// render all child nodes
296
	for (unsigned int i = 0; i < scene->mRootNode->mNumChildren;++i)
297
		RenderNode(scene->mRootNode->mChildren[i], true );
298
299
	if(wireframe) 
300
	{
301
		devices.d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
302
	}
303
}
304
305
////////////////////////////////////////////////////////////
306
// Render a single node
307
////////////////////////////////////////////////////////////
308
bool RenderNode(aiNode* piNode, bool bAlpha)
309
{
310
	aiMatrix4x4 aiMe;
311
	aiMatrix4x4* piMatrix = new aiMatrix4x4();
312
313
	for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
314
	{
315
		if (bAlpha)
316
			meshrender->DrawSorted(piNode->mMeshes[i], aiMe);
317
		else 
318
			meshrender->DrawUnsorted(piNode->mMeshes[i]);
319
	}
320
321
322
	return true;
323
}
324
325
////////////////////////////////////////////////////////////
326
// Release
327
////////////////////////////////////////////////////////////
328
void Release()
329
{
330
	bool bNoMaterials = false;
331
	if (!scene)
332
		return;
333
334
	// TODO: Move this to a proper destructor
335
	for (unsigned int i = 0; i < scene->mNumMeshes;++i)
336
	{
337
		if(apcMeshes[i]->piVB)
338
		{
339
			apcMeshes[i]->piVB->Release();
340
			apcMeshes[i]->piVB = NULL;
341
		}
342
		if(apcMeshes[i]->piVBNormals)
343
		{
344
			apcMeshes[i]->piVBNormals->Release();
345
			apcMeshes[i]->piVBNormals = NULL;
346
		}
347
		if(apcMeshes[i]->piIB)
348
		{
349
			apcMeshes[i]->piIB->Release();
350
			apcMeshes[i]->piIB = NULL;
351
		}
352
353
		if (!bNoMaterials)
354
		{
355
			if(apcMeshes[i]->piEffect)
356
			{
357
				apcMeshes[i]->piEffect->Release();
358
				apcMeshes[i]->piEffect = NULL;
359
			}
360
			if(apcMeshes[i]->piDiffuseTexture)
361
			{
362
				apcMeshes[i]->piDiffuseTexture->Release();
363
				apcMeshes[i]->piDiffuseTexture = NULL;
364
			}
365
			if(apcMeshes[i]->piNormalTexture)
366
			{
367
				apcMeshes[i]->piNormalTexture->Release();
368
				apcMeshes[i]->piNormalTexture = NULL;
369
			}
370
			if(apcMeshes[i]->piSpecularTexture)
371
			{
372
				apcMeshes[i]->piSpecularTexture->Release();
373
				apcMeshes[i]->piSpecularTexture = NULL;
374
			}
375
			if(apcMeshes[i]->piAmbientTexture)
376
			{
377
				apcMeshes[i]->piAmbientTexture->Release();
378
				apcMeshes[i]->piAmbientTexture = NULL;
379
			}
380
			if(apcMeshes[i]->piEmissiveTexture)
381
			{
382
				apcMeshes[i]->piEmissiveTexture->Release();
383
				apcMeshes[i]->piEmissiveTexture = NULL;
384
			}
385
			if(apcMeshes[i]->piOpacityTexture)
386
			{
387
				apcMeshes[i]->piOpacityTexture->Release();
388
				apcMeshes[i]->piOpacityTexture = NULL;
389
			}
390
			if(apcMeshes[i]->piShininessTexture)
391
			{
392
				apcMeshes[i]->piShininessTexture->Release();
393
				apcMeshes[i]->piShininessTexture = NULL;
394
			}
395
		}
396
	}
397
}