feat: major engine overhaul - scene demo with lighting, sphere, ground
- Scene Demo: cube + sphere + ground plane with proper lighting - Audio: XAudio2 dynamic loading + WAV playback - Physics: expanded collision system - Renderer: improved pipeline with materials - UI: extended widget system - VisualScript: enhanced serializer + block interactions - ASM: optimized math/memory/profiling routines - Window: mouse input + scroll support
This commit is contained in:
1 parent
2653926d85
commit
0669d102ce
35 files changed
+1844
-314
No files matched your search
+2
-2
@@ -142,8 +142,8 @@ static void on_mouse_move(int x, int y) {
|
||||
g_mouse_x = x; g_mouse_y = y;
|
||||
}
|
||||
|
||||
static void on_mouse_button(int button) {
|
||||
if (button == 0) {
|
||||
static void on_mouse_button(int button, int pressed) {
|
||||
if (button == 0 && pressed) {
|
||||
if (g_mouse_click == 0) {
|
||||
g_mouse_click = 1;
|
||||
g_mouse_click_x = g_mouse_x;
|
||||
|
||||
+159
-59
@@ -1,71 +1,159 @@
|
||||
#include "../Engine/Core/engine.h"
|
||||
#include "../Engine/Core/logger.h"
|
||||
#include "../Engine/Core/timer.h"
|
||||
#include "../Engine/Window/window.h"
|
||||
#include "../Engine/Core/asset_manager.h"
|
||||
#include "../Engine/Rendering/graphics_device.h"
|
||||
#include "../Engine/Rendering/renderer.h"
|
||||
#include "../Engine/Rendering/shader.h"
|
||||
#include "../Engine/Rendering/mesh.h"
|
||||
#include "../Engine/Rendering/material.h"
|
||||
#include "../Engine/Rendering/texture.h"
|
||||
#include "../Engine/Rendering/camera.h"
|
||||
#include "../Engine/Scene/scene_graph.h"
|
||||
#include "../Engine/Scene/scene_render.h"
|
||||
#include "../Engine/Scene/scene_serialize.h"
|
||||
#include "../Engine/include/engine_api.h"
|
||||
#include "../Engine/ASM/math_c_fallback.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Windows.h>
|
||||
|
||||
static GraphicsDevice* g_dev = NULL;
|
||||
static Shader* g_shader = NULL;
|
||||
static Mesh* g_cube = NULL;
|
||||
static Scene* g_scene = NULL;
|
||||
static AssetManager* g_assets = NULL;
|
||||
static Asset* g_shader_asset = NULL;
|
||||
static Camera g_camera;
|
||||
static float g_angle = 0.0f;
|
||||
static int g_mouse_down[3] = {0};
|
||||
static int g_last_mouse_x = 0, g_last_mouse_y = 0;
|
||||
static int g_mouse_first = 1;
|
||||
|
||||
static void mat4_transpose(const Mat4* in, Mat4* out) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
out->m[i][j] = in->m[j][i];
|
||||
static SceneNode* create_primitive_node(Scene* scene, SceneNode* parent, AssetManager* am,
|
||||
ID3D11Device* dev, const char* name, MeshType type,
|
||||
Vec3 pos, Vec3 rot, Vec3 scale,
|
||||
Material* material) {
|
||||
SceneNode* node = scene_create_node(scene, name);
|
||||
if (!node) return NULL;
|
||||
if (parent) scene_set_parent(node, parent);
|
||||
node->position = pos;
|
||||
node->scale = scale;
|
||||
quat_from_euler(rot.x, rot.y, rot.z, &node->rotation);
|
||||
|
||||
Asset* mesh_asset = asset_manager_load_mesh(am, dev, name);
|
||||
if (!mesh_asset) {
|
||||
const char* builtin = NULL;
|
||||
if (type == MESH_CUBE) builtin = "cube";
|
||||
else if (type == MESH_SPHERE) builtin = "sphere";
|
||||
else if (type == MESH_PLANE) builtin = "plane";
|
||||
if (builtin) mesh_asset = asset_manager_load_mesh(am, dev, builtin);
|
||||
}
|
||||
|
||||
if (mesh_asset && material) {
|
||||
MeshRenderer* mr = mesh_renderer_create(type, (Mesh*)asset_data(mesh_asset), material);
|
||||
scene_node_set_mesh_renderer(node, mr);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static Scene* create_default_scene(AssetManager* am, ID3D11Device* dev) {
|
||||
Scene* scene = (Scene*)malloc(sizeof(Scene));
|
||||
if (!scene) return NULL;
|
||||
scene_init(scene);
|
||||
|
||||
SceneNode* root = scene->root;
|
||||
root->name[0] = '\0';
|
||||
strncpy(root->name, "root", sizeof(root->name) - 1);
|
||||
|
||||
Shader* shader = (Shader*)asset_data(g_shader_asset);
|
||||
|
||||
Material* mat_red = material_create(shader, NULL);
|
||||
mat_red->color = (Vec4){1.0f, 0.3f, 0.2f, 1.0f};
|
||||
|
||||
Material* mat_blue = material_create(shader, NULL);
|
||||
mat_blue->color = (Vec4){0.2f, 0.5f, 1.0f, 1.0f};
|
||||
|
||||
Material* mat_ground = material_create(shader, NULL);
|
||||
mat_ground->color = (Vec4){0.3f, 0.3f, 0.35f, 1.0f};
|
||||
|
||||
// 中心红色立方体
|
||||
create_primitive_node(scene, root, am, dev, "cube", MESH_CUBE,
|
||||
(Vec3){0, 0, 0}, (Vec3){0, 0, 0}, (Vec3){1, 1, 1}, mat_red);
|
||||
// 右侧蓝色球体
|
||||
create_primitive_node(scene, root, am, dev, "sphere", MESH_SPHERE,
|
||||
(Vec3){2.0f, 0, 0}, (Vec3){0, 0, 0}, (Vec3){0.8f, 0.8f, 0.8f}, mat_blue);
|
||||
// 下方地面
|
||||
create_primitive_node(scene, root, am, dev, "ground", MESH_PLANE,
|
||||
(Vec3){0, -1.0f, 0}, (Vec3){0, 0, 0}, (Vec3){1, 1, 1}, mat_ground);
|
||||
|
||||
scene_update(scene);
|
||||
return scene;
|
||||
}
|
||||
|
||||
static void on_render(Engine* engine) {
|
||||
if (!g_dev || !g_shader || !g_cube) return;
|
||||
Renderer* r = engine_get_renderer(engine);
|
||||
GraphicsDevice* dev = engine_get_graphics_device(engine);
|
||||
if (!r || !dev || !g_scene) return;
|
||||
|
||||
float w = (float)window_get_width(engine->window);
|
||||
float h = (float)window_get_height(engine->window);
|
||||
renderer_set_view(r, camera_get_view(&g_camera));
|
||||
renderer_set_projection(r, camera_get_projection(&g_camera));
|
||||
|
||||
graphics_device_clear(g_dev, 0.15f, 0.15f, 0.2f, 1.0f);
|
||||
renderer_begin_frame(r);
|
||||
scene_update(g_scene);
|
||||
scene_render(g_scene, r);
|
||||
renderer_end_frame(r);
|
||||
|
||||
g_dev->context->lpVtbl->IASetPrimitiveTopology(g_dev->context, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
if (engine->frame_count == 60) {
|
||||
graphics_device_save_screenshot(dev, "screenshot1.bmp");
|
||||
}
|
||||
if (engine->frame_count == 180) {
|
||||
graphics_device_save_screenshot(dev, "screenshot2.bmp");
|
||||
}
|
||||
}
|
||||
|
||||
Mat4 model, wvp, wvp_t;
|
||||
mat4_rotate_y(g_angle, &model);
|
||||
Mat4* view = (Mat4*)camera_get_view(&g_camera);
|
||||
Mat4* proj = (Mat4*)camera_get_projection(&g_camera);
|
||||
|
||||
Mat4 vp;
|
||||
mat4_multiply(view, proj, &vp);
|
||||
mat4_multiply(&model, &vp, &wvp);
|
||||
mat4_transpose(&wvp, &wvp_t);
|
||||
|
||||
shader_bind(g_shader, g_dev->context);
|
||||
shader_set_matrix(g_shader, g_dev->context, (float*)&wvp_t);
|
||||
|
||||
ID3D11DepthStencilView* dsv = g_dev->depth_stencil;
|
||||
g_dev->context->lpVtbl->OMSetRenderTargets(g_dev->context, 1, &g_dev->render_target, dsv);
|
||||
D3D11_VIEWPORT vp2 = {0};
|
||||
vp2.Width = w; vp2.Height = h; vp2.MaxDepth = 1.0f;
|
||||
g_dev->context->lpVtbl->RSSetViewports(g_dev->context, 1, &vp2);
|
||||
g_dev->context->lpVtbl->RSSetState(g_dev->context, NULL);
|
||||
|
||||
mesh_draw(g_cube, g_dev->context);
|
||||
graphics_device_present(g_dev);
|
||||
|
||||
g_angle += 0.02f;
|
||||
static void on_update(Engine* engine, double dt) {
|
||||
(void)engine; (void)dt;
|
||||
}
|
||||
|
||||
static void on_key(Engine* engine, int key) {
|
||||
if (key == VK_ESCAPE) engine_request_quit(engine);
|
||||
if (key == 'W' || key == 'w') camera_move_forward(&g_camera, 0.5f);
|
||||
if (key == 'S' || key == 's') camera_move_forward(&g_camera, -0.5f);
|
||||
if (key == 'A' || key == 'a') camera_move_right(&g_camera, -0.5f);
|
||||
if (key == 'D' || key == 'd') camera_move_right(&g_camera, 0.5f);
|
||||
if (key == VK_LEFT) camera_rotate_yaw(&g_camera, -0.1f);
|
||||
if (key == VK_RIGHT) camera_rotate_yaw(&g_camera, 0.1f);
|
||||
if (key == VK_UP) camera_rotate_pitch(&g_camera, -0.1f);
|
||||
if (key == VK_DOWN) camera_rotate_pitch(&g_camera, 0.1f);
|
||||
}
|
||||
|
||||
static void on_mouse_move(Engine* engine, int x, int y) {
|
||||
(void)engine;
|
||||
if (g_mouse_down[0]) {
|
||||
if (g_mouse_first) {
|
||||
g_last_mouse_x = x;
|
||||
g_last_mouse_y = y;
|
||||
g_mouse_first = 0;
|
||||
} else {
|
||||
float dx = (float)(x - g_last_mouse_x);
|
||||
float dy = (float)(y - g_last_mouse_y);
|
||||
camera_rotate_yaw(&g_camera, dx * 0.005f);
|
||||
camera_rotate_pitch(&g_camera, dy * 0.005f);
|
||||
g_last_mouse_x = x;
|
||||
g_last_mouse_y = y;
|
||||
}
|
||||
} else {
|
||||
g_mouse_first = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_mouse_button(Engine* engine, int button, int pressed) {
|
||||
(void)engine;
|
||||
if (button >= 0 && button < 3) g_mouse_down[button] = pressed;
|
||||
}
|
||||
|
||||
static void on_resize(Engine* engine, int width, int height) {
|
||||
if (g_dev && width > 0 && height > 0) {
|
||||
graphics_device_resize(g_dev, width, height);
|
||||
Renderer* r = engine_get_renderer(engine);
|
||||
if (r && width > 0 && height > 0) {
|
||||
renderer_resize(r, width, height);
|
||||
g_camera.aspect = (float)width / (float)height;
|
||||
g_camera.dirty = 1;
|
||||
}
|
||||
@@ -75,7 +163,7 @@ int main(int argc, char* argv[]) {
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EngineConfig config = engine_default_config();
|
||||
config.app_name = "MiMo Engine - Cube Demo";
|
||||
config.app_name = "MiMo Engine - Scene Demo";
|
||||
config.vsync = 0;
|
||||
config.window_width = 1280;
|
||||
config.window_height = 720;
|
||||
@@ -86,39 +174,51 @@ int main(int argc, char* argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_dev = graphics_device_create();
|
||||
if (!graphics_device_init(g_dev, window_get_handle(engine->window), config.window_width, config.window_height, 0)) {
|
||||
LOG_FATAL("D3D11 init failed");
|
||||
GraphicsDevice* dev = engine_get_graphics_device(engine);
|
||||
Renderer* r = engine_get_renderer(engine);
|
||||
|
||||
g_assets = asset_manager_create();
|
||||
g_shader_asset = asset_manager_load_shader(g_assets, dev->device, NULL, NULL);
|
||||
if (!g_shader_asset) {
|
||||
LOG_FATAL("Shader load failed");
|
||||
return -1;
|
||||
}
|
||||
LOG_INFO("D3D11 device ready");
|
||||
LOG_INFO("Shader loaded via AssetManager");
|
||||
|
||||
g_shader = shader_create();
|
||||
if (!shader_compile(g_shader, g_dev->device, NULL, NULL, 0, 0)) {
|
||||
LOG_FATAL("Shader compile failed");
|
||||
return -1;
|
||||
Shader* default_shader = (Shader*)asset_data(g_shader_asset);
|
||||
|
||||
g_scene = scene_load("scene.txt", dev->device, default_shader);
|
||||
if (!g_scene) {
|
||||
LOG_INFO("No scene.txt found, creating default scene");
|
||||
g_scene = create_default_scene(g_assets, dev->device);
|
||||
if (!scene_save(g_scene, "scene.txt")) {
|
||||
LOG_WARN("Failed to save scene.txt");
|
||||
}
|
||||
}
|
||||
LOG_INFO("Shader compiled");
|
||||
|
||||
g_cube = mesh_create_cube(g_dev->device);
|
||||
LOG_INFO("Cube mesh created");
|
||||
|
||||
float aspect = (float)config.window_width / (float)config.window_height;
|
||||
float aspect = (float)config.window_width / config.window_height;
|
||||
g_camera = camera_perspective(1.0472f, aspect, 0.1f, 100.0f);
|
||||
g_camera.position = (Vec3){0, 1.5f, -4.0f};
|
||||
g_camera.position = (Vec3){0, 0.5f, -5.0f};
|
||||
g_camera.target = (Vec3){0, 0, 0};
|
||||
g_camera.dirty = 1;
|
||||
|
||||
renderer_set_view(r, camera_get_view(&g_camera));
|
||||
renderer_set_projection(r, camera_get_projection(&g_camera));
|
||||
|
||||
engine_set_update_callback(engine, on_update);
|
||||
engine_set_render_callback(engine, on_render);
|
||||
engine_set_key_callback(engine, on_key);
|
||||
engine_set_mouse_move_callback(engine, on_mouse_move);
|
||||
engine_set_mouse_button_callback(engine, on_mouse_button);
|
||||
engine_set_resize_callback(engine, on_resize);
|
||||
|
||||
LOG_INFO("Running cube demo...");
|
||||
LOG_INFO("Running scene demo...");
|
||||
engine_run(engine);
|
||||
|
||||
mesh_destroy(g_cube);
|
||||
shader_destroy(g_shader);
|
||||
graphics_device_destroy(g_dev);
|
||||
scene_destroy_renderers(g_scene);
|
||||
scene_destroy(g_scene);
|
||||
free(g_scene);
|
||||
asset_manager_destroy(g_assets);
|
||||
engine_shutdown(engine);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user