Sfoglia il codice sorgente

test assimp model loading

Zoadian 11 anni fa
parent
commit
45eec489aa
4 ha cambiato i file con 316 aggiunte e 53 eliminazioni
  1. 2 0
      dub.json
  2. 191 39
      source/app.d
  3. 79 0
      source/three/assimp/package.d
  4. 44 14
      source/three/init.d

+ 2 - 0
dub.json

@@ -11,6 +11,8 @@
 		"derelict-gl3" : "~master",
 		"derelict-glfw3" : "~master",
 		"derelict-ft" : "~master",
+		"derelict-fi" : "~master",
+		"derelict-assimp3" : "~master",
 		"derelict_extras-anttweakbar" : "~master",
 		"stdx" : "~master",
 		"nitro" : "~master"

+ 191 - 39
source/app.d

@@ -8,6 +8,125 @@ import three.gl.util;
 
 import derelict.anttweakbar.anttweakbar;
 import derelict.glfw3.glfw3;
+import derelict.assimp3.assimp;
+
+import std.string;
+
+struct Vertex {
+	float x, y, z;
+}
+
+struct Normal {
+	float x, y, z;
+}
+
+struct UV {
+	float u, v;
+}
+
+struct Color {
+	float r, g, b, a;
+}
+
+struct Vector {
+	float x, y, z;
+}
+
+struct Quaternion {
+	float x, y, z, w;
+}
+
+
+final class Mesh {
+public:
+	Vertex[] vertexData;
+	Normal[] normalData;
+	UV[] textureData;
+	Color[] colorData;
+
+	Unique!(VertexArrayObject) vao;
+	Unique!(VertexBufferObject!(VertexBufferObjectTarget.Array)) vboVertexData;
+	Unique!(VertexBufferObject!(VertexBufferObjectTarget.Array)) vboNormalData;
+	Unique!(VertexBufferObject!(VertexBufferObjectTarget.Array)) vboTextureData;
+	Unique!(VertexBufferObject!(VertexBufferObjectTarget.Array)) vboColorData;
+
+	this(string filePath) {
+		writeln("loading scene: ", filePath);
+		auto scene = aiImportFile(filePath.toStringz(),	aiProcess_Triangulate);
+		writeln("meshes: ", scene.mNumMeshes);
+		for(uint m = 0; m < scene.mNumMeshes; ++m) {  
+			const(aiMesh*) mesh = scene.mMeshes[m];
+			assert(mesh !is null);
+			writeln("mesh[", m, "] faces : ", mesh.mNumFaces);
+			for (uint f = 0; f < mesh.mNumFaces; ++f) {	 
+				const(aiFace*) face = &mesh.mFaces[f];
+				assert(face !is null);
+				
+				for(uint v = 0; v < 3; ++v) {
+					aiVector3D p, n, uv; 
+					assert(face.mNumIndices > v);
+					uint vertex = face.mIndices[v];
+					assert(mesh.mNumVertices > vertex);
+					p = mesh.mVertices[vertex];
+					n = mesh.mNormals[vertex];
+					
+					// check if the mesh has texture coordinates
+					if(mesh.mTextureCoords[0] !is null) {
+						uv = mesh.mTextureCoords[0][vertex];
+					}
+					
+					vertexData ~= Vertex(p.x, p.y, p.z);
+					normalData ~= Normal(n.x, n.y, n.z);
+					textureData ~= UV(uv.x, uv.y);
+					colorData ~= Color(n.x, n.y, n.z, 1.0f);
+				}
+			}
+		}
+		writeln("unloading scene: ", filePath);
+		aiReleaseImport(scene);
+
+		//-----------------------------
+		// upload
+		vao = new VertexArrayObject();
+		vao.bind();
+		
+		vboVertexData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
+		vboVertexData.bind();
+		GLuint attribIndex = 0;
+		glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Vertex.sizeof * vertexData.length) , vertexData.ptr, GL_STATIC_DRAW);		
+		glEnableVertexAttribArray(attribIndex);
+		glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
+		vboVertexData.unbind();
+		
+		vboNormalData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
+		vboNormalData.bind();
+		attribIndex = 1;
+		glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Normal.sizeof * normalData.length) , normalData.ptr, GL_STATIC_DRAW);		
+		glEnableVertexAttribArray(attribIndex);
+		glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
+		vboNormalData.unbind();
+		
+		vboTextureData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
+		vboTextureData.bind();
+		attribIndex = 2;
+		glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(UV.sizeof * textureData.length) , textureData.ptr, GL_STATIC_DRAW);		
+		glEnableVertexAttribArray(attribIndex);
+		glVertexAttribPointer(attribIndex, 2, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
+		vboTextureData.unbind();
+		
+		vboColorData = new VertexBufferObject!(VertexBufferObjectTarget.Array);
+		vboColorData.bind();
+		attribIndex = 3;
+		glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(Color.sizeof * colorData.length) , colorData.ptr, GL_STATIC_DRAW);		
+		glEnableVertexAttribArray(attribIndex);
+		glVertexAttribPointer(attribIndex, 4, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
+		vboColorData.unbind();		
+		
+		vao.unbind();
+	}
+}
+
+
 
 class Tester {
 	Unique!(Window) _window;
@@ -24,8 +143,13 @@ class Tester {
 		//_window.destroy();
 		deinitThree();
 	}
-	
+
 	void run() {
+		auto mesh = new Mesh("C:/Coding/models/Collada/duck.dae");
+
+		//-----------------
+		// Create TweakBar
+		writeln("creating TweakBar");
 		double time        = 0, dt;              // Current time and enlapsed time
 		double turn        = 0;                  // Model turn counter
 		double speed       = 0.3;                // Model rotation speed
@@ -35,32 +159,30 @@ class Tester {
 		float bgColor[3]   = [0.1f, 0.2f, 0.4f]; // Background color
 		ubyte cubeColor[4] = [255, 0, 0, 128];   // Model color (32bits RGBA)
 
-		TwWindowSize(640, 480);
+		auto quat = Quaternion(0,0,0,1);
+
+//		auto w = this._window.getBounds()[2];
+//		auto h = this._window.getBounds()[3];
+		TwWindowSize(1600, 900);
 
 		// Create a tweak bar
 		auto bar = TwNewBar("TweakBar");
-		TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.
-		
+		TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLFW and OpenGL.' "); // Message added to the help bar.		
 		// Add 'speed' to 'bar': it is a modifable (RW) variable of type TW_TYPE_DOUBLE. Its key shortcuts are [s] and [S].
-		TwAddVarRW(bar, "speed", TW_TYPE_DOUBLE, &speed,
-		           " label='Rot speed' min=0 max=2 step=0.01 keyIncr=s keyDecr=S help='Rotation speed (turns/second)' ");
-		
+		TwAddVarRW(bar, "speed", TW_TYPE_DOUBLE, &speed, " label='Rot speed' min=0 max=2 step=0.01 keyIncr=s keyDecr=S help='Rotation speed (turns/second)' ");		
 		// Add 'wire' to 'bar': it is a modifable variable of type TW_TYPE_BOOL32 (32 bits boolean). Its key shortcut is [w].
-		TwAddVarRW(bar, "wire", TW_TYPE_BOOL32, &wire,
-		           " label='Wireframe mode' key=CTRL+w help='Toggle wireframe display mode.' ");
-		
+		TwAddVarRW(bar, "wire", TW_TYPE_BOOL32, &wire, " label='Wireframe mode' key=CTRL+w help='Toggle wireframe display mode.' ");		
 		// Add 'time' to 'bar': it is a read-only (RO) variable of type TW_TYPE_DOUBLE, with 1 precision digit
 		TwAddVarRO(bar, "time", TW_TYPE_DOUBLE, &time, " label='Time' precision=1 help='Time (in seconds).' ");
-
+		//
 		TwAddVarRO(bar, "frameCount", TW_TYPE_UINT32, &frameCount, " label='FrameCount' precision=1 help='FrameCount (in counts).' ");
-		TwAddVarRO(bar, "fps", TW_TYPE_DOUBLE, &fps, " label='fps' precision=1 help='fps (in fps).' ");
-		
+		TwAddVarRO(bar, "fps", TW_TYPE_DOUBLE, &fps, " label='fps' precision=1 help='fps (in fps).' ");		
 		// Add 'bgColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR3F (3 floats color)
-		TwAddVarRW(bar, "bgColor", TW_TYPE_COLOR3F, &bgColor, " label='Background color' ");
-		
+		TwAddVarRW(bar, "bgColor", TW_TYPE_COLOR3F, &bgColor, " label='Background color' ");		
 		// Add 'cubeColor' to 'bar': it is a modifable variable of type TW_TYPE_COLOR32 (32 bits color) with alpha
-		TwAddVarRW(bar, "cubeColor", TW_TYPE_COLOR32, &cubeColor,
-		           " label='Cube color' alpha help='Color and transparency of the cube.' ");
+		TwAddVarRW(bar, "cubeColor", TW_TYPE_COLOR32, &cubeColor, " label='Cube color' alpha help='Color and transparency of the cube.' ");
+		//
+//		TwAddVarRW(bar, "quaternion", TW_TYPE_QUAT4F, &quat, " label='Cube color' alpha help='Color and transparency of the cube.' ");
 
 
 		//-----------------
@@ -71,17 +193,7 @@ class Tester {
 			Vector3f( 0.0f,  1.0f, 0.0f)
 		];
 
-		Unique!(VertexArrayObject) vao = new VertexArrayObject();
-		vao.bind();
-		Unique!(VertexBufferObject!(VertexBufferObjectTarget.Array)) vbo = new VertexBufferObject!(VertexBufferObjectTarget.Array);
-		vbo.bind();
 
-		GLuint attribIndex = 0;
-		glBufferData(GL_ARRAY_BUFFER, cast(ptrdiff_t)(vertices.sizeof) , vertices.ptr, GL_STATIC_DRAW);		
-		glEnableVertexAttribArray(attribIndex);
-		glVertexAttribPointer(attribIndex, 3, GL_FLOAT, GL_FALSE, 0, cast(void*)0);
-		vbo.unbind();
-		vao.unbind();
 
 		//-----------------
 		// Create Shaders
@@ -89,9 +201,12 @@ class Tester {
 			#version 420 core
 
 			layout(location = 0) in vec3 in_position;
-			//layout(location = 1) in vec3 in_normal;
-			//layout(location = 2) in vec2 in_texcoord;
-			//layout(location = 3) in vec3 in_color;
+			layout(location = 1) in vec3 in_normal;
+			layout(location = 2) in vec2 in_texcoord;
+			layout(location = 3) in vec4 in_color;
+
+
+			out vec4 v_color;	
 
 			out gl_PerVertex 
 			{
@@ -100,18 +215,20 @@ class Tester {
 
 			void main()
 			{
-				gl_Position = vec4(0.5 * in_position.x, 0.5 * in_position.y, in_position.z, 1.0);
+				gl_Position = vec4(0.005 * in_position.x, 0.005 * in_position.y, 0.005* in_position.z, 1.0);
+		    	v_color = in_color;
 			}
 		";
 
 		enum fragmentShaderSource = "
 			#version 420 core
+			in vec4 v_color;
 
 			out vec4 FragColor;
 
 			void main()
 			{
-				FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+				FragColor = v_color;
 			}
 		";
 
@@ -128,6 +245,12 @@ class Tester {
 		assert(shaderPipeline.isValidProgramPipeline, shaderPipeline.infoLog());
 		shaderPipeline.unbind();
 
+
+		this._window.onSize.connect!"onSize"(this);
+		this._window.onPosition.connect!"onPosition"(this);
+		this._window.onButton.connect!"onButton"(this);
+		this._window.onCursorPos.connect!"onCursorPos"(this);
+
 		//-----------------
 		// Render Loop
 		glfwSetTime(0);
@@ -136,11 +259,11 @@ class Tester {
 			this._window.clear(0, 0, 0.5, 1);
 
 			shaderPipeline.bind();
-			vao.bind();
-			vbo.bind();
-			glDrawArrays(GL_TRIANGLES, 0, 3);
-			vbo.unbind();
-			vao.unbind();
+			mesh.vao.bind();
+			//vboVertexData.bind();
+			glDrawArrays(GL_TRIANGLES, 0, mesh.vertexData.length);
+			//vbo.unbind();
+			mesh.vao.unbind();
 			shaderPipeline.unbind();
 
 			TwDraw();
@@ -148,13 +271,42 @@ class Tester {
 			this._window.swapBuffers();
 
 			++frameCount;
-			if(frameCount % 100 == 0) {
+			//if(frameCount % 100 == 0) {
 				updateWindows();
 				time = glfwGetTime();
 				fps = cast(double)frameCount / time;
-			}
+			//}
 		}
 	}
+
+
+	void onSize(Window w, int x, int y) {
+	}
+
+	void onPosition(Window w, int x, int y) {
+	}
+
+
+//#define GLFW_MOUSE_BUTTON_LAST      GLFW_MOUSE_BUTTON_8
+//#define GLFW_MOUSE_BUTTON_LEFT      GLFW_MOUSE_BUTTON_1
+//#define GLFW_MOUSE_BUTTON_RIGHT     GLFW_MOUSE_BUTTON_2
+//#define GLFW_MOUSE_BUTTON_MIDDLE    GLFW_MOUSE_BUTTON_3
+//
+//
+//	TW_MOUSE_LEFT   = 1,
+//		TW_MOUSE_MIDDLE = 2,
+//		TW_MOUSE_RIGHT  = 3
+
+	void onButton(Window w , int b, ButtonAction a) {
+		TwMouseAction action = a == ButtonAction.Pressed ? TW_MOUSE_PRESSED : TW_MOUSE_RELEASED;
+		TwMouseButtonID button = b;
+		TwMouseButton(action, button);
+	}
+
+	void onCursorPos(Window w, double x, double y) {
+
+		TwMouseMotion(cast(int)x, this._window.getBounds()[3] - cast(int)y);
+	}
 	
 	void stop() {
 		this._keepRunning = false;

+ 79 - 0
source/three/assimp/package.d

@@ -0,0 +1,79 @@
+// Written in the D programming language.
+/**						   
+Copyright: Copyright Felix 'Zoadian' Hufnagel 2014-.
+
+License:   $(WEB http://www.gnu.org/licenses/lgpl.html, LGPLv3).
+
+Authors:   $(WEB zoadian.de, Felix 'Zoadian' Hufnagel)
+*/
+
+
+
+module three.assimp;
+
+import std.traits;
+
+
+version(none){
+
+Model loadModel(string filePath, Vec3f position = Vec3f(0,0,0), Vec3f scale = Vec3f(1,1,1), Quatf orientation = Quatf(0,0,0,1)) {
+	if(!exists(filePath)) throw new Exception("File does not exist");
+	try{			
+		"loading model: ".writeln(filePath);
+		auto scene = aiImportFile(filePath.toStringz(),	0
+		                          //| aiPostProcessSteps.CalcTangentSpace
+		                          //| aiPostProcessSteps.Triangulate
+		                          //| aiPostProcessSteps.JoinIdenticalVertices
+		                          //| aiPostProcessSteps.GenNormals
+		                          //| aiPostProcessSteps.FlipWindingOrder
+		                          //| aiPostProcessSteps.SortByPType
+		                          );
+		
+		Mesh[] meshes;	
+		
+		for(uint k = 0; k < scene.mNumMeshes; ++k) {  
+			
+			"mesh".writeln();
+			const(aiMesh*) mesh = scene.mMeshes[k];
+			assert(mesh !is null);
+			float[] vertexData;
+			
+			for (uint t = 0; t < mesh.mNumFaces; ++t) {	 
+				//"face".writeln();
+				const(aiFace*) face = &mesh.mFaces[t];
+				assert(face !is null);
+				for(uint v = 0; v < 3; ++v) {  
+					//"a".writeln();
+					aiVector3D p, n, uv;  
+					assert(face.mNumIndices > v);
+					uint vertex = face.mIndices[v];
+					assert(mesh.mNumVertices > vertex);
+					p = mesh.mVertices[vertex];
+					n = mesh.mNormals[vertex];	              
+					
+					// check if the mesh has texture coordinates
+					if(mesh.mTextureCoords[0] !is null) {
+						uv = mesh.mTextureCoords[0][vertex];
+					}
+					
+					//TODO: speed this up!
+					vertexData ~= [p.x, p.y, p.z, n.x, n.y, n.z, uv.x, uv.y, 1.0f, 1.0f, 1.0f];
+				}
+			}
+			
+			"genvdata".writeln();
+			//alias VertexData!(VertexBufferObject!(BufferTarget.Array, VTX_POSITION, VTX_NORMAL, VTX_TEXCOORD, VTX_COLOR)) AssimpVertexData;
+			//meshes ~= new VertexMesh!(AssimpVertexData)(vertexData, mesh.mNumFaces);
+		}
+		
+		
+		"release".writeln();
+		aiReleaseImport(scene);
+		"loaded".writeln();
+		return new Model(position, scale, orientation, meshes);	 
+	}catch(Exception e)
+	{
+		assert(0);
+	}
+}
+}

+ 44 - 14
source/three/init.d

@@ -2,8 +2,10 @@ module three.init;
 
 import derelict.opengl3.gl3;
 import derelict.glfw3.glfw3;
-//import derelict.freetype.ft;
 import derelict.anttweakbar.anttweakbar;
+import derelict.freeimage.freeimage;	
+import derelict.freetype.ft;
+import derelict.assimp3.assimp;
 
 import three.glfw.window;
 
@@ -11,16 +13,37 @@ import std.stdio;
 import std.conv;
 import std.typecons;
 
+
+private static FT_Library _s_freeTypeLibrary;
+
 Unique!(Window) initThree() {
+	"Starting Three.d".writeln();
+
+	"Loading OpenGL".writeln();
 	DerelictGL3.load();
+
+	"Loading GLFW".writeln();
 	DerelictGLFW3.load();
-	//DerelictFT.load();
-	
-	//~ if(!freeTypeInit()) throw new Exception("FreeType init failed");
-	if(!glfwInit()) throw new Exception("GLFW init failed");
-	
-	Unique!(Window) window = new Window("Fray", 1024, 768);
+
+	"Loading FreeImage".writeln();
+	DerelictFI.load();	  
+
+//	"Loading FreeType".writeln();
+//	DerelictFT.load();
+
+	"Loading Assimp".writeln();
+	DerelictASSIMP3.load();
+
+	"Loading AntTweakBar".writeln();
+	DerelictAntTweakBar.load();
+
+	"Initialising GLFW".writeln();
+	if(!glfwInit()) throw new Exception("Initialising GLFW failed");
+
+	"Creating Window".writeln();
+	Unique!(Window) window = new Window("Fray", 1600, 900);
 	
+	"ReLoading OpenGL".writeln();
 	try {
 		GLVersion glVersion = DerelictGL3.reload();
 		writeln("Loaded OpenGL Version", to!string(glVersion));
@@ -28,16 +51,23 @@ Unique!(Window) initThree() {
 		writeln("exception: "~ e.msg);
 	}
 
-	DerelictAntTweakBar.load();
-	TwInit(TW_OPENGL_CORE, null);
-
-	return window.release();
+//	"Initialising FreeType".writeln();
+//	if(!FT_Init_FreeType(&_s_freeTypeLibrary)) throw new Exception("Initialising FreeType failed");
 
+	"Initialising AntTweakBar".writeln();
+	if(TwInit(TW_OPENGL_CORE, null) == 0) throw new Exception("Initialising AntTweakBar failed");
 
+	return window.release();
 }
 
-void deinitThree() {
-	glfwTerminate();	 
+void deinitThree() { 
+
+	"Terminating AntTweakBar".writeln();
 	TwTerminate();
-	//freeTypeDeinit();
+
+//	"Terminating FreeType".writeln();
+//	FT_Done_FreeType(_s_freeTypeLibrary);
+
+	"Terminating GLFW".writeln();
+	glfwTerminate();	
 }