summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/teleia/src/mesh.rs127
-rw-r--r--crates/teleia/src/scene.rs4
-rw-r--r--crates/teleia_macros/src/lib.rs27
3 files changed, 120 insertions, 38 deletions
diff --git a/crates/teleia/src/mesh.rs b/crates/teleia/src/mesh.rs
index 16a4380..536058d 100644
--- a/crates/teleia/src/mesh.rs
+++ b/crates/teleia/src/mesh.rs
@@ -11,6 +11,10 @@ pub const ATTRIB_COLOR: u32 = 5;
pub struct Mesh {
pub vao: glow::VertexArray,
+ pub vbo_vertex: glow::NativeBuffer,
+ pub vbo_index: glow::NativeBuffer,
+ pub vbo_normal: Option<glow::NativeBuffer>,
+ pub vbo_texcoord: Option<glow::NativeBuffer>,
pub mode: u32, // glow::TRIANGLES, etc.
pub index_count: usize,
pub index_type: u32, // glow::BYTE, glow::FLOAT, etc.
@@ -18,19 +22,58 @@ pub struct Mesh {
}
impl Mesh {
- pub fn build(
+ pub fn new_empty(ctx: &context::Context, normals: bool, texcoords: bool) -> Self {
+ unsafe {
+ let vao = ctx.gl.create_vertex_array().expect("failed to initialize vao");
+ ctx.gl.bind_vertex_array(Some(vao));
+
+ let vbo_vertex = ctx.gl.create_buffer().expect("failed to create buffer object");
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_vertex));
+ ctx.gl.vertex_attrib_pointer_f32(ATTRIB_VERTEX, 3, glow::FLOAT, false, 0, 0);
+ ctx.gl.enable_vertex_attrib_array(ATTRIB_VERTEX);
+
+ let vbo_index = ctx.gl.create_buffer().expect("failed to create buffer object");
+ ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(vbo_index));
+
+ let vbo_normal = if normals {
+ let vbo_normal = ctx.gl.create_buffer().expect("failed to create buffer object");
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_normal));
+ ctx.gl.vertex_attrib_pointer_f32(ATTRIB_NORMAL, 3, glow::FLOAT, false, 0, 0);
+ ctx.gl.enable_vertex_attrib_array(ATTRIB_NORMAL);
+ Some(vbo_normal)
+ } else { None };
+
+ let vbo_texcoord = if texcoords {
+ let vbo_texcoord = ctx.gl.create_buffer().expect("failed to create buffer object");
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_texcoord));
+ ctx.gl.vertex_attrib_pointer_f32(ATTRIB_TEXCOORD, 2, glow::FLOAT, false, 0, 0);
+ ctx.gl.enable_vertex_attrib_array(ATTRIB_TEXCOORD);
+ Some(vbo_texcoord)
+ } else { None };
+
+ Self {
+ vao,
+ vbo_vertex,
+ vbo_index,
+ vbo_normal,
+ vbo_texcoord,
+ mode: glow::TRIANGLES,
+ index_count: 0,
+ index_type: glow::UNSIGNED_INT,
+ index_offset: 0,
+ }
+ }
+ }
+ pub fn upload(
+ &mut self,
ctx: &context::Context,
vertices: &[f32],
indices: &[u32],
snormals: Option<&[f32]>,
stexcoords: Option<&[f32]>,
- ) -> Self {
+ ) {
unsafe {
- let vao = ctx.gl.create_vertex_array().expect("failed to initialize vao");
- ctx.gl.bind_vertex_array(Some(vao));
-
- let buf = ctx.gl.create_buffer().expect("failed to create buffer object");
- ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(buf));
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vbo_vertex));
ctx.gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
std::slice::from_raw_parts(
@@ -39,11 +82,7 @@ impl Mesh {
),
glow::STATIC_DRAW,
);
- ctx.gl.vertex_attrib_pointer_f32(ATTRIB_VERTEX, 3, glow::FLOAT, false, 0, 0);
- ctx.gl.enable_vertex_attrib_array(ATTRIB_VERTEX);
-
- let indices_vbo = ctx.gl.create_buffer().expect("failed to create buffer object");
- ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(indices_vbo));
+ ctx.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.vbo_index));
ctx.gl.buffer_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER,
std::slice::from_raw_parts(
@@ -53,9 +92,8 @@ impl Mesh {
glow::STATIC_DRAW,
);
- if let Some(normals) = snormals {
- let normals_vbo = ctx.gl.create_buffer().expect("failed to create buffer object");
- ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(normals_vbo));
+ if let Some(vbo_normal) = self.vbo_normal && let Some(normals) = snormals {
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_normal));
ctx.gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
std::slice::from_raw_parts(
@@ -64,13 +102,11 @@ impl Mesh {
),
glow::STATIC_DRAW,
);
- ctx.gl.vertex_attrib_pointer_f32(ATTRIB_NORMAL, 3, glow::FLOAT, false, 0, 0);
- ctx.gl.enable_vertex_attrib_array(ATTRIB_NORMAL);
- }
+ Some(vbo_normal)
+ } else { None };
- if let Some(texcoords) = stexcoords {
- let texcoords_vbo = ctx.gl.create_buffer().expect("failed to create buffer object");
- ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(texcoords_vbo));
+ if let Some(vbo_texcoord) = self.vbo_texcoord && let Some(texcoords) = stexcoords {
+ ctx.gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo_texcoord));
ctx.gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
std::slice::from_raw_parts(
@@ -79,20 +115,47 @@ impl Mesh {
),
glow::STATIC_DRAW,
);
- ctx.gl.vertex_attrib_pointer_f32(ATTRIB_TEXCOORD, 2, glow::FLOAT, false, 0, 0);
- ctx.gl.enable_vertex_attrib_array(ATTRIB_TEXCOORD);
- }
-
- Self {
- vao,
- mode: glow::TRIANGLES,
- index_count: indices.len(),
- index_type: glow::UNSIGNED_INT,
- index_offset: 0,
- }
+ Some(vbo_texcoord)
+ } else { None };
+ self.index_count = indices.len();
}
}
+ pub fn build(
+ ctx: &context::Context,
+ vertices: &[f32],
+ indices: &[u32],
+ snormals: Option<&[f32]>,
+ stexcoords: Option<&[f32]>,
+ ) -> Self {
+ let mut ret = Self::new_empty(ctx, snormals.is_some(), stexcoords.is_some());
+ ret.upload(ctx, vertices, indices, snormals, stexcoords);
+ ret
+ }
+
+ pub fn upload_obj(&mut self, ctx: &context::Context, mut bytes: &[u8]) {
+ let lopts = tobj::LoadOptions {
+ triangulate: true,
+ single_index: true,
+ ..Default::default()
+ };
+ let (meshes, _materials) = tobj::load_obj_buf(
+ &mut bytes,
+ &lopts,
+ |_| Err(tobj::LoadError::GenericFailure)
+ ).expect("failed to load mesh");
+ let mesh = meshes.into_iter().next()
+ .expect("failed to load mesh")
+ .mesh;
+ self.upload(
+ ctx,
+ &mesh.positions,
+ &mesh.indices,
+ Some(&mesh.normals),
+ Some(&mesh.texcoords),
+ )
+ }
+
pub fn from_obj(ctx: &context::Context, mut bytes: &[u8]) -> Self {
let lopts = tobj::LoadOptions {
triangulate: true,
diff --git a/crates/teleia/src/scene.rs b/crates/teleia/src/scene.rs
index 0c1c25e..d00f098 100644
--- a/crates/teleia/src/scene.rs
+++ b/crates/teleia/src/scene.rs
@@ -199,6 +199,10 @@ impl Scene {
Primitive {
mesh: mesh::Mesh {
vao,
+ vbo_vertex: vertices_buf,
+ vbo_index: indices_buf,
+ vbo_normal: None,
+ vbo_texcoord: None,
mode,
index_count: indices.len(),
index_type: glow::UNSIGNED_INT,
diff --git a/crates/teleia_macros/src/lib.rs b/crates/teleia_macros/src/lib.rs
index d8ee109..c780154 100644
--- a/crates/teleia_macros/src/lib.rs
+++ b/crates/teleia_macros/src/lib.rs
@@ -6,10 +6,11 @@ use heck::ToUpperCamelCase;
#[derive(Debug, Hash, PartialEq, Eq)]
struct Designator {
+ path: String,
parts: Vec<String>,
}
impl Designator {
- fn new(fbase: &str, path: &Path, shorten: bool) -> Self {
+ fn new(fbase: &str, mut path: &Path, shorten: bool) -> Self {
let mut parts: Vec<_> = path.strip_prefix(fbase).unwrap().with_extension("").components()
.filter_map(|c| match c {
std::path::Component::Normal(o) => Some(o.to_str().unwrap().to_owned()),
@@ -18,13 +19,27 @@ impl Designator {
.collect();
if shorten {
parts.pop();
+ path = path.parent().expect("path has no parent");
}
Self {
+ path: path.to_str().expect("path is not a string").to_owned(),
parts
}
}
- fn enum_entry(&self, _fnm: &str) -> String {
- self.parts.join(" ").to_upper_camel_case().to_string()
+ fn enum_entry(&self, fnm: &str) -> String {
+ let singular = match fnm {
+ "meshes" => "mesh",
+ "textures" => "texture",
+ "materials" => "material",
+ "shaders" => "shader",
+ _ => fnm,
+ };
+ let mut ret = format!("\n#[doc=\"newton-{}: {}\"]\n", singular, self.path);
+ ret += &self.parts.join(" ").to_upper_camel_case();
+ ret
+ }
+ fn enum_element(&self, _fnm: &str) -> String {
+ self.parts.join(" ").to_upper_camel_case()
}
fn load_expr(&self, fnm: &str) -> Option<String> {
let i = format!("assets/{}/{}", fnm, self.parts.join("/"));
@@ -71,7 +86,7 @@ impl Field {
let mut ents = Vec::new();
for d in self.entries.iter() {
if let Some(exp) = d.load_expr(&self.nm) {
- ents.push((d.enum_entry(&self.nm), exp));
+ ents.push((d.enum_entry(&self.nm), d.enum_element(&self.nm), exp));
}
}
let (enm, ty) = match self.nm.as_str() {
@@ -81,11 +96,11 @@ impl Field {
"shaders" => ("Shader", "teleia::shader::Shader"),
_ => return None,
};
- let enums: Vec<_> = ents.iter().map(|(e, _)| e.clone()).collect();
+ let enums: Vec<_> = ents.iter().map(|(e, _, _)| e.clone()).collect();
let edecl = format!("#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, enum_map::Enum)]
pub enum {} {{ {} }}", enm, enums.join(", "));
let decl = format!("pub {}: enum_map::EnumMap<{}, {}>", self.nm, enm, ty);
- let inits: Vec<_> = ents.into_iter().map(|(e, exp)| format!("{}::{} => {}", enm, e, exp)).collect();
+ let inits: Vec<_> = ents.into_iter().map(|(_, e, exp)| format!("{}::{} => {}", enm, e, exp)).collect();
let init = format!("{}: enum_map::enum_map!({})", self.nm, inits.join(", "));
Some((edecl, decl, init))
}