diff --git a/example/damaged_helmet/color_pass.cpp b/example/damaged_helmet/color_pass.cpp index 1b6f4bf..30d38e2 100644 --- a/example/damaged_helmet/color_pass.cpp +++ b/example/damaged_helmet/color_pass.cpp @@ -170,85 +170,81 @@ void ColorPass::draw(RenderContext &ctx, const glm::ivec2 &resolution, // Set viewport ctx.setViewport(0, 0, resolution.x, resolution.y); - // Iterate over entities with Mesh component - auto meshView = scene.view(); - for (auto entity : meshView) { - auto &mesh = meshView.get(entity).mesh; - auto &transform = meshView.get(entity); - - if (!mesh) + // Iterate over entities with Primitive and Material components + auto primitiveView = scene.view(); + for (auto [entity, primitiveComp, materialComp, transform] : primitiveView.each()) { + if (!primitiveComp.primitive) continue; - // Update uniform buffers + const auto &primitive = *primitiveComp.primitive; + + // Update transform uniform buffer TransformUBO transformData; transformData.model = transform.matrix; m_transform_ubo.set_sub_data(0, sizeof(TransformUBO), &transformData); - // Render each primitive in the mesh - for (const auto &primitive : mesh->primitives) { - // Bind vertex buffers - if (primitive.positions) { - ctx.bindVertexBuffer(0, *primitive.positions, 0, sizeof(glm::vec3)); - } - if (primitive.normals) { - ctx.bindVertexBuffer(1, *primitive.normals, 0, sizeof(glm::vec3)); + // Bind vertex buffers + if (primitive.positions) { + ctx.bindVertexBuffer(0, *primitive.positions, 0, sizeof(glm::vec3)); + } + if (primitive.normals) { + ctx.bindVertexBuffer(1, *primitive.normals, 0, sizeof(glm::vec3)); + } + if (primitive.texcoords) { + ctx.bindVertexBuffer(2, *primitive.texcoords, 0, sizeof(glm::vec2)); + } + if (primitive.colors) { + ctx.bindVertexBuffer(3, *primitive.colors, 0, sizeof(glm::vec3)); + } + + // Bind index buffer if present + if (primitive.indices) { + ctx.bindIndexBuffer(*primitive.indices, primitive.indexType); + } + + // Update material UBO and bind textures from Material component + if (materialComp.material) { + const auto &mat = materialComp.material; + const auto &pbr = mat->pbrMetallicRoughness; + + // Prepare material data + MaterialUBO materialData; + materialData.baseColorFactor = pbr.baseColorFactor; + materialData.emissiveFactor = mat->emissiveFactor; + materialData.metallicFactor = pbr.metallicFactor; + materialData.roughnessFactor = pbr.roughnessFactor; + m_material_ubo.set_sub_data(0, sizeof(MaterialUBO), &materialData); + + // Bind textures with sampler + if (pbr.baseColorTexture && pbr.baseColorTexture->image) { + ctx.bindTexture(0, *pbr.baseColorTexture->image, *m_sampler); } - if (primitive.texcoords) { - ctx.bindVertexBuffer(2, *primitive.texcoords, 0, sizeof(glm::vec2)); + if (pbr.metallicRoughnessTexture && + pbr.metallicRoughnessTexture->image) { + ctx.bindTexture(1, *pbr.metallicRoughnessTexture->image, + *m_sampler); } - if (primitive.colors) { - ctx.bindVertexBuffer(3, *primitive.colors, 0, sizeof(glm::vec3)); + if (mat->normalTexture && mat->normalTexture->image) { + ctx.bindTexture(2, *mat->normalTexture->image, *m_sampler); } - - // Bind index buffer if present - if (primitive.indices) { - ctx.bindIndexBuffer(*primitive.indices, primitive.indexType); + if (mat->emissiveTexture && mat->emissiveTexture->image) { + ctx.bindTexture(3, *mat->emissiveTexture->image, *m_sampler); } - - // Update material UBO and bind textures - if (primitive.material) { - const auto &mat = primitive.material; - const auto &pbr = mat->pbrMetallicRoughness; - - // Prepare material data - MaterialUBO materialData; - materialData.baseColorFactor = pbr.baseColorFactor; - materialData.emissiveFactor = mat->emissiveFactor; - materialData.metallicFactor = pbr.metallicFactor; - materialData.roughnessFactor = pbr.roughnessFactor; - m_material_ubo.set_sub_data(0, sizeof(MaterialUBO), &materialData); - - // Bind textures with sampler - directly from material - if (pbr.baseColorTexture && pbr.baseColorTexture->image) { - ctx.bindTexture(0, *pbr.baseColorTexture->image, *m_sampler); - } - if (pbr.metallicRoughnessTexture && - pbr.metallicRoughnessTexture->image) { - ctx.bindTexture(1, *pbr.metallicRoughnessTexture->image, - *m_sampler); - } - if (mat->normalTexture && mat->normalTexture->image) { - ctx.bindTexture(2, *mat->normalTexture->image, *m_sampler); - } - if (mat->emissiveTexture && mat->emissiveTexture->image) { - ctx.bindTexture(3, *mat->emissiveTexture->image, *m_sampler); - } - if (mat->occlusionTexture && mat->occlusionTexture->image) { - ctx.bindTexture(4, *mat->occlusionTexture->image, *m_sampler); - } + if (mat->occlusionTexture && mat->occlusionTexture->image) { + ctx.bindTexture(4, *mat->occlusionTexture->image, *m_sampler); } + } - ctx.bindUniformBuffer(0, m_transform_ubo); - ctx.bindUniformBuffer(1, m_camera_ubo); - ctx.bindUniformBuffer(2, m_lighting_ubo); - ctx.bindUniformBuffer(3, m_material_ubo); + ctx.bindUniformBuffer(0, m_transform_ubo); + ctx.bindUniformBuffer(1, m_camera_ubo); + ctx.bindUniformBuffer(2, m_lighting_ubo); + ctx.bindUniformBuffer(3, m_material_ubo); - // Draw the primitive - if (primitive.hasIndices()) { - ctx.drawElements(primitive.indexCount, nullptr); - } else if (primitive.positions) { - ctx.drawArrays(0, primitive.vertexCount); - } + // Draw the primitive + if (primitive.hasIndices()) { + ctx.drawElements(primitive.indexCount, nullptr); + } else if (primitive.positions) { + ctx.drawArrays(0, primitive.vertexCount); } } diff --git a/source/paimon/app/panel/scene_panel.cpp b/source/paimon/app/panel/scene_panel.cpp index 26cc2de..539232b 100644 --- a/source/paimon/app/panel/scene_panel.cpp +++ b/source/paimon/app/panel/scene_panel.cpp @@ -155,32 +155,315 @@ void ScenePanel::drawComponents(ecs::Entity entity) { // Camera component if (entity.hasComponent()) { if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Text("Camera Component"); - // TODO: Add camera properties editing + auto &cameraComp = entity.getComponent(); + + if (cameraComp.camera) { + auto cameraType = cameraComp.camera->getType(); + + // Camera type dropdown + const char* types[] = { "Perspective", "Orthographic" }; + int currentType = (cameraType == sg::Camera::Type::Perspective) ? 0 : 1; + + if (ImGui::Combo("Type", ¤tType, types, 2)) { + // Switch camera type + if (currentType == 0 && cameraType != sg::Camera::Type::Perspective) { + cameraComp.camera = std::make_shared(); + } else if (currentType == 1 && cameraType != sg::Camera::Type::Orthographic) { + cameraComp.camera = std::make_shared(); + } + } + + ImGui::Separator(); + + // Perspective camera properties + if (cameraComp.camera->getType() == sg::Camera::Type::Perspective) { + auto* perspCamera = dynamic_cast(cameraComp.camera.get()); + if (perspCamera) { + // Convert FOV to degrees for display + float fovDegrees = glm::degrees(perspCamera->yfov); + if (ImGui::SliderFloat("Field of View", &fovDegrees, 1.0f, 120.0f, "%.1f°")) { + perspCamera->yfov = glm::radians(fovDegrees); + } + + ImGui::DragFloat("Aspect Ratio", &perspCamera->aspectRatio, 0.01f, 0.1f, 10.0f); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("0 = use viewport aspect ratio"); + } + + ImGui::DragFloat("Near Plane", &perspCamera->znear, 0.01f, 0.001f, 10.0f, "%.3f"); + ImGui::DragFloat("Far Plane", &perspCamera->zfar, 1.0f, 1.0f, 1000.0f); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("0 = infinite far plane"); + } + } + } + // Orthographic camera properties + else if (cameraComp.camera->getType() == sg::Camera::Type::Orthographic) { + auto* orthoCamera = dynamic_cast(cameraComp.camera.get()); + if (orthoCamera) { + ImGui::DragFloat("Horizontal Mag", &orthoCamera->xmag, 0.1f, 0.1f, 100.0f); + ImGui::DragFloat("Vertical Mag", &orthoCamera->ymag, 0.1f, 0.1f, 100.0f); + ImGui::DragFloat("Near Plane", &orthoCamera->znear, 0.01f, 0.001f, 10.0f, "%.3f"); + ImGui::DragFloat("Far Plane", &orthoCamera->zfar, 1.0f, 1.0f, 1000.0f); + } + } + + ImGui::Separator(); + + // Display camera vectors (read-only) + ImGui::Text("Position: (%.2f, %.2f, %.2f)", + cameraComp.position.x, cameraComp.position.y, cameraComp.position.z); + ImGui::Text("Direction: (%.2f, %.2f, %.2f)", + cameraComp.direction.x, cameraComp.direction.y, cameraComp.direction.z); + } else { + ImGui::Text("No camera object assigned"); + } } } - // Mesh component - if (entity.hasComponent()) { - if (ImGui::CollapsingHeader("Mesh", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Text("Mesh Component"); - // TODO: Add mesh properties + // Primitive component + if (entity.hasComponent()) { + if (ImGui::CollapsingHeader("Primitive", ImGuiTreeNodeFlags_DefaultOpen)) { + auto &primitiveComp = entity.getComponent(); + + if (primitiveComp.primitive) { + auto &primitive = *primitiveComp.primitive; + + // Topology + const char* topologyNames[] = { + "Points", "Lines", "Line Loop", "Line Strip", + "Triangles", "Triangle Strip", "Triangle Fan" + }; + int topologyIndex = static_cast(primitive.mode); + ImGui::Text("Topology: %s", topologyNames[topologyIndex]); + + ImGui::Separator(); + + // Vertex data + ImGui::Text("Vertex Count: %zu", primitive.vertexCount); + + ImGui::Text("Attributes:"); + ImGui::Indent(); + ImGui::Text("Positions: %s", primitive.positions ? "✓" : "✗"); + ImGui::Text("Normals: %s", primitive.normals ? "✓" : "✗"); + ImGui::Text("Texcoords: %s", primitive.texcoords ? "✓" : "✗"); + ImGui::Text("Colors: %s", primitive.colors ? "✓" : "✗"); + ImGui::Unindent(); + + ImGui::Separator(); + + // Index data + if (primitive.hasIndices()) { + ImGui::Text("Index Count: %zu", primitive.indexCount); + + // Map DataType enum to display string + const char* indexTypeName = "Unknown"; + switch (primitive.indexType) { + case DataType::Byte: indexTypeName = "Byte"; break; + case DataType::UByte: indexTypeName = "UByte"; break; + case DataType::Short: indexTypeName = "Short"; break; + case DataType::UShort: indexTypeName = "UShort"; break; + case DataType::Int: indexTypeName = "Int"; break; + case DataType::UInt: indexTypeName = "UInt"; break; + case DataType::Float: indexTypeName = "Float"; break; + case DataType::Double: indexTypeName = "Double"; break; + } + ImGui::Text("Index Type: %s", indexTypeName); + } else { + ImGui::Text("No Indices (Non-indexed rendering)"); + } + + } else { + ImGui::Text("No primitive object assigned"); + } } } // Material component if (entity.hasComponent()) { if (ImGui::CollapsingHeader("Material", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Text("Material Component"); - // TODO: Add material properties editing + auto &materialComp = entity.getComponent(); + + if (materialComp.material) { + auto &material = *materialComp.material; + + // PBR Metallic-Roughness + if (ImGui::TreeNodeEx("PBR Metallic-Roughness", ImGuiTreeNodeFlags_DefaultOpen)) { + auto &pbr = material.pbrMetallicRoughness; + + ImGui::ColorEdit4("Base Color", glm::value_ptr(pbr.baseColorFactor)); + ImGui::Text("Base Color Texture: %s", pbr.baseColorTexture ? "Assigned" : "None"); + + ImGui::SliderFloat("Metallic", &pbr.metallicFactor, 0.0f, 1.0f); + ImGui::SliderFloat("Roughness", &pbr.roughnessFactor, 0.0f, 1.0f); + ImGui::Text("Metallic-Roughness Texture: %s", + pbr.metallicRoughnessTexture ? "Assigned" : "None"); + + ImGui::TreePop(); + } + + // Normal Mapping + if (ImGui::TreeNodeEx("Normal Mapping", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Text("Normal Texture: %s", material.normalTexture ? "Assigned" : "None"); + if (material.normalTexture) { + ImGui::SliderFloat("Normal Scale", &material.normalScale, 0.0f, 2.0f); + } + ImGui::TreePop(); + } + + // Occlusion Mapping + if (ImGui::TreeNodeEx("Occlusion Mapping", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Text("Occlusion Texture: %s", material.occlusionTexture ? "Assigned" : "None"); + if (material.occlusionTexture) { + ImGui::SliderFloat("Occlusion Strength", &material.occlusionStrength, 0.0f, 1.0f); + } + ImGui::TreePop(); + } + + // Emissive + if (ImGui::TreeNodeEx("Emissive", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::ColorEdit3("Emissive Factor", glm::value_ptr(material.emissiveFactor)); + ImGui::Text("Emissive Texture: %s", material.emissiveTexture ? "Assigned" : "None"); + ImGui::TreePop(); + } + + ImGui::Separator(); + + // Alpha Mode + const char* alphaModes[] = { "Opaque", "Mask", "Blend" }; + int currentAlphaMode = static_cast(material.alphaMode); + if (ImGui::Combo("Alpha Mode", ¤tAlphaMode, alphaModes, 3)) { + material.alphaMode = static_cast(currentAlphaMode); + } + + if (material.alphaMode == sg::AlphaMode::Mask) { + ImGui::SliderFloat("Alpha Cutoff", &material.alphaCutoff, 0.0f, 1.0f); + } + + ImGui::Checkbox("Double Sided", &material.doubleSided); + + // Anisotropy (KHR_materials_anisotropy) + if (ImGui::TreeNode("Anisotropy")) { + ImGui::SliderFloat("Strength##Aniso", &material.anisotropy.strength, 0.0f, 1.0f); + ImGui::SliderFloat("Rotation##Aniso", &material.anisotropy.rotation, 0.0f, 360.0f, "%.1f°"); + ImGui::Text("Texture: %s", material.anisotropy.texture ? "Assigned" : "None"); + ImGui::TreePop(); + } + + // Clearcoat (KHR_materials_clearcoat) + if (ImGui::TreeNode("Clearcoat")) { + ImGui::SliderFloat("Factor##Clearcoat", &material.clearcoat.factor, 0.0f, 1.0f); + ImGui::Text("Texture: %s", material.clearcoat.texture ? "Assigned" : "None"); + ImGui::SliderFloat("Roughness##Clearcoat", &material.clearcoat.roughnessFactor, 0.0f, 1.0f); + ImGui::Text("Roughness Texture: %s", + material.clearcoat.roughnessTexture ? "Assigned" : "None"); + ImGui::Text("Normal Texture: %s", + material.clearcoat.normalTexture ? "Assigned" : "None"); + if (material.clearcoat.normalTexture) { + ImGui::SliderFloat("Normal Scale##Clearcoat", &material.clearcoat.normalScale, 0.0f, 2.0f); + } + ImGui::TreePop(); + } + + } else { + ImGui::Text("No material object assigned"); + } } } // Light component if (entity.hasComponent()) { if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Text("Light Component"); - // TODO: Add light properties editing + auto &lightComp = entity.getComponent(); + + if (lightComp.light) { + auto lightType = lightComp.light->getType(); + + // Light type dropdown + const char* types[] = { "Directional", "Point", "Spot" }; + int currentType = static_cast(lightType); + + if (ImGui::Combo("Type", ¤tType, types, 3)) { + // Switch light type + switch (currentType) { + case 0: // Directional + if (lightType != sg::PunctualLight::Type::Directional) { + lightComp.light = std::make_shared(); + } + break; + case 1: // Point + if (lightType != sg::PunctualLight::Type::Point) { + lightComp.light = std::make_shared(); + } + break; + case 2: // Spot + if (lightType != sg::PunctualLight::Type::Spot) { + lightComp.light = std::make_shared(); + } + break; + } + } + + ImGui::Separator(); + + // Common light properties + ImGui::ColorEdit3("Color", glm::value_ptr(lightComp.light->color)); + ImGui::DragFloat("Intensity", &lightComp.light->intensity, 0.1f, 0.0f, 100.0f); + ImGui::DragFloat("Range", &lightComp.light->range, 0.1f, 0.0f, 1000.0f); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("0 = infinite range"); + } + + ImGui::Separator(); + + // Type-specific properties + if (lightType == sg::PunctualLight::Type::Directional) { + ImGui::Text("Direction: (%.2f, %.2f, %.2f)", + lightComp.direction.x, lightComp.direction.y, lightComp.direction.z); + ImGui::TextWrapped("Tip: Direction is controlled by Transform rotation"); + } + else if (lightType == sg::PunctualLight::Type::Point) { + ImGui::Text("Position: (%.2f, %.2f, %.2f)", + lightComp.position.x, lightComp.position.y, lightComp.position.z); + ImGui::TextWrapped("Tip: Position is controlled by Transform translation"); + } + else if (lightType == sg::PunctualLight::Type::Spot) { + auto* spotLight = dynamic_cast(lightComp.light.get()); + if (spotLight) { + ImGui::Text("Position: (%.2f, %.2f, %.2f)", + lightComp.position.x, lightComp.position.y, lightComp.position.z); + ImGui::Text("Direction: (%.2f, %.2f, %.2f)", + lightComp.direction.x, lightComp.direction.y, lightComp.direction.z); + + ImGui::Separator(); + + // Convert cone angles to degrees for display + float innerDegrees = glm::degrees(spotLight->innerConeAngle); + float outerDegrees = glm::degrees(spotLight->outerConeAngle); + + if (ImGui::SliderFloat("Inner Cone Angle", &innerDegrees, 0.0f, 90.0f, "%.1f°")) { + spotLight->innerConeAngle = glm::radians(innerDegrees); + // Ensure inner <= outer + if (spotLight->innerConeAngle > spotLight->outerConeAngle) { + spotLight->outerConeAngle = spotLight->innerConeAngle; + } + } + + if (ImGui::SliderFloat("Outer Cone Angle", &outerDegrees, 0.0f, 90.0f, "%.1f°")) { + spotLight->outerConeAngle = glm::radians(outerDegrees); + // Ensure outer >= inner + if (spotLight->outerConeAngle < spotLight->innerConeAngle) { + spotLight->innerConeAngle = spotLight->outerConeAngle; + } + } + + ImGui::TextWrapped("Tip: Position and direction are controlled by Transform"); + } + } + + } else { + ImGui::Text("No light object assigned"); + } } } } @@ -205,9 +488,9 @@ void ScenePanel::drawAddComponentButton(ecs::Entity entity) { } } - if (!entity.hasComponent()) { - if (ImGui::MenuItem("Mesh")) { - entity.addComponent(); + if (!entity.hasComponent()) { + if (ImGui::MenuItem("Primitive")) { + entity.addComponent(); } } diff --git a/source/paimon/core/ecs/components.h b/source/paimon/core/ecs/components.h index 33f7445..a6251f1 100644 --- a/source/paimon/core/ecs/components.h +++ b/source/paimon/core/ecs/components.h @@ -50,9 +50,9 @@ struct GlobalTransform { glm::mat4 matrix = glm::mat4(1.0f); }; -/// Mesh component - references mesh data -struct Mesh { - std::shared_ptr mesh; +/// Primitive component - references primitive data +struct Primitive { + std::shared_ptr primitive; }; /// Material component - references material data diff --git a/source/paimon/core/io/gltf.cpp b/source/paimon/core/io/gltf.cpp index 0112d5e..bff6506 100644 --- a/source/paimon/core/io/gltf.cpp +++ b/source/paimon/core/io/gltf.cpp @@ -26,7 +26,7 @@ PrimitiveTopology parsePrimitiveMode(int primitiveMode) { case TINYGLTF_MODE_LINE: return PrimitiveTopology::Lines; case TINYGLTF_MODE_LINE_LOOP: - return PrimitiveTopology::LinesLoop; + return PrimitiveTopology::LineLoop; case TINYGLTF_MODE_LINE_STRIP: return PrimitiveTopology::LineStrip; case TINYGLTF_MODE_TRIANGLES: @@ -372,8 +372,6 @@ void GltfLoader::parseMeshes() { sg_primitive.indexType = parseCompnentType(accessor.componentType); sg_primitive.indices = m_accessors[primitive.indices]; } - - sg_primitive.material = m_materials[primitive.material]; } m_meshes.push_back(std::move(sg_mesh)); } @@ -442,18 +440,18 @@ void GltfLoader::parseCameras() { void GltfLoader::parseNode(const tinygltf::Node &node, ecs::Entity parent, ecs::Scene &scene) { // Create entity for this node - auto entity = scene.createEntity(node.name); + auto nodeEntity = scene.createEntity(node.name); // Parent components - auto &parentComp = entity.getComponent(); + auto &parentComp = nodeEntity.getComponent(); parentComp.parent = parent; // Parent should have a Children component; append this child auto &parentChildren = parent.getComponent(); - parentChildren.children.push_back(entity); + parentChildren.children.push_back(nodeEntity); // Transform component (TRS only) - auto &transform = entity.getComponent(); + auto &transform = nodeEntity.getComponent(); if (node.matrix.empty()) { // Use TRS directly transform.translation = node.translation.empty() @@ -473,21 +471,43 @@ void GltfLoader::parseNode(const tinygltf::Node &node, ecs::Entity parent, ecs:: transform.translation, skew, perspective); } - // Mesh Component + // Mesh Component - create child entities for each primitive if (node.mesh >= 0) { + const auto& sg_mesh = m_meshes[node.mesh]; + const auto& mesh = m_model.meshes[node.mesh]; - - entity.addComponent(m_meshes[node.mesh]); + for (size_t i = 0; i < sg_mesh->primitives.size(); ++i) { + // Create child entity for each primitive + auto primitiveEntity = scene.createEntity(node.name + "_primitive_" + std::to_string(i)); + + // Set parent relationship + auto& primitiveParentComp = primitiveEntity.getComponent(); + primitiveParentComp.parent = nodeEntity; + + // Add to parent's children + auto& entityChildren = nodeEntity.getComponent(); + entityChildren.children.push_back(primitiveEntity); + + // Add Primitive component + auto primitive = std::make_shared(sg_mesh->primitives[i]); + primitiveEntity.addComponent(primitive); + + // Add Material component if available + // Note: In glTF, a mesh primitive can reference a material + if (mesh.primitives[i].material >= 0) { + primitiveEntity.addComponent(m_materials[mesh.primitives[i].material]); + } + } } // Light Component (from KHR_lights_punctual extension) if (node.light >= 0) { - entity.addComponent(m_lights[node.light]); + nodeEntity.addComponent(m_lights[node.light]); } if (node.camera >= 0) { // Camera Component can be handled here if needed - entity.addComponent(m_cameras[node.camera]); + nodeEntity.addComponent(m_cameras[node.camera]); } // Skin Component @@ -500,7 +520,7 @@ void GltfLoader::parseNode(const tinygltf::Node &node, ecs::Entity parent, ecs:: // which simplifies GlobalTransform computation later for (int childIndex : node.children) { const auto &childNode = m_model.nodes[childIndex]; - parseNode(childNode, entity, scene); + parseNode(childNode, nodeEntity, scene); } } diff --git a/source/paimon/core/sg/mesh.h b/source/paimon/core/sg/mesh.h index c57d154..233ced7 100644 --- a/source/paimon/core/sg/mesh.h +++ b/source/paimon/core/sg/mesh.h @@ -4,7 +4,6 @@ #include -#include "paimon/core/sg/material.h" #include "paimon/opengl/buffer.h" #include "paimon/opengl/state/vertex_input.h" #include "paimon/opengl/type.h" @@ -25,8 +24,6 @@ struct Primitive { DataType indexType = DataType::UInt; std::shared_ptr indices; - std::shared_ptr material = nullptr; - bool hasIndices() const { return indices != nullptr; } static std::vector bindings(); diff --git a/source/paimon/opengl/type.h b/source/paimon/opengl/type.h index 9c22b28..955b8b9 100644 --- a/source/paimon/opengl/type.h +++ b/source/paimon/opengl/type.h @@ -216,7 +216,7 @@ enum class PrimitiveTopology : GLenum { Points = GL_POINTS, Lines = GL_LINES, LineAdjacency = GL_LINES_ADJACENCY, - LinesLoop = GL_LINE_LOOP, + LineLoop = GL_LINE_LOOP, LineStrip = GL_LINE_STRIP, LineStripAdjacency = GL_LINE_STRIP_ADJACENCY, Triangles = GL_TRIANGLES,