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);
|
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)
|
if (!m_SelectionContext.empty() && false)
|
||||||
{
|
{
|
||||||
auto& selection = m_SelectionContext[0];
|
auto& selection = m_SelectionContext[0];
|
||||||
@ -530,10 +520,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UI::Property("Show Bounding Boxes", m_UIShowBoundingBoxes))
|
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);
|
|
||||||
|
|
||||||
const char* label = m_SelectionMode == SelectionMode::Entity ? "Entity" : "Mesh";
|
const char* label = m_SelectionMode == SelectionMode::Entity ? "Entity" : "Mesh";
|
||||||
if (ImGui::Button(label))
|
if (ImGui::Button(label))
|
||||||
@ -903,7 +890,7 @@ namespace Prism
|
|||||||
|
|
||||||
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
||||||
{
|
{
|
||||||
if (m_ViewportPanelFocused)
|
if (m_ViewportPanelFocused || m_ViewportPanelHovered)
|
||||||
{
|
{
|
||||||
switch (e.GetKeyCode())
|
switch (e.GetKeyCode())
|
||||||
{
|
{
|
||||||
@ -921,7 +908,7 @@ namespace Prism
|
|||||||
break;
|
break;
|
||||||
case KeyCode::F:
|
case KeyCode::F:
|
||||||
{
|
{
|
||||||
if (m_SelectionContext.size() == 0)
|
if (m_SelectionContext.empty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Entity selectedEntity = m_SelectionContext[0].Entity;
|
Entity selectedEntity = m_SelectionContext[0].Entity;
|
||||||
@ -964,7 +951,7 @@ namespace Prism
|
|||||||
case KeyCode::B:
|
case KeyCode::B:
|
||||||
// Toggle bounding boxes
|
// Toggle bounding boxes
|
||||||
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
||||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
ShowBoundingBoxes(m_UIShowBoundingBoxes,false);
|
||||||
break;
|
break;
|
||||||
case KeyCode::D:
|
case KeyCode::D:
|
||||||
if (m_SelectionContext.size())
|
if (m_SelectionContext.size())
|
||||||
@ -1053,7 +1040,21 @@ namespace Prism
|
|||||||
return a.Distance < b.Distance;
|
return a.Distance < b.Distance;
|
||||||
});
|
});
|
||||||
if (!m_SelectionContext.empty())
|
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]);
|
OnSelected(m_SelectionContext[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1062,7 +1063,6 @@ namespace Prism
|
|||||||
void EditorLayer::ShowBoundingBoxes(bool show, bool onTop)
|
void EditorLayer::ShowBoundingBoxes(bool show, bool onTop)
|
||||||
{
|
{
|
||||||
SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop;
|
SceneRenderer::GetOptions().ShowBoundingBoxes = show && !onTop;
|
||||||
m_DrawOnTopBoundingBoxes = show && onTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorLayer::SelectEntity(Entity entity)
|
void EditorLayer::SelectEntity(Entity entity)
|
||||||
|
|||||||
@ -138,10 +138,8 @@ namespace Prism
|
|||||||
|
|
||||||
// configure button
|
// configure button
|
||||||
bool m_AllowViewportCameraEvents = false;
|
bool m_AllowViewportCameraEvents = false;
|
||||||
bool m_DrawOnTopBoundingBoxes = false;
|
|
||||||
|
|
||||||
bool m_UIShowBoundingBoxes = false;
|
bool m_UIShowBoundingBoxes = false;
|
||||||
bool m_UIShowBoundingBoxesOnTop = false;
|
|
||||||
|
|
||||||
enum class SceneType : uint32_t
|
enum class SceneType : uint32_t
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,62 +1,23 @@
|
|||||||
Scene: Scene Name
|
Scene: Scene Name
|
||||||
Environment:
|
Environment:
|
||||||
AssetHandle: 1249421934001634765
|
AssetHandle: 17073147362577408906
|
||||||
Light:
|
Light:
|
||||||
Direction: [-0.314, -0.941, -0.209]
|
Direction: [-0.314, -0.941, -0.209]
|
||||||
Radiance: [0, 0, 0]
|
Radiance: [0, 0, 0]
|
||||||
Multiplier: 0
|
Multiplier: 1
|
||||||
Entities:
|
Entities:
|
||||||
- Entity: 18090260616187152572
|
- Entity: 3696833073589069488
|
||||||
Parent: 0
|
Parent: 0
|
||||||
Children:
|
Children:
|
||||||
[]
|
[]
|
||||||
TagComponent:
|
TagComponent:
|
||||||
Tag: Directional Light
|
Tag: venice_dawn_1_4k
|
||||||
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
|
|
||||||
TransformComponent:
|
TransformComponent:
|
||||||
Position: [0, 0, 0]
|
Position: [0, 0, 0]
|
||||||
Rotation: [0, 0, 0]
|
Rotation: [0, 0, 0]
|
||||||
Scale: [1, 1, 1]
|
Scale: [1, 1, 1]
|
||||||
SkyLightComponent:
|
SkyLightComponent:
|
||||||
EnvironmentMap: 1249421934001634765
|
EnvironmentMap: 17073147362577408906
|
||||||
Intensity: 1
|
Intensity: 1
|
||||||
Angle: 0
|
Angle: 0
|
||||||
PhysicsLayers:
|
PhysicsLayers:
|
||||||
|
|||||||
@ -58,11 +58,12 @@ void main()
|
|||||||
vs_Output.WorldTransform = mat3(u_Transform);
|
vs_Output.WorldTransform = mat3(u_Transform);
|
||||||
vs_Output.Binormal = a_Binormal;
|
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));
|
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
|
#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["scene"] = AssetType::Scene;
|
||||||
s_Types["pmx"] = AssetType::Mesh;
|
s_Types["pmx"] = AssetType::Mesh;
|
||||||
s_Types["fbx"] = AssetType::Mesh;
|
s_Types["fbx"] = AssetType::Mesh;
|
||||||
|
s_Types["dae"] = AssetType::Mesh;
|
||||||
s_Types["obj"] = AssetType::Mesh;
|
s_Types["obj"] = AssetType::Mesh;
|
||||||
s_Types["png"] = AssetType::Texture;
|
s_Types["png"] = AssetType::Texture;
|
||||||
s_Types["tga"] = AssetType::Texture;
|
s_Types["tga"] = AssetType::Texture;
|
||||||
|
|||||||
@ -50,10 +50,10 @@ namespace Prism
|
|||||||
|
|
||||||
if (Input::IsMouseButtonPressed(MouseButton::Right) && !altPressed)
|
if (Input::IsMouseButtonPressed(MouseButton::Right) && !altPressed)
|
||||||
{
|
{
|
||||||
Input::SetCursorMode(CursorMode::Disable);
|
|
||||||
|
|
||||||
if (!m_IsRightButtonDownState)
|
if (!m_IsRightButtonDownState)
|
||||||
{
|
{
|
||||||
|
Input::SetCursorMode(CursorMode::Disable);
|
||||||
m_InitialMousePosition = { Input::GetMouseX(), Input::GetMouseY() };
|
m_InitialMousePosition = { Input::GetMouseX(), Input::GetMouseY() };
|
||||||
m_IsRightButtonDownState = true;
|
m_IsRightButtonDownState = true;
|
||||||
m_FreeLookActive = true;
|
m_FreeLookActive = true;
|
||||||
@ -183,6 +183,7 @@ namespace Prism
|
|||||||
UI::Property("focus", m_FocalPoint);
|
UI::Property("focus", m_FocalPoint);
|
||||||
UI::Property("position", m_Position);
|
UI::Property("position", m_Position);
|
||||||
UI::Separator();
|
UI::Separator();
|
||||||
|
UI::Property("Max Speed", m_MaxSpeed);
|
||||||
UI::Property("Current Speed", m_Velocity);
|
UI::Property("Current Speed", m_Velocity);
|
||||||
UI::EndPropertyGrid();
|
UI::EndPropertyGrid();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
@ -198,10 +199,20 @@ namespace Prism
|
|||||||
m_ViewMatrix = glm::inverse(m_ViewMatrix);
|
m_ViewMatrix = glm::inverse(m_ViewMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorCamera::OnMouseScroll(MouseScrolledEvent& e)
|
bool EditorCamera::OnMouseScroll(const MouseScrolledEvent& e)
|
||||||
{
|
{
|
||||||
const float delta = e.GetOffsetY() * 0.1f;
|
const float delta = e.GetOffsetY();
|
||||||
MouseZoom(delta);
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ namespace Prism
|
|||||||
private:
|
private:
|
||||||
void UpdateCameraView();
|
void UpdateCameraView();
|
||||||
|
|
||||||
bool OnMouseScroll(MouseScrolledEvent& e);
|
bool OnMouseScroll(const MouseScrolledEvent& e);
|
||||||
void MousePan(const glm::vec2& delta);
|
void MousePan(const glm::vec2& delta);
|
||||||
void MouseRotate(const glm::vec2& delta);
|
void MouseRotate(const glm::vec2& delta);
|
||||||
void MouseZoom(float delta);
|
void MouseZoom(float delta);
|
||||||
|
|||||||
@ -139,6 +139,11 @@ namespace Prism
|
|||||||
m_SelectionContext = entity;
|
m_SelectionContext = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entity SceneHierarchyPanel::GetSelected() const
|
||||||
|
{
|
||||||
|
return m_SelectionContext;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void SceneHierarchyPanel::AddComponentPopup(const char* componentName)
|
void SceneHierarchyPanel::AddComponentPopup(const char* componentName)
|
||||||
{
|
{
|
||||||
@ -311,27 +316,6 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
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)
|
void SceneHierarchyPanel::DrawEntityNode(Entity entity)
|
||||||
@ -582,10 +566,43 @@ namespace Prism
|
|||||||
|
|
||||||
ImGui::SeparatorText("3D Component");
|
ImGui::SeparatorText("3D Component");
|
||||||
AddComponentPopup<MeshComponent>("Mesh");
|
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<RigidBodyComponent>("RigidBody");
|
||||||
AddComponentPopup<BoxColliderComponent>("BoxCollider");
|
AddComponentPopup<BoxColliderComponent>("BoxCollider", [&](BoxColliderComponent& component)
|
||||||
AddComponentPopup<SphereColliderComponent>("SphereCollider");
|
{
|
||||||
AddComponentPopup<CapsuleColliderComponent>("CapsuleCollider");
|
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)
|
AddComponentPopup<MeshColliderComponent>("MeshCollider", [&](MeshColliderComponent& component)
|
||||||
{
|
{
|
||||||
if (m_SelectionContext.HasComponent<MeshComponent>())
|
if (m_SelectionContext.HasComponent<MeshComponent>())
|
||||||
@ -636,9 +653,67 @@ namespace Prism
|
|||||||
|
|
||||||
UI::BeginPropertyGrid();
|
UI::BeginPropertyGrid();
|
||||||
UI::PropertyAssetReference("Mesh", meshComponent.Mesh, AssetType::Mesh);
|
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();
|
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) {
|
DrawComponent<CameraComponent>("Camera", entity, [](CameraComponent& cameraComponent) {
|
||||||
// Projection Type
|
// Projection Type
|
||||||
const char* projTypeStrings[] = { "Perspective", "Orthographic" };
|
const char* projTypeStrings[] = { "Perspective", "Orthographic" };
|
||||||
|
|||||||
@ -18,6 +18,7 @@ namespace Prism
|
|||||||
|
|
||||||
void SetContext(const Ref<Scene>& scene);
|
void SetContext(const Ref<Scene>& scene);
|
||||||
void SetSelected(Entity entity);
|
void SetSelected(Entity entity);
|
||||||
|
Entity GetSelected() const;
|
||||||
void SetSelectionChangedCallback(const std::function<void(Entity)>& func) { m_SelectionChangedCallback = func; }
|
void SetSelectionChangedCallback(const std::function<void(Entity)>& func) { m_SelectionChangedCallback = func; }
|
||||||
void SetEntityDeletedCallback(const std::function<void(Entity)>& func) { m_EntityDeletedCallback = func; }
|
void SetEntityDeletedCallback(const std::function<void(Entity)>& func) { m_EntityDeletedCallback = func; }
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#define CAMERA_H
|
#define CAMERA_H
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "Prism/Core/Ref.h"
|
||||||
#include "Prism/Core/TimeStep.h"
|
#include "Prism/Core/TimeStep.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
#include "assimp/LogStream.hpp"
|
#include "assimp/LogStream.hpp"
|
||||||
#include "assimp/postprocess.h"
|
#include "assimp/postprocess.h"
|
||||||
#include "assimp/scene.h"
|
#include "assimp/scene.h"
|
||||||
#include "glad/glad.h"
|
|
||||||
|
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -144,6 +143,23 @@ namespace Prism
|
|||||||
// Vertices
|
// Vertices
|
||||||
if (m_IsAnimated)
|
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++)
|
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
||||||
{
|
{
|
||||||
AnimatedVertex vertex;
|
AnimatedVertex vertex;
|
||||||
@ -169,7 +185,7 @@ namespace Prism
|
|||||||
|
|
||||||
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
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.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 };
|
vertex.Normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z };
|
||||||
|
|
||||||
@ -211,41 +227,31 @@ namespace Prism
|
|||||||
// Bones
|
// Bones
|
||||||
if (m_IsAnimated)
|
if (m_IsAnimated)
|
||||||
{
|
{
|
||||||
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = scene->mMeshes[m];
|
aiMesh* mesh = scene->mMeshes[m];
|
||||||
Submesh& submesh = m_Submeshes[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++)
|
// 从 Skeleton 获取骨骼索引
|
||||||
{
|
uint32_t boneIndex = m_Skeleton->GetBoneIndex(boneName);
|
||||||
aiBone* bone = mesh->mBones[i];
|
if (boneIndex == uint32_t(-1))
|
||||||
std::string boneName(bone->mName.data);
|
{
|
||||||
uint32_t boneIndex = 0;
|
PM_CORE_ERROR("Bone '{}' not found in skeleton!", boneName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_BoneMapping.find(boneName) == m_BoneMapping.end())
|
for (size_t j = 0; j < bone->mNumWeights; j++)
|
||||||
{
|
{
|
||||||
// Allocate an index for a new bone
|
uint32_t VertexID = submesh.BaseVertex + bone->mWeights[j].mVertexId;
|
||||||
boneIndex = m_BoneCount;
|
float Weight = bone->mWeights[j].mWeight;
|
||||||
m_BoneCount++;
|
m_AnimatedVertices[VertexID].AddBoneData(boneIndex, Weight);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Material
|
// Material
|
||||||
@ -541,6 +547,11 @@ namespace Prism
|
|||||||
|
|
||||||
void Mesh::OnUpdate(TimeStep deltaTime)
|
void Mesh::OnUpdate(TimeStep deltaTime)
|
||||||
{
|
{
|
||||||
|
if (m_AnimatorController)
|
||||||
|
{
|
||||||
|
m_AnimatorController->Update(deltaTime);
|
||||||
|
}
|
||||||
|
/*
|
||||||
if (m_IsAnimated)
|
if (m_IsAnimated)
|
||||||
{
|
{
|
||||||
if (m_AnimationPlaying)
|
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
|
// TODO: We only need to recalc bones if rendering has been requested at the current animation frame
|
||||||
BoneTransform(m_AnimationTime);
|
BoneTransform(m_AnimationTime);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -594,6 +606,7 @@ namespace Prism
|
|||||||
PM_MESH_LOG("------------------------------------------------------");
|
PM_MESH_LOG("------------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void Mesh::BoneTransform(float time)
|
void Mesh::BoneTransform(float time)
|
||||||
{
|
{
|
||||||
ReadNodeHierarchy(time, m_Scene->mRootNode, glm::mat4(1.0f));
|
ReadNodeHierarchy(time, m_Scene->mRootNode, glm::mat4(1.0f));
|
||||||
@ -642,6 +655,7 @@ namespace Prism
|
|||||||
result += "--";
|
result += "--";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void Mesh::TraverseNodes(const aiNode* node, const glm::mat4& parentTransform, uint32_t level)
|
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)
|
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < animation->mNumChannels; i++)
|
for (uint32_t i = 0; i < animation->mNumChannels; i++)
|
||||||
@ -779,4 +794,5 @@ namespace Prism
|
|||||||
auto aiVec = start + factor * delta;
|
auto aiVec = start + factor * delta;
|
||||||
return { aiVec.x, aiVec.y, aiVec.z };
|
return { aiVec.x, aiVec.y, aiVec.z };
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
#include "Prism/Core/TimeStep.h"
|
#include "Prism/Core/TimeStep.h"
|
||||||
#include "Prism/Core/Math/AABB.h"
|
#include "Prism/Core/Math/AABB.h"
|
||||||
#include "../Asset/Asset.h"
|
#include "../Asset/Asset.h"
|
||||||
|
#include "Prism/Animation/AnimatorController.h"
|
||||||
|
#include "Prism/Animation/Skeleton.h"
|
||||||
|
|
||||||
struct aiNode;
|
struct aiNode;
|
||||||
struct aiAnimation;
|
struct aiAnimation;
|
||||||
@ -58,12 +60,12 @@ namespace Prism
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(Index) == 3 * sizeof(uint32_t));
|
static_assert(sizeof(Index) == 3 * sizeof(uint32_t));
|
||||||
|
|
||||||
struct BoneInfo
|
struct MeshBoneInfo
|
||||||
{
|
{
|
||||||
glm::mat4 BoneOffset;
|
glm::mat4 BoneOffset;
|
||||||
glm::mat4 FinalTransformation;
|
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
|
struct VertexBoneData
|
||||||
@ -107,11 +109,9 @@ namespace Prism
|
|||||||
class PRISM_API Mesh : public Asset
|
class PRISM_API Mesh : public Asset
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
Mesh(const std::string& filename);
|
Mesh(const std::string& filename);
|
||||||
Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform);
|
Mesh(const std::vector<Vertex>& vertices, const std::vector<Index>& indices, const glm::mat4& transform);
|
||||||
~Mesh();
|
~Mesh() override;
|
||||||
|
|
||||||
void OnUpdate(TimeStep deltaTime);
|
void OnUpdate(TimeStep deltaTime);
|
||||||
void DumpVertexBuffer();
|
void DumpVertexBuffer();
|
||||||
@ -131,31 +131,26 @@ namespace Prism
|
|||||||
|
|
||||||
bool IsAnimated() const { return m_IsAnimated; }
|
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:
|
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);
|
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:
|
private:
|
||||||
std::vector<Submesh> m_Submeshes;
|
|
||||||
|
|
||||||
std::unique_ptr<Assimp::Importer> m_Importer;
|
std::unique_ptr<Assimp::Importer> m_Importer;
|
||||||
|
const aiScene* m_Scene;
|
||||||
|
|
||||||
glm::mat4 m_InverseTransform;
|
glm::mat4 m_InverseTransform;
|
||||||
|
|
||||||
uint32_t m_BoneCount = 0;
|
|
||||||
std::vector<BoneInfo> m_BoneInfo;
|
|
||||||
|
|
||||||
// Ref<VertexArray> m_VertexArray;
|
|
||||||
Ref<Pipeline> m_Pipeline;
|
Ref<Pipeline> m_Pipeline;
|
||||||
Ref<VertexBuffer> m_VertexBuffer;
|
Ref<VertexBuffer> m_VertexBuffer;
|
||||||
Ref<IndexBuffer> m_IndexBuffer;
|
Ref<IndexBuffer> m_IndexBuffer;
|
||||||
@ -164,9 +159,11 @@ namespace Prism
|
|||||||
std::vector<Vertex> m_StaticVertices;
|
std::vector<Vertex> m_StaticVertices;
|
||||||
std::vector<AnimatedVertex> m_AnimatedVertices;
|
std::vector<AnimatedVertex> m_AnimatedVertices;
|
||||||
std::vector<Index> m_Indices;
|
std::vector<Index> m_Indices;
|
||||||
std::unordered_map<std::string, uint32_t> m_BoneMapping;
|
std::vector<Submesh> m_Submeshes;
|
||||||
std::vector<glm::mat4> m_BoneTransforms;
|
|
||||||
const aiScene* m_Scene;
|
Ref<Skeleton> m_Skeleton;
|
||||||
|
Ref<AnimationController> m_AnimatorController;
|
||||||
|
|
||||||
|
|
||||||
// Material
|
// Material
|
||||||
Ref<Shader> m_MeshShader;
|
Ref<Shader> m_MeshShader;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
|
|
||||||
#include "Renderer2D.h"
|
#include "Renderer2D.h"
|
||||||
|
#include "Renderer3D.h"
|
||||||
#include "RendererAPI.h"
|
#include "RendererAPI.h"
|
||||||
#include "SceneRenderer.h"
|
#include "SceneRenderer.h"
|
||||||
#include "glad/glad.h"
|
#include "glad/glad.h"
|
||||||
@ -35,6 +36,7 @@ namespace Prism
|
|||||||
GetShaderLibrary()->Load("assets/shaders/PBRShader_Static.glsl");
|
GetShaderLibrary()->Load("assets/shaders/PBRShader_Static.glsl");
|
||||||
GetShaderLibrary()->Load("assets/shaders/PBRShader_Anim.glsl");
|
GetShaderLibrary()->Load("assets/shaders/PBRShader_Anim.glsl");
|
||||||
|
|
||||||
|
// this to Init 2D and 3D Renderer
|
||||||
SceneRenderer::Init();
|
SceneRenderer::Init();
|
||||||
|
|
||||||
// FullScreen Quad
|
// FullScreen Quad
|
||||||
@ -58,8 +60,6 @@ namespace Prism
|
|||||||
|
|
||||||
s_Data.m_FullscreenQuadVertexBuffer = VertexBuffer::Create(fullScreenQuadVertex, sizeof(fullScreenQuadVertex[0]) * sizeof(fullScreenQuadVertex));
|
s_Data.m_FullscreenQuadVertexBuffer = VertexBuffer::Create(fullScreenQuadVertex, sizeof(fullScreenQuadVertex[0]) * sizeof(fullScreenQuadVertex));
|
||||||
s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
|
s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
|
||||||
|
|
||||||
Renderer2D::Init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Clear()
|
void Renderer::Clear()
|
||||||
@ -192,10 +192,11 @@ namespace Prism
|
|||||||
|
|
||||||
if (mesh->m_IsAnimated)
|
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("]");
|
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);
|
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||||
@ -227,10 +228,11 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
if (mesh->m_IsAnimated)
|
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("]");
|
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);
|
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.CameraViewProj = viewProj;
|
||||||
s_Data.DepthTest = depthTest;
|
s_Data.DepthTest = depthTest;
|
||||||
|
|
||||||
s_Data.TextureShader->Bind();
|
|
||||||
s_Data.TextureShader->SetMat4("u_ViewProjection", viewProj);
|
|
||||||
|
|
||||||
s_Data.QuadIndexCount = 0;
|
s_Data.QuadIndexCount = 0;
|
||||||
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
|
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
|
||||||
|
|
||||||
@ -206,8 +203,10 @@ namespace Prism
|
|||||||
s_Data.TextureSlotIndex = 1;
|
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);
|
uint32_t dataSize = (uint32_t)((uint8_t*)s_Data.QuadVertexBufferPtr - (uint8_t*)s_Data.QuadVertexBufferBase);
|
||||||
if (dataSize)
|
if (dataSize)
|
||||||
{
|
{
|
||||||
@ -257,6 +256,7 @@ namespace Prism
|
|||||||
s_Data.Stats.DrawCalls++;
|
s_Data.Stats.DrawCalls++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renderPass) Renderer::EndRenderPass();
|
||||||
#if OLD
|
#if OLD
|
||||||
Flush();
|
Flush();
|
||||||
#endif
|
#endif
|
||||||
@ -614,6 +614,12 @@ namespace Prism
|
|||||||
s_Data.QuadIndexCount = 0;
|
s_Data.QuadIndexCount = 0;
|
||||||
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
|
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;
|
s_Data.TextureSlotIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "RenderPass.h"
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
@ -18,7 +19,7 @@ namespace Prism
|
|||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
|
||||||
static void BeginScene(const glm::mat4& viewProj, bool depthTest = true);
|
static void BeginScene(const glm::mat4& viewProj, bool depthTest = true);
|
||||||
static void EndScene();
|
static void EndScene(const Ref<RenderPass>& renderPass = nullptr);
|
||||||
static void Flush();
|
static void Flush();
|
||||||
|
|
||||||
// Primitives
|
// 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 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();
|
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 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 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 std::pair<Ref<TextureCube>, Ref<TextureCube>> CreateEnvironmentMap(const std::string& filepath);
|
||||||
|
|
||||||
static Ref<RenderPass> GetFinalRenderPass();
|
static Ref<RenderPass> GetFinalRenderPass();
|
||||||
|
static Ref<RenderPass> GetGeoPass();
|
||||||
static Ref<Texture2D> GetFinalColorBuffer();
|
static Ref<Texture2D> GetFinalColorBuffer();
|
||||||
|
|
||||||
static void SetFocusPoint(const glm::vec2& point);
|
static void SetFocusPoint(const glm::vec2& point);
|
||||||
|
|
||||||
// TODO: Temp
|
// TODO: Temp
|
||||||
static uint32_t GetFinalColorBufferRendererID();
|
static uint32_t GetFinalColorBufferRendererID();
|
||||||
|
|
||||||
static SceneRendererOptions& GetOptions();
|
static SceneRendererOptions& GetOptions();
|
||||||
|
|
||||||
static void OnImGuiRender();
|
static void OnImGuiRender();
|
||||||
private:
|
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 <glm/gtx/quaternion.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "Prism/Animation/Skeleton.h"
|
||||||
#include "Prism/Core/Math/Math.h"
|
#include "Prism/Core/Math/Math.h"
|
||||||
#include "Prism/Renderer/SceneEnvironment.h"
|
#include "Prism/Renderer/SceneEnvironment.h"
|
||||||
|
|
||||||
@ -99,6 +100,16 @@ namespace Prism
|
|||||||
operator Ref<Prism::Mesh> () { return Mesh; }
|
operator Ref<Prism::Mesh> () { return Mesh; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AnimationComponent
|
||||||
|
{
|
||||||
|
Ref<Skeleton> SkeletonAsset;
|
||||||
|
Ref<AnimationController> AnimationController;
|
||||||
|
|
||||||
|
AnimationComponent() = default;
|
||||||
|
AnimationComponent(const AnimationComponent&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ScriptComponent
|
struct ScriptComponent
|
||||||
{
|
{
|
||||||
|
|||||||
@ -36,6 +36,20 @@ namespace Prism
|
|||||||
return m_Scene->m_Registry.get<T>(m_EntityHandle);
|
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>
|
template<typename T>
|
||||||
bool HasComponent() const
|
bool HasComponent() const
|
||||||
{
|
{
|
||||||
@ -77,6 +91,7 @@ namespace Prism
|
|||||||
|
|
||||||
|
|
||||||
UUID GetUUID() { return GetComponent<IDComponent>().ID; }
|
UUID GetUUID() { return GetComponent<IDComponent>().ID; }
|
||||||
|
UUID GetUUID() const { return GetComponent<IDComponent>().ID; }
|
||||||
UUID GetSceneUUID() const { return m_Scene->GetUUID(); }
|
UUID GetSceneUUID() const { return m_Scene->GetUUID(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
#include "Prism/Core/Input.h"
|
#include "Prism/Core/Input.h"
|
||||||
#include "Prism/Core/Math/Math.h"
|
#include "Prism/Core/Math/Math.h"
|
||||||
#include "Prism/Renderer/Renderer.h"
|
#include "Prism/Renderer/Renderer.h"
|
||||||
#include "Prism/Renderer/Renderer2D.h"
|
|
||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
@ -233,18 +232,21 @@ namespace Prism
|
|||||||
|
|
||||||
void Scene::OnRenderRuntime(const TimeStep ts)
|
void Scene::OnRenderRuntime(const TimeStep ts)
|
||||||
{
|
{
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
// RENDER 3D SCENE //
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
Entity cameraEntity = GetMainCameraEntity();
|
Entity cameraEntity = GetMainCameraEntity();
|
||||||
if (!cameraEntity)
|
if (!cameraEntity)
|
||||||
return;
|
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!");
|
PM_CORE_ASSERT(cameraEntity, "Scene does not contain any cameras!");
|
||||||
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
SceneCamera& camera = cameraEntity.GetComponent<CameraComponent>();
|
||||||
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
camera.SetViewportSize(m_ViewportWidth, m_ViewportHeight);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// RENDER 3D SCENE //
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Process lights
|
// Process lights
|
||||||
{
|
{
|
||||||
m_LightEnvironment = LightEnvironment();
|
m_LightEnvironment = LightEnvironment();
|
||||||
@ -281,49 +283,45 @@ namespace Prism
|
|||||||
|
|
||||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
|
||||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix });
|
SceneRenderer::BeginScene(this, { static_cast<Camera>(camera), cameraViewMatrix });
|
||||||
for (auto entity : group)
|
|
||||||
{
|
{
|
||||||
const auto& [transformComponent, meshComponent] = group.get<TransformComponent, MeshComponent>(entity);
|
const auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
||||||
if (meshComponent.Mesh)
|
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)
|
// TODO: Should we render (logically)
|
||||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
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();
|
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)
|
void Scene::OnRenderEditor(const TimeStep ts, const EditorCamera& editorCamera)
|
||||||
@ -335,12 +333,12 @@ namespace Prism
|
|||||||
// Process lights
|
// Process lights
|
||||||
{
|
{
|
||||||
m_LightEnvironment = LightEnvironment();
|
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;
|
uint32_t directionalLightIndex = 0;
|
||||||
for (auto entity : lights)
|
for (const auto entity : lights)
|
||||||
{
|
{
|
||||||
auto [transformComponent, lightComponent] = lights.get<TransformComponent, DirectionalLightComponent>(entity);
|
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++] =
|
m_LightEnvironment.DirectionalLights[directionalLightIndex++] =
|
||||||
{
|
{
|
||||||
direction,
|
direction,
|
||||||
@ -353,148 +351,105 @@ namespace Prism
|
|||||||
|
|
||||||
// TODO: only one sky light at the moment!
|
// 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())
|
if (!lights.empty())
|
||||||
{
|
{
|
||||||
for (auto entity : lights)
|
for (const auto entity : lights)
|
||||||
{
|
{
|
||||||
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
|
auto [transformComponent, skyLightComponent] = lights.get<TransformComponent, SkyLightComponent>(entity);
|
||||||
m_Environment = skyLightComponent.SceneEnvironment;
|
m_Environment = skyLightComponent.SceneEnvironment;
|
||||||
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
m_EnvironmentIntensity = skyLightComponent.Intensity;
|
||||||
SetSkybox(m_Environment->RadianceMap);
|
SetSkybox(m_Environment->RadianceMap);
|
||||||
}
|
}
|
||||||
}else
|
|
||||||
{
|
|
||||||
// TODO:
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
m_SkyboxMaterial->Set("u_TextureLod", m_SkyboxLod);
|
||||||
|
|
||||||
auto group = m_Registry.group<MeshComponent>(entt::get<TransformComponent>);
|
// TODO: this value should be storage and can modify
|
||||||
SceneRenderer::BeginScene(this, { static_cast<Camera>(editorCamera), editorCamera.GetViewMatrix(), 0.1f, 1000.0f, 45.0f }); // TODO: real values
|
|
||||||
|
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);
|
for (const auto [entity, meshComponent, transformComponent]: group.each())
|
||||||
if (meshComponent.Mesh)
|
|
||||||
{
|
{
|
||||||
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)
|
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
|
else
|
||||||
SceneRenderer::SubmitMesh(meshComponent, transform);
|
SceneRenderer::SubmitQuad(transformComponent.GetTransform(), spriteRendererComponent.Color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render camera icon
|
||||||
{
|
{
|
||||||
const auto view = m_Registry.view<BoxColliderComponent>();
|
const auto cameras = m_Registry.view<CameraComponent>();
|
||||||
for (const auto entity : view)
|
if (!cameras.empty())
|
||||||
{
|
{
|
||||||
Entity e = { entity, this };
|
for (auto& entity : cameras)
|
||||||
auto& collider = e.GetComponent<BoxColliderComponent>();
|
{
|
||||||
glm::mat4 transform = GetTransformRelativeToParent(e);
|
Entity e = { entity, this };
|
||||||
|
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_CameraIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_SelectedEntity == entity)
|
const auto lights = m_Registry.view<SkyLightComponent>();
|
||||||
SceneRenderer::SubmitColliderMesh(collider, transform);
|
if (!lights.empty())
|
||||||
}
|
{
|
||||||
}
|
for (auto& entity : lights)
|
||||||
|
{
|
||||||
{
|
Entity e = { entity, this };
|
||||||
const auto view = m_Registry.view<SphereColliderComponent>();
|
SceneRenderer::SubmitBillBoardQuad(e.Transform().Translation, m_LightIcon, editorCamera.GetPosition(), editorCamera.GetUpDirection());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneRenderer::EndScene();
|
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)
|
void Scene::OnEvent(Event& e)
|
||||||
|
|||||||
@ -105,7 +105,7 @@ namespace Prism
|
|||||||
void SetPhysics2DGravity(float gravity);
|
void SetPhysics2DGravity(float gravity);
|
||||||
|
|
||||||
// Editor-specific
|
// Editor-specific
|
||||||
void SetSelectedEntity(entt::entity entity) { m_SelectedEntity = entity; }
|
void SetSelectedEntity(const entt::entity entity) { m_SelectedEntity = entity; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UUID m_SceneID;
|
UUID m_SceneID;
|
||||||
@ -143,6 +143,7 @@ namespace Prism
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Entity;
|
friend class Entity;
|
||||||
|
friend class Renderer3D;
|
||||||
friend class SceneRenderer;
|
friend class SceneRenderer;
|
||||||
friend class SceneSerializer;
|
friend class SceneSerializer;
|
||||||
friend class SceneHierarchyPanel;
|
friend class SceneHierarchyPanel;
|
||||||
|
|||||||
Reference in New Issue
Block a user