Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions scripts/generate_uv_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def write_obj(path, name, vertices, uvs, normals, faces, mtl_lib, mtl_name):

def gen_plane(filepath, size=4.0, subdivs=5, mtl_name='textured'):
verts, uvs, norms, faces = [], [], [], []
N = normal = (0, 1, 0)
normal = (0, 1, 0)

# Grid of (subdivs+1) x (subdivs+1) vertices
def idx(ix, iz):
Expand All @@ -63,7 +63,7 @@ def idx(ix, iz):
z = -size / 2 + iz * size / subdivs
verts.append((x, 0.0, z))
uvs.append((ix / subdivs, iz / subdivs))
norms.append(N)
norms.append(normal)

# Two triangles per cell
for ix in range(subdivs):
Expand Down
37 changes: 23 additions & 14 deletions src/rayon/gpu_renderers/scene_builder_cuda.cu
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,22 @@ static CudaScene::Geometry convertGeometry(const GeometryDesc &desc)
static_cast<float>(desc.data.triangle.n2.y()),
static_cast<float>(desc.data.triangle.n2.z()));
geom.data.triangle.has_normals = desc.data.triangle.has_normals;
// UV coordinates
geom.data.triangle.uv0 = f2(static_cast<float>(desc.data.triangle.uv0.x()),
static_cast<float>(desc.data.triangle.uv0.y()));
geom.data.triangle.uv1 = f2(static_cast<float>(desc.data.triangle.uv1.x()),
static_cast<float>(desc.data.triangle.uv1.y()));
geom.data.triangle.uv2 = f2(static_cast<float>(desc.data.triangle.uv2.x()),
static_cast<float>(desc.data.triangle.uv2.y()));
// UV coordinates — only copy valid data; zero-initialize when UVs are absent
if (desc.data.triangle.has_uvs)
{
geom.data.triangle.uv0 = f2(static_cast<float>(desc.data.triangle.uv0.x()),
static_cast<float>(desc.data.triangle.uv0.y()));
geom.data.triangle.uv1 = f2(static_cast<float>(desc.data.triangle.uv1.x()),
static_cast<float>(desc.data.triangle.uv1.y()));
geom.data.triangle.uv2 = f2(static_cast<float>(desc.data.triangle.uv2.x()),
static_cast<float>(desc.data.triangle.uv2.y()));
}
else
{
geom.data.triangle.uv0 = f2(0.0f, 0.0f);
geom.data.triangle.uv1 = f2(0.0f, 0.0f);
geom.data.triangle.uv2 = f2(0.0f, 0.0f);
}
geom.data.triangle.has_uvs = desc.data.triangle.has_uvs;
break;

Expand Down Expand Up @@ -404,21 +413,21 @@ void CudaSceneBuilder::freeGPUScene(CudaScene::Scene *d_scene)
if (host_scene.d_textures && host_scene.num_textures > 0)
{
std::vector<cudaTextureObject_t> host_tex(static_cast<size_t>(host_scene.num_textures));
cudaMemcpy(host_tex.data(), host_scene.d_textures,
host_scene.num_textures * sizeof(cudaTextureObject_t),
cudaMemcpyDeviceToHost);
CUDA_CHECK(cudaMemcpy(host_tex.data(), host_scene.d_textures,
host_scene.num_textures * sizeof(cudaTextureObject_t),
cudaMemcpyDeviceToHost));
for (int i = 0; i < host_scene.num_textures; ++i)
{
if (host_tex[i])
{
cudaResourceDesc rd = {};
cudaGetTextureObjectResourceDesc(&rd, host_tex[i]);
cudaDestroyTextureObject(host_tex[i]);
CUDA_CHECK(cudaGetTextureObjectResourceDesc(&rd, host_tex[i]));
CUDA_CHECK(cudaDestroyTextureObject(host_tex[i]));
if (rd.resType == cudaResourceTypeArray && rd.res.array.array)
cudaFreeArray(rd.res.array.array);
CUDA_CHECK(cudaFreeArray(rd.res.array.array));
}
}
cudaFree(host_scene.d_textures);
CUDA_CHECK(cudaFree(host_scene.d_textures));
}

// Free the scene struct itself (now on device)
Expand Down
10 changes: 8 additions & 2 deletions src/rayon/scenes/obj_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class OBJLoader
* The caller-supplied @p fallback_mat_id is used only for faces that
* belong to a group with no usemtl directive (or when no .mtl is found).
* Pass -1 for @p fallback_mat_id to require all materials to come from
* the .mtl file (faces without usemtl are then skipped with a warning).
* the .mtl file (faces without usemtl are then skipped with a one-time warning).
*
* @param filename Path to .obj file
* @param scene Scene to add triangles to
Expand Down Expand Up @@ -70,6 +70,7 @@ class OBJLoader
std::map<std::string, int> mtl_name_to_scene_id;

int active_mat_id = fallback_mat_id; // Current material for faces
bool face_skip_warned = false; // One-time warning when faces are skipped without a material

auto resolveMtlMaterial = [&](const std::string &name) -> int {
auto cached = mtl_name_to_scene_id.find(name);
Expand Down Expand Up @@ -167,7 +168,12 @@ class OBJLoader
{
if (active_mat_id < 0)
{
// No material yet and no fallback — skip
// No material yet and no fallback — skip with a one-time warning per file
if (!face_skip_warned)
{
std::cerr << "OBJ Loader: face(s) skipped — no 'usemtl' encountered and no fallback material provided\n";
face_skip_warned = true;
}
continue;
}

Expand Down
6 changes: 6 additions & 0 deletions src/rayon/scenes/scene_description.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,9 @@ class SceneDescription {
geom.data.triangle.v2 = v2;
geom.data.triangle.has_normals = false;
geom.data.triangle.has_uvs = false;
geom.data.triangle.uv0 = Vec3(0, 0, 0);
geom.data.triangle.uv1 = Vec3(0, 0, 0);
geom.data.triangle.uv2 = Vec3(0, 0, 0);

// Compute bounding box with epsilon padding to avoid zero-thickness AABBs
constexpr double eps = 1e-4;
Expand Down Expand Up @@ -637,6 +640,9 @@ class SceneDescription {
geom.data.triangle.n2 = n2;
geom.data.triangle.has_normals = true;
geom.data.triangle.has_uvs = false;
geom.data.triangle.uv0 = Vec3(0, 0, 0);
geom.data.triangle.uv1 = Vec3(0, 0, 0);
geom.data.triangle.uv2 = Vec3(0, 0, 0);

// Compute bounding box with epsilon padding to avoid zero-thickness AABBs
constexpr double eps = 1e-4;
Expand Down
Loading