Skip to content

Commit

Permalink
lib: Move vertex buffers from scene to meshes
Browse files Browse the repository at this point in the history
I forget what the reasoning was for having these in the scene. Our
dynamic array implementation may realloc(), so I had to awkwardly grab
the handles and assign them to meshes after all the vertex buffers were
loaded. Weird. Now each mesh owns a single vertex buffer. I don't even
think this is worse for cache locality, since the shared vertex buffer
array also had separate allocations for each vertex buf.
  • Loading branch information
vkoskiv committed Jul 2, 2024
1 parent 70439b4 commit fb3157c
Show file tree
Hide file tree
Showing 15 changed files with 65 additions and 109 deletions.
2 changes: 1 addition & 1 deletion bindings/blender_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def sync_scene(self, depsgraph):
faces.append(to_cr_face(me, poly))
facebuf = (c_ray.cr_face * len(faces))(*faces)
cr_mesh.bind_faces(bytearray(facebuf), len(faces))
cr_mesh.bind_vertex_buf(cr_vertex_buf(self.cr_scene, me))
cr_mesh.bind_vertex_buf(me)

# Set background shader
bl_nodetree = bpy.data.worlds[0].node_tree
Expand Down
35 changes: 20 additions & 15 deletions bindings/c_ray.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,26 @@ def __init__(self, scene_ptr, name):
self.instances = []
self.cr_idx = _lib.scene_mesh_new(self.scene_ptr, self.name)

def bind_vertex_buf(self, buf):
_lib.mesh_bind_vertex_buf(self.scene_ptr, self.cr_idx, buf.cr_idx)
def bind_vertex_buf(self, me):
verts = []
for v in me.vertices:
cr_vert = cr_vector()
cr_vert.x = v.co[0]
cr_vert.y = v.co[1]
cr_vert.z = v.co[2]
verts.append(cr_vert)
normals = []
texcoords = []
vbuf = (cr_vector * len(verts))(*verts)
nbuf = (cr_vector * len(normals))(*normals)
tbuf = (cr_coord * len(texcoords))(*texcoords)
self.v = bytearray(vbuf)
self.vn = len(verts)
self.n = bytearray(nbuf)
self.nn = len(normals)
self.t = bytearray(tbuf)
self.tn = len(texcoords)
_lib.mesh_bind_vertex_buf(self.scene_ptr, self.cr_idx, self.v, self.vn, self.n, self.nn, self.t, self.tn)
def bind_faces(self, faces, face_count):
_lib.mesh_bind_faces(self.scene_ptr, self.cr_idx, faces, face_count)
def instance_new(self):
Expand Down Expand Up @@ -399,17 +417,6 @@ def bind_materials(self, material_set):
self.material_set = material_set
_lib.instance_bind_material_set(self.scene_ptr, self.cr_idx, self.material_set.cr_idx)

class vertex_buf:
def __init__(self, scene_ptr, v, vn, n, nn, t, tn):
self.cr_ptr = scene_ptr
self.v = v
self.vn = vn
self.n = n
self.nn = nn
self.t = t
self.tn = tn
self.cr_idx = _lib.scene_vertex_buf_new(self.cr_ptr, self.v, self.vn, self.n, self.nn, self.t, self.tn)

class material_set:
def __init__(self, scene_ptr):
self.scene_ptr = scene_ptr
Expand Down Expand Up @@ -469,8 +476,6 @@ def set_background(self, material):
name = b'cray.shader_node'
capsule = ct.pythonapi.PyCapsule_New(ct.byref(material.cr_struct), name, None)
return _lib.scene_set_background(self.cr_ptr, capsule)
def vertex_buf_new(self, v, vn, n, nn, t, tn):
return vertex_buf(self.cr_ptr, v, vn, n, nn, t, tn)

class renderer:
def __init__(self, path = None):
Expand Down
21 changes: 4 additions & 17 deletions bindings/cray_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,17 @@ static PyObject *py_cr_scene_add_sphere(PyObject *self, PyObject *args) {
return PyLong_FromLong(sphere);
}

static PyObject *py_cr_scene_vertex_buf_new(PyObject *self, PyObject *args) {
static PyObject *py_cr_mesh_bind_vertex_buf(PyObject *self, PyObject *args) {
(void)self; (void)args;
PyObject *s_ext;
cr_mesh mesh;
PyObject *vec_buff;
size_t vec_count;
PyObject *nor_buff;
size_t nor_count;
PyObject *tex_buff;
size_t tex_count;
if (!PyArg_ParseTuple(args, "OOnOnOn", &s_ext, &vec_buff, &vec_count, &nor_buff, &nor_count, &tex_buff, &tex_count)) {
if (!PyArg_ParseTuple(args, "OlOnOnOn", &s_ext, &mesh, &vec_buff, &vec_count, &nor_buff, &nor_count, &tex_buff, &tex_count)) {
return NULL;
}
Py_buffer vec_view;
Expand Down Expand Up @@ -367,7 +368,7 @@ static PyObject *py_cr_scene_vertex_buf_new(PyObject *self, PyObject *args) {
memcpy(texcoords, tex_view.buf, tex_count * sizeof(*texcoords));

struct cr_scene *s = PyCapsule_GetPointer(s_ext, "cray.cr_scene");
cr_vertex_buf buf = cr_scene_vertex_buf_new(s, (struct cr_vertex_buf_param){
cr_mesh_bind_vertex_buf(s, mesh, (struct cr_vertex_buf_param){
.vertices = vertices,
.vertex_count = vec_count,
.normals = normals,
Expand All @@ -379,19 +380,6 @@ static PyObject *py_cr_scene_vertex_buf_new(PyObject *self, PyObject *args) {
free(vertices);
free(normals);
free(texcoords);
return PyLong_FromLong(buf);
}

static PyObject *py_cr_mesh_bind_vertex_buf(PyObject *self, PyObject *args) {
(void)self; (void)args;
PyObject *s_ext;
cr_mesh mesh;
cr_vertex_buf vbuf;
if (!PyArg_ParseTuple(args, "Oll", &s_ext, &mesh, &vbuf)) {
return NULL;
}
struct cr_scene *s = PyCapsule_GetPointer(s_ext, "cray.cr_scene");
cr_mesh_bind_vertex_buf(s, mesh, vbuf);
Py_RETURN_NONE;
}

Expand Down Expand Up @@ -742,7 +730,6 @@ static PyMethodDef cray_methods[] = {
{ "renderer_scene_get", py_cr_renderer_scene_get, METH_VARARGS, "" },
{ "scene_totals", py_cr_scene_totals, METH_VARARGS, "" },
{ "scene_add_sphere", py_cr_scene_add_sphere, METH_VARARGS, "" },
{ "scene_vertex_buf_new", py_cr_scene_vertex_buf_new, METH_VARARGS, "" },
{ "mesh_bind_vertex_buf", py_cr_mesh_bind_vertex_buf, METH_VARARGS, "" },
{ "mesh_bind_faces", py_cr_mesh_bind_faces, METH_VARARGS, "" },
{ "scene_mesh_new", py_cr_scene_mesh_new, METH_VARARGS, "" },
Expand Down
9 changes: 3 additions & 6 deletions include/c-ray/c-ray.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,6 @@ struct cr_vertex_buf_param {
size_t tex_coord_count;
};

typedef cr_object cr_vertex_buf;
CR_EXPORT cr_vertex_buf cr_scene_vertex_buf_new(struct cr_scene *s_ext, struct cr_vertex_buf_param in);
CR_EXPORT void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, cr_vertex_buf buf);

struct cr_face {
int vertex_idx[MAX_CRAY_VERTEX_COUNT];
int normal_idx[MAX_CRAY_VERTEX_COUNT];
Expand All @@ -197,11 +193,12 @@ struct cr_face {
bool has_normals;
};

CR_EXPORT void cr_mesh_bind_faces(struct cr_scene *s_ext, cr_mesh mesh, struct cr_face *faces, size_t face_count);

CR_EXPORT cr_mesh cr_scene_mesh_new(struct cr_scene *s_ext, const char *name);
CR_EXPORT cr_mesh cr_scene_get_mesh(struct cr_scene *s_ext, const char *name);

CR_EXPORT void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, struct cr_vertex_buf_param buf);
CR_EXPORT void cr_mesh_bind_faces(struct cr_scene *s_ext, cr_mesh mesh, struct cr_face *faces, size_t face_count);

// -- Camera --
// FIXME: Use cr_vector
// TODO: Support quaternions, or maybe just a mtx4x4?
Expand Down
6 changes: 3 additions & 3 deletions src/common/json_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,14 @@ static void parse_mesh(struct cr_renderer *r, const cJSON *data, int idx, int me

if (!result.meshes.count) return;

cr_vertex_buf vbuf = cr_scene_vertex_buf_new(scene, (struct cr_vertex_buf_param){
struct cr_vertex_buf_param vbuf = {
.vertices = (struct cr_vector *)result.geometry.vertices.items,
.vertex_count = result.geometry.vertices.count,
.normals = (struct cr_vector *)result.geometry.normals.items,
.normal_count = result.geometry.normals.count,
.tex_coords = (struct cr_coord *)result.geometry.texture_coords.items,
.tex_coord_count = result.geometry.texture_coords.count,
});

};
// Per JSON 'meshes' array element, these apply to materials before we assign them to instances
const struct cJSON *global_overrides = cJSON_GetObjectItem(data, "materials");

Expand Down Expand Up @@ -359,6 +358,7 @@ static void parse_mesh(struct cr_renderer *r, const cJSON *data, int idx, int me
for (size_t i = 0; i < result.meshes.count; ++i) {
cr_mesh mesh = cr_scene_mesh_new(scene, result.meshes.items[i].name);
cr_mesh_bind_vertex_buf(scene, mesh, vbuf);

cr_mesh_bind_faces(scene, mesh, result.meshes.items[i].faces.items, result.meshes.items[i].faces.count);
cr_instance m_instance = cr_instance_new(scene, mesh, cr_object_mesh);
cr_instance_bind_material_set(scene, m_instance, file_set);
Expand Down
6 changes: 3 additions & 3 deletions src/lib/accelerators/bvh.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,9 +557,9 @@ static inline bool traverse_bvh_generic(

static void get_poly_bbox_and_center(const void *userData, unsigned i, struct boundingBox *bbox, struct vector *center) {
const struct mesh *mesh = userData;
struct vector v0 = mesh->vbuf->vertices.items[mesh->polygons.items[i].vertexIndex[0]];
struct vector v1 = mesh->vbuf->vertices.items[mesh->polygons.items[i].vertexIndex[1]];
struct vector v2 = mesh->vbuf->vertices.items[mesh->polygons.items[i].vertexIndex[2]];
struct vector v0 = mesh->vbuf.vertices.items[mesh->polygons.items[i].vertexIndex[0]];
struct vector v1 = mesh->vbuf.vertices.items[mesh->polygons.items[i].vertexIndex[1]];
struct vector v2 = mesh->vbuf.vertices.items[mesh->polygons.items[i].vertexIndex[2]];
*center = vec_get_midpoint(v0, v1, v2);
bbox->min = vec_min(v0, vec_min(v1, v2));
bbox->max = vec_max(v0, vec_max(v1, v2));
Expand Down
35 changes: 14 additions & 21 deletions src/lib/api/c-ray.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,36 +254,29 @@ cr_sphere cr_scene_add_sphere(struct cr_scene *s_ext, float radius) {
return sphere_arr_add(&scene->spheres, (struct sphere){ .radius = radius });
}

cr_vertex_buf cr_scene_vertex_buf_new(struct cr_scene *s_ext, struct cr_vertex_buf_param in) {
if (!s_ext) return -1;
void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, struct cr_vertex_buf_param buf) {
if (!s_ext) return;
struct world *scene = (struct world *)s_ext;
if ((size_t)mesh > scene->meshes.count - 1) return;
struct mesh *m = &scene->meshes.items[mesh];
struct vertex_buffer new = { 0 };
// TODO: T_arr_add_n()
if (in.vertices && in.vertex_count) {
for (size_t i = 0; i < in.vertex_count; ++i) {
vector_arr_add(&new.vertices, *(struct vector *)&in.vertices[i]);
if (buf.vertices && buf.vertex_count) {
for (size_t i = 0; i < buf.vertex_count; ++i) {
vector_arr_add(&new.vertices, *(struct vector *)&buf.vertices[i]);
}
}
if (in.normals && in.normal_count) {
for (size_t i = 0; i < in.normal_count; ++i) {
vector_arr_add(&new.normals, *(struct vector *)&in.normals[i]);
if (buf.normals && buf.normal_count) {
for (size_t i = 0; i < buf.normal_count; ++i) {
vector_arr_add(&new.normals, *(struct vector *)&buf.normals[i]);
}
}
if (in.tex_coords && in.tex_coord_count) {
for (size_t i = 0; i < in.tex_coord_count; ++i) {
coord_arr_add(&new.texture_coords, *(struct coord *)&in.tex_coords[i]);
if (buf.tex_coords && buf.tex_coord_count) {
for (size_t i = 0; i < buf.tex_coord_count; ++i) {
coord_arr_add(&new.texture_coords, *(struct coord *)&buf.tex_coords[i]);
}
}
return vertex_buffer_arr_add(&scene->v_buffers, new);
}

void cr_mesh_bind_vertex_buf(struct cr_scene *s_ext, cr_mesh mesh, cr_vertex_buf buf) {
if (!s_ext) return;
struct world *scene = (struct world *)s_ext;
if ((size_t)mesh > scene->meshes.count - 1) return;
struct mesh *m = &scene->meshes.items[mesh];
if ((size_t)buf > scene->v_buffers.count - 1) return;
m->vbuf_idx = buf;
m->vbuf = new;
}

void cr_mesh_bind_faces(struct cr_scene *s_ext, cr_mesh mesh, struct cr_face *faces, size_t face_count) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/datatypes/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ void mesh_free(struct mesh *mesh) {
free(mesh->name);
poly_arr_free(&mesh->polygons);
destroy_bvh(mesh->bvh);
vertex_buf_free(&mesh->vbuf);
}
}
3 changes: 1 addition & 2 deletions src/lib/datatypes/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ typedef struct cr_face cr_face;
dyn_array_def(cr_face)

struct mesh {
struct vertex_buffer *vbuf;
struct vertex_buffer vbuf;
struct poly_arr polygons;
struct bvh *bvh;
size_t vbuf_idx;
float surface_area;
char *name;
float rayOffset;
Expand Down
12 changes: 6 additions & 6 deletions src/lib/datatypes/poly.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
bool rayIntersectsWithPolygon(const struct mesh *mesh, const struct lightRay *ray, const struct poly *poly, struct hitRecord *isect) {
// Möller-Trumbore ray-triangle intersection routine
// (see "Fast, Minimum Storage Ray-Triangle Intersection", by T. Möller and B. Trumbore)
struct vector e1 = vec_sub(mesh->vbuf->vertices.items[poly->vertexIndex[0]], mesh->vbuf->vertices.items[poly->vertexIndex[1]]);
struct vector e2 = vec_sub(mesh->vbuf->vertices.items[poly->vertexIndex[2]], mesh->vbuf->vertices.items[poly->vertexIndex[0]]);
struct vector e1 = vec_sub(mesh->vbuf.vertices.items[poly->vertexIndex[0]], mesh->vbuf.vertices.items[poly->vertexIndex[1]]);
struct vector e2 = vec_sub(mesh->vbuf.vertices.items[poly->vertexIndex[2]], mesh->vbuf.vertices.items[poly->vertexIndex[0]]);
struct vector n = vec_cross(e1, e2);

struct vector c = vec_sub(mesh->vbuf->vertices.items[poly->vertexIndex[0]], ray->start);
struct vector c = vec_sub(mesh->vbuf.vertices.items[poly->vertexIndex[0]], ray->start);
struct vector r = vec_cross(ray->direction, c);
float invDet = 1.0f / vec_dot(n, ray->direction);

Expand All @@ -37,9 +37,9 @@ bool rayIntersectsWithPolygon(const struct mesh *mesh, const struct lightRay *ra
isect->uv = (struct coord) { u, v };
isect->distance = t;
if (likely(poly->hasNormals)) {
struct vector upcomp = vec_scale(mesh->vbuf->normals.items[poly->normalIndex[1]], u);
struct vector vpcomp = vec_scale(mesh->vbuf->normals.items[poly->normalIndex[2]], v);
struct vector wpcomp = vec_scale(mesh->vbuf->normals.items[poly->normalIndex[0]], w);
struct vector upcomp = vec_scale(mesh->vbuf.normals.items[poly->normalIndex[1]], u);
struct vector vpcomp = vec_scale(mesh->vbuf.normals.items[poly->normalIndex[2]], v);
struct vector wpcomp = vec_scale(mesh->vbuf.normals.items[poly->normalIndex[0]], w);

isect->surfaceNormal = vec_add(vec_add(upcomp, vpcomp), wpcomp);
} else {
Expand Down
2 changes: 0 additions & 2 deletions src/lib/datatypes/scene.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ void scene_destroy(struct world *scene) {

cr_shader_node_free(scene->bg_desc);

scene->v_buffers.elem_free = vertex_buf_free;
vertex_buffer_arr_free(&scene->v_buffers);
instance_arr_free(&scene->instances);
sphere_arr_free(&scene->spheres);
if (scene->asset_path) free(scene->asset_path);
Expand Down
1 change: 0 additions & 1 deletion src/lib/datatypes/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ struct world {
const struct bsdfNode *background;
struct cr_shader_node *bg_desc;
struct texture_asset_arr textures;
struct vertex_buffer_arr v_buffers;
struct bsdf_buffer_arr shader_buffers;
struct mesh_arr meshes;
struct instance_arr instances;
Expand Down
24 changes: 3 additions & 21 deletions src/lib/protocol/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ struct poly_arr deserialize_faces(const cJSON *in) {
static cJSON *serialize_mesh(const struct mesh in) {
cJSON *out = cJSON_CreateObject();
cJSON_AddItemToObject(out, "polygons", serialize_faces(in.polygons));
cJSON_AddNumberToObject(out, "vbuf_idx", in.vbuf_idx);
cJSON_AddItemToObject(out, "vbuf", serialize_vertex_buffer(in.vbuf));
// TODO: name
return out;
}
Expand All @@ -352,7 +352,7 @@ static struct mesh deserialize_mesh(const cJSON *in) {
if (!in) return out;

out.polygons = deserialize_faces(cJSON_GetObjectItem(in, "polygons"));
out.vbuf_idx = cJSON_GetNumberValue(cJSON_GetObjectItem(in, "vbuf_idx"));
out.vbuf = deserialize_vertex_buffer(cJSON_GetObjectItem(in, "vbuf"));

return out;
}
Expand Down Expand Up @@ -721,12 +721,6 @@ static cJSON *serialize_scene(const struct world *in) {
}
cJSON_AddItemToObject(out, "textures", textures);

cJSON *v_buffers = cJSON_CreateArray();
for (size_t i = 0; i < in->v_buffers.count; ++i) {
cJSON_AddItemToArray(v_buffers, serialize_vertex_buffer(in->v_buffers.items[i]));
}
cJSON_AddItemToObject(out, "v_buffers", v_buffers);

// Note: We only really need the descriptions, since we can't serialize the actual shaders anyway
cJSON *shader_buffers = cJSON_CreateArray();
for (size_t i = 0; i < in->shader_buffers.count; ++i) {
Expand Down Expand Up @@ -794,13 +788,7 @@ struct world *deserialize_scene(const cJSON *in) {
});
}
}
const cJSON *v_buffers = cJSON_GetObjectItem(in, "v_buffers");
if (cJSON_IsArray(v_buffers)) {
cJSON *v_buffer = NULL;
cJSON_ArrayForEach(v_buffer, v_buffers) {
vertex_buffer_arr_add(&out->v_buffers, deserialize_vertex_buffer(v_buffer));
}
}

const cJSON *shader_buffers = cJSON_GetObjectItem(in, "shader_buffers");
if (cJSON_IsArray(shader_buffers)) {
cJSON *s_buffer = NULL;
Expand All @@ -826,12 +814,6 @@ struct world *deserialize_scene(const cJSON *in) {
}
}

// Hook up vertex buffers to meshes
for (size_t i = 0; i < out->meshes.count; ++i) {
struct mesh *m = &out->meshes.items[i];
m->vbuf = &out->v_buffers.items[m->vbuf_idx];
}

cJSON *spheres = cJSON_GetObjectItem(in, "spheres");
if (cJSON_IsArray(spheres)) {
cJSON *sphere = NULL;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/renderer/instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct instance new_sphere_instance(struct sphere_arr *spheres, size_t idx, floa
}

static struct coord getTexMapMesh(const struct mesh *mesh, const struct hitRecord *isect) {
if (mesh->vbuf->texture_coords.count == 0) return (struct coord){-1.0f, -1.0f};
if (mesh->vbuf.texture_coords.count == 0) return (struct coord){-1.0f, -1.0f};
struct poly *p = isect->polygon;
if (p->textureIndex[0] == -1) return (struct coord){-1.0f, -1.0f};

Expand All @@ -144,9 +144,9 @@ static struct coord getTexMapMesh(const struct mesh *mesh, const struct hitRecor
const float w = 1.0f - u - v;

//Weighted texture coordinates
const struct coord ucomponent = coord_scale(u, mesh->vbuf->texture_coords.items[p->textureIndex[1]]);
const struct coord vcomponent = coord_scale(v, mesh->vbuf->texture_coords.items[p->textureIndex[2]]);
const struct coord wcomponent = coord_scale(w, mesh->vbuf->texture_coords.items[p->textureIndex[0]]);
const struct coord ucomponent = coord_scale(u, mesh->vbuf.texture_coords.items[p->textureIndex[1]]);
const struct coord vcomponent = coord_scale(v, mesh->vbuf.texture_coords.items[p->textureIndex[2]]);
const struct coord wcomponent = coord_scale(w, mesh->vbuf.texture_coords.items[p->textureIndex[0]]);

// textureXY = u * v1tex + v * v2tex + w * v3tex
return coord_add(coord_add(ucomponent, vcomponent), wcomponent);
Expand Down
Loading

0 comments on commit fb3157c

Please sign in to comment.