add AnimationComponent, Skeleton, AnimationClip; add single Renderer3D class, remove some useless code; problem now renderer2D cannot blend with Renderer3D
This commit is contained in:
@ -76,16 +76,6 @@ namespace Prism
|
||||
|
||||
m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera);
|
||||
|
||||
if (m_DrawOnTopBoundingBoxes)
|
||||
{
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
// TODO: Renderer::DrawAABB(m_MeshEntity.GetComponent<MeshComponent>(), m_MeshEntity.GetComponent<TransformComponent>());
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
if (!m_SelectionContext.empty() && false)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
@ -530,10 +520,7 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
if (UI::Property("Show Bounding Boxes", m_UIShowBoundingBoxes))
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
if (m_UIShowBoundingBoxes && UI::Property("On Top", m_UIShowBoundingBoxesOnTop))
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
UI::Property("Show Bounding Boxes", m_UIShowBoundingBoxes);
|
||||
|
||||
const char* label = m_SelectionMode == SelectionMode::Entity ? "Entity" : "Mesh";
|
||||
if (ImGui::Button(label))
|
||||
@ -903,7 +890,7 @@ namespace Prism
|
||||
|
||||
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
||||
{
|
||||
if (m_ViewportPanelFocused)
|
||||
if (m_ViewportPanelFocused || m_ViewportPanelHovered)
|
||||
{
|
||||
switch (e.GetKeyCode())
|
||||
{
|
||||
@ -921,7 +908,7 @@ namespace Prism
|
||||
break;
|
||||
case KeyCode::F:
|
||||
{
|
||||
if (m_SelectionContext.size() == 0)
|
||||
if (m_SelectionContext.empty())
|
||||
break;
|
||||
|
||||
Entity selectedEntity = m_SelectionContext[0].Entity;
|
||||
@ -964,7 +951,7 @@ namespace Prism
|
||||
case KeyCode::B:
|
||||
// Toggle bounding boxes
|
||||
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes,false);
|
||||
break;
|
||||
case KeyCode::D:
|
||||
if (m_SelectionContext.size())
|
||||
@ -1053,7 +1040,21 @@ namespace Prism
|
||||
return a.Distance < b.Distance;
|
||||
});
|
||||
if (!m_SelectionContext.empty())
|
||||
{
|
||||
if (auto alreadySelectedEntity = m_SceneHierarchyPanel->GetSelected();
|
||||
m_SelectionContext.size() != 1 && alreadySelectedEntity)
|
||||
{
|
||||
const auto alreadySelectedEntityID = alreadySelectedEntity.GetUUID();
|
||||
|
||||
for (const auto& selectedEntity : m_SelectionContext)
|
||||
{
|
||||
if (alreadySelectedEntityID == selectedEntity.Entity.GetUUID()) continue;
|
||||
OnSelected(selectedEntity);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
OnSelected(m_SelectionContext[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1062,7 +1063,6 @@ namespace Prism
|
||||
void EditorLayer::ShowBoundingBoxes(bool show, bool onTop)
|
||||
{
|
||||
SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop;
|
||||
m_DrawOnTopBoundingBoxes = show && onTop;
|
||||
}
|
||||
|
||||
void EditorLayer::SelectEntity(Entity entity)
|
||||
|
||||
@ -138,10 +138,8 @@ namespace Prism
|
||||
|
||||
// configure button
|
||||
bool m_AllowViewportCameraEvents = false;
|
||||
bool m_DrawOnTopBoundingBoxes = false;
|
||||
|
||||
bool m_UIShowBoundingBoxes = false;
|
||||
bool m_UIShowBoundingBoxesOnTop = false;
|
||||
|
||||
enum class SceneType : uint32_t
|
||||
{
|
||||
|
||||
@ -1,62 +1,23 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetHandle: 1249421934001634765
|
||||
AssetHandle: 17073147362577408906
|
||||
Light:
|
||||
Direction: [-0.314, -0.941, -0.209]
|
||||
Radiance: [0, 0, 0]
|
||||
Multiplier: 0
|
||||
Multiplier: 1
|
||||
Entities:
|
||||
- Entity: 18090260616187152572
|
||||
- Entity: 3696833073589069488
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Directional Light
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, -2.7340124]
|
||||
Scale: [0.9999992, 0.9999992, 1]
|
||||
DirectionalLightComponent:
|
||||
Radiance: [1, 1, 1]
|
||||
CastShadows: true
|
||||
SoftShadows: true
|
||||
LightSize: 0.5
|
||||
- Entity: 18154648535203342017
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 6.282704, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
MeshComponent:
|
||||
AssetID: 133168951455480052
|
||||
- Entity: 386484027514287028
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Cube
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [50, 1, 50]
|
||||
MeshComponent:
|
||||
AssetID: 133168951455480052
|
||||
- Entity: 6827989772960183355
|
||||
Parent: 0
|
||||
Children:
|
||||
[]
|
||||
TagComponent:
|
||||
Tag: Sky Light
|
||||
Tag: venice_dawn_1_4k
|
||||
TransformComponent:
|
||||
Position: [0, 0, 0]
|
||||
Rotation: [0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
SkyLightComponent:
|
||||
EnvironmentMap: 1249421934001634765
|
||||
EnvironmentMap: 17073147362577408906
|
||||
Intensity: 1
|
||||
Angle: 0
|
||||
PhysicsLayers:
|
||||
|
||||
@ -58,11 +58,12 @@ void main()
|
||||
vs_Output.WorldTransform = mat3(u_Transform);
|
||||
vs_Output.Binormal = a_Binormal;
|
||||
|
||||
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
vs_Output.FragPosLightSpace = u_LightSpaceMatrix * u_Transform * localPosition;
|
||||
|
||||
vs_Output.ViewPosition = vec3(u_ViewMatrix * vec4(vs_Output.WorldPosition, 1.0));
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
// gl_Position = u_ViewProjectionMatrix * u_Transform * vec4(a_Position, 1.0);
|
||||
gl_Position = u_ViewProjectionMatrix * u_Transform * localPosition;
|
||||
}
|
||||
|
||||
#type fragment
|
||||
|
||||
79
Prism/src/Prism/Animation/AnimationClip.cpp
Normal file
79
Prism/src/Prism/Animation/AnimationClip.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#include "AnimationClip.h"
|
||||
|
||||
#include "assimp/scene.h"
|
||||
|
||||
struct aiAnimation;
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
AnimationClip::AnimationClip(const aiScene* scene)
|
||||
{
|
||||
const aiAnimation* anim = scene->mAnimations[0]; // 先只处理第一个动画
|
||||
m_Duration = (float)anim->mDuration;
|
||||
m_TicksPerSecond = (float)(anim->mTicksPerSecond != 0 ? anim->mTicksPerSecond : 25.0);
|
||||
|
||||
for (uint32_t i = 0; i < anim->mNumChannels; i++)
|
||||
{
|
||||
aiNodeAnim* nodeAnim = anim->mChannels[i];
|
||||
BoneChannel channel;
|
||||
channel.BoneName = nodeAnim->mNodeName.C_Str();
|
||||
|
||||
// 位置关键帧
|
||||
for (uint32_t j = 0; j < nodeAnim->mNumPositionKeys; j++)
|
||||
{
|
||||
const auto& key = nodeAnim->mPositionKeys[j];
|
||||
channel.Positions.emplace_back((float)key.mTime,
|
||||
glm::vec3(key.mValue.x, key.mValue.y, key.mValue.z));
|
||||
}
|
||||
// 旋转关键帧
|
||||
for (uint32_t j = 0; j < nodeAnim->mNumRotationKeys; j++)
|
||||
{
|
||||
const auto& key = nodeAnim->mRotationKeys[j];
|
||||
channel.Rotations.emplace_back((float)key.mTime,
|
||||
glm::quat(key.mValue.w, key.mValue.x, key.mValue.y, key.mValue.z));
|
||||
}
|
||||
// 缩放关键帧
|
||||
for (uint32_t j = 0; j < nodeAnim->mNumScalingKeys; j++)
|
||||
{
|
||||
const auto& key = nodeAnim->mScalingKeys[j];
|
||||
channel.Scalings.emplace_back((float)key.mTime,
|
||||
glm::vec3(key.mValue.x, key.mValue.y, key.mValue.z));
|
||||
}
|
||||
m_BoneChannels.push_back(channel);
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 AnimationClip::SampleAtTime(const float timeTicks, const std::string& boneName, const glm::mat4& defaultTransform) const
|
||||
{
|
||||
for (const auto& channel : m_BoneChannels) {
|
||||
if (channel.BoneName == boneName) {
|
||||
const glm::vec3 pos = SampleChannel(channel.Positions, timeTicks, glm::vec3(0.0f));
|
||||
const glm::quat rot = SampleChannel(channel.Rotations, timeTicks, glm::quat(1.0f, 0.0f, 0.0f, 0.0f));
|
||||
const glm::vec3 scl = SampleChannel(channel.Scalings, timeTicks, glm::vec3(1.0f));
|
||||
return glm::translate(glm::mat4(1.0f), pos) * glm::toMat4(rot) * glm::scale(glm::mat4(1.0f), scl);
|
||||
}
|
||||
}
|
||||
return defaultTransform;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T AnimationClip::SampleChannel(const std::vector<KeyFrame<T>>& keys, float time, const T& defaultValue) const
|
||||
{
|
||||
if (keys.empty()) return defaultValue;
|
||||
if (time <= keys.front().Time) return keys.front().Value;
|
||||
if (time >= keys.back().Time) return keys.back().Value;
|
||||
|
||||
// 找到当前时间所在的关键帧区间
|
||||
for (size_t i = 0; i < keys.size() - 1; ++i) {
|
||||
if (time >= keys[i].Time && time <= keys[i+1].Time) {
|
||||
float t = (time - keys[i].Time) / (keys[i+1].Time - keys[i].Time);
|
||||
return Interpolate(keys[i].Value, keys[i+1].Value, t);
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
63
Prism/src/Prism/Animation/AnimationClip.h
Normal file
63
Prism/src/Prism/Animation/AnimationClip.h
Normal file
@ -0,0 +1,63 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#ifndef PRISM_ANIMATIONCLIP_H
|
||||
#define PRISM_ANIMATIONCLIP_H
|
||||
#include "Prism/Asset/Asset.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
|
||||
struct aiScene;
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
template<typename T>
|
||||
struct KeyFrame
|
||||
{
|
||||
float Time = 0.0f;
|
||||
T Value;
|
||||
|
||||
KeyFrame() = default;
|
||||
KeyFrame(const float t, const T& v) : Time(t), Value(v) {}
|
||||
};
|
||||
|
||||
struct BoneChannel {
|
||||
std::string BoneName;
|
||||
std::vector<KeyFrame<glm::vec3>> Positions;
|
||||
std::vector<KeyFrame<glm::quat>> Rotations;
|
||||
std::vector<KeyFrame<glm::vec3>> Scalings;
|
||||
};
|
||||
|
||||
|
||||
class PRISM_API AnimationClip : public Asset
|
||||
{
|
||||
public:
|
||||
AnimationClip(const aiScene* scene);
|
||||
glm::mat4 SampleAtTime(float timeTicks, const std::string& boneName, const glm::mat4& defaultTransform) const;
|
||||
|
||||
private:
|
||||
// 辅助采样模板函数
|
||||
template<typename T>
|
||||
T SampleChannel(const std::vector<KeyFrame<T>>& keys, float time, const T& defaultValue) const;
|
||||
|
||||
glm::vec3 Interpolate(const glm::vec3& a, const glm::vec3& b, const float t) const {
|
||||
return glm::mix(a, b, t);
|
||||
}
|
||||
glm::quat Interpolate(const glm::quat& a, const glm::quat& b, const float t) const {
|
||||
return glm::slerp(a, b, t);
|
||||
}
|
||||
|
||||
public:
|
||||
float m_Duration = 0.0f;
|
||||
float m_TicksPerSecond;
|
||||
std::vector<BoneChannel> m_BoneChannels;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //PRISM_ANIMATIONCLIP_H
|
||||
115
Prism/src/Prism/Animation/AnimatorController.cpp
Normal file
115
Prism/src/Prism/Animation/AnimatorController.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#include "AnimatorController.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
AnimationController::~AnimationController()
|
||||
{
|
||||
}
|
||||
|
||||
void AnimationController::Update(const float deltaTime)
|
||||
{
|
||||
if (m_State != PLAY || !m_currentClip || !m_skeleton)
|
||||
return;
|
||||
|
||||
const float rawTime = m_AnimationCurrentTime + deltaTime * m_currentClip->m_TicksPerSecond * m_TimeMultiplier;
|
||||
const float duration = m_currentClip->m_Duration;
|
||||
|
||||
if (!m_Loop && rawTime >= duration)
|
||||
{
|
||||
m_AnimationCurrentTime = 0.0f;
|
||||
m_State = STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AnimationCurrentTime = fmod(rawTime, duration);
|
||||
}
|
||||
|
||||
ComputeBoneTransforms(m_AnimationCurrentTime);
|
||||
|
||||
}
|
||||
|
||||
void AnimationController::ComputeBoneTransforms(float time)
|
||||
{
|
||||
const auto boneCount = (uint32_t)m_skeleton->m_Bones.size();
|
||||
m_FinalBoneTransforms.resize(boneCount);
|
||||
|
||||
std::vector<glm::mat4> localTransforms(boneCount, glm::mat4(1.0f));
|
||||
for (uint32_t i = 0; i < boneCount; i++)
|
||||
{
|
||||
const BoneInfo& bone = m_skeleton->m_Bones[i];
|
||||
if (m_currentClip)
|
||||
{
|
||||
localTransforms[i] = m_currentClip->SampleAtTime(time, bone.Name, bone.LocalBindPose);
|
||||
}
|
||||
else
|
||||
{
|
||||
localTransforms[i] = bone.LocalBindPose;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 递归计算全局变换(从根骨骼开始)
|
||||
std::function<void(uint32_t, const glm::mat4&)> computeGlobal = [&](const uint32_t boneIdx, const glm::mat4& parentGlobal)
|
||||
{
|
||||
const glm::mat4 global = parentGlobal * localTransforms[boneIdx];
|
||||
glm::mat4 final = global * m_skeleton->m_Bones[boneIdx].InverseTransform;
|
||||
final = m_GlobalInverseTransform * final;
|
||||
m_FinalBoneTransforms[boneIdx] = final;
|
||||
|
||||
for (uint32_t childIdx = 0; childIdx < boneCount; childIdx++)
|
||||
{
|
||||
if (m_skeleton->m_Bones[childIdx].ParentIndex == (int)boneIdx)
|
||||
{
|
||||
computeGlobal(childIdx, global);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < boneCount; i++)
|
||||
{
|
||||
if (m_skeleton->m_Bones[i].ParentIndex == -1)
|
||||
{
|
||||
computeGlobal(i, glm::mat4(1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationController::ComputeBindPoseTransforms()
|
||||
{
|
||||
if (!m_skeleton) return;
|
||||
|
||||
uint32_t boneCount = (uint32_t)m_skeleton->m_Bones.size();
|
||||
m_FinalBoneTransforms.resize(boneCount);
|
||||
|
||||
// 1. 收集每个骨骼的绑定姿势局部变换
|
||||
std::vector<glm::mat4> localTransforms(boneCount);
|
||||
for (uint32_t i = 0; i < boneCount; i++)
|
||||
localTransforms[i] = m_skeleton->m_Bones[i].LocalBindPose;
|
||||
|
||||
// 2. 递归计算全局变换,并应用逆绑定矩阵和全局逆矩阵
|
||||
std::function<void(uint32_t, const glm::mat4&)> computeGlobal =
|
||||
[&](uint32_t idx, const glm::mat4& parentGlobal)
|
||||
{
|
||||
glm::mat4 global = parentGlobal * localTransforms[idx];
|
||||
glm::mat4 final = m_GlobalInverseTransform * global * m_skeleton->m_Bones[idx].InverseTransform;
|
||||
m_FinalBoneTransforms[idx] = final;
|
||||
|
||||
// 处理子骨骼
|
||||
for (uint32_t child = 0; child < boneCount; child++)
|
||||
{
|
||||
if (m_skeleton->m_Bones[child].ParentIndex == (int)idx)
|
||||
computeGlobal(child, global);
|
||||
}
|
||||
};
|
||||
|
||||
// 从所有根骨骼开始递归
|
||||
for (uint32_t i = 0; i < boneCount; i++)
|
||||
{
|
||||
if (m_skeleton->m_Bones[i].ParentIndex == -1)
|
||||
computeGlobal(i, glm::mat4(1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
67
Prism/src/Prism/Animation/AnimatorController.h
Normal file
67
Prism/src/Prism/Animation/AnimatorController.h
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#ifndef PRISM_ANIMATORCONTROLLER_H
|
||||
#define PRISM_ANIMATORCONTROLLER_H
|
||||
#include "AnimationClip.h"
|
||||
#include "Skeleton.h"
|
||||
#include "Prism/Asset/Asset.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API AnimationController : public Asset
|
||||
{
|
||||
public:
|
||||
enum AnimationState : uint8_t
|
||||
{
|
||||
STOP = 0,
|
||||
PLAY,
|
||||
PAUSE
|
||||
};
|
||||
|
||||
public:
|
||||
~AnimationController();
|
||||
|
||||
void Update(const float deltaTime);
|
||||
|
||||
const std::vector<glm::mat4>& GetFinalBoneTransforms() const { return m_FinalBoneTransforms; }
|
||||
|
||||
|
||||
void AnimationController::SetSkeleton(const Ref<Skeleton>& skeleton)
|
||||
{
|
||||
m_skeleton = skeleton;
|
||||
if (m_skeleton)
|
||||
{
|
||||
ComputeBindPoseTransforms();
|
||||
}
|
||||
}
|
||||
void AnimationController::SetAnimationClip(const Ref<AnimationClip>& clip) { m_currentClip = clip; }
|
||||
void AnimationController::SetGlobalInverseTransform(const glm::mat4& inv) { m_GlobalInverseTransform = inv; }
|
||||
|
||||
void Play() { m_State = PLAY; }
|
||||
void Pause() { m_State = PAUSE; }
|
||||
void Stop() { if (m_State == STOP) return; m_State = STOP; m_AnimationCurrentTime = 0.0f; ComputeBindPoseTransforms(); }
|
||||
AnimationState GetAnimationState() const { return m_State; }
|
||||
|
||||
float& GetCurrentTime() { return m_AnimationCurrentTime; }
|
||||
float& GetMultiplierTime() { return m_TimeMultiplier; }
|
||||
bool& GetLoop() { return m_Loop; }
|
||||
private:
|
||||
void ComputeBoneTransforms(float time);
|
||||
void ComputeBindPoseTransforms();
|
||||
|
||||
Ref<Skeleton> m_skeleton = nullptr;
|
||||
Ref<AnimationClip> m_currentClip = nullptr;
|
||||
AnimationState m_State = STOP;
|
||||
|
||||
float m_AnimationCurrentTime = 0.0f;
|
||||
float m_TimeMultiplier = 1.0f;
|
||||
bool m_Loop = false;
|
||||
std::vector<glm::mat4> m_FinalBoneTransforms;
|
||||
|
||||
glm::mat4 m_GlobalInverseTransform = glm::mat4(1.0f);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PRISM_ANIMATORCONTROLLER_H
|
||||
68
Prism/src/Prism/Animation/Skeleton.cpp
Normal file
68
Prism/src/Prism/Animation/Skeleton.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#include "Skeleton.h"
|
||||
|
||||
#include "assimp/scene.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
// TODO: this maybe move Utils
|
||||
extern glm::mat4 Mat4FromAssimpMat4(const aiMatrix4x4& matrix);
|
||||
|
||||
|
||||
Skeleton::Skeleton(const aiScene* scene)
|
||||
{
|
||||
// 收集所有骨骼(通过所有 Mesh 中的 aiBone)
|
||||
for (uint32_t am = 0; am < scene->mNumMeshes; am++)
|
||||
{
|
||||
const aiMesh* aMesh = scene->mMeshes[am];
|
||||
for (uint32_t i = 0; i < aMesh->mNumBones; i++)
|
||||
{
|
||||
const aiBone* bone = aMesh->mBones[i];
|
||||
if (std::string boneName = bone->mName.C_Str(); m_NameToIndex.find(boneName) == m_NameToIndex.end())
|
||||
{
|
||||
const auto boneIndex = (uint32_t)m_Bones.size();
|
||||
BoneInfo bi;
|
||||
bi.Name = boneName;
|
||||
bi.InverseTransform = Mat4FromAssimpMat4(bone->mOffsetMatrix);
|
||||
bi.ParentIndex = -1; // 稍后设置
|
||||
|
||||
m_Bones.push_back(bi);
|
||||
m_NameToIndex[boneName] = boneIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置骨骼的父子关系及默认局部变换(遍历节点树)
|
||||
std::unordered_map<std::string, uint32_t>& nameToIdx = m_NameToIndex;
|
||||
std::function<void(aiNode*, int)> traverseNodes = [&](const aiNode* node, const int parentBoneIdx)
|
||||
{
|
||||
const std::string nodeName = node->mName.C_Str();
|
||||
const auto it = nameToIdx.find(nodeName);
|
||||
int currentBoneIdx = -1;
|
||||
if (it != nameToIdx.end())
|
||||
{
|
||||
currentBoneIdx = (int)it->second;
|
||||
BoneInfo& bone = m_Bones[currentBoneIdx];
|
||||
bone.ParentIndex = parentBoneIdx;
|
||||
// 存储默认局部变换(绑定姿势下相对于父节点的变换)
|
||||
bone.LocalBindPose = Mat4FromAssimpMat4(node->mTransformation);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
||||
{
|
||||
traverseNodes(node->mChildren[i], currentBoneIdx);
|
||||
}
|
||||
};
|
||||
traverseNodes(scene->mRootNode, -1);
|
||||
}
|
||||
|
||||
uint32_t Skeleton::GetBoneIndex(const std::string& name) const
|
||||
{
|
||||
const auto it = m_NameToIndex.find(name);
|
||||
return (it != m_NameToIndex.end()) ? it->second : static_cast<uint32_t>(-1);
|
||||
}
|
||||
}
|
||||
35
Prism/src/Prism/Animation/Skeleton.h
Normal file
35
Prism/src/Prism/Animation/Skeleton.h
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/9.
|
||||
//
|
||||
|
||||
#ifndef PRISM_SKELETON_H
|
||||
#define PRISM_SKELETON_H
|
||||
#include "glm/glm.hpp"
|
||||
#include "Prism/Asset/Asset.h"
|
||||
|
||||
struct aiScene;
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct BoneInfo
|
||||
{
|
||||
std::string Name;
|
||||
int ParentIndex; // -1 is Root
|
||||
glm::mat4 LocalBindPose;
|
||||
glm::mat4 InverseTransform; // aiScene::mOffsetMatrix
|
||||
};
|
||||
|
||||
class PRISM_API Skeleton : public Asset
|
||||
{
|
||||
public:
|
||||
Skeleton(const aiScene* scene);
|
||||
uint32_t GetBoneIndex(const std::string& name) const;
|
||||
|
||||
public:
|
||||
std::vector<BoneInfo> m_Bones;
|
||||
std::unordered_map<std::string, uint32_t> m_NameToIndex;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_SKELETON_H
|
||||
@ -23,6 +23,7 @@ namespace Prism
|
||||
s_Types["scene"] = AssetType::Scene;
|
||||
s_Types["pmx"] = AssetType::Mesh;
|
||||
s_Types["fbx"] = AssetType::Mesh;
|
||||
s_Types["dae"] = AssetType::Mesh;
|
||||
s_Types["obj"] = AssetType::Mesh;
|
||||
s_Types["png"] = AssetType::Texture;
|
||||
s_Types["tga"] = AssetType::Texture;
|
||||
|
||||
@ -50,10 +50,10 @@ namespace Prism
|
||||
|
||||
if (Input::IsMouseButtonPressed(MouseButton::Right) && !altPressed)
|
||||
{
|
||||
Input::SetCursorMode(CursorMode::Disable);
|
||||
|
||||
if (!m_IsRightButtonDownState)
|
||||
{
|
||||
Input::SetCursorMode(CursorMode::Disable);
|
||||
m_InitialMousePosition = { Input::GetMouseX(), Input::GetMouseY() };
|
||||
m_IsRightButtonDownState = true;
|
||||
m_FreeLookActive = true;
|
||||
@ -183,6 +183,7 @@ namespace Prism
|
||||
UI::Property("focus", m_FocalPoint);
|
||||
UI::Property("position", m_Position);
|
||||
UI::Separator();
|
||||
UI::Property("Max Speed", m_MaxSpeed);
|
||||
UI::Property("Current Speed", m_Velocity);
|
||||
UI::EndPropertyGrid();
|
||||
ImGui::End();
|
||||
@ -198,10 +199,20 @@ namespace Prism
|
||||
m_ViewMatrix = glm::inverse(m_ViewMatrix);
|
||||
}
|
||||
|
||||
bool EditorCamera::OnMouseScroll(MouseScrolledEvent& e)
|
||||
bool EditorCamera::OnMouseScroll(const MouseScrolledEvent& e)
|
||||
{
|
||||
const float delta = e.GetOffsetY() * 0.1f;
|
||||
MouseZoom(delta);
|
||||
const float delta = e.GetOffsetY();
|
||||
|
||||
if (m_IsRightButtonDownState)
|
||||
{
|
||||
const float factor = m_MaxSpeed * 0.1f;
|
||||
m_MaxSpeed += delta * factor;
|
||||
m_MaxSpeed = std::clamp(m_MaxSpeed, 0.1f, 50.0f);
|
||||
}else
|
||||
{
|
||||
MouseZoom(delta * 0.1f);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ namespace Prism
|
||||
private:
|
||||
void UpdateCameraView();
|
||||
|
||||
bool OnMouseScroll(MouseScrolledEvent& e);
|
||||
bool OnMouseScroll(const MouseScrolledEvent& e);
|
||||
void MousePan(const glm::vec2& delta);
|
||||
void MouseRotate(const glm::vec2& delta);
|
||||
void MouseZoom(float delta);
|
||||
|
||||
@ -139,6 +139,11 @@ namespace Prism
|
||||
m_SelectionContext = entity;
|
||||
}
|
||||
|
||||
Entity SceneHierarchyPanel::GetSelected() const
|
||||
{
|
||||
return m_SelectionContext;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SceneHierarchyPanel::AddComponentPopup(const char* componentName)
|
||||
{
|
||||
@ -311,27 +316,6 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
|
||||
#if TODO
|
||||
ImGui::Begin("Mesh Debug");
|
||||
if (ImGui::CollapsingHeader(mesh->m_FilePath.c_str()))
|
||||
{
|
||||
if (mesh->m_IsAnimated)
|
||||
{
|
||||
if (ImGui::CollapsingHeader("Animation"))
|
||||
{
|
||||
if (ImGui::Button(mesh->m_AnimationPlaying ? "Pause" : "Play"))
|
||||
mesh->m_AnimationPlaying = !mesh->m_AnimationPlaying;
|
||||
|
||||
ImGui::SliderFloat("##AnimationTime", &mesh->m_AnimationTime, 0.0f, (float)mesh->m_Scene->mAnimations[0]->mDuration);
|
||||
ImGui::DragFloat("Time Scale", &mesh->m_TimeMultiplier, 0.05f, 0.0f, 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SceneHierarchyPanel::DrawEntityNode(Entity entity)
|
||||
@ -582,10 +566,43 @@ namespace Prism
|
||||
|
||||
ImGui::SeparatorText("3D Component");
|
||||
AddComponentPopup<MeshComponent>("Mesh");
|
||||
AddComponentPopup<AnimationComponent>("Animation", [&](AnimationComponent& component)
|
||||
{
|
||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||
{
|
||||
const auto meshComponent = m_SelectionContext.GetComponent<MeshComponent>();
|
||||
if (meshComponent.Mesh->IsAnimated())
|
||||
{
|
||||
component.AnimationController = meshComponent.Mesh->GetAnimatorController();
|
||||
component.SkeletonAsset = meshComponent.Mesh->GetSkeleton();
|
||||
}
|
||||
}
|
||||
});
|
||||
AddComponentPopup<RigidBodyComponent>("RigidBody");
|
||||
AddComponentPopup<BoxColliderComponent>("BoxCollider");
|
||||
AddComponentPopup<SphereColliderComponent>("SphereCollider");
|
||||
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider");
|
||||
AddComponentPopup<BoxColliderComponent>("BoxCollider", [&](BoxColliderComponent& component)
|
||||
{
|
||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||
{
|
||||
component.DebugMesh = MeshFactory::CreateBox(component.Size);
|
||||
}
|
||||
});
|
||||
|
||||
AddComponentPopup<SphereColliderComponent>("SphereCollider", [&](SphereColliderComponent& component)
|
||||
{
|
||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||
{
|
||||
component.DebugMesh = MeshFactory::CreateSphere(component.Radius);
|
||||
}
|
||||
});
|
||||
|
||||
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider", [&](CapsuleColliderComponent& component)
|
||||
{
|
||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||
{
|
||||
component.DebugMesh = MeshFactory::CreateCapsule(component.Radius, component.Radius);
|
||||
}
|
||||
});
|
||||
|
||||
AddComponentPopup<MeshColliderComponent>("MeshCollider", [&](MeshColliderComponent& component)
|
||||
{
|
||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||
@ -636,9 +653,67 @@ namespace Prism
|
||||
|
||||
UI::BeginPropertyGrid();
|
||||
UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh);
|
||||
UI::Property("AnimationPlaying", meshComponent.Mesh->m_AnimationPlaying);
|
||||
UI::Property("TimeMultiple", meshComponent.Mesh->m_TimeMultiplier);
|
||||
UI::Property("AnimationTime", meshComponent.Mesh->m_AnimationTime);
|
||||
UI::Property("WorldTime", meshComponent.Mesh->m_WorldTime);
|
||||
|
||||
UI::EndPropertyGrid();
|
||||
});
|
||||
|
||||
DrawComponent<AnimationComponent>("AnimatorController", entity, [this](AnimationComponent& animatorComponent)
|
||||
{
|
||||
// UI::BeginPropertyGrid();
|
||||
// UI::PropertyAssetReference("Animation", animatorComponent.AnimationController, AssetType::Other);
|
||||
// UI::PropertyAssetReference("", animatorComponent.SkeletonAsset, AssetType::Other);
|
||||
// UI::EndPropertyGrid();
|
||||
|
||||
if (animatorComponent.AnimationController)
|
||||
{
|
||||
UI::BeginPropertyGrid();
|
||||
UI::Property("Current Time", animatorComponent.AnimationController->GetCurrentTime());
|
||||
UI::Property("Multiplier Time", animatorComponent.AnimationController->GetMultiplierTime());
|
||||
UI::Property("Loop", animatorComponent.AnimationController->GetLoop());
|
||||
UI::EndPropertyGrid();
|
||||
|
||||
const AnimationController::AnimationState animationState = animatorComponent.AnimationController->GetAnimationState();
|
||||
if (ImGui::Button("Play"))
|
||||
{
|
||||
if (animationState != AnimationController::PLAY)
|
||||
animatorComponent.AnimationController->Play();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Pause"))
|
||||
{
|
||||
if (animationState != AnimationController::PAUSE)
|
||||
animatorComponent.AnimationController->Pause();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Stop"))
|
||||
{
|
||||
if (animationState != AnimationController::STOP)
|
||||
animatorComponent.AnimationController->Stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Load Animation: Not implement");
|
||||
if (ImGui::Button("Try get from exist Mesh"))
|
||||
{
|
||||
if (const auto meshComponent = m_SelectionContext.TryGetComponent<MeshComponent>())
|
||||
{
|
||||
if (meshComponent->Mesh->IsAnimated())
|
||||
{
|
||||
animatorComponent.AnimationController = meshComponent->Mesh->GetAnimatorController();
|
||||
animatorComponent.SkeletonAsset = meshComponent->Mesh->GetSkeleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
|
||||
// Projection Type
|
||||
const char* projTypeStrings[] = { "Perspective", "Orthographic" };
|
||||
|
||||
@ -18,6 +18,7 @@ namespace Prism
|
||||
|
||||
void SetContext(const Ref<Scene>& scene);
|
||||
void SetSelected(Entity entity);
|
||||
Entity GetSelected() const;
|
||||
void SetSelectionChangedCallback(const std::function<void(Entity)>& func) { m_SelectionChangedCallback = func; }
|
||||
void SetEntityDeletedCallback(const std::function<void(Entity)>& func) { m_EntityDeletedCallback = func; }
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#define CAMERA_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Core/TimeStep.h"
|
||||
|
||||
namespace Prism
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include "assimp/LogStream.hpp"
|
||||
#include "assimp/postprocess.h"
|
||||
#include "assimp/scene.h"
|
||||
#include "glad/glad.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <filesystem>
|
||||
@ -144,6 +143,23 @@ namespace Prism
|
||||
// Vertices
|
||||
if (m_IsAnimated)
|
||||
{
|
||||
// 1. 创建 Skeleton
|
||||
m_Skeleton = Ref<Skeleton>::Create(scene);
|
||||
|
||||
|
||||
// ---------- 2. 如果有动画,创建 AnimationClip ----------
|
||||
if (scene->mNumAnimations > 0)
|
||||
{
|
||||
Ref<AnimationClip> clip = Ref<AnimationClip>::Create(scene);
|
||||
|
||||
// ---------- 3. 创建 AnimatorController ----------
|
||||
m_AnimatorController = Ref<AnimationController>::Create();
|
||||
m_AnimatorController->SetSkeleton(m_Skeleton);
|
||||
m_AnimatorController->SetAnimationClip(clip);
|
||||
m_AnimatorController->SetGlobalInverseTransform(m_InverseTransform); // 根节点逆矩阵
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
AnimatedVertex vertex;
|
||||
@ -169,7 +185,7 @@ namespace Prism
|
||||
|
||||
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
Vertex vertex;
|
||||
Vertex vertex{};
|
||||
vertex.Position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z };
|
||||
vertex.Normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z };
|
||||
|
||||
@ -211,41 +227,31 @@ namespace Prism
|
||||
// Bones
|
||||
if (m_IsAnimated)
|
||||
{
|
||||
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[m];
|
||||
Submesh& submesh = m_Submeshes[m];
|
||||
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[m];
|
||||
Submesh& submesh = m_Submeshes[m];
|
||||
for (size_t i = 0; i < mesh->mNumBones; i++)
|
||||
{
|
||||
aiBone* bone = mesh->mBones[i];
|
||||
std::string boneName = bone->mName.C_Str();
|
||||
|
||||
for (size_t i = 0; i < mesh->mNumBones; i++)
|
||||
{
|
||||
aiBone* bone = mesh->mBones[i];
|
||||
std::string boneName(bone->mName.data);
|
||||
uint32_t boneIndex = 0;
|
||||
// 从 Skeleton 获取骨骼索引
|
||||
uint32_t boneIndex = m_Skeleton->GetBoneIndex(boneName);
|
||||
if (boneIndex == uint32_t(-1))
|
||||
{
|
||||
PM_CORE_ERROR("Bone '{}' not found in skeleton!", boneName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_BoneMapping.find(boneName) == m_BoneMapping.end())
|
||||
{
|
||||
// Allocate an index for a new bone
|
||||
boneIndex = m_BoneCount;
|
||||
m_BoneCount++;
|
||||
BoneInfo bi;
|
||||
m_BoneInfo.push_back(bi);
|
||||
m_BoneInfo[boneIndex].BoneOffset = Mat4FromAssimpMat4(bone->mOffsetMatrix);
|
||||
m_BoneMapping[boneName] = boneIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
PM_CORE_TRACE("Found existing bone in map");
|
||||
boneIndex = m_BoneMapping[boneName];
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < bone->mNumWeights; j++)
|
||||
{
|
||||
uint32_t VertexID = submesh.BaseVertex + bone->mWeights[j].mVertexId;
|
||||
float Weight = bone->mWeights[j].mWeight;
|
||||
m_AnimatedVertices[VertexID].AddBoneData(boneIndex, Weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < bone->mNumWeights; j++)
|
||||
{
|
||||
uint32_t VertexID = submesh.BaseVertex + bone->mWeights[j].mVertexId;
|
||||
float Weight = bone->mWeights[j].mWeight;
|
||||
m_AnimatedVertices[VertexID].AddBoneData(boneIndex, Weight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Material
|
||||
@ -541,6 +547,11 @@ namespace Prism
|
||||
|
||||
void Mesh::OnUpdate(TimeStep deltaTime)
|
||||
{
|
||||
if (m_AnimatorController)
|
||||
{
|
||||
m_AnimatorController->Update(deltaTime);
|
||||
}
|
||||
/*
|
||||
if (m_IsAnimated)
|
||||
{
|
||||
if (m_AnimationPlaying)
|
||||
@ -555,6 +566,7 @@ namespace Prism
|
||||
// TODO: We only need to recalc bones if rendering has been requested at the current animation frame
|
||||
BoneTransform(m_AnimationTime);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -594,6 +606,7 @@ namespace Prism
|
||||
PM_MESH_LOG("------------------------------------------------------");
|
||||
}
|
||||
|
||||
/*
|
||||
void Mesh::BoneTransform(float time)
|
||||
{
|
||||
ReadNodeHierarchy(time, m_Scene->mRootNode, glm::mat4(1.0f));
|
||||
@ -642,6 +655,7 @@ namespace Prism
|
||||
result += "--";
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
||||
{
|
||||
@ -662,6 +676,7 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
||||
{
|
||||
for (uint32_t i = 0; i < animation->mNumChannels; i++)
|
||||
@ -779,4 +794,5 @@ namespace Prism
|
||||
auto aiVec = start + factor * delta;
|
||||
return { aiVec.x, aiVec.y, aiVec.z };
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include "Prism/Core/TimeStep.h"
|
||||
#include "Prism/Core/Math/AABB.h"
|
||||
#include "../Asset/Asset.h"
|
||||
#include "Prism/Animation/AnimatorController.h"
|
||||
#include "Prism/Animation/Skeleton.h"
|
||||
|
||||
struct aiNode;
|
||||
struct aiAnimation;
|
||||
@ -58,12 +60,12 @@ namespace Prism
|
||||
};
|
||||
static_assert(sizeof(Index) == 3 * sizeof(uint32_t));
|
||||
|
||||
struct BoneInfo
|
||||
struct MeshBoneInfo
|
||||
{
|
||||
glm::mat4 BoneOffset;
|
||||
glm::mat4 FinalTransformation;
|
||||
|
||||
BoneInfo() : BoneOffset(glm::mat4(1.0f)), FinalTransformation(glm::mat4(1.0f)) {}
|
||||
MeshBoneInfo() : BoneOffset(glm::mat4(1.0f)), FinalTransformation(glm::mat4(1.0f)) {}
|
||||
};
|
||||
|
||||
struct VertexBoneData
|
||||
@ -107,11 +109,9 @@ namespace Prism
|
||||
class PRISM_API Mesh : public Asset
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
Mesh(const std::string& filename);
|
||||
Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform);
|
||||
~Mesh();
|
||||
~Mesh() override;
|
||||
|
||||
void OnUpdate(TimeStep deltaTime);
|
||||
void DumpVertexBuffer();
|
||||
@ -131,31 +131,26 @@ namespace Prism
|
||||
|
||||
bool IsAnimated() const { return m_IsAnimated; }
|
||||
|
||||
std::vector<Triangle> GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); }
|
||||
std::vector<Triangle> GetTriangleCache(const uint32_t index) const { return m_TriangleCache.at(index); }
|
||||
|
||||
Ref<Skeleton> GetSkeleton() const { return m_Skeleton; }
|
||||
Ref<AnimationController> GetAnimatorController() const { return m_AnimatorController; }
|
||||
std::vector<glm::mat4> m_EmptyTransforms{};
|
||||
|
||||
const std::vector<glm::mat4>& GetBoneTransforms() const
|
||||
{
|
||||
return m_AnimatorController ? m_AnimatorController->GetFinalBoneTransforms() : m_EmptyTransforms;
|
||||
}
|
||||
private:
|
||||
void BoneTransform(float time);
|
||||
void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform);
|
||||
void TraverseNodes(const aiNode* node, const glm::mat4& parentTransform = glm::mat4(1.0f), uint32_t level = 0);
|
||||
|
||||
const aiNodeAnim* FindNodeAnim(const aiAnimation* animation, const std::string& nodeName);
|
||||
uint32_t FindPosition(float AnimationTime, const aiNodeAnim* pNodeAnim);
|
||||
uint32_t FindRotation(float AnimationTime, const aiNodeAnim* pNodeAnim);
|
||||
uint32_t FindScaling(float AnimationTime, const aiNodeAnim* pNodeAnim);
|
||||
glm::vec3 InterpolateTranslation(float animationTime, const aiNodeAnim* nodeAnim);
|
||||
glm::quat InterpolateRotation(float animationTime, const aiNodeAnim* nodeAnim);
|
||||
glm::vec3 InterpolateScale(float animationTime, const aiNodeAnim* nodeAnim);
|
||||
|
||||
private:
|
||||
std::vector<Submesh> m_Submeshes;
|
||||
|
||||
std::unique_ptr<Assimp::Importer> m_Importer;
|
||||
const aiScene* m_Scene;
|
||||
|
||||
glm::mat4 m_InverseTransform;
|
||||
|
||||
uint32_t m_BoneCount = 0;
|
||||
std::vector<BoneInfo> m_BoneInfo;
|
||||
|
||||
// Ref<VertexArray> m_VertexArray;
|
||||
Ref<Pipeline> m_Pipeline;
|
||||
Ref<VertexBuffer> m_VertexBuffer;
|
||||
Ref<IndexBuffer> m_IndexBuffer;
|
||||
@ -164,9 +159,11 @@ namespace Prism
|
||||
std::vector<Vertex> m_StaticVertices;
|
||||
std::vector<AnimatedVertex> m_AnimatedVertices;
|
||||
std::vector<Index> m_Indices;
|
||||
std::unordered_map<std::string, uint32_t> m_BoneMapping;
|
||||
std::vector<glm::mat4> m_BoneTransforms;
|
||||
const aiScene* m_Scene;
|
||||
std::vector<Submesh> m_Submeshes;
|
||||
|
||||
Ref<Skeleton> m_Skeleton;
|
||||
Ref<AnimationController> m_AnimatorController;
|
||||
|
||||
|
||||
// Material
|
||||
Ref<Shader> m_MeshShader;
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "Renderer2D.h"
|
||||
#include "Renderer3D.h"
|
||||
#include "RendererAPI.h"
|
||||
#include "SceneRenderer.h"
|
||||
#include "glad/glad.h"
|
||||
@ -35,6 +36,7 @@ namespace Prism
|
||||
GetShaderLibrary()->Load("assets/shaders/PBRShader_Static.glsl");
|
||||
GetShaderLibrary()->Load("assets/shaders/PBRShader_Anim.glsl");
|
||||
|
||||
// this to Init 2D and 3D Renderer
|
||||
SceneRenderer::Init();
|
||||
|
||||
// FullScreen Quad
|
||||
@ -58,8 +60,6 @@ namespace Prism
|
||||
|
||||
s_Data.m_FullscreenQuadVertexBuffer = VertexBuffer::Create(fullScreenQuadVertex, sizeof(fullScreenQuadVertex[0]) * sizeof(fullScreenQuadVertex));
|
||||
s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
|
||||
|
||||
Renderer2D::Init();
|
||||
}
|
||||
|
||||
void Renderer::Clear()
|
||||
@ -192,10 +192,11 @@ namespace Prism
|
||||
|
||||
if (mesh->m_IsAnimated)
|
||||
{
|
||||
for (size_t i = 0; i < mesh->m_BoneTransforms.size(); i++)
|
||||
const auto& boneTransform = mesh->GetBoneTransforms();
|
||||
for (size_t i = 0; i < boneTransform.size(); i++)
|
||||
{
|
||||
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||
mesh->m_MeshShader->SetMat4(uniformName, mesh->m_BoneTransforms[i]);
|
||||
shader->SetMat4(uniformName, boneTransform[i]);
|
||||
}
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
@ -227,10 +228,11 @@ namespace Prism
|
||||
{
|
||||
if (mesh->m_IsAnimated)
|
||||
{
|
||||
for (size_t i = 0; i < mesh->m_BoneTransforms.size(); i++)
|
||||
const auto& boneTransform = mesh->GetBoneTransforms();
|
||||
for (size_t i = 0; i < boneTransform.size(); i++)
|
||||
{
|
||||
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||
shader->SetMat4(uniformName, mesh->m_BoneTransforms[i]);
|
||||
shader->SetMat4(uniformName, boneTransform[i]);
|
||||
}
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
@ -186,14 +186,11 @@ namespace Prism
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer2D::BeginScene(const glm::mat4& viewProj, bool depthTest)
|
||||
void Renderer2D::BeginScene(const glm::mat4& viewProj, const bool depthTest)
|
||||
{
|
||||
s_Data.CameraViewProj = viewProj;
|
||||
s_Data.DepthTest = depthTest;
|
||||
|
||||
s_Data.TextureShader->Bind();
|
||||
s_Data.TextureShader->SetMat4("u_ViewProjection", viewProj);
|
||||
|
||||
s_Data.QuadIndexCount = 0;
|
||||
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
|
||||
|
||||
@ -206,8 +203,10 @@ namespace Prism
|
||||
s_Data.TextureSlotIndex = 1;
|
||||
}
|
||||
|
||||
void Renderer2D::EndScene()
|
||||
void Renderer2D::EndScene(const Ref<RenderPass>& renderPass)
|
||||
{
|
||||
if (renderPass) Renderer::BeginRenderPass(renderPass, false);
|
||||
|
||||
uint32_t dataSize = (uint32_t)((uint8_t*)s_Data.QuadVertexBufferPtr - (uint8_t*)s_Data.QuadVertexBufferBase);
|
||||
if (dataSize)
|
||||
{
|
||||
@ -257,6 +256,7 @@ namespace Prism
|
||||
s_Data.Stats.DrawCalls++;
|
||||
}
|
||||
|
||||
if (renderPass) Renderer::EndRenderPass();
|
||||
#if OLD
|
||||
Flush();
|
||||
#endif
|
||||
@ -614,6 +614,12 @@ namespace Prism
|
||||
s_Data.QuadIndexCount = 0;
|
||||
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
|
||||
|
||||
s_Data.CircleIndexCount = 0;
|
||||
s_Data.CircleVertexBufferPtr = s_Data.CircleVertexBufferBase;
|
||||
|
||||
s_Data.LineIndexCount = 0;
|
||||
s_Data.LineVertexBufferPtr = s_Data.LineVertexBufferBase;
|
||||
|
||||
s_Data.TextureSlotIndex = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "RenderPass.h"
|
||||
#include "Texture.h"
|
||||
|
||||
namespace Prism
|
||||
@ -18,7 +19,7 @@ namespace Prism
|
||||
static void Shutdown();
|
||||
|
||||
static void BeginScene(const glm::mat4& viewProj, bool depthTest = true);
|
||||
static void EndScene();
|
||||
static void EndScene(const Ref<RenderPass>& renderPass = nullptr);
|
||||
static void Flush();
|
||||
|
||||
// Primitives
|
||||
|
||||
1244
Prism/src/Prism/Renderer/Renderer3D.cpp
Normal file
1244
Prism/src/Prism/Renderer/Renderer3D.cpp
Normal file
File diff suppressed because it is too large
Load Diff
68
Prism/src/Prism/Renderer/Renderer3D.h
Normal file
68
Prism/src/Prism/Renderer/Renderer3D.h
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/10.
|
||||
//
|
||||
|
||||
#ifndef PRISM_RENDERER3D_H
|
||||
#define PRISM_RENDERER3D_H
|
||||
#include "Texture.h"
|
||||
#include "glm/glm.hpp"
|
||||
#include "Prism/Core/Ref.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class Shader;
|
||||
class RenderPass;
|
||||
struct SceneRendererOptions;
|
||||
struct MeshColliderComponent;
|
||||
struct CapsuleColliderComponent;
|
||||
struct BoxColliderComponent;
|
||||
struct SphereColliderComponent;
|
||||
class MaterialInstance;
|
||||
class Mesh;
|
||||
struct SceneRendererCamera;
|
||||
class Scene;
|
||||
|
||||
class PRISM_API Renderer3D
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
|
||||
static void SetViewportSize(uint32_t width, uint32_t height);
|
||||
|
||||
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera);
|
||||
static void EndScene(Ref<RenderPass>& renderPass);
|
||||
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
||||
|
||||
static void SubmitColliderMesh(const BoxColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static void SubmitColliderMesh(const SphereColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static void SubmitColliderMesh(const CapsuleColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static void SubmitColliderMesh(const MeshColliderComponent& component, const glm::mat4& parentTransform = glm::mat4(1.0f));
|
||||
static std::pair<Ref<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath);
|
||||
|
||||
// static Ref<RenderPass> GetFinalRenderPass();
|
||||
static Ref<RenderPass> GetGeoPass();
|
||||
static Ref<Texture2D> GetFinalColorBuffer();
|
||||
|
||||
static void SetFocusPoint(const glm::vec2& point);
|
||||
|
||||
// TODO: Temp
|
||||
// static uint32_t GetFinalColorBufferRendererID();
|
||||
|
||||
static SceneRendererOptions& GetOptions();
|
||||
|
||||
private:
|
||||
static void FlushDrawList(Ref<RenderPass>& outRenderPass);
|
||||
|
||||
static void AutoExposurePass();
|
||||
static void GeometryPass();
|
||||
// static void CompositePass();
|
||||
// static void BloomBlurPass();
|
||||
static void ShadowMapPass();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_RENDERER3D_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -35,9 +35,44 @@ namespace Prism
|
||||
|
||||
static void SetViewportSize(uint32_t width, uint32_t height);
|
||||
|
||||
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera);
|
||||
static void BeginScene(const Scene* scene, const SceneRendererCamera& camera, bool enable2DDepthTest = true);
|
||||
static void EndScene();
|
||||
|
||||
// Renderer2D
|
||||
static void SubmitQuad(const glm::mat4& transform, const glm::vec4& color);
|
||||
static void SubmitQuad(const glm::mat4& transform, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
|
||||
/**
|
||||
* draw a Billboard's texture
|
||||
* @param position entity position
|
||||
* @param texture entity texture
|
||||
* @param cameraPos editcamera or camera postion
|
||||
* @param upDirection default (0.0f, 1.0f, 0.0f)
|
||||
* @param tilingFactor default 0
|
||||
* @param tintColor default (1.0f, 1.0f, 1.0f)
|
||||
*/
|
||||
static void SubmitBillBoardQuad(const glm::vec3& position, const Ref<Texture2D>& texture, const glm::vec3& cameraPos, const glm::vec3& upDirection = glm::vec3(0.0f, 1.0f, 0.0f), float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
|
||||
static void SubmitQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color);
|
||||
static void SubmitQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color);
|
||||
static void SubmitQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
static void SubmitQuad(const glm::vec3& position, const glm::vec2& size, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
|
||||
static void SubmitRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color);
|
||||
static void SubmitRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color);
|
||||
static void SubmitRotatedQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
static void SubmitRotatedQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
|
||||
|
||||
static void SubmitRotatedRect(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color);
|
||||
static void SubmitRotatedRect(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color);
|
||||
|
||||
static void SubmitCircle(const glm::vec2& position, float radius, const glm::vec4& color, float thickness = 0.05f);
|
||||
static void SubmitCircle(const glm::vec3& position, float radius, const glm::vec4& color, float thickness = 0.05f);
|
||||
|
||||
static void SubmitLine(const glm::vec3& p0, const glm::vec3& p1, const glm::vec4& color = glm::vec4(1.0f));
|
||||
|
||||
|
||||
// Renderer3D
|
||||
static void SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& overrideMaterial = nullptr);
|
||||
static void SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform = glm::mat4(1.0f));
|
||||
|
||||
@ -49,24 +84,16 @@ namespace Prism
|
||||
static std::pair<Ref<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath);
|
||||
|
||||
static Ref<RenderPass> GetFinalRenderPass();
|
||||
static Ref<RenderPass> GetGeoPass();
|
||||
static Ref<Texture2D> GetFinalColorBuffer();
|
||||
|
||||
static void SetFocusPoint(const glm::vec2& point);
|
||||
|
||||
// TODO: Temp
|
||||
static uint32_t GetFinalColorBufferRendererID();
|
||||
|
||||
static SceneRendererOptions& GetOptions();
|
||||
|
||||
static void OnImGuiRender();
|
||||
private:
|
||||
static void FlushDrawList();
|
||||
static void AutoExposurePass();
|
||||
static void GeometryPass();
|
||||
static void CompositePass();
|
||||
static void BloomBlurPass();
|
||||
|
||||
static void ShadowMapPass();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "Prism/Animation/Skeleton.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
#include "Prism/Renderer/SceneEnvironment.h"
|
||||
|
||||
@ -99,6 +100,16 @@ namespace Prism
|
||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||
};
|
||||
|
||||
struct AnimationComponent
|
||||
{
|
||||
Ref<Skeleton> SkeletonAsset;
|
||||
Ref<AnimationController> AnimationController;
|
||||
|
||||
AnimationComponent() = default;
|
||||
AnimationComponent(const AnimationComponent&) = default;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ScriptComponent
|
||||
{
|
||||
|
||||
@ -36,6 +36,20 @@ namespace Prism
|
||||
return m_Scene->m_Registry.get<T>(m_EntityHandle);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& GetComponent() const
|
||||
{
|
||||
PM_CORE_ASSERT(HasComponent<T>(), "Entity doesn't have component!");
|
||||
return m_Scene->m_Registry.get<T>(m_EntityHandle);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* TryGetComponent() const
|
||||
{
|
||||
return m_Scene->m_Registry.try_get<T>(m_EntityHandle);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool HasComponent() const
|
||||
{
|
||||
@ -77,6 +91,7 @@ namespace Prism
|
||||
|
||||
|
||||
UUID GetUUID() { return GetComponent<IDComponent>().ID; }
|
||||
UUID GetUUID() const { return GetComponent<IDComponent>().ID; }
|
||||
UUID GetSceneUUID() const { return m_Scene->GetUUID(); }
|
||||
|
||||
private:
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Core/Math/Math.h"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -233,18 +232,21 @@ namespace Prism
|
||||
|
||||
void Scene::OnRenderRuntime(const TimeStep ts)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 3D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
Entity cameraEntity = GetMainCameraEntity();
|
||||
if (!cameraEntity)
|
||||
return;
|
||||
|
||||
const glm::mat4 cameraViewMatrix = glm::inverse(GetTransformRelativeToParent(cameraEntity));
|
||||
const glm::mat4 cameraViewMatrix = glm::inverse(GetTransformRelativeToParent(cameraEntity));
|
||||
PM_CORE_ASSERT(cameraEntity, "Scene does not contain any cameras!");
|
||||
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
||||
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 3D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Process lights
|
||||
{
|
||||
m_LightEnvironment = LightEnvironment();
|
||||
@ -281,49 +283,45 @@ namespace Prism
|
||||
|
||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||
|
||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix });
|
||||
for (auto entity : group)
|
||||
{
|
||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||
if (meshComponent.Mesh)
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
for (const auto entity : group)
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||
if (meshComponent.Mesh)
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity(entity, this));
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
// TODO: Should we render (logically)
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 2D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// render sprite
|
||||
{
|
||||
const auto entitiesGroup = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
|
||||
for (const auto entity : entitiesGroup)
|
||||
{
|
||||
auto [transformComponent, spriteRendererComponent] = entitiesGroup.get<TransformComponent, SpriteRendererComponent>(entity);
|
||||
if (spriteRendererComponent.Texture)
|
||||
SceneRenderer::SubmitQuad(transformComponent.GetTransform(), spriteRendererComponent.Texture, spriteRendererComponent.TilingFactor, spriteRendererComponent.Color);
|
||||
else
|
||||
SceneRenderer::SubmitQuad(transformComponent.GetTransform(), spriteRendererComponent.Color);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
SceneRenderer::EndScene();
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 2D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const glm::mat4 cameraViewProjection = cameraViewMatrix * camera.GetProjectionMatrix();
|
||||
Renderer2D::BeginScene(cameraViewProjection, false);
|
||||
|
||||
// render sprite
|
||||
{
|
||||
const auto entitiesGroup = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
|
||||
for (const auto entity : entitiesGroup)
|
||||
{
|
||||
auto [transformComponent, spriteRendererComponent] = entitiesGroup.get<TransformComponent, SpriteRendererComponent>(entity);
|
||||
if (spriteRendererComponent.Texture)
|
||||
Renderer2D::DrawQuad(transformComponent.GetTransform(), spriteRendererComponent.Texture, spriteRendererComponent.TilingFactor, spriteRendererComponent.Color);
|
||||
else
|
||||
Renderer2D::DrawQuad(transformComponent.GetTransform(), spriteRendererComponent.Color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
||||
@ -335,12 +333,12 @@ namespace Prism
|
||||
// Process lights
|
||||
{
|
||||
m_LightEnvironment = LightEnvironment();
|
||||
auto lights = m_Registry.group<DirectionalLightComponent>(entt::get<TransformComponent>);
|
||||
const auto lights = m_Registry.group<DirectionalLightComponent>(entt::get<TransformComponent>);
|
||||
uint32_t directionalLightIndex = 0;
|
||||
for (auto entity : lights)
|
||||
for (const auto entity : lights)
|
||||
{
|
||||
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
|
||||
glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
|
||||
const glm::vec3 direction = -glm::normalize(glm::mat3(transformComponent.GetTransform()) * glm::vec3(1.0f));
|
||||
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||
{
|
||||
direction,
|
||||
@ -353,148 +351,105 @@ namespace Prism
|
||||
|
||||
// TODO: only one sky light at the moment!
|
||||
{
|
||||
auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||
const auto lights = m_Registry.group<SkyLightComponent>(entt::get<TransformComponent>);
|
||||
if (!lights.empty())
|
||||
{
|
||||
for (auto entity : lights)
|
||||
for (const auto entity : lights)
|
||||
{
|
||||
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
|
||||
m_Environment = skyLightComponent.SceneEnvironment;
|
||||
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
||||
SetSkybox(m_Environment->RadianceMap);
|
||||
}
|
||||
}else
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||
|
||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f }); // TODO: real values
|
||||
// TODO: this value should be storage and can modify
|
||||
|
||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f});
|
||||
{
|
||||
for (const auto entity : group)
|
||||
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||
{
|
||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
||||
if (meshComponent.Mesh)
|
||||
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
Entity e = {entity, this};
|
||||
|
||||
glm::mat4 transform = GetTransformRelativeToParent(Entity{ entity, this });
|
||||
if (meshComponent.Mesh)
|
||||
{
|
||||
meshComponent.Mesh->OnUpdate(ts);
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
// TODO: Should we render (logically)
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform);
|
||||
else
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
}
|
||||
|
||||
// Renderer Collider
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitSelectedMesh(meshComponent, transform);
|
||||
{
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (const auto collider = e.TryGetComponent<BoxColliderComponent>())
|
||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||
if (const auto collider = e.TryGetComponent<SphereColliderComponent>())
|
||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||
if (const auto collider = e.TryGetComponent<CapsuleColliderComponent>())
|
||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||
if (const auto collider = e.TryGetComponent<MeshColliderComponent>())
|
||||
SceneRenderer::SubmitColliderMesh(*collider, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 2D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// render sprite
|
||||
{
|
||||
const auto entitiesGroup = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
|
||||
for (const auto entity : entitiesGroup)
|
||||
{
|
||||
auto [transformComponent, spriteRendererComponent] = entitiesGroup.get<TransformComponent, SpriteRendererComponent>(entity);
|
||||
if (spriteRendererComponent.Texture)
|
||||
SceneRenderer::SubmitQuad(transformComponent.GetTransform(), spriteRendererComponent.Texture, spriteRendererComponent.TilingFactor, spriteRendererComponent.Color);
|
||||
else
|
||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
||||
SceneRenderer::SubmitQuad(transformComponent.GetTransform(), spriteRendererComponent.Color);
|
||||
}
|
||||
}
|
||||
|
||||
// render camera icon
|
||||
{
|
||||
const auto view = m_Registry.view<BoxColliderComponent>();
|
||||
for (const auto entity : view)
|
||||
const auto cameras = m_Registry.view<CameraComponent>();
|
||||
if (!cameras.empty())
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<BoxColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
for (auto& entity : cameras)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_CameraIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto view = m_Registry.view<SphereColliderComponent>();
|
||||
for (const auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<SphereColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto view = m_Registry.view<CapsuleColliderComponent>();
|
||||
for (const auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<CapsuleColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto view = m_Registry.view<MeshColliderComponent>();
|
||||
for (const auto entity : view)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
auto& collider = e.GetComponent<MeshColliderComponent>();
|
||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
||||
|
||||
if (m_SelectedEntity == entity)
|
||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
||||
const auto lights = m_Registry.view<SkyLightComponent>();
|
||||
if (!lights.empty())
|
||||
{
|
||||
for (auto& entity : lights)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
SceneRenderer::EndScene();
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// RENDER 2D SCENE //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = editorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
|
||||
// render sprite
|
||||
{
|
||||
const auto entitiesGroup = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
|
||||
for (const auto entity : entitiesGroup)
|
||||
{
|
||||
auto [transformComponent, spriteRendererComponent] = entitiesGroup.get<TransformComponent, SpriteRendererComponent>(entity);
|
||||
if (spriteRendererComponent.Texture)
|
||||
Renderer2D::DrawQuad(transformComponent.GetTransform(), spriteRendererComponent.Texture, spriteRendererComponent.TilingFactor, spriteRendererComponent.Color);
|
||||
else
|
||||
Renderer2D::DrawQuad(transformComponent.GetTransform(), spriteRendererComponent.Color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// render camera icon
|
||||
{
|
||||
const auto cameras = m_Registry.view<CameraComponent>();
|
||||
if (!cameras.empty())
|
||||
{
|
||||
for (auto& entity : cameras)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
Renderer2D::DrawBillBoardQuad(e.Transform().Translation, m_CameraIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
}
|
||||
}
|
||||
|
||||
const auto lights = m_Registry.view<SkyLightComponent>();
|
||||
if (!lights.empty())
|
||||
{
|
||||
for (auto& entity : lights)
|
||||
{
|
||||
Entity e = { entity, this };
|
||||
Renderer2D::DrawBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void Scene::OnEvent(Event& e)
|
||||
|
||||
@ -105,7 +105,7 @@ namespace Prism
|
||||
void SetPhysics2DGravity(float gravity);
|
||||
|
||||
// Editor-specific
|
||||
void SetSelectedEntity(entt::entity entity) { m_SelectedEntity = entity; }
|
||||
void SetSelectedEntity(const entt::entity entity) { m_SelectedEntity = entity; }
|
||||
|
||||
private:
|
||||
UUID m_SceneID;
|
||||
@ -143,6 +143,7 @@ namespace Prism
|
||||
|
||||
private:
|
||||
friend class Entity;
|
||||
friend class Renderer3D;
|
||||
friend class SceneRenderer;
|
||||
friend class SceneSerializer;
|
||||
friend class SceneHierarchyPanel;
|
||||
|
||||
Reference in New Issue
Block a user