Skip to content

Commit e82b339

Browse files
feat: model loader (#28)
* feat: add assimp library to vendor * feat: add model class with loading and drawing * feat: add ModelRendererComponent with deserialization * feat: add model deserialization to AssetLoader * feat: add bone weight and id to vertex * feat: add model rendering support to ForwardRenderer * refactor: precompute if material have textures or not and add metallicRoughness texture * feat(litShader): add textureMetalRoughness handling * fix(cmake): add model-renderer component to the project executable * feat: drone model to test * fix: remove old debug prints * feat(model): enhance texture loading with wrapping and filtering parameters * feat(model): update model loading to support scene-based texture handling and embedded textures * fix: fix light leak behind objects * refactor: use assetloader cache for model loading * chore: change drone model from gltf to glb * refactor: change material hash in assetloader * feat(model): enhance model handling with combined mesh generation and draw command struct * feat(model): refactor model class to use name for unique identification and remove ID_COUNTER * feat(config): add model config for testing * fix(config): fix rifle path and add rifle model * fix(mesh): set default transform to identity matrix in deserialization * feat(model): replace generateDrawCommands with direct submesh handling in ForwardRenderer * fix(asset-loader): handle model name correctly * fix(config): correctly place flashlight of gun * fix(config): move model to assets key instead of game key * chore: fix uniform naming in lit.frag for textureMetalnesssRoughness * fix(litMaterial): initialize TextureMask to zero * fix(mesh): update bone IDs attribute pointer and return types for vertex and index getters * perf(ai-glm-utils): add inline specifier to conversion functions for better optimization * fix(model): update tangent type to vec4 and handle normal mapping in model loading * fix(model): remove mesh if no material found * refactor(model): remove incomplete bone data processing implementation * fix(model): ensure combined mesh is deleted and pointer is reset in destructor * fix(model): improve tangent and bitangent calculation in OBJ loading * feat(model): add support for system-installed Assimp * refactor(forward-renderer):revert changes to render-command header * fix: update tangent in comibned mesh and fix material memory leak * chore(material): remove unused function metho declaration * chore(config): remove unrelated game mesh * fix: reorder asset-loader include for consistency
1 parent 6911398 commit e82b339

28 files changed

Lines changed: 1109 additions & 50 deletions

.gitmodules

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
path = vendor/glfw
33
url = https://github.com/glfw/glfw.git
44
shallow = true
5+
56
[submodule "vendor/bullet3"]
67
path = vendor/bullet3
78
url = https://github.com/bulletphysics/bullet3.git
89
shallow = true
10+
911
[submodule "vendor/openal-soft"]
1012
path = vendor/openal-soft
1113
url = https://github.com/kcat/openal-soft.git
1214
shallow = true
15+
16+
[submodule "vendor/assimp"]
17+
path = vendor/assimp
18+
url = https://github.com/assimp/assimp.git
19+
shallow = true

CMakeLists.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ option(USE_SYSTEM_LIBS "Use system-installed libraries instead of the bundled ve
3131
option(USE_SYSTEM_OPENAL "Use system-installed OpenAL-Soft instead of the bundled version" $ENV{USE_SYSTEM_OPENAL})
3232
option(USE_SYSTEM_BULLET "Use system-installed Bullet3 instead of the bundled version" $ENV{USE_SYSTEM_BULLET})
3333
option(USE_SYSTEM_GLFW "Use system-installed GLFW instead of the bundled version" $ENV{USE_SYSTEM_GLFW})
34+
option(USE_SYSTEM_ASSIMP "Use system-installed Assimp instead of the bundled version" $ENV{USE_SYSTEM_ASSIMP})
3435

3536
if(USE_SYSTEM_LIBS)
3637
set(USE_SYSTEM_OPENAL ON CACHE BOOL "" FORCE)
3738
set(USE_SYSTEM_BULLET ON CACHE BOOL "" FORCE)
3839
set(USE_SYSTEM_GLFW ON CACHE BOOL "" FORCE)
40+
set(USE_SYSTEM_ASSIMP ON CACHE BOOL "" FORCE)
3941
endif()
4042

4143
# ---- Vendor Libraries ----
@@ -160,6 +162,29 @@ if(USE_VENDOR_OPENAL)
160162
add_subdirectory(vendor/openal-soft)
161163
endif()
162164

165+
# ---- Assimp ----
166+
set(USE_VENDOR_ASSIMP ON CACHE BOOL "" FORCE)
167+
if(USE_SYSTEM_ASSIMP)
168+
find_package(assimp QUIET)
169+
if(assimp_FOUND)
170+
message(STATUS "Using system-installed Assimp: ${assimp_VERSION}")
171+
set(USE_VENDOR_ASSIMP OFF CACHE BOOL "" FORCE)
172+
else()
173+
message(STATUS "Using bundled Assimp")
174+
endif()
175+
endif()
176+
177+
if(USE_VENDOR_ASSIMP)
178+
set(ASSIMP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
179+
set(ASSIMP_BUILD_SAMPLES OFF CACHE BOOL "" FORCE)
180+
set(ASSIMP_INSTALL OFF CACHE BOOL "" FORCE)
181+
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
182+
set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE BOOL "" FORCE)
183+
set(ASSIMP_BUILD_MINIZIP ON CACHE BOOL "" FORCE)
184+
set(ASSIMP_BUILD_ZLIB ON CACHE BOOL "" FORCE)
185+
add_subdirectory(vendor/assimp)
186+
endif()
187+
163188
# ---- GLAD ----
164189
add_library(glad STATIC
165190
vendor/glad/src/gl.c
@@ -213,6 +238,8 @@ add_executable(${PROJECT_NAME}
213238

214239
src/common/mesh/mesh-utils.cpp
215240

241+
src/common/model/model.cpp
242+
216243
src/common/texture/sampler.cpp
217244
src/common/texture/texture-utils.cpp
218245
src/common/texture/screenshot.cpp
@@ -226,6 +253,7 @@ add_executable(${PROJECT_NAME}
226253

227254
src/common/components/camera.cpp
228255
src/common/components/mesh-renderer.cpp
256+
src/common/components/model-renderer.cpp
229257
src/common/components/free-camera-controller.cpp
230258
src/common/components/movement.cpp
231259
src/common/components/light.cpp
@@ -264,6 +292,7 @@ target_link_libraries(${PROJECT_NAME}
264292
BulletCollision
265293
BulletSoftBody
266294
LinearMath
295+
assimp::assimp
267296
)
268297

269298
if(USE_SYSTEM_OPENAL AND OpenAL_FOUND)
@@ -278,6 +307,13 @@ else()
278307
)
279308
endif()
280309

310+
if(USE_SYSTEM_ASSIMP AND assimp_FOUND)
311+
target_include_directories(${PROJECT_NAME}
312+
PRIVATE
313+
${assimp_INCLUDE_DIRS}
314+
)
315+
endif()
316+
281317
target_compile_definitions(${PROJECT_NAME}
282318
PRIVATE
283319
$<$<CONFIG:Debug>:COLLISION_DEBUG_DRAW>
14.4 MB
Binary file not shown.

assets/gltf/weapons/rifle.glb

9.59 MB
Binary file not shown.

assets/shaders/lit.frag

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ struct Material {
3737

3838
sampler2D textureEmissive;
3939
bool hasTextureEmissive;
40+
41+
sampler2D hasTextureMetalnessRoughness;
42+
bool hasMetalnessRoughness;
4043
};
4144
uniform Material material;
4245
uniform float alphaThreshold;
@@ -69,19 +72,29 @@ vec3 sampleAlbedo(vec2 uv) {
6972
}
7073

7174
float sampleMetallic(vec2 uv) {
72-
return material.hasTextureMetallic ? texture(material.textureMetallic, uv).r * material.metallic : material.metallic;
75+
if(material.hasMetalnessRoughness)
76+
return texture(material.hasTextureMetalnessRoughness, uv).b * material.metallic; // B channel
77+
if(material.hasTextureMetallic)
78+
return texture(material.textureMetallic, uv).r * material.metallic;
79+
return material.metallic;
7380
}
7481

7582
float sampleRoughness(vec2 uv) {
76-
return material.hasTextureRoughness ? texture(material.textureRoughness, uv).r * material.roughness : material.roughness;
83+
if(material.hasMetalnessRoughness)
84+
return texture(material.hasTextureMetalnessRoughness, uv).g * material.roughness; // G channel
85+
if(material.hasTextureRoughness)
86+
return texture(material.textureRoughness, uv).r * material.roughness;
87+
return material.roughness;
7788
}
7889

7990
float sampleAO(vec2 uv) {
8091
return material.hasTextureAmbientOcclusion ? texture(material.textureAmbientOcclusion, uv).r * material.ambientOcclusion : material.ambientOcclusion;
8192
}
8293

8394
vec3 sampleEmission(vec2 uv) {
84-
return material.hasTextureEmissive ? texture(material.textureEmissive, uv).rgb * material.emission : material.emission;
95+
if(material.hasTextureEmissive)
96+
return texture(material.textureEmissive, uv).rgb; // texture owns the color
97+
return material.emission; // factor only when no texture
8598
}
8699

87100
vec3 sampleNormal(vec2 uv) {
@@ -111,6 +124,9 @@ vec3 calcLight(
111124
vec3 toLight = light.position - fs_in.worldPos;
112125
float dist = length(toLight);
113126
L = normalize(toLight);
127+
if(dot(toLight, N) <= 0.0) {
128+
return vec3(0.0);
129+
}
114130

115131
// quadratic attenuation: 1 / (c + l*d + q*d^2)
116132
attenuation = 1.0 / (light.attenuation.x + light.attenuation.y * dist + light.attenuation.z * dist * dist);

assets/shaders/lit.vert

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ layout(location = 0) in vec3 position;
44
layout(location = 1) in vec4 color;
55
layout(location = 2) in vec2 tex_coord;
66
layout(location = 3) in vec3 normal;
7-
layout(location = 4) in vec3 tangent;
7+
layout(location = 4) in vec4 tangent;
8+
layout(location = 5) in ivec4 bone_ids;
9+
layout(location = 6) in vec4 weights;
810

911
out Varyings {
1012
vec4 color;
@@ -30,8 +32,8 @@ void main() {
3032
vs_out.worldNormal = N;
3133

3234
// TBN matrix for normal mapping
33-
vec3 T = normalize(normalMatrix * tangent);
35+
vec3 T = normalize(normalMatrix * tangent.xyz);
3436
T = normalize(T - dot(T, N) * N); // re-orthogonalize
35-
vec3 B = cross(N, T);
37+
vec3 B = cross(N, T) * tangent.w; // bitangent with handedness
3638
vs_out.TBN = mat3(T, B, N);
3739
}

config/app.jsonc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@
177177
"texture": "moon",
178178
"sampler": "default"
179179
}
180+
},
181+
"models": {
182+
"drone": "assets/gltf/mech_drone/mech_drone.glb"
180183
}
181184
},
182185
"game": {

0 commit comments

Comments
 (0)