mirror of https://github.com/mode777/rayjs.git
				
				
				
			improve lightmapper
This commit is contained in:
		
							parent
							
								
									64a195f2e5
								
							
						
					
					
						commit
						03a6079549
					
				| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
        "glad.h": "c",
 | 
					        "glad.h": "c",
 | 
				
			||||||
        "lightmapper.h": "c",
 | 
					        "lightmapper.h": "c",
 | 
				
			||||||
        "compare": "c",
 | 
					        "compare": "c",
 | 
				
			||||||
        "memory": "c"
 | 
					        "memory": "c",
 | 
				
			||||||
 | 
					        "rlgl.h": "c"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -44,4 +44,5 @@ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE thirdparty/raygui/src)
 | 
				
			||||||
target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib)
 | 
					target_link_libraries(${CMAKE_PROJECT_NAME} quickjs raylib)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(lightmapper_example src/lightmapper_example.c)
 | 
					add_executable(lightmapper_example src/lightmapper_example.c)
 | 
				
			||||||
 | 
					target_include_directories(lightmapper_example PRIVATE include)
 | 
				
			||||||
target_link_libraries(lightmapper_example raylib lightmapper)
 | 
					target_link_libraries(lightmapper_example raylib lightmapper)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,18 +1,12 @@
 | 
				
			||||||
#define _USE_MATH_DEFINES
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
//#include "glad/glad.h"
 | 
					 | 
				
			||||||
#define GLAD_MALLOC(sz) malloc(sz)
 | 
					 | 
				
			||||||
#define GLAD_FREE(sz) free(sz)
 | 
					 | 
				
			||||||
//#define GLAD_GL_IMPLEMENTATION
 | 
					 | 
				
			||||||
#include "../thirdparty/raylib/src/external/glad.h"
 | 
					 | 
				
			||||||
//#include "GLFW/glfw3.h"
 | 
					 | 
				
			||||||
#include "raylib.h"
 | 
					 | 
				
			||||||
#include "rlgl.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <raylib.h>
 | 
				
			||||||
 | 
					#include <rlgl.h>
 | 
				
			||||||
 | 
					#include <external/glad.h>
 | 
				
			||||||
#define LIGHTMAPPER_IMPLEMENTATION
 | 
					#define LIGHTMAPPER_IMPLEMENTATION
 | 
				
			||||||
#define LM_DEBUG_INTERPOLATION
 | 
					#define LM_DEBUG_INTERPOLATION
 | 
				
			||||||
#include "lightmapper.h"
 | 
					#include "lightmapper.h"
 | 
				
			||||||
| 
						 | 
					@ -28,14 +22,15 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GLuint program;
 | 
						//GLuint program;
 | 
				
			||||||
 | 
						Shader raylib_shader;
 | 
				
			||||||
	GLint u_lightmap;
 | 
						GLint u_lightmap;
 | 
				
			||||||
	GLint u_projection;
 | 
						GLint u_mvp;
 | 
				
			||||||
	GLint u_view;
 | 
						Texture raylib_texture;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	GLuint lightmap;
 | 
						GLuint lightmap;
 | 
				
			||||||
	int w, h;
 | 
						int w, h;
 | 
				
			||||||
    Model raylib_model;
 | 
					    Model raylib_model;
 | 
				
			||||||
 | 
						Camera camera;
 | 
				
			||||||
} scene_t;
 | 
					} scene_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int initScene(scene_t *scene);
 | 
					static int initScene(scene_t *scene);
 | 
				
			||||||
| 
						 | 
					@ -74,10 +69,13 @@ static int bake(scene_t *scene)
 | 
				
			||||||
	int vp[4];
 | 
						int vp[4];
 | 
				
			||||||
	float view[16], projection[16];
 | 
						float view[16], projection[16];
 | 
				
			||||||
	double lastUpdateTime = 0.0;
 | 
						double lastUpdateTime = 0.0;
 | 
				
			||||||
 | 
						rlEnableDepthTest();
 | 
				
			||||||
 | 
						rlDisableColorBlend();
 | 
				
			||||||
	while (lmBegin(ctx, vp, view, projection))
 | 
						while (lmBegin(ctx, vp, view, projection))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// render to lightmapper framebuffer
 | 
							// render to lightmapper framebuffer
 | 
				
			||||||
		rlViewport(vp[0], vp[1], vp[2], vp[3]);
 | 
							rlViewport(vp[0], vp[1], vp[2], vp[3]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		drawScene(scene, view, projection);
 | 
							drawScene(scene, view, projection);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		// display progress every second (printf is expensive)
 | 
							// display progress every second (printf is expensive)
 | 
				
			||||||
| 
						 | 
					@ -91,6 +89,9 @@ static int bake(scene_t *scene)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lmEnd(ctx);
 | 
							lmEnd(ctx);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						rlDisableDepthTest();
 | 
				
			||||||
 | 
						rlEnableColorBlend();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
 | 
						//printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lmDestroy(ctx);
 | 
						lmDestroy(ctx);
 | 
				
			||||||
| 
						 | 
					@ -119,7 +120,16 @@ static int bake(scene_t *scene)
 | 
				
			||||||
	// upload result
 | 
						// upload result
 | 
				
			||||||
	rlUnloadTexture(scene->lightmap);
 | 
						rlUnloadTexture(scene->lightmap);
 | 
				
			||||||
	scene->lightmap = rlLoadTexture(tempub, w, h, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
 | 
						scene->lightmap = rlLoadTexture(tempub, w, h, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
 | 
				
			||||||
 | 
						Texture texture;
 | 
				
			||||||
 | 
						texture.id = scene->lightmap;
 | 
				
			||||||
 | 
						texture.width = w;
 | 
				
			||||||
 | 
						texture.height = h;
 | 
				
			||||||
 | 
						texture.mipmaps = 1;
 | 
				
			||||||
 | 
						texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
 | 
				
			||||||
 | 
						scene->raylib_texture = texture;
 | 
				
			||||||
	free(tempub);
 | 
						free(tempub);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scene->raylib_model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// // save result to a file
 | 
						// // save result to a file
 | 
				
			||||||
	// if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
 | 
						// if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
 | 
				
			||||||
| 
						 | 
					@ -129,14 +139,6 @@ static int bake(scene_t *scene)
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void error_callback(int error, const char *description)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	fprintf(stderr, "Error: %s\n", description);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void fpsCameraViewMatrix(float *view);
 | 
					 | 
				
			||||||
static void perspectiveMatrix(float *out, float fovy, float aspect, float zNear, float zFar);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int first = 1;
 | 
					static int first = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mainLoop(scene_t *scene)
 | 
					static void mainLoop(scene_t *scene)
 | 
				
			||||||
| 
						 | 
					@ -149,19 +151,21 @@ static void mainLoop(scene_t *scene)
 | 
				
			||||||
	int w = GetScreenWidth() * GetWindowScaleDPI().x;
 | 
						int w = GetScreenWidth() * GetWindowScaleDPI().x;
 | 
				
			||||||
	int h = GetScreenHeight() * GetWindowScaleDPI().y;
 | 
						int h = GetScreenHeight() * GetWindowScaleDPI().y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glViewport(0, 0, w, h);
 | 
						rlViewport(0, 0, w, h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// camera for glfw window
 | 
						// camera for glfw window
 | 
				
			||||||
	float view[16], projection[16];
 | 
						float view[16], projection[16];
 | 
				
			||||||
	fpsCameraViewMatrix(view);
 | 
						//fpsCameraViewMatrix(view);
 | 
				
			||||||
	perspectiveMatrix(projection, 45.0f, (float)w / (float)h, 0.01f, 100.0f);
 | 
						//perspectiveMatrix(projection, 45.0f, (float)w / (float)h, 0.01f, 100.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BeginDrawing();
 | 
						BeginDrawing();
 | 
				
			||||||
	// draw to screen with a blueish sky
 | 
						BeginMode3D(scene->camera);
 | 
				
			||||||
	glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
 | 
						ClearBackground(BLUE);
 | 
				
			||||||
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
						rlEnableDepthTest();
 | 
				
			||||||
	drawScene(scene, view, projection);
 | 
						//drawScene(scene, view, projection);
 | 
				
			||||||
 | 
						DrawModel(scene->raylib_model, (Vector3) {0.0f,0.0f,0.0f}, 1, WHITE);
 | 
				
			||||||
 | 
						rlDisableDepthTest();
 | 
				
			||||||
 | 
						EndMode3D();
 | 
				
			||||||
	EndDrawing();
 | 
						EndDrawing();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -195,10 +199,6 @@ int main(int argc, char* argv[])
 | 
				
			||||||
	return EXIT_SUCCESS;
 | 
						return EXIT_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// helpers ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount);
 | 
					 | 
				
			||||||
static GLuint loadProgram(const char *vp, const char *fp, const char **attributes, int attributeCount);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int initScene(scene_t *scene)
 | 
					static int initScene(scene_t *scene)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// load mesh
 | 
						// load mesh
 | 
				
			||||||
| 
						 | 
					@ -207,96 +207,72 @@ static int initScene(scene_t *scene)
 | 
				
			||||||
	if(m.normals != NULL) puts("Has normals");
 | 
						if(m.normals != NULL) puts("Has normals");
 | 
				
			||||||
	if(m.texcoords != NULL) puts("Has texcoords");
 | 
						if(m.texcoords != NULL) puts("Has texcoords");
 | 
				
			||||||
	if(m.texcoords2 != NULL) puts("Has texcoords2");
 | 
						if(m.texcoords2 != NULL) puts("Has texcoords2");
 | 
				
			||||||
    //scene->vertices = myModel.meshes[0].
 | 
						if(m.indices != NULL) puts("Has indices");
 | 
				
			||||||
	// if (!loadSimpleObjFile("thirdparty/lightmapper/example/gazebo.obj", &scene->vertices, &scene->vertexCount, &scene->indices, &scene->indexCount))
 | 
					    
 | 
				
			||||||
	// {
 | 
						scene->w = 512;
 | 
				
			||||||
	// 	fprintf(stderr, "Error loading obj file\n");
 | 
						scene->h = 512;
 | 
				
			||||||
	// 	return 0;
 | 
						scene->lightmap = LoadTextureFromImage(GenImageColor(1,1,BLACK)).id;
 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// glGenVertexArrays(1, &scene->vao);
 | 
					 | 
				
			||||||
	// glBindVertexArray(scene->vao);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// glGenBuffers(1, &scene->vbo);
 | 
					 | 
				
			||||||
	// glBindBuffer(GL_ARRAY_BUFFER, scene->vbo);
 | 
					 | 
				
			||||||
	// glBufferData(GL_ARRAY_BUFFER, scene->vertexCount * sizeof(vertex_t), scene->vertices, GL_STATIC_DRAW);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// glGenBuffers(1, &scene->ibo);
 | 
					 | 
				
			||||||
	// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene->ibo);
 | 
					 | 
				
			||||||
	// glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene->indexCount * sizeof(unsigned short), scene->indices, GL_STATIC_DRAW);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// glEnableVertexAttribArray(0);
 | 
					 | 
				
			||||||
	// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, p));
 | 
					 | 
				
			||||||
	// glEnableVertexAttribArray(1);
 | 
					 | 
				
			||||||
	// glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, t));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create lightmap texture
 | 
					 | 
				
			||||||
	scene->w = 654;
 | 
					 | 
				
			||||||
	scene->h = 654;
 | 
					 | 
				
			||||||
	glGenTextures(1, &scene->lightmap);
 | 
					 | 
				
			||||||
	glBindTexture(GL_TEXTURE_2D, scene->lightmap);
 | 
					 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
					 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
					 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
					 | 
				
			||||||
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
					 | 
				
			||||||
	unsigned char emissive[] = { 0, 0, 0, 255 };
 | 
					 | 
				
			||||||
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// load shader
 | 
						// load shader
 | 
				
			||||||
	const char *vp =
 | 
						const char *vp =
 | 
				
			||||||
		"#version 150 core\n"
 | 
							"#version 150 core\n"
 | 
				
			||||||
		"in vec3 a_position;\n"
 | 
							"in vec3 vertexPosition;\n"
 | 
				
			||||||
		"in vec2 a_texcoord;\n"
 | 
							"in vec2 vertexTexCoord;\n"
 | 
				
			||||||
		"uniform mat4 u_view;\n"
 | 
							"uniform mat4 mvp;\n"
 | 
				
			||||||
		"uniform mat4 u_projection;\n"
 | 
					 | 
				
			||||||
		"out vec2 v_texcoord;\n"
 | 
							"out vec2 v_texcoord;\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		"void main()\n"
 | 
							"void main()\n"
 | 
				
			||||||
		"{\n"
 | 
							"{\n"
 | 
				
			||||||
		"gl_Position = u_projection * (u_view * vec4(a_position, 1.0));\n"
 | 
							"gl_Position = mvp * vec4(vertexPosition, 1.0);\n"
 | 
				
			||||||
		"v_texcoord = vec2(a_texcoord.x, a_texcoord.y);\n"
 | 
							"v_texcoord = vertexTexCoord;\n"
 | 
				
			||||||
		"}\n";
 | 
							"}\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *fp =
 | 
						const char *fp =
 | 
				
			||||||
		"#version 150 core\n"
 | 
							"#version 150 core\n"
 | 
				
			||||||
		"in vec2 v_texcoord;\n"
 | 
							"in vec2 v_texcoord;\n"
 | 
				
			||||||
		"uniform sampler2D u_lightmap;\n"
 | 
							"uniform sampler2D texture0;\n"
 | 
				
			||||||
		"out vec4 o_color;\n"
 | 
							"out vec4 o_color;\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		"void main()\n"
 | 
							"void main()\n"
 | 
				
			||||||
		"{\n"
 | 
							"{\n"
 | 
				
			||||||
		"o_color = vec4(texture(u_lightmap, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n"
 | 
							"o_color = vec4(texture(texture0, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n"
 | 
				
			||||||
		"}\n";
 | 
							"}\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *attribs[] =
 | 
						//scene->program = rlLoadShaderCode(vp, fp);
 | 
				
			||||||
	{
 | 
						scene->raylib_shader = LoadShaderFromMemory(vp, fp);
 | 
				
			||||||
		"a_position",
 | 
					 | 
				
			||||||
		"a_texcoord"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scene->program = loadProgram(vp, fp, attribs, 2);
 | 
						scene->u_lightmap = rlGetLocationUniform(scene->raylib_shader.id, "texture0");
 | 
				
			||||||
	if (!scene->program)
 | 
						scene->u_mvp = rlGetLocationUniform(scene->raylib_shader.id, "mvp");
 | 
				
			||||||
	{
 | 
					
 | 
				
			||||||
		fprintf(stderr, "Error loading shader\n");
 | 
						//scene->raylib_model.materials[0].shader = scene->raylib_shader;
 | 
				
			||||||
		return 0;
 | 
						
 | 
				
			||||||
	}
 | 
						Camera camera = { 0 };
 | 
				
			||||||
	scene->u_view = glGetUniformLocation(scene->program, "u_view");
 | 
					    camera.position = (Vector3){ 1.0f, 0.5f, 1.0f }; // Camera position
 | 
				
			||||||
	scene->u_projection = glGetUniformLocation(scene->program, "u_projection");
 | 
					    camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };     // Camera looking at point
 | 
				
			||||||
	scene->u_lightmap = glGetUniformLocation(scene->program, "u_lightmap");
 | 
					    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
 | 
				
			||||||
 | 
					    camera.fovy = 45.0f;                                // Camera field-of-view Y
 | 
				
			||||||
 | 
					    camera.projection = CAMERA_PERSPECTIVE;                   // Camera mode type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scene->camera = camera;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void multiplyMatrices(float *out, float *a, float *b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (int y = 0; y < 4; y++)
 | 
				
			||||||
 | 
							for (int x = 0; x < 4; x++)
 | 
				
			||||||
 | 
								out[y * 4 + x] = a[x] * b[y * 4] + a[4 + x] * b[y * 4 + 1] + a[8 + x] * b[y * 4 + 2] + a[12 + x] * b[y * 4 + 3];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void drawScene(scene_t *scene, float *view, float *projection)
 | 
					static void drawScene(scene_t *scene, float *view, float *projection)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	Mesh m = scene->raylib_model.meshes[0];
 | 
						Mesh m = scene->raylib_model.meshes[0];
 | 
				
			||||||
	glEnable(GL_DEPTH_TEST);
 | 
					 | 
				
			||||||
	glDisable(GL_BLEND);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glUseProgram(scene->program);
 | 
						rlEnableShader(scene->raylib_shader.id);
 | 
				
			||||||
	glUniform1i(scene->u_lightmap, 0);
 | 
						float mvp[16];
 | 
				
			||||||
	glUniformMatrix4fv(scene->u_projection, 1, GL_FALSE, projection);
 | 
						multiplyMatrices(mvp, projection, view);
 | 
				
			||||||
	glUniformMatrix4fv(scene->u_view, 1, GL_FALSE, view);
 | 
						glUniformMatrix4fv(scene->u_mvp, 1, GL_FALSE, mvp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glBindTexture(GL_TEXTURE_2D, scene->lightmap);
 | 
						glBindTexture(GL_TEXTURE_2D, scene->lightmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,250 +284,7 @@ static void drawScene(scene_t *scene, float *view, float *projection)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void destroyScene(scene_t *scene)
 | 
					static void destroyScene(scene_t *scene)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// free(scene->vertices);
 | 
						UnloadModel(scene->raylib_model);
 | 
				
			||||||
	// free(scene->indices);
 | 
						UnloadTexture(scene->raylib_texture);
 | 
				
			||||||
	// glDeleteVertexArrays(1, &scene->vao);
 | 
						UnloadShader(scene->raylib_shader);
 | 
				
			||||||
	// glDeleteBuffers(1, &scene->vbo);
 | 
					}
 | 
				
			||||||
	// glDeleteBuffers(1, &scene->ibo);
 | 
					 | 
				
			||||||
	glDeleteTextures(1, &scene->lightmap);
 | 
					 | 
				
			||||||
	glDeleteProgram(scene->program);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	FILE *file = fopen(filename, "rt");
 | 
					 | 
				
			||||||
	if (!file)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	char line[1024];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// first pass
 | 
					 | 
				
			||||||
	unsigned int np = 0, nn = 0, nt = 0, nf = 0;
 | 
					 | 
				
			||||||
	while (!feof(file))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fgets(line, 1024, file);
 | 
					 | 
				
			||||||
		if (line[0] == '#') continue;
 | 
					 | 
				
			||||||
		if (line[0] == 'v')
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (line[1] == ' ') { np++; continue; }
 | 
					 | 
				
			||||||
			if (line[1] == 'n') { nn++; continue; }
 | 
					 | 
				
			||||||
			if (line[1] == 't') { nt++; continue; }
 | 
					 | 
				
			||||||
			assert(!"unknown vertex attribute");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (line[0] == 'f') { nf++; continue; }
 | 
					 | 
				
			||||||
		assert(!"unknown identifier");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	assert(np && np == nn && np == nt && nf); // only supports obj files without separately indexed vertex attributes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// allocate memory
 | 
					 | 
				
			||||||
	*vertexCount = np;
 | 
					 | 
				
			||||||
	*vertices = calloc(np, sizeof(vertex_t));
 | 
					 | 
				
			||||||
	*indexCount = nf * 3;
 | 
					 | 
				
			||||||
	*indices = calloc(nf * 3, sizeof(unsigned short));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// second pass
 | 
					 | 
				
			||||||
	fseek(file, 0, SEEK_SET);
 | 
					 | 
				
			||||||
	unsigned int cp = 0, cn = 0, ct = 0, cf = 0;
 | 
					 | 
				
			||||||
	while (!feof(file))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fgets(line, 1024, file);
 | 
					 | 
				
			||||||
		if (line[0] == '#') continue;
 | 
					 | 
				
			||||||
		if (line[0] == 'v')
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (line[1] == ' ') { float *p = (*vertices)[cp++].p; char *e1, *e2; p[0] = (float)strtod(line + 2, &e1); p[1] = (float)strtod(e1, &e2); p[2] = (float)strtod(e2, 0); continue; }
 | 
					 | 
				
			||||||
			if (line[1] == 'n') { /*float *n = (*vertices)[cn++].n; char *e1, *e2; n[0] = (float)strtod(line + 3, &e1); n[1] = (float)strtod(e1, &e2); n[2] = (float)strtod(e2, 0);*/ continue; } // no normals needed
 | 
					 | 
				
			||||||
			if (line[1] == 't') { float *t = (*vertices)[ct++].t; char *e1;      t[0] = (float)strtod(line + 3, &e1); t[1] = (float)strtod(e1, 0);                                continue; }
 | 
					 | 
				
			||||||
			assert(!"unknown vertex attribute");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (line[0] == 'f')
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			unsigned short *tri = (*indices) + cf;
 | 
					 | 
				
			||||||
			cf += 3;
 | 
					 | 
				
			||||||
			char *e1, *e2, *e3 = line + 1;
 | 
					 | 
				
			||||||
			for (int i = 0; i < 3; i++)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				unsigned long pi = strtoul(e3 + 1, &e1, 10);
 | 
					 | 
				
			||||||
				assert(e1[0] == '/');
 | 
					 | 
				
			||||||
				unsigned long ti = strtoul(e1 + 1, &e2, 10);
 | 
					 | 
				
			||||||
				assert(e2[0] == '/');
 | 
					 | 
				
			||||||
				unsigned long ni = strtoul(e2 + 1, &e3, 10);
 | 
					 | 
				
			||||||
				assert(pi == ti && pi == ni);
 | 
					 | 
				
			||||||
				tri[i] = (unsigned short)(pi - 1);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		assert(!"unknown identifier");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fclose(file);
 | 
					 | 
				
			||||||
	return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GLuint loadShader(GLenum type, const char *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	GLuint shader = glCreateShader(type);
 | 
					 | 
				
			||||||
	if (shader == 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fprintf(stderr, "Could not create shader!\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	glShaderSource(shader, 1, &source, NULL);
 | 
					 | 
				
			||||||
	glCompileShader(shader);
 | 
					 | 
				
			||||||
	GLint compiled;
 | 
					 | 
				
			||||||
	glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
 | 
					 | 
				
			||||||
	if (!compiled)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fprintf(stderr, "Could not compile shader!\n");
 | 
					 | 
				
			||||||
		GLint infoLen = 0;
 | 
					 | 
				
			||||||
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
 | 
					 | 
				
			||||||
		if (infoLen)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			char* infoLog = (char*)malloc(infoLen);
 | 
					 | 
				
			||||||
			glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
 | 
					 | 
				
			||||||
			fprintf(stderr, "%s\n", infoLog);
 | 
					 | 
				
			||||||
			free(infoLog);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		glDeleteShader(shader);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return shader;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static GLuint loadProgram(const char *vp, const char *fp, const char **attributes, int attributeCount)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vp);
 | 
					 | 
				
			||||||
	if (!vertexShader)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fp);
 | 
					 | 
				
			||||||
	if (!fragmentShader)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		glDeleteShader(vertexShader);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GLuint program = glCreateProgram();
 | 
					 | 
				
			||||||
	if (program == 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fprintf(stderr, "Could not create program!\n");
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	glAttachShader(program, vertexShader);
 | 
					 | 
				
			||||||
	glAttachShader(program, fragmentShader);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (int i = 0; i < attributeCount; i++)
 | 
					 | 
				
			||||||
		glBindAttribLocation(program, i, attributes[i]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	glLinkProgram(program);
 | 
					 | 
				
			||||||
	glDeleteShader(vertexShader);
 | 
					 | 
				
			||||||
	glDeleteShader(fragmentShader);
 | 
					 | 
				
			||||||
	GLint linked;
 | 
					 | 
				
			||||||
	glGetProgramiv(program, GL_LINK_STATUS, &linked);
 | 
					 | 
				
			||||||
	if (!linked)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		fprintf(stderr, "Could not link program!\n");
 | 
					 | 
				
			||||||
		GLint infoLen = 0;
 | 
					 | 
				
			||||||
		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
 | 
					 | 
				
			||||||
		if (infoLen)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			char* infoLog = (char*)malloc(sizeof(char) * infoLen);
 | 
					 | 
				
			||||||
			glGetProgramInfoLog(program, infoLen, NULL, infoLog);
 | 
					 | 
				
			||||||
			fprintf(stderr, "%s\n", infoLog);
 | 
					 | 
				
			||||||
			free(infoLog);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		glDeleteProgram(program);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return program;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void multiplyMatrices(float *out, float *a, float *b)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	for (int y = 0; y < 4; y++)
 | 
					 | 
				
			||||||
		for (int x = 0; x < 4; x++)
 | 
					 | 
				
			||||||
			out[y * 4 + x] = a[x] * b[y * 4] + a[4 + x] * b[y * 4 + 1] + a[8 + x] * b[y * 4 + 2] + a[12 + x] * b[y * 4 + 3];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void translationMatrix(float *out, float x, float y, float z)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	out[ 0] = 1.0f; out[ 1] = 0.0f; out[ 2] = 0.0f; out[ 3] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 4] = 0.0f; out[ 5] = 1.0f; out[ 6] = 0.0f; out[ 7] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 8] = 0.0f; out[ 9] = 0.0f; out[10] = 1.0f; out[11] = 0.0f;
 | 
					 | 
				
			||||||
	out[12] = x;    out[13] = y;    out[14] = z;    out[15] = 1.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void rotationMatrix(float *out, float angle, float x, float y, float z)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	angle *= (float)M_PI / 180.0f;
 | 
					 | 
				
			||||||
	float c = cosf(angle), s = sinf(angle), c2 = 1.0f - c;
 | 
					 | 
				
			||||||
	out[ 0] = x*x*c2 + c;   out[ 1] = y*x*c2 + z*s; out[ 2] = x*z*c2 - y*s; out[ 3] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 4] = x*y*c2 - z*s; out[ 5] = y*y*c2 + c;   out[ 6] = y*z*c2 + x*s; out[ 7] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 8] = x*z*c2 + y*s; out[ 9] = y*z*c2 - x*s; out[10] = z*z*c2 + c;   out[11] = 0.0f;
 | 
					 | 
				
			||||||
	out[12] = 0.0f;         out[13] = 0.0f;         out[14] = 0.0f;         out[15] = 1.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void transformPosition(float *out, float *m, float *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	float d = 1.0f / (m[3] * p[0] + m[7] * p[1] + m[11] * p[2] + m[15]);
 | 
					 | 
				
			||||||
	out[2] =     d * (m[2] * p[0] + m[6] * p[1] + m[10] * p[2] + m[14]);
 | 
					 | 
				
			||||||
	out[1] =     d * (m[1] * p[0] + m[5] * p[1] + m[ 9] * p[2] + m[13]);
 | 
					 | 
				
			||||||
	out[0] =     d * (m[0] * p[0] + m[4] * p[1] + m[ 8] * p[2] + m[12]);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void transposeMatrix(float *out, float *m)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	out[ 0] = m[0]; out[ 1] = m[4]; out[ 2] = m[ 8]; out[ 3] = m[12];
 | 
					 | 
				
			||||||
	out[ 4] = m[1]; out[ 5] = m[5]; out[ 6] = m[ 9]; out[ 7] = m[13];
 | 
					 | 
				
			||||||
	out[ 8] = m[2]; out[ 9] = m[6]; out[10] = m[10]; out[11] = m[14];
 | 
					 | 
				
			||||||
	out[12] = m[3]; out[13] = m[7]; out[14] = m[11]; out[15] = m[15];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void perspectiveMatrix(float *out, float fovy, float aspect, float zNear, float zFar)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	float f = 1.0f / tanf(fovy * (float)M_PI / 360.0f);
 | 
					 | 
				
			||||||
	float izFN = 1.0f / (zNear - zFar);
 | 
					 | 
				
			||||||
	out[ 0] = f / aspect; out[ 1] = 0.0f; out[ 2] = 0.0f;                       out[ 3] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 4] = 0.0f;       out[ 5] = f;    out[ 6] = 0.0f;                       out[ 7] = 0.0f;
 | 
					 | 
				
			||||||
	out[ 8] = 0.0f;       out[ 9] = 0.0f; out[10] = (zFar + zNear) * izFN;      out[11] = -1.0f;
 | 
					 | 
				
			||||||
	out[12] = 0.0f;       out[13] = 0.0f; out[14] = 2.0f * zFar * zNear * izFN; out[15] = 0.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void fpsCameraViewMatrix(float *view)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// initial camera config
 | 
					 | 
				
			||||||
	static float position[] = { 0.0f, 0.3f, 1.5f };
 | 
					 | 
				
			||||||
	static float rotation[] = { 0.0f, 0.0f };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// mouse look
 | 
					 | 
				
			||||||
	static double lastMouse[] = { 0.0, 0.0 };
 | 
					 | 
				
			||||||
	Vector2 m = GetMousePosition();
 | 
					 | 
				
			||||||
	double mouse[2] = { m.x, m.y };
 | 
					 | 
				
			||||||
	//glfwGetCursorPos(window, &mouse[0], &mouse[1]);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		rotation[0] += (float)(mouse[1] - lastMouse[1]) * -0.2f;
 | 
					 | 
				
			||||||
		rotation[1] += (float)(mouse[0] - lastMouse[0]) * -0.2f;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	lastMouse[0] = mouse[0];
 | 
					 | 
				
			||||||
	lastMouse[1] = mouse[1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	float rotationY[16], rotationX[16], rotationYX[16];
 | 
					 | 
				
			||||||
	rotationMatrix(rotationX, rotation[0], 1.0f, 0.0f, 0.0f);
 | 
					 | 
				
			||||||
	rotationMatrix(rotationY, rotation[1], 0.0f, 1.0f, 0.0f);
 | 
					 | 
				
			||||||
	multiplyMatrices(rotationYX, rotationY, rotationX);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// keyboard movement (WSADEQ)
 | 
					 | 
				
			||||||
	float speed = (IsKeyDown(KEY_LEFT_SHIFT)) ? 0.1f : 0.01f;
 | 
					 | 
				
			||||||
	float movement[3] = {0};
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) movement[2] -= speed;
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) movement[2] += speed;
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) movement[0] -= speed;
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) movement[0] += speed;
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) movement[1] -= speed;
 | 
					 | 
				
			||||||
	// if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) movement[1] += speed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	float worldMovement[3];
 | 
					 | 
				
			||||||
	transformPosition(worldMovement, rotationYX, movement);
 | 
					 | 
				
			||||||
	position[0] += worldMovement[0];
 | 
					 | 
				
			||||||
	position[1] += worldMovement[1];
 | 
					 | 
				
			||||||
	position[2] += worldMovement[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// construct view matrix
 | 
					 | 
				
			||||||
	float inverseRotation[16], inverseTranslation[16];
 | 
					 | 
				
			||||||
	transposeMatrix(inverseRotation, rotationYX);
 | 
					 | 
				
			||||||
	translationMatrix(inverseTranslation, -position[0], -position[1], -position[2]);
 | 
					 | 
				
			||||||
	multiplyMatrices(view, inverseRotation, inverseTranslation); // = inverse(translation(position) * rotationYX);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue