666 lines
17 KiB
D
666 lines
17 KiB
D
import aliases;
|
|
import includes;
|
|
import vulkan : Destroy;
|
|
import vulkan;
|
|
import assets;
|
|
import util;
|
|
import alloc;
|
|
import platform;
|
|
import math;
|
|
import core.stdc.math : cosf, sinf;
|
|
import std.algorithm.sorting;
|
|
import fonts;
|
|
|
|
f32 g_DELTA;
|
|
|
|
struct UIVertex
|
|
{
|
|
Vec2 dst_start;
|
|
Vec2 dst_end;
|
|
Vec2 src_start;
|
|
Vec2 src_end;
|
|
Vec4 col;
|
|
}
|
|
|
|
struct UIPushConst
|
|
{
|
|
Vec2 res;
|
|
}
|
|
|
|
struct Vertex
|
|
{
|
|
Vec4 color;
|
|
Vec4 tangent;
|
|
Vec3 pos;
|
|
Vec3 normal;
|
|
Vec2 uv;
|
|
}
|
|
|
|
struct MeshPart
|
|
{
|
|
u32 mat;
|
|
u32 offset;
|
|
u32 length;
|
|
}
|
|
|
|
struct Model
|
|
{
|
|
Vec3 pos = Vec3(0.0);
|
|
Buffer vertex_buffer;
|
|
Buffer index_buffer;
|
|
MeshPart[] parts;
|
|
|
|
string name;
|
|
|
|
Buffer[] materials;
|
|
ImageView[] textures;
|
|
|
|
Vec3[] positions;
|
|
u32[] pos_indices;
|
|
u32[] indices;
|
|
}
|
|
|
|
struct Game
|
|
{
|
|
Renderer rd;
|
|
Arena arena;
|
|
Arena frame_arena;
|
|
|
|
PlatformWindow* window;
|
|
|
|
Pipeline ui_pipeline;
|
|
DescSetLayout ui_desc_layout;
|
|
DescSet ui_desc_set;
|
|
PipelineLayout ui_layout;
|
|
|
|
UIVertex[] ui_vertex_buf;
|
|
u32[] ui_index_buf;
|
|
u32 ui_count;
|
|
|
|
ImageView default_tex;
|
|
ImageView font_tex;
|
|
|
|
UIPushConst ui_pc;
|
|
|
|
Timer timer;
|
|
}
|
|
|
|
Game
|
|
InitGame(PlatformWindow* window)
|
|
{
|
|
Game g = {
|
|
rd: InitRenderer(window, MB(24), MB(32)),
|
|
arena: CreateArena(MB(32)),
|
|
frame_arena: CreateArena(MB(16)),
|
|
window: window,
|
|
timer: CreateTimer(),
|
|
};
|
|
|
|
UVec2 ext = GetExtent(&g.rd);
|
|
|
|
DescLayoutBinding[] layout_bindings = [
|
|
{ binding: 0, descriptorType: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptorCount: 1, stageFlags: VK_SHADER_STAGE_ALL },
|
|
];
|
|
|
|
g.ui_desc_layout = CreateDescSetLayout(&g.rd, layout_bindings);
|
|
g.ui_desc_set = AllocDescSet(&g.rd, g.ui_desc_layout);
|
|
g.ui_layout = CreatePipelineLayout(&g.rd, g.ui_desc_layout, UIPushConst.sizeof);
|
|
|
|
u8[16*16*4] white_tex;
|
|
white_tex[] = u8.max;
|
|
|
|
u8[] atlas = LoadAssetData(&g.frame_arena, "textures/atlas.png");
|
|
int width, height, has_ch;
|
|
auto img = stbi_load_from_memory(atlas.ptr, cast(int)atlas.length, &width, &height, &has_ch, 4);
|
|
assert(width == FONT_ATLAS.width && height == FONT_ATLAS.height && has_ch == 1, "atlas height and width do not match");
|
|
u8[] img_slice = img[0 .. width * height * 4];
|
|
|
|
CreateImageView(&g.rd, &g.font_tex, FONT_ATLAS.width, FONT_ATLAS.height, 4, img_slice);
|
|
CreateImageView(&g.rd, &g.default_tex, 16, 16, 4, white_tex);
|
|
|
|
WriteGUI(&g.rd, g.ui_desc_set, &g.font_tex);
|
|
|
|
GfxPipelineInfo ui_info = {
|
|
vertex_shader: "shaders/gui.vert.spv",
|
|
frag_shader: "shaders/gui.frag.spv",
|
|
input_rate: IR.Instance,
|
|
input_rate_stride: UIVertex.sizeof,
|
|
layout: g.ui_layout,
|
|
vertex_attributes: [
|
|
{ binding: 0, location: 0, format: FMT.RG_F32, offset: UIVertex.dst_start.offsetof },
|
|
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.dst_end.offsetof },
|
|
{ binding: 0, location: 2, format: FMT.RG_F32, offset: UIVertex.src_start.offsetof },
|
|
{ binding: 0, location: 3, format: FMT.RG_F32, offset: UIVertex.src_end.offsetof },
|
|
{ binding: 0, location: 4, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
|
|
],
|
|
};
|
|
|
|
g.ui_pipeline = CreateGraphicsPipeline(&g.rd, &ui_info);
|
|
|
|
PrintShaderDisassembly(&g.rd, g.ui_pipeline, VK_SHADER_STAGE_VERTEX_BIT);
|
|
PrintShaderDisassembly(&g.rd, g.ui_pipeline, VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
|
|
g.ui_vertex_buf = GetUIVertexBuffer(&g.rd);
|
|
g.ui_index_buf = GetUIIndexBuffer(&g.rd);
|
|
|
|
WaitForTransfers(&g.rd);
|
|
|
|
Reset(&g.frame_arena);
|
|
|
|
return g;
|
|
}
|
|
|
|
void
|
|
Copy(Model* dst, Model* src)
|
|
{
|
|
dst.vertex_buffer = src.vertex_buffer;
|
|
dst.index_buffer = src.index_buffer;
|
|
dst.parts = src.parts;
|
|
dst.materials = src.materials;
|
|
dst.textures = src.textures;
|
|
}
|
|
|
|
void
|
|
ProcessInputs(Game* g, Camera* cam)
|
|
{
|
|
HandleInputs(cam, &g.window.inputs);
|
|
}
|
|
|
|
void
|
|
Cycle(Game* g)
|
|
{
|
|
g_DELTA = DeltaTime(&g.timer);
|
|
|
|
g.ui_count = 0;
|
|
|
|
Reset(&g.frame_arena);
|
|
|
|
DrawRect(g, 500.0, 500.0, 800.0, 800.0, Vec4(0.2, 0.3, 0.7, 1.0));
|
|
DrawText(g, 200.0, 200.0, 32.0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
|
|
|
BeginFrame(&g.rd);
|
|
|
|
UVec2 ext = GetExtent(&g.rd);
|
|
g.ui_pc.res.x = cast(f32)ext.x;
|
|
g.ui_pc.res.y = cast(f32)ext.y;
|
|
|
|
BeginRendering(&g.rd);
|
|
|
|
PushConstants(&g.rd, g.ui_pipeline, &g.ui_pc);
|
|
|
|
Bind(&g.rd, g.ui_pipeline, g.ui_desc_set);
|
|
|
|
BindUIBuffers(&g.rd);
|
|
|
|
DrawIndexed(&g.rd, 6, g.ui_count, 0);
|
|
|
|
FinishRendering(&g.rd);
|
|
|
|
SubmitAndPresent(&g.rd);
|
|
}
|
|
|
|
pragma(inline): void
|
|
DrawModel(Game* g, Model* model)
|
|
{
|
|
BindBuffers(&g.rd, &model.index_buffer, &model.vertex_buffer);
|
|
foreach(i, part; model.parts)
|
|
{
|
|
DrawIndexed(&g.rd, part.length, 1, part.offset);
|
|
}
|
|
}
|
|
|
|
void
|
|
Destroy(Game* g)
|
|
{
|
|
WaitIdle(&g.rd);
|
|
|
|
Destroy(&g.rd, g.ui_pipeline);
|
|
Destroy(&g.rd);
|
|
}
|
|
|
|
void
|
|
Destroy(Renderer* rd, Model* model)
|
|
{
|
|
Destroy(rd, &model.vertex_buffer);
|
|
Destroy(rd, &model.index_buffer);
|
|
|
|
foreach(i, mat; model.materials)
|
|
{
|
|
Destroy(rd, model.materials.ptr + i);
|
|
}
|
|
|
|
foreach(i, view; model.textures)
|
|
{
|
|
Destroy(rd, model.textures.ptr + i);
|
|
}
|
|
}
|
|
|
|
struct Camera
|
|
{
|
|
Vec3 velocity = Vec3(0.0);
|
|
Vec3 pos = Vec3(0.0, 0.0, 2.0);
|
|
f32 pitch = 0.0;
|
|
f32 yaw = 0.0;
|
|
}
|
|
|
|
pragma(inline): void
|
|
HandleInputs(Camera* cam, Inputs* inputs)
|
|
{
|
|
foreach(i; 0 .. inputs.count)
|
|
{
|
|
InputEvent event = inputs.events[i];
|
|
switch(event.key)
|
|
{
|
|
case Input.W: cam.velocity.z = event.pressed ? -1.0 : 0.0; break;
|
|
case Input.S: cam.velocity.z = event.pressed ? 1.0 : 0.0; break;
|
|
case Input.A: cam.velocity.x = event.pressed ? -1.0 : 0.0; break;
|
|
case Input.D: cam.velocity.x = event.pressed ? 1.0 : 0.0; break;
|
|
case Input.Space: cam.velocity.y = event.pressed ? 1.0 : 0.0; break;
|
|
case Input.LeftCtrl: cam.velocity.y = event.pressed ? -1.0 : 0.0; break;
|
|
case Input.MouseMotion:
|
|
{
|
|
// (0, 0) top left
|
|
cam.yaw += cast(f32)(event.rel_x) / 200.0;
|
|
cam.pitch += cast(f32)(event.rel_y) / 200.0;
|
|
} break;
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Mat4
|
|
RotationMatrix(Camera* cam)
|
|
{
|
|
Quat pitch = QuatFromAxis(cam.pitch, Vec3(1.0, 0.0, 0.0));
|
|
Quat yaw = QuatFromAxis(cam.yaw, Vec3(0.0, 1.0, 0.0));
|
|
return cast(Mat4)(yaw) * cast(Mat4)(pitch);
|
|
}
|
|
|
|
Mat4
|
|
ViewMatrix(Camera* cam)
|
|
{
|
|
Mat4 translation = Mat4Identity();
|
|
Translate(&translation, cam.pos);
|
|
Mat4 rotation = RotationMatrix(cam);
|
|
return Inverse(translation * rotation);
|
|
}
|
|
|
|
void
|
|
Update(Camera* cam)
|
|
{
|
|
Mat4 rotation = RotationMatrix(cam);
|
|
Vec4 pos = rotation * Vec4(cam.velocity * g_DELTA, 0.0);
|
|
cam.pos += pos.xyz;
|
|
}
|
|
|
|
void
|
|
Sort(Game* g, Vec3 pos, Model* model)
|
|
{
|
|
f32[] lengths = AllocArray!(f32)(&g.frame_arena, model.positions.length);
|
|
|
|
foreach(i; 0 .. lengths.length)
|
|
{
|
|
model.pos_indices[i] = cast(u32)i;
|
|
lengths.ptr[i] = fabs(Norm(&pos) - Norm(model.positions.ptr + i));
|
|
}
|
|
|
|
makeIndex!("a < b")(lengths, model.pos_indices);
|
|
|
|
Logf("%s", model.positions.length);
|
|
|
|
foreach(i, v; model.pos_indices)
|
|
{
|
|
model.indices[i+0] = cast(u32)((3*v)+0);
|
|
model.indices[i+1] = cast(u32)((3*v)+1);
|
|
model.indices[i+2] = cast(u32)((3*v)+2);
|
|
}
|
|
|
|
UpdateIndexBuffer(&g.rd, model);
|
|
}
|
|
|
|
void
|
|
DrawText(Game* g, f32 x, f32 y, f32 px, string str)
|
|
{
|
|
f32 x_pos = x;
|
|
foreach(ch; str)
|
|
{
|
|
foreach(glyph; FONT_ATLAS.glyphs)
|
|
{
|
|
if (ch == glyph.ch)
|
|
{
|
|
UIVertex* v = g.ui_vertex_buf.ptr + g.ui_count;
|
|
|
|
f32 w = px * (glyph.plane_right - glyph.plane_left);
|
|
f32 h = px * (glyph.plane_bottom - glyph.plane_top);
|
|
f32 y_pos = px * glyph.plane_bottom;
|
|
|
|
v.dst_start.x = x_pos;
|
|
v.dst_start.y = y + h - y_pos;
|
|
v.dst_end.x = x_pos + w;
|
|
v.dst_end.y = y - y_pos;
|
|
|
|
v.src_start.x = glyph.atlas_left;
|
|
v.src_start.y = glyph.atlas_top;
|
|
v.src_end.x = glyph.atlas_right;
|
|
v.src_end.y = glyph.atlas_bottom;
|
|
|
|
v.col = Vec4(1.0, 1.0, 1.0, 1.0);
|
|
|
|
x_pos += px * glyph.advance;
|
|
|
|
AddUIIndices(g);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
AddUIIndices(Game* g)
|
|
{
|
|
g.ui_index_buf[0] = 0;
|
|
g.ui_index_buf[1] = 1;
|
|
g.ui_index_buf[2] = 2;
|
|
g.ui_index_buf[3] = 2;
|
|
g.ui_index_buf[4] = 1;
|
|
g.ui_index_buf[5] = 3;
|
|
|
|
g.ui_count += 1;
|
|
}
|
|
|
|
void
|
|
DrawRect(Game* g, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
|
|
{
|
|
// Y reversed
|
|
g.ui_vertex_buf[g.ui_count].dst_start.x = p0_x;
|
|
g.ui_vertex_buf[g.ui_count].dst_start.y = p0_y;
|
|
g.ui_vertex_buf[g.ui_count].dst_end.x = p1_x;
|
|
g.ui_vertex_buf[g.ui_count].dst_end.y = p1_y;
|
|
g.ui_vertex_buf[g.ui_count].col = col;
|
|
|
|
AddUIIndices(g);
|
|
}
|
|
|
|
// TODO: integrate this with vulkan again
|
|
Model
|
|
LoadModel(Game* g, string name)
|
|
{
|
|
AssetInfo info; // = GetAssetInfo(name);
|
|
|
|
u8[] data = LoadAssetData(&g.frame_arena, name);
|
|
Model model = {
|
|
name: name,
|
|
};
|
|
|
|
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
|
|
scope(exit) m3d_free(m3d);
|
|
|
|
u32[] tex_lookup = AllocArray!(u32)(&g.frame_arena, m3d.numtexture);
|
|
model.textures = AllocArray!(ImageView)(&g.arena, m3d.numtexture);
|
|
foreach(i; 0 .. m3d.numtexture)
|
|
{
|
|
u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f;
|
|
u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch];
|
|
|
|
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
|
CreateImageView(&g.rd, &model.textures[i], w, h, ch, tex_data);
|
|
|
|
//tex_lookup[i] = Pop(&g.rd, DT.SampledImage);
|
|
}
|
|
|
|
Material[] mats = AllocArray!(Material)(&g.frame_arena, m3d.nummaterial);
|
|
u32[] mat_lookup = AllocArray!(u32)(&g.frame_arena, m3d.nummaterial);
|
|
model.materials = AllocArray!(Buffer)(&g.arena, m3d.nummaterial);
|
|
foreach(i; 0 .. m3d.nummaterial)
|
|
{
|
|
const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
|
|
|
|
foreach(j; 0 .. m3d.material[i].numprop)
|
|
{
|
|
switch (m3d.material[i].prop[j].type)
|
|
{
|
|
case m3dp_Kd: ConvertColor(&mats[i].albedo, m3d.material[i].prop[j].value.color); break;
|
|
case m3dp_Ka: ConvertColor(&mats[i].ambient, m3d.material[i].prop[j].value.color); break;
|
|
case m3dp_Ks: ConvertColor(&mats[i].specular, m3d.material[i].prop[j].value.color); break;
|
|
case m3dp_Ns: mats[i].shininess = m3d.material[i].prop[j].value.fnum; break;
|
|
case m3dp_d: mats[i].alpha = m3d.material[i].prop[j].value.fnum; break;
|
|
case m3dp_map_Kd:
|
|
{
|
|
mats[i].albedo_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
|
mats[i].albedo_has_texture = true;
|
|
} break;
|
|
case m3dp_map_Ka:
|
|
{
|
|
mats[i].ambient_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
|
mats[i].ambient_has_texture = true;
|
|
} break;
|
|
case m3dp_map_Ks:
|
|
{
|
|
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
|
mats[i].specular_has_texture = true;
|
|
} break;
|
|
case m3dp_map_D:
|
|
{
|
|
mats[i].alpha_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
|
mats[i].alpha_has_texture = true;
|
|
} break;
|
|
default: Logf("Unsupported property: %s", M3DPropToStr(m3d.material[i].prop[j].type)); break;
|
|
}
|
|
}
|
|
|
|
CreateBuffer(&g.rd, &model.materials[i], BT.Uniform, Material.sizeof, false);
|
|
assert(Transfer(&g.rd, &model.materials[i], &mats[i]), "LoadModel failure: Transfer error when transferring material");
|
|
|
|
//mat_lookup[i] = Pop(&g.rd, DT.Material);
|
|
}
|
|
|
|
u32 mesh_count = 0;
|
|
u64 last = u64.max;
|
|
foreach(i; 0 .. m3d.numface)
|
|
{
|
|
if (m3d.face[i].materialid != last)
|
|
{
|
|
last = m3d.face[i].materialid;
|
|
mesh_count += 1;
|
|
}
|
|
}
|
|
|
|
model.parts = AllocArray!(MeshPart)(&g.arena, mesh_count);
|
|
last = u64.max;
|
|
u32 index = 0;
|
|
foreach(i; 0 .. m3d.numface)
|
|
{
|
|
if (last == u64.max)
|
|
{
|
|
model.parts[index].mat = (m3d.face[i].materialid != u32.max) ? mat_lookup[m3d.face[i].materialid] : 0;
|
|
model.parts[index].offset = 0;
|
|
last = m3d.face[i].materialid;
|
|
}
|
|
else if (m3d.face[i].materialid != last)
|
|
{
|
|
u32 vertex_index = i * 3;
|
|
|
|
model.parts[index].length = vertex_index - model.parts[index].offset;
|
|
index += 1;
|
|
|
|
model.parts[index].mat = mat_lookup[m3d.face[i].materialid];
|
|
model.parts[index].offset = vertex_index;
|
|
last = m3d.face[i].materialid;
|
|
}
|
|
else if (i == m3d.numface-1)
|
|
{
|
|
u32 vertex_index = i * 3;
|
|
model.parts[index].length = vertex_index+3 - model.parts[index].offset;
|
|
}
|
|
}
|
|
|
|
m3dv_t* vertex;
|
|
|
|
u32[] indices = AllocArray!(u32)(&g.arena, m3d.numface * 3);
|
|
Vertex[] vertices = AllocArray!(Vertex)(&g.frame_arena, m3d.numface * 3);
|
|
Vec3[] positions = AllocArray!(Vec3)(&g.arena, m3d.numface);
|
|
u32[] pos_indices = AllocArray!(u32)(&g.arena, m3d.numface);
|
|
|
|
foreach(i; 0 .. m3d.numface)
|
|
{
|
|
u32 vi = (i * 3);
|
|
u32 i0 = vi+0;
|
|
u32 i1 = vi+1;
|
|
u32 i2 = vi+2;
|
|
|
|
CopyVertex(&vertices[i0].pos, &m3d.vertex[m3d.face[i].vertex[0]]);
|
|
CopyVertex(&vertices[i1].pos, &m3d.vertex[m3d.face[i].vertex[1]]);
|
|
CopyVertex(&vertices[i2].pos, &m3d.vertex[m3d.face[i].vertex[2]]);
|
|
|
|
CopyVertex(&vertices[i0].normal, &m3d.vertex[m3d.face[i].normal[0]]);
|
|
CopyVertex(&vertices[i1].normal, &m3d.vertex[m3d.face[i].normal[1]]);
|
|
CopyVertex(&vertices[i2].normal, &m3d.vertex[m3d.face[i].normal[2]]);
|
|
|
|
ConvertColor(&vertices[i0].color, m3d.vertex[m3d.face[i].vertex[0]].color);
|
|
ConvertColor(&vertices[i1].color, m3d.vertex[m3d.face[i].vertex[1]].color);
|
|
ConvertColor(&vertices[i2].color, m3d.vertex[m3d.face[i].vertex[2]].color);
|
|
|
|
if (m3d.numtmap)
|
|
{
|
|
vertices[i0].uv.x = m3d.tmap[m3d.face[i].texcoord[0]].u;
|
|
vertices[i0].uv.y = m3d.tmap[m3d.face[i].texcoord[0]].v;
|
|
|
|
vertices[i1].uv.x = m3d.tmap[m3d.face[i].texcoord[1]].u;
|
|
vertices[i1].uv.y = m3d.tmap[m3d.face[i].texcoord[1]].v;
|
|
|
|
vertices[i2].uv.x = m3d.tmap[m3d.face[i].texcoord[2]].u;
|
|
vertices[i2].uv.y = m3d.tmap[m3d.face[i].texcoord[2]].v;
|
|
}
|
|
|
|
indices[i0] = i0;
|
|
indices[i1] = i1;
|
|
indices[i2] = i2;
|
|
|
|
Vec3 center = (vertices[i0].pos + vertices[i1].pos + vertices[i2].pos) / 3.0;
|
|
|
|
positions[i] = center;
|
|
pos_indices[i] = i;
|
|
}
|
|
|
|
for(u64 i = 0; i < indices.length; i += 3)
|
|
{
|
|
u32 i0 = indices[i+0];
|
|
u32 i1 = indices[i+1];
|
|
u32 i2 = indices[i+2];
|
|
|
|
Vec3 edge1 = vertices[i1].pos - vertices[i0].pos;
|
|
Vec3 edge2 = vertices[i2].pos - vertices[i0].pos;
|
|
|
|
Vec2 delta_uv1 = vertices[i1].uv - vertices[i0].uv;
|
|
Vec2 delta_uv2 = vertices[i2].uv - vertices[i0].uv;
|
|
|
|
f32 dividend = delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y;
|
|
f32 fc = 1.0 / dividend;
|
|
|
|
Vec3 tangent = Vec3(
|
|
fc * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x),
|
|
fc * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y),
|
|
fc * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z)
|
|
);
|
|
|
|
Normalize(&tangent);
|
|
|
|
f32 handedness = ((delta_uv1.y * delta_uv2.x - delta_uv2.y * delta_uv1.x) < 0.0) ? -1.0 : 1.0;
|
|
|
|
Vec3 t = tangent * handedness;
|
|
|
|
vertices[i0].tangent = Vec4(t, handedness);
|
|
vertices[i1].tangent = Vec4(t, handedness);
|
|
vertices[i2].tangent = Vec4(t, handedness);
|
|
}
|
|
|
|
assert(vertices.length > 0 && indices.length > 0, "Error loading model");
|
|
|
|
CreateBuffer(&g.rd, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false);
|
|
CreateBuffer(&g.rd, &model.index_buffer, BT.Index, indices.length * u32.sizeof, false);
|
|
|
|
assert(Transfer(&g.rd, &model.vertex_buffer, vertices), "LoadModel failure: Unable to transfer vertex buffer");
|
|
assert(Transfer(&g.rd, &model.index_buffer, indices), "LoadModel failure: Unable to transfer index buffer");
|
|
|
|
//WriteDescriptors(&g.rd, DT.Material, model.materials, mat_lookup);
|
|
//WriteDescriptors(&g.rd, DT.SampledImage, model.textures, tex_lookup);
|
|
|
|
model.positions = positions;
|
|
model.indices = indices;
|
|
model.pos_indices = pos_indices;
|
|
|
|
return model;
|
|
}
|
|
|
|
string
|
|
M3DPropToStr(u8 type)
|
|
{
|
|
string result = "Unknown";
|
|
switch(type)
|
|
{
|
|
case m3dp_Kd: result = "Diffuse"; break;
|
|
case m3dp_Ka: result = "Ambient"; break;
|
|
case m3dp_Ks: result = "Specular Color"; break;
|
|
case m3dp_Ns: result = "Specular Exponent"; break;
|
|
case m3dp_Ke: result = "Emissive"; break;
|
|
case m3dp_Tf: result = "Transmission"; break;
|
|
case m3dp_Km: result = "Bump Strength"; break;
|
|
case m3dp_d: result = "Alpha"; break;
|
|
case m3dp_il: result = "Illumination"; break;
|
|
case m3dp_Pr: result = "Roughness"; break;
|
|
case m3dp_Pm: result = "Metallic"; break;
|
|
case m3dp_Ps: result = "Sheen"; break;
|
|
case m3dp_Ni: result = "Refraction"; break;
|
|
case m3dp_Nt: result = "Face Thickness"; break;
|
|
case m3dp_map_Kd: result = "Diffuse Texture"; break;
|
|
case m3dp_map_Ka: result = "Ambient Texture"; break;
|
|
case m3dp_map_Ks: result = "Specular Texture"; break;
|
|
case m3dp_map_Ns: result = "Specular Exponent Texture"; break;
|
|
case m3dp_map_Ke: result = "Emissive Texture"; break;
|
|
case m3dp_map_Tf: result = "Transmission Texture"; break;
|
|
case m3dp_map_Km: result = "Bump Map"; break;
|
|
case m3dp_map_D: result = "Alpha Map"; break;
|
|
case m3dp_map_N: result = "Normal Map"; break;
|
|
case m3dp_map_Pr: result = "Roughness Map"; break;
|
|
case m3dp_map_Pm: result = "Metallic Map"; break;
|
|
case m3dp_map_Ps: result = "Sheen Map"; break;
|
|
case m3dp_map_Ni: result = "Refraction Map"; break;
|
|
case m3dp_map_Nt: result = "Thickness Map"; break;
|
|
default: break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
pragma(inline): void
|
|
CopyVertex(Vec3* dst, m3dv_t* src)
|
|
{
|
|
dst.x = src.x;
|
|
dst.y = src.y;
|
|
dst.z = src.z;
|
|
}
|
|
|
|
void
|
|
ReadModel(Game* g, string name)
|
|
{
|
|
AssetInfo info; // = GetAssetInfo(name);
|
|
|
|
u8[] data = LoadAssetData(&g.frame_arena, name);
|
|
|
|
m3d_t* m3d = m3d_load(data.ptr, null, null, null);
|
|
|
|
foreach(i; 0 .. m3d.numtexture)
|
|
{
|
|
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
|
}
|
|
|
|
if (m3d.numtexture == 0)
|
|
{
|
|
Log("No textures in model");
|
|
}
|
|
|
|
foreach(i; 0 .. m3d.nummaterial)
|
|
{
|
|
const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
|
|
}
|
|
}
|