Somewhat working camera
This commit is contained in:
Vendored
+2
@@ -55,6 +55,7 @@
|
||||
"environment": [],
|
||||
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
||||
"requireExactSource": false,
|
||||
"visualizerFile": "${workspaceRoot}/Seele.natvis",
|
||||
"logging": {
|
||||
"moduleLoad": false,
|
||||
"exceptions": true,
|
||||
@@ -82,6 +83,7 @@
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole",
|
||||
"cwd": "${workspaceRoot}/bin/Debug",
|
||||
"visualizerFile": "${workspaceRoot}/Seele.natvis",
|
||||
"environment": [],
|
||||
},
|
||||
]
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="Seele::Map<*>">
|
||||
<DisplayString>{{size={_size}}</DisplayString>
|
||||
<DisplayString>{{ size={_size} }</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<Item Name="[comp]">comp</Item>
|
||||
|
||||
Vendored
+1
-1
Submodule external/slang updated: 858c7c57b1...c4790309ec
@@ -28,10 +28,10 @@ void computeFrustums(ComputeShaderInput in)
|
||||
|
||||
float4 screenSpace[4];
|
||||
|
||||
screenSpace[0] = float4(in.dispatchThreadID.xy * BLOCK_SIZE, 1.0f, 1.0f);
|
||||
screenSpace[1] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||
screenSpace[2] = float4(float2(in.dispatchThreadID.x, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||
screenSpace[3] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||
screenSpace[0] = float4(in.dispatchThreadID.xy * BLOCK_SIZE, -1.0f, 1.0f);
|
||||
screenSpace[1] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y) * BLOCK_SIZE, -1.0f, 1.0f);
|
||||
screenSpace[2] = float4(float2(in.dispatchThreadID.x, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f);
|
||||
screenSpace[3] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, -1.0f, 1.0f);
|
||||
|
||||
//Convert to viewSpace
|
||||
float3 viewSpace[4];
|
||||
@@ -44,10 +44,10 @@ void computeFrustums(ComputeShaderInput in)
|
||||
//Compute frustum
|
||||
Frustum frustum;
|
||||
|
||||
frustum.planes[0] = computePlane(eyePos, viewSpace[0], viewSpace[2]);
|
||||
frustum.planes[1] = computePlane(eyePos, viewSpace[3], viewSpace[1]);
|
||||
frustum.planes[2] = computePlane(eyePos, viewSpace[1], viewSpace[0]);
|
||||
frustum.planes[3] = computePlane(eyePos, viewSpace[2], viewSpace[3]);
|
||||
frustum.planes[0] = computePlane(eyePos, viewSpace[2], viewSpace[0]);
|
||||
frustum.planes[1] = computePlane(eyePos, viewSpace[1], viewSpace[3]);
|
||||
frustum.planes[2] = computePlane(eyePos, viewSpace[0], viewSpace[1]);
|
||||
frustum.planes[3] = computePlane(eyePos, viewSpace[3], viewSpace[2]);
|
||||
|
||||
if(in.dispatchThreadID.x < numThreads.x && in.dispatchThreadID.y < numThreads.y)
|
||||
{
|
||||
|
||||
@@ -32,9 +32,9 @@ VertexStageOutput vertexMain(
|
||||
float4 clipSpacePosition;
|
||||
|
||||
float3x3 tangentToLocal = cache.getTangentToLocal();
|
||||
MaterialVertexParameter vertexParams = input.getMaterialVertexParameters(cache, worldPosition, tangentToLocal);
|
||||
|
||||
float4 viewSpacePosition = mul(gViewParams.viewMatrix, float4(worldPosition, 1));
|
||||
MaterialVertexParameter vertexParams = input.getMaterialVertexParameters(cache, worldPosition, viewSpacePosition.xyz, tangentToLocal);
|
||||
|
||||
clipSpacePosition = mul(gViewParams.projectionMatrix, viewSpacePosition);
|
||||
output.position = clipSpacePosition;
|
||||
output.shaderAttributeInterpolation = input.getInterpolants(cache, vertexParams);
|
||||
@@ -66,12 +66,13 @@ float4 fragmentMain(
|
||||
uint startOffset = gridValue.x;
|
||||
uint lightCount = gridValue.y;
|
||||
|
||||
for (int j = 0; j < lightCount; ++j)
|
||||
for (int j = 0; j < numPointLights; ++j)
|
||||
{
|
||||
uint lightIndex = lightIndexList[startOffset + j];
|
||||
PointLight pointLight = pointLights[lightIndex];
|
||||
//uint lightIndex = lightIndexList[startOffset + j];
|
||||
PointLight pointLight = pointLights[j];
|
||||
if(pointLight.colorRange.w < length(pointLight.getViewPos() - input.viewPosition)) continue;
|
||||
result += pointLight.illuminate(materialParams, brdf, viewDir);
|
||||
}
|
||||
return float4(result, 0.1f);
|
||||
return float4(result, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,18 +4,18 @@ import Common;
|
||||
|
||||
interface ILightEnv
|
||||
{
|
||||
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo);
|
||||
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo);
|
||||
};
|
||||
|
||||
struct DirectionalLight : ILightEnv
|
||||
{
|
||||
float4 color;
|
||||
float4 direction;
|
||||
float4 intensity;
|
||||
float4 color;
|
||||
float4 direction;
|
||||
float4 intensity;
|
||||
|
||||
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 wo)
|
||||
{
|
||||
return intensity.xyz * brdf.evaluate(wo, normalize(direction.xyz), input.worldNormal, input.worldTangent, input.worldBiTangent, color.xyz);
|
||||
{
|
||||
return intensity.xyz * brdf.evaluate(wo, normalize(direction.xyz), input.worldNormal, input.worldTangent, input.worldBiTangent, color.xyz);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,40 +25,40 @@ struct PointLight : ILightEnv
|
||||
float4 colorRange;
|
||||
|
||||
float3 illuminate<B:IBRDF>(MaterialFragmentParameter input, B brdf, float3 viewDir)
|
||||
{
|
||||
{
|
||||
float3 lightVec = positionWS.xyz - input.worldPosition;
|
||||
float d = length(lightVec);
|
||||
float3 direction = normalize(lightVec);
|
||||
float illuminance = max(1 - d / colorRange.w, 0);
|
||||
return illuminance * brdf.evaluate(viewDir, direction, input.worldNormal, input.worldTangent, input.worldBiTangent, colorRange.xyz);
|
||||
return illuminance * brdf.evaluate(viewDir, direction, input.worldNormal, input.worldTangent, input.worldBiTangent, colorRange.xyz);
|
||||
}
|
||||
|
||||
bool insidePlane(Plane plane)
|
||||
{
|
||||
bool insidePlane(Plane plane)
|
||||
{
|
||||
return dot(plane.n, getViewPos().xyz) - plane.d < -colorRange.w;
|
||||
}
|
||||
}
|
||||
|
||||
bool insideFrustum(Frustum frustum, float zNear, float zFar)
|
||||
{
|
||||
bool insideFrustum(Frustum frustum, float zNear, float zFar)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if(getViewPos().z - colorRange.w > zNear || getViewPos().z + colorRange.w < zFar)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
for(int i = 0; i < 4 && result; ++i)
|
||||
{
|
||||
if(insidePlane(frustum.planes[i]))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
float3 getViewPos()
|
||||
{
|
||||
return mul(gViewParams.viewMatrix, positionWS).xyz;
|
||||
}
|
||||
if(getViewPos().z - colorRange.w > zNear || getViewPos().z + colorRange.w < zFar)
|
||||
{
|
||||
//result = false;
|
||||
}
|
||||
for(int i = 0; i < 4 && result; ++i)
|
||||
{
|
||||
if(insidePlane(frustum.planes[i]))
|
||||
{
|
||||
//result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
float3 getViewPos()
|
||||
{
|
||||
return mul(gViewParams.viewMatrix, positionWS).xyz;
|
||||
}
|
||||
};
|
||||
|
||||
layout(set = INDEX_LIGHT_ENV, binding = 0, std430)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
struct MaterialVertexParameter
|
||||
{
|
||||
float3 worldPosition;
|
||||
float3 viewPosition;
|
||||
float3x3 tangentToWorld;
|
||||
#if NUM_MATERIAL_TEXCOORDS
|
||||
float2 texCoords[NUM_MATERIAL_TEXCOORDS];
|
||||
|
||||
@@ -45,6 +45,7 @@ struct VertexValueCache
|
||||
struct ShaderAttributeInterpolation
|
||||
{
|
||||
float3 worldPosition;
|
||||
float3 viewPosition;
|
||||
float3 normal;
|
||||
float3 tangent;
|
||||
float3 biTangent;
|
||||
@@ -158,10 +159,11 @@ struct VertexShaderInput
|
||||
return cache;
|
||||
}
|
||||
|
||||
MaterialVertexParameter getMaterialVertexParameters(VertexValueCache cache, float3 worldPosition, float3x3 tangentToLocal)
|
||||
MaterialVertexParameter getMaterialVertexParameters(VertexValueCache cache, float3 worldPosition, float3 viewPosition, float3x3 tangentToLocal)
|
||||
{
|
||||
MaterialVertexParameter result;
|
||||
result.worldPosition = worldPosition;
|
||||
result.viewPosition = viewPosition;
|
||||
result.vertexColor = cache.color;
|
||||
result.tangentToWorld = cache.getTangentToWorld();
|
||||
// TODO instancing
|
||||
@@ -186,6 +188,7 @@ struct VertexShaderInput
|
||||
result.biTangent = mul(gSceneData.localToWorld, float4(biTangent, 0.0f)).xyz;
|
||||
result.color = color;
|
||||
result.worldPosition = vertexParams.worldPosition;
|
||||
result.viewPosition = vertexParams.viewPosition;
|
||||
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
|
||||
{
|
||||
if(i % 2)
|
||||
|
||||
@@ -27,7 +27,8 @@ void AssetRegistry::importFile(const std::string &filePath)
|
||||
std::filesystem::path fsPath = std::filesystem::path(filePath);
|
||||
std::string extension = fsPath.extension().string();
|
||||
if (extension.compare(".fbx") == 0
|
||||
|| extension.compare(".obj") == 0)
|
||||
|| extension.compare(".obj") == 0
|
||||
|| extension.compare(".blend") == 0)
|
||||
{
|
||||
get().importMesh(fsPath);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
template<typename A>
|
||||
concept iterable = requires(A&& a)
|
||||
{
|
||||
a.begin(); a.end();
|
||||
};
|
||||
template<class F, class... Args>
|
||||
concept invocable = std::invocable<F, Args...>;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ enum class InputAction
|
||||
REPEAT = 2
|
||||
};
|
||||
|
||||
enum class KeyModifier
|
||||
enum class KeyModifier : uint32
|
||||
{
|
||||
MOD_SHIFT = 0x0001,
|
||||
MOD_CONTROL = 0x0002,
|
||||
|
||||
@@ -20,7 +20,7 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
Job BasePassMeshProcessor::processMeshBatch(
|
||||
MainJob BasePassMeshProcessor::processMeshBatch(
|
||||
const MeshBatch& batch,
|
||||
// const PPrimitiveComponent primitiveComponent,
|
||||
const Gfx::PRenderPass& renderPass,
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass);
|
||||
virtual ~BasePassMeshProcessor();
|
||||
|
||||
virtual Job processMeshBatch(
|
||||
virtual MainJob processMeshBatch(
|
||||
const MeshBatch& batch,
|
||||
// const PPrimitiveComponent primitiveComponent,
|
||||
const Gfx::PRenderPass& renderPass,
|
||||
|
||||
@@ -18,7 +18,7 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
Job DepthPrepassMeshProcessor::processMeshBatch(
|
||||
MainJob DepthPrepassMeshProcessor::processMeshBatch(
|
||||
const MeshBatch& batch,
|
||||
// const PPrimitiveComponent primitiveComponent,
|
||||
const Gfx::PRenderPass& renderPass,
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics);
|
||||
virtual ~DepthPrepassMeshProcessor();
|
||||
|
||||
virtual Job processMeshBatch(
|
||||
virtual MainJob processMeshBatch(
|
||||
const MeshBatch& batch,
|
||||
const Gfx::PRenderPass& renderPass,
|
||||
Gfx::PPipelineLayout pipelineLayout,
|
||||
|
||||
@@ -98,7 +98,7 @@ MainJob LightCullingPass::render()
|
||||
computeCommand->bindPipeline(cullingPipeline);
|
||||
Array<Gfx::PDescriptorSet> descriptorSets = {cullingDescriptorSet, lightEnvDescriptorSet};
|
||||
computeCommand->bindDescriptor(descriptorSets);
|
||||
computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
|
||||
//computeCommand->dispatch(dispatchParams.numThreadGroups.x, dispatchParams.numThreadGroups.y, dispatchParams.numThreadGroups.z);
|
||||
Array<Gfx::PComputeCommand> commands = {computeCommand};
|
||||
graphics->executeCommands(commands);
|
||||
depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
protected:
|
||||
PScene scene;
|
||||
Gfx::PGraphics graphics;
|
||||
virtual Job processMeshBatch(
|
||||
virtual MainJob processMeshBatch(
|
||||
const MeshBatch& batch,
|
||||
// const PPrimitiveComponent primitiveComponent,
|
||||
const Gfx::PRenderPass& renderPass,
|
||||
|
||||
@@ -81,7 +81,7 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
|
||||
assert(state == State::RenderPassActive);
|
||||
if(commands.size() == 0)
|
||||
{
|
||||
std::cout << "No commands provided" << std::endl;
|
||||
//std::cout << "No commands provided" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock(handleLock);
|
||||
|
||||
@@ -106,11 +106,10 @@ void MaterialAsset::load()
|
||||
std::string defaultString = defaultValue.value().get<std::string>();
|
||||
p->data = AssetRegistry::findTexture(defaultString);
|
||||
}
|
||||
else
|
||||
if(p->data == nullptr)
|
||||
{
|
||||
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
|
||||
}
|
||||
assert(p->data != nullptr);
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("SamplerState") == 0)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
using namespace Seele;
|
||||
|
||||
Transform::Transform()
|
||||
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
|
||||
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ Transform::Transform(Transform &&other)
|
||||
: position(other.position), rotation(other.rotation), scale(other.scale)
|
||||
{
|
||||
other.position = Vector4(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(1, 0, 0, 0);
|
||||
other.scale = Vector4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ Transform::Transform(const Transform &other)
|
||||
}
|
||||
|
||||
Transform::Transform(Vector position)
|
||||
: position(Vector4(position, 0)), rotation(Quaternion(0, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
|
||||
: position(Vector4(position, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
|
||||
{
|
||||
}
|
||||
Transform::Transform(Vector position, Quaternion rotation)
|
||||
@@ -144,6 +144,19 @@ Vector Transform::getScale() const
|
||||
return Vector(scale);
|
||||
}
|
||||
|
||||
Vector Transform::getForward() const
|
||||
{
|
||||
return Vector(0, 0, 1) * rotation;
|
||||
}
|
||||
Vector Transform::getRight() const
|
||||
{
|
||||
return Vector(1, 0, 0) * rotation;
|
||||
}
|
||||
Vector Transform::getUp() const
|
||||
{
|
||||
return Vector(0, 1, 0) * rotation;
|
||||
}
|
||||
|
||||
bool Transform::equals(const Transform &other, float tolerance)
|
||||
{
|
||||
if (abs(position - other.position).length() > tolerance)
|
||||
@@ -174,6 +187,13 @@ void Transform::multiply(Transform *outTransform, const Transform *a, const Tran
|
||||
outTransform->position = b->rotation * (b->scale * a->position) + b->position;
|
||||
outTransform->scale = b->scale * a->scale;
|
||||
}
|
||||
void Transform::add(Transform *outTransform, const Transform *a, const Transform *b)
|
||||
{
|
||||
outTransform->position = a->position + b->position;
|
||||
outTransform->rotation = a->rotation + b->rotation;
|
||||
outTransform->scale = a->scale + b->scale;
|
||||
}
|
||||
|
||||
|
||||
Transform &Transform::operator=(const Transform &other)
|
||||
{
|
||||
@@ -189,11 +209,18 @@ Transform &Transform::operator=(Transform &&other)
|
||||
rotation = other.rotation;
|
||||
scale = other.scale;
|
||||
other.position = Vector4(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(0, 0, 0, 0);
|
||||
other.rotation = Quaternion(1, 0, 0, 0);
|
||||
other.scale = Vector4(0, 0, 0, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Transform Transform::operator+(const Transform & other) const
|
||||
{
|
||||
Transform outTransform;
|
||||
add(&outTransform, this, &other);
|
||||
return outTransform;
|
||||
}
|
||||
|
||||
Transform Transform::operator*(const Transform &other) const
|
||||
{
|
||||
Transform outTransform;
|
||||
|
||||
@@ -23,12 +23,17 @@ public:
|
||||
Vector getPosition() const;
|
||||
Quaternion getRotation() const;
|
||||
Vector getScale() const;
|
||||
Vector getForward() const;
|
||||
Vector getRight() const;
|
||||
Vector getUp() const;
|
||||
|
||||
bool equals(const Transform &other, float tolerance = 0.000000001f);
|
||||
static void multiply(Transform *outTransform, const Transform *a, const Transform *b);
|
||||
static void add(Transform *outTransform, const Transform *a, const Transform *b);
|
||||
|
||||
Transform &operator=(const Transform &other);
|
||||
Transform &operator=(Transform &&other);
|
||||
Transform operator+(const Transform& other) const;
|
||||
Transform operator*(const Transform &other) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -64,30 +64,6 @@ static inline float normalizeRotatorAxis(float angle)
|
||||
return angle;
|
||||
}
|
||||
|
||||
static inline Quaternion toQuaternion(const Vector &other)
|
||||
{
|
||||
Quaternion result;
|
||||
const float DEG_TO_RAD = glm::pi<float>() / (180.f);
|
||||
const float RADS_DIVIDED_BY_2 = DEG_TO_RAD / 2.f;
|
||||
|
||||
const float PitchNoWinding = fmod(other.x, 360.0f);
|
||||
const float YawNoWinding = fmod(other.y, 360.0f);
|
||||
const float RollNoWinding = fmod(other.z, 360.0f);
|
||||
|
||||
const float SP = sin(PitchNoWinding * RADS_DIVIDED_BY_2);
|
||||
const float SY = sin(YawNoWinding * RADS_DIVIDED_BY_2);
|
||||
const float SR = sin(RollNoWinding * RADS_DIVIDED_BY_2);
|
||||
|
||||
const float CP = cos(PitchNoWinding * RADS_DIVIDED_BY_2);
|
||||
const float CY = cos(YawNoWinding * RADS_DIVIDED_BY_2);
|
||||
const float CR = cos(RollNoWinding * RADS_DIVIDED_BY_2);
|
||||
|
||||
result.x = CR * SP * SY - SR * CP * CY;
|
||||
result.y = -CR * SP * CY - SR * CP * SY;
|
||||
result.z = CR * CP * SY - SR * SP * CY;
|
||||
result.w = CR * CP * CY + SR * SP * SY;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline Vector toRotator(const Quaternion &other)
|
||||
{
|
||||
|
||||
@@ -74,23 +74,23 @@ void Actor::detachChild(PActor child)
|
||||
child->setParent(nullptr);
|
||||
child->notifySceneAttach(nullptr);
|
||||
}
|
||||
void Actor::setWorldLocation(Vector location)
|
||||
{
|
||||
rootComponent->setWorldLocation(location);
|
||||
}
|
||||
|
||||
void Actor::setWorldRotation(Quaternion rotation)
|
||||
{
|
||||
rootComponent->setWorldRotation(rotation);
|
||||
}
|
||||
void Actor::setWorldRotation(Vector rotation)
|
||||
{
|
||||
rootComponent->setWorldRotation(rotation);
|
||||
}
|
||||
void Actor::setWorldScale(Vector scale)
|
||||
{
|
||||
rootComponent->setWorldScale(scale);
|
||||
}
|
||||
//void Actor::setAbsoluteLocation(Vector location)
|
||||
//{
|
||||
// rootComponent->setWorldLocation(location);
|
||||
//}
|
||||
//
|
||||
//void Actor::setAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// rootComponent->setAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::setAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// rootComponent->setAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::setWorldScale(Vector scale)
|
||||
//{
|
||||
// rootComponent->setWorldScale(scale);
|
||||
//}
|
||||
void Actor::setRelativeLocation(Vector location)
|
||||
{
|
||||
rootComponent->setRelativeLocation(location);
|
||||
@@ -107,17 +107,29 @@ void Actor::setRelativeScale(Vector scale)
|
||||
{
|
||||
rootComponent->setRelativeScale(scale);
|
||||
}
|
||||
void Actor::addWorldTranslation(Vector translation)
|
||||
//void Actor::addAbsoluteTranslation(Vector translation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteTranslation(translation);
|
||||
//}
|
||||
//void Actor::addAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteRotation(rotation);
|
||||
//}
|
||||
//void Actor::addAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// rootComponent->addAbsoluteRotation(rotation);
|
||||
//}
|
||||
void Actor::addRelativeLocation(Vector translation)
|
||||
{
|
||||
rootComponent->addWorldTranslation(translation);
|
||||
rootComponent->addRelativeLocation(translation);
|
||||
}
|
||||
void Actor::addWorldRotation(Quaternion rotation)
|
||||
void Actor::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
rootComponent->addWorldRotation(rotation);
|
||||
rootComponent->addRelativeRotation(rotation);
|
||||
}
|
||||
void Actor::addWorldRotation(Vector rotation)
|
||||
void Actor::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
rootComponent->addWorldRotation(rotation);
|
||||
rootComponent->addRelativeRotation(rotation);
|
||||
}
|
||||
PComponent Actor::getRootComponent()
|
||||
{
|
||||
|
||||
@@ -26,19 +26,23 @@ public:
|
||||
void addChild(PActor child);
|
||||
void detachChild(PActor child);
|
||||
Array<PActor> getChildren();
|
||||
void setWorldLocation(Vector location);
|
||||
void setWorldRotation(Quaternion rotation);
|
||||
void setWorldRotation(Vector rotation);
|
||||
void setWorldScale(Vector scale);
|
||||
//void setAbsoluteLocation(Vector location);
|
||||
//void setAbsoluteRotation(Quaternion rotation);
|
||||
//void setAbsoluteRotation(Vector rotation);
|
||||
//void setWorldScale(Vector scale);
|
||||
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
void addWorldTranslation(Vector translation);
|
||||
void addWorldRotation(Quaternion rotation);
|
||||
void addWorldRotation(Vector rotation);
|
||||
//void addAbsoluteTranslation(Vector translation);
|
||||
//void addAbsoluteRotation(Quaternion rotation);
|
||||
//void addAbsoluteRotation(Vector rotation);
|
||||
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
|
||||
PComponent getRootComponent();
|
||||
void setRootComponent(PComponent newRoot);
|
||||
|
||||
@@ -14,8 +14,6 @@ CameraActor::CameraActor()
|
||||
cameraComponent->aspectRatio = 1.777778f;
|
||||
cameraComponent->setParent(sceneComponent);
|
||||
cameraComponent->setOwner(this);
|
||||
addWorldTranslation(Vector(0, 0, 50));
|
||||
addWorldRotation(Vector(0, -100, 0));
|
||||
}
|
||||
|
||||
CameraActor::~CameraActor()
|
||||
|
||||
@@ -6,19 +6,16 @@
|
||||
using namespace Seele;
|
||||
|
||||
CameraComponent::CameraComponent()
|
||||
: aspectRatio(0)
|
||||
, fieldOfView(0)
|
||||
: aspectRatio(0)
|
||||
, fieldOfView(0)
|
||||
, bNeedsViewBuild(true)
|
||||
, bNeedsProjectionBuild(true)
|
||||
, originPoint(0, 0, 0)
|
||||
, cameraPosition(0, 0, 50)
|
||||
, eye(Vector())
|
||||
, projectionMatrix(Matrix4())
|
||||
, viewMatrix(Matrix4())
|
||||
, projectionMatrix(Matrix4())
|
||||
, viewMatrix(Matrix4())
|
||||
{
|
||||
distance = 50;
|
||||
rotationX = 0;
|
||||
rotationY = -1.f;
|
||||
rotationY = 0;
|
||||
setRelativeLocation(Vector(0, 10, -50));
|
||||
}
|
||||
|
||||
CameraComponent::~CameraComponent()
|
||||
@@ -27,54 +24,52 @@ CameraComponent::~CameraComponent()
|
||||
|
||||
void CameraComponent::mouseMove(float deltaX, float deltaY)
|
||||
{
|
||||
//0.01 mouse sensitivity
|
||||
rotationX += deltaX/500.f;
|
||||
rotationY += deltaY/500.f;
|
||||
rotationY = std::clamp(rotationY, -1.5f, 1.5f);
|
||||
getParent()->setWorldRotation(glm::rotate(glm::quat(), rotationX, Vector(0, 1, 0)));
|
||||
getParent()->setWorldRotation(glm::rotate(glm::quat(), rotationY, Vector(1, 0, 0)));
|
||||
bNeedsViewBuild = true;
|
||||
rotationX -= deltaX / 1000.f;
|
||||
rotationY += deltaY / 1000.f;
|
||||
//std::cout << "X:" << rotationX << " Y: " << rotationY << std::endl;
|
||||
setRelativeRotation(Vector(rotationY, rotationX, 0));
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::mouseScroll(double x)
|
||||
void CameraComponent::mouseScroll(float x)
|
||||
{
|
||||
distance -= static_cast<float>(x);
|
||||
distance = std::max(distance, 1.f);
|
||||
getParent()->addWorldTranslation(Vector(0, 0, x));
|
||||
bNeedsViewBuild = true;
|
||||
addRelativeLocation(getTransform().getForward()*x);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::moveOrigin(float up)
|
||||
void CameraComponent::moveX(float amount)
|
||||
{
|
||||
originPoint.y += up;
|
||||
getParent()->addWorldTranslation(Vector(0, up, 0));
|
||||
bNeedsViewBuild = true;
|
||||
addRelativeLocation(getTransform().getForward()*amount);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::moveY(float amount)
|
||||
{
|
||||
addRelativeLocation(getTransform().getRight()*amount);
|
||||
bNeedsViewBuild = true;
|
||||
}
|
||||
|
||||
void CameraComponent::buildViewMatrix()
|
||||
{
|
||||
Matrix4 rotation = glm::rotate(Matrix4(1.0f), rotationX, Vector(0, 1, 0));
|
||||
rotation = glm::rotate(rotation, rotationY, Vector(1, 0, 0));
|
||||
Vector4 translation(0, 0, distance, 1);
|
||||
translation = rotation * translation;
|
||||
Vector eyePos = getTransform().getPosition();
|
||||
Vector lookAt = eyePos + getTransform().getForward();
|
||||
std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
|
||||
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
||||
|
||||
cameraPosition = originPoint + Vector(translation);
|
||||
viewMatrix = glm::lookAt(cameraPosition, originPoint, Vector(0, 1, 0));
|
||||
|
||||
bNeedsViewBuild = false;
|
||||
bNeedsViewBuild = false;
|
||||
}
|
||||
|
||||
void CameraComponent::buildProjectionMatrix()
|
||||
{
|
||||
projectionMatrix = glm::perspective(fieldOfView, aspectRatio, 1.0f, 1000.f);
|
||||
static Matrix4 correctionMatrix =
|
||||
Matrix4(
|
||||
Vector4(1, 0, 0, 0),
|
||||
Vector4(0, 1, 0, 0),
|
||||
Vector4(0, 0, 0.5f, 0),
|
||||
Vector4(0, 0, 0.5f, 1));
|
||||
projectionMatrix = correctionMatrix * projectionMatrix;
|
||||
bNeedsProjectionBuild = false;
|
||||
static Matrix4 correctionMatrix =
|
||||
Matrix4(
|
||||
Vector4(1, 0, 0, 0),
|
||||
Vector4(0, 1, 0, 0),
|
||||
Vector4(0, 0, 0.5f, 0),
|
||||
Vector4(0, 0, 0.5f, 1));
|
||||
projectionMatrix = correctionMatrix * projectionMatrix;
|
||||
bNeedsProjectionBuild = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,51 +10,43 @@ public:
|
||||
CameraComponent();
|
||||
virtual ~CameraComponent();
|
||||
|
||||
Matrix4 getViewMatrix()
|
||||
{
|
||||
if (bNeedsViewBuild)
|
||||
{
|
||||
buildViewMatrix();
|
||||
}
|
||||
return viewMatrix;
|
||||
}
|
||||
Matrix4 getProjectionMatrix()
|
||||
{
|
||||
if (bNeedsProjectionBuild)
|
||||
{
|
||||
buildProjectionMatrix();
|
||||
}
|
||||
return projectionMatrix;
|
||||
}
|
||||
Vector getCameraPosition()
|
||||
{
|
||||
if(bNeedsViewBuild)
|
||||
{
|
||||
buildViewMatrix();
|
||||
}
|
||||
return cameraPosition;
|
||||
}
|
||||
void mouseMove(float deltaX, float deltaY);
|
||||
void mouseScroll(double x);
|
||||
void moveOrigin(float up);
|
||||
float aspectRatio;
|
||||
float fieldOfView;
|
||||
Matrix4 getViewMatrix()
|
||||
{
|
||||
if (bNeedsViewBuild)
|
||||
{
|
||||
buildViewMatrix();
|
||||
}
|
||||
return viewMatrix;
|
||||
}
|
||||
Matrix4 getProjectionMatrix()
|
||||
{
|
||||
if (bNeedsProjectionBuild)
|
||||
{
|
||||
buildProjectionMatrix();
|
||||
}
|
||||
return projectionMatrix;
|
||||
}
|
||||
Vector getCameraPosition()
|
||||
{
|
||||
return getTransform().getPosition();
|
||||
}
|
||||
void mouseMove(float deltaX, float deltaY);
|
||||
void mouseScroll(float x);
|
||||
void moveX(float amount);
|
||||
void moveY(float amount);
|
||||
float aspectRatio;
|
||||
float fieldOfView;
|
||||
private:
|
||||
bool bNeedsViewBuild;
|
||||
bool bNeedsProjectionBuild;
|
||||
void buildViewMatrix();
|
||||
void buildProjectionMatrix();
|
||||
bool bNeedsProjectionBuild;
|
||||
void buildViewMatrix();
|
||||
void buildProjectionMatrix();
|
||||
|
||||
float rotationX;
|
||||
float rotationY;
|
||||
float distance;
|
||||
|
||||
Vector eye;
|
||||
Vector originPoint;
|
||||
Vector cameraPosition;
|
||||
//Transforms relative to actor
|
||||
Matrix4 viewMatrix;
|
||||
Matrix4 projectionMatrix;
|
||||
//Transforms relative to actor
|
||||
Matrix4 viewMatrix;
|
||||
Matrix4 projectionMatrix;
|
||||
float rotationX;
|
||||
float rotationY;
|
||||
};
|
||||
DEFINE_REF(CameraComponent)
|
||||
} // namespace Seele
|
||||
|
||||
@@ -6,9 +6,6 @@ using namespace Seele;
|
||||
|
||||
Component::Component()
|
||||
{
|
||||
relativeLocation = Vector(0);
|
||||
relativeRotation = Vector(0);
|
||||
relativeScale = Vector(1, 1, 1);
|
||||
}
|
||||
Component::~Component()
|
||||
{
|
||||
@@ -89,162 +86,101 @@ void Component::notifySceneAttach(PScene scene)
|
||||
child->notifySceneAttach(scene);
|
||||
}
|
||||
}
|
||||
void Component::setWorldLocation(Vector location)
|
||||
{
|
||||
Vector newRelLocation = location;
|
||||
if (parent != nullptr)
|
||||
{
|
||||
Transform parentToWorld = getParent()->getTransform();
|
||||
newRelLocation = parentToWorld.inverseTransformPosition(location);
|
||||
}
|
||||
setRelativeLocation(newRelLocation);
|
||||
}
|
||||
void Component::setWorldRotation(Vector rotation)
|
||||
{
|
||||
Vector newRelRotator = rotation;
|
||||
if (parent == nullptr)
|
||||
{
|
||||
setRelativeRotation(rotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
setWorldRotation(toQuaternion(newRelRotator));
|
||||
}
|
||||
}
|
||||
void Component::setWorldRotation(Quaternion rotation)
|
||||
{
|
||||
Quaternion newRelRotation = getRelativeWorldRotation(rotation);
|
||||
setRelativeRotation(newRelRotation);
|
||||
}
|
||||
void Component::setWorldScale(Vector scale)
|
||||
{
|
||||
Vector newRelScale = scale;
|
||||
if (parent != nullptr)
|
||||
{
|
||||
Transform parentToWorld = parent->getTransform();
|
||||
newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
|
||||
}
|
||||
setRelativeScale(newRelScale);
|
||||
}
|
||||
|
||||
//void Component::setAbsoluteLocation(Vector location)
|
||||
//{
|
||||
// Vector newRelLocation = location;
|
||||
// if (parent != nullptr)
|
||||
// {
|
||||
// Transform parentToWorld = getParent()->getTransform();
|
||||
// newRelLocation = parentToWorld.inverseTransformPosition(location);
|
||||
// }
|
||||
// setRelativeLocation(newRelLocation);
|
||||
//}
|
||||
//void Component::setAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// Vector newRelRotator = rotation;
|
||||
// if (parent == nullptr)
|
||||
// {
|
||||
// setRelativeRotation(rotation);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// setAbsoluteRotation(toQuaternion(newRelRotator));
|
||||
// }
|
||||
//}
|
||||
//void Component::setAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// Quaternion newRelRotation = getRelativeWorldRotation(rotation);
|
||||
// setRelativeRotation(newRelRotation);
|
||||
//}
|
||||
//void Component::setWorldScale(Vector scale)
|
||||
//{
|
||||
// Vector newRelScale = scale;
|
||||
// if (parent != nullptr)
|
||||
// {
|
||||
// Transform parentToWorld = parent->getTransform();
|
||||
// newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
|
||||
// }
|
||||
// setRelativeScale(newRelScale);
|
||||
//}
|
||||
|
||||
void Component::setRelativeLocation(Vector location)
|
||||
{
|
||||
setRelativeLocationAndRotation(location, relativeRotation);
|
||||
transform = Transform(location, transform.getRotation(), transform.getScale());
|
||||
}
|
||||
void Component::setRelativeRotation(Vector rotation)
|
||||
{
|
||||
setRelativeLocationAndRotation(relativeLocation, toQuaternion(rotation));
|
||||
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
||||
}
|
||||
void Component::setRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
setRelativeLocationAndRotation(relativeLocation, rotation);
|
||||
transform = Transform(transform.getPosition(), rotation, transform.getScale());
|
||||
}
|
||||
void Component::setRelativeScale(Vector scale)
|
||||
{
|
||||
if (scale != relativeScale)
|
||||
{
|
||||
relativeScale = scale;
|
||||
updateComponentTransform(relativeRotation);
|
||||
}
|
||||
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||
}
|
||||
void Component::addWorldTranslation(Vector translation)
|
||||
|
||||
//void Component::addAbsoluteTranslation(Vector translation)
|
||||
//{
|
||||
// const Vector newWorldLocation = translation + getTransform().getPosition();
|
||||
// setAbsoluteLocation(newWorldLocation);
|
||||
//}
|
||||
//void Component::addAbsoluteRotation(Vector rotation)
|
||||
//{
|
||||
// const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
|
||||
// setAbsoluteRotation(newWorldRotation);
|
||||
//}
|
||||
//void Component::addAbsoluteRotation(Quaternion rotation)
|
||||
//{
|
||||
// const Quaternion newWorldRotation = rotation * getTransform().getRotation();
|
||||
// setAbsoluteRotation(newWorldRotation);
|
||||
//}
|
||||
|
||||
void Component::addRelativeLocation(Vector translation)
|
||||
{
|
||||
const Vector newWorldLocation = translation + getTransform().getPosition();
|
||||
setWorldLocation(newWorldLocation);
|
||||
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||
}
|
||||
void Component::addWorldRotation(Vector rotation)
|
||||
void Component::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
|
||||
setWorldRotation(newWorldRotation);
|
||||
transform = Transform(transform.getPosition(), transform.getRotation() + Quaternion(rotation), transform.getScale());
|
||||
}
|
||||
void Component::addWorldRotation(Quaternion rotation)
|
||||
void Component::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
const Quaternion newWorldRotation = rotation * getTransform().getRotation();
|
||||
setWorldRotation(newWorldRotation);
|
||||
transform = Transform(transform.getPosition(), transform.getRotation(), transform.getScale());
|
||||
}
|
||||
|
||||
Transform Component::getTransform() const
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
|
||||
void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
|
||||
Transform Component::getAbsoluteTransform() const
|
||||
{
|
||||
if (parent != nullptr)
|
||||
{
|
||||
Transform parentTransform = parent->getTransform();
|
||||
newLocation = parentTransform.inverseTransformPosition(newLocation);
|
||||
newRotation = glm::inverse(parentTransform.getRotation()) * newRotation;
|
||||
}
|
||||
|
||||
const Vector newRelRotation = toRotator(newRotation);
|
||||
if (newLocation != relativeLocation || newRelRotation != relativeLocation)
|
||||
{
|
||||
relativeLocation = newLocation;
|
||||
relativeRotation = newRelRotation;
|
||||
updateComponentTransform(newRelRotation);
|
||||
}
|
||||
}
|
||||
|
||||
void Component::propagateTransformUpdate()
|
||||
{
|
||||
for (auto child : children)
|
||||
{
|
||||
child->updateComponentTransform(child->relativeRotation);
|
||||
}
|
||||
}
|
||||
|
||||
void Component::updateComponentTransform(Quaternion relativeRotationQuat)
|
||||
{
|
||||
if (parent != nullptr && !parent->bComponentTransformClean)
|
||||
{
|
||||
parent->updateComponentTransform(parent->relativeRotation);
|
||||
|
||||
if (bComponentTransformClean)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
bComponentTransformClean = true;
|
||||
Transform newTransform;
|
||||
const Transform relTransform(relativeLocation, relativeRotationQuat, relativeScale);
|
||||
if(parent != nullptr)
|
||||
{
|
||||
newTransform = relTransform * parent->getTransform();
|
||||
return transform + parent->getAbsoluteTransform();
|
||||
}
|
||||
else
|
||||
{
|
||||
newTransform = relTransform;
|
||||
}
|
||||
bool bHasChanged = !getTransform().equals(newTransform);
|
||||
if (bHasChanged)
|
||||
{
|
||||
transform = newTransform;
|
||||
propagateTransformUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Quaternion Component::getRelativeWorldRotation(Quaternion worldRotation)
|
||||
{
|
||||
Quaternion newRelRotation = worldRotation;
|
||||
if (parent != nullptr)
|
||||
{
|
||||
const Transform parentToWorld = parent->getTransform();
|
||||
|
||||
const Quaternion parentToWorldQuat = parentToWorld.getRotation();
|
||||
const Quaternion newRelQuat = glm::inverse(parentToWorldQuat) * worldRotation;
|
||||
newRelRotation = newRelQuat;
|
||||
}
|
||||
return newRelRotation;
|
||||
}
|
||||
|
||||
void Component::setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation)
|
||||
{
|
||||
if (!bComponentTransformClean)
|
||||
{
|
||||
updateComponentTransform(toQuaternion(relativeRotation));
|
||||
}
|
||||
|
||||
const Transform desiredRelTransform(newLocation, newRotation);
|
||||
const Transform desiredWorldTransform = desiredRelTransform; // Check for absolutes etc
|
||||
|
||||
internalSetTransform(desiredWorldTransform.getPosition(), desiredWorldTransform.getRotation());
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
@@ -28,27 +28,33 @@ public:
|
||||
void addChildComponent(PComponent component);
|
||||
virtual void notifySceneAttach(PScene scene);
|
||||
|
||||
void setWorldLocation(Vector location);
|
||||
void setWorldRotation(Vector rotation);
|
||||
void setWorldRotation(Quaternion rotation);
|
||||
void setWorldScale(Vector scale);
|
||||
//void setAbsoluteLocation(Vector location);
|
||||
//void setAbsoluteRotation(Vector rotation);
|
||||
//void setAbsoluteRotation(Quaternion rotation);
|
||||
//void setWorldScale(Vector scale);
|
||||
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
void addWorldTranslation(Vector translation);
|
||||
void addWorldRotation(Vector rotation);
|
||||
void addWorldRotation(Quaternion rotation);
|
||||
//void addAbsoluteTranslation(Vector translation);
|
||||
//void addAbsoluteRotation(Vector rotation);
|
||||
//void addAbsoluteRotation(Quaternion rotation);
|
||||
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
|
||||
Transform getTransform() const;
|
||||
Transform getAbsoluteTransform() const;
|
||||
|
||||
template<typename ComponentType>
|
||||
RefPtr<ComponentType> getComponent()
|
||||
{
|
||||
return tryFindComponent<ComponentType>();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ComponentType>
|
||||
RefPtr<ComponentType> tryFindComponent()
|
||||
@@ -68,15 +74,6 @@ private:
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void internalSetTransform(Vector newLocation, Quaternion newRotation);
|
||||
void propagateTransformUpdate();
|
||||
void updateComponentTransform(Quaternion relativeRotationQuat);
|
||||
Quaternion getRelativeWorldRotation(Quaternion worldRotation);
|
||||
void setRelativeLocationAndRotation(Vector newLocation, Quaternion newRotation);
|
||||
uint8 bComponentTransformClean : 1;
|
||||
Vector relativeLocation;
|
||||
Vector relativeRotation;
|
||||
Vector relativeScale;
|
||||
Transform transform;
|
||||
PScene owningScene;
|
||||
PActor owner;
|
||||
|
||||
@@ -50,5 +50,5 @@ void PrimitiveComponent::notifySceneAttach(PScene scene)
|
||||
|
||||
Matrix4 PrimitiveComponent::getRenderMatrix()
|
||||
{
|
||||
return getTransform().toMatrix();
|
||||
return getAbsoluteTransform().toMatrix();
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ Scene::Scene(Gfx::PGraphics graphics)
|
||||
lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1);
|
||||
lightEnv.numDirectionalLights = 1;
|
||||
srand((unsigned int)time(NULL));
|
||||
for(uint32 i = 0; i < 256; ++i)
|
||||
for(uint32 i = 0; i < 16; ++i)
|
||||
{
|
||||
lightEnv.pointLights[i].colorRange = Vector4(frand(), frand(), frand(), frand() * 300);
|
||||
lightEnv.pointLights[i].positionWS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1);
|
||||
}
|
||||
lightEnv.numPointLights = 256;
|
||||
lightEnv.numPointLights = 16;
|
||||
lightEnv.pointLights[0].colorRange = Vector4(1, 0, 1, 1000);
|
||||
lightEnv.pointLights[0].positionWS = Vector4(0, 10, 0, 1);
|
||||
}
|
||||
@@ -41,19 +41,28 @@ void Scene::start()
|
||||
}
|
||||
}
|
||||
|
||||
static float lastUpdate;
|
||||
static uint64 numUpdates;
|
||||
|
||||
Job Scene::beginUpdate(double deltaTime)
|
||||
{
|
||||
//std::cout << "Scene::beginUpdate" << std::endl;
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
Array<Job> jobs;
|
||||
for(auto actor : rootActors)
|
||||
{
|
||||
jobs.addAll(actor->launchTick(static_cast<float>(deltaTime)));
|
||||
}
|
||||
co_await Job::all(jobs);
|
||||
//std::cout << "Scene::beginUpdate finished waiting" << std::endl;
|
||||
for(auto job : jobs)
|
||||
auto endTime = std::chrono::high_resolution_clock::now();
|
||||
float delta = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count();
|
||||
lastUpdate += delta;
|
||||
numUpdates++;
|
||||
if(lastUpdate > 1.0f)
|
||||
{
|
||||
assert(job.done());
|
||||
lastUpdate -= 1.0f;
|
||||
std::cout << numUpdates << " updates per second" << std::endl;
|
||||
numUpdates = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ struct DirectionalLight
|
||||
struct PointLight
|
||||
{
|
||||
Vector4 positionWS;
|
||||
//Vector4 positionVS;
|
||||
Vector4 colorRange;
|
||||
};
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
void update()
|
||||
{
|
||||
// lock should not be necessary, but lets keep it for now
|
||||
std::scoped_lock lock(dataLock);
|
||||
//std::scoped_lock lock(dataLock);
|
||||
data = toBeWritten;
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
+71
-65
@@ -3,7 +3,6 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
std::atomic_uint64_t Seele::globalCounter;
|
||||
|
||||
Event::Event()
|
||||
: flag(std::make_shared<StateStore>())
|
||||
@@ -16,11 +15,20 @@ Event::Event(nullptr_t)
|
||||
}
|
||||
|
||||
Event::Event(const std::string &name)
|
||||
: name(name)
|
||||
, flag(std::make_shared<StateStore>())
|
||||
: flag(std::make_shared<StateStore>())
|
||||
{
|
||||
flag->name = name;
|
||||
}
|
||||
|
||||
|
||||
Event::Event(const std::source_location &location)
|
||||
: flag(std::make_shared<StateStore>())
|
||||
{
|
||||
flag->name = location.function_name();
|
||||
flag->location = location;
|
||||
}
|
||||
|
||||
|
||||
void Event::raise()
|
||||
{
|
||||
std::scoped_lock lock(flag->lock);
|
||||
@@ -50,43 +58,34 @@ ThreadPool::ThreadPool(uint32 threadCount)
|
||||
running.store(true);
|
||||
for (uint32 i = 0; i < threadCount; ++i)
|
||||
{
|
||||
workers[i] = std::thread(&ThreadPool::threadLoop, this, false);
|
||||
workers[i] = std::thread(&ThreadPool::threadLoop, this);
|
||||
workers[i].detach();
|
||||
}
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
cleanup();
|
||||
workers.clear();
|
||||
}
|
||||
|
||||
void ThreadPool::cleanup()
|
||||
void ThreadPool::waitIdle()
|
||||
{
|
||||
bool temp = true;
|
||||
running.compare_exchange_strong(temp, false);
|
||||
if(!temp)
|
||||
return;
|
||||
while(true)
|
||||
{
|
||||
std::scoped_lock lock(jobQueueLock);
|
||||
jobQueueCV.notify_all();
|
||||
std::unique_lock lock(numIdlingLock);
|
||||
numIdlingIncr.wait(lock);
|
||||
if(numIdling == workers.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
std::scoped_lock lock(mainJobLock);
|
||||
mainJobCV.notify_all();
|
||||
}
|
||||
for (auto &thread : workers)
|
||||
{
|
||||
thread.join();
|
||||
}
|
||||
workers.clear();
|
||||
waitingJobs.clear();
|
||||
waitingMainJobs.clear();
|
||||
}
|
||||
void ThreadPool::enqueueWaiting(Event &event, Promise* job)
|
||||
{
|
||||
assert(!job->done());
|
||||
std::scoped_lock lock(waitingLock);
|
||||
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
|
||||
waitingJobs[event].push_back(job);
|
||||
waitingJobs[event].add(job);
|
||||
job->addRef();
|
||||
}
|
||||
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
|
||||
@@ -94,15 +93,15 @@ void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
|
||||
assert(!job->done());
|
||||
std::scoped_lock lock(waitingMainLock);
|
||||
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
|
||||
waitingMainJobs[event].push_back(job);
|
||||
waitingMainJobs[event].add(job);
|
||||
job->addRef();
|
||||
}
|
||||
void ThreadPool::scheduleJob(Promise* job)
|
||||
{
|
||||
assert(!job->done());
|
||||
std::scoped_lock lock(jobQueueLock);
|
||||
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
|
||||
jobQueue.push_back(job);
|
||||
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
|
||||
jobQueue.add(job);
|
||||
jobQueueCV.notify_one();
|
||||
job->addRef();
|
||||
}
|
||||
@@ -110,8 +109,8 @@ void ThreadPool::scheduleJob(MainPromise* job)
|
||||
{
|
||||
assert(!job->done());
|
||||
std::scoped_lock lock(mainJobLock);
|
||||
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
|
||||
mainJobs.push_back(job);
|
||||
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
|
||||
mainJobs.add(job);
|
||||
mainJobCV.notify_one();
|
||||
job->addRef();
|
||||
}
|
||||
@@ -120,79 +119,86 @@ void ThreadPool::notify(Event &event)
|
||||
//std::cout << "Event " << event.name << " raised" << std::endl;
|
||||
{
|
||||
std::scoped_lock lock(jobQueueLock, waitingLock);
|
||||
std::list<Promise*> jobs = std::move(waitingJobs[event]);
|
||||
List<Promise*> jobs = std::move(waitingJobs[event]);
|
||||
waitingJobs.erase(event);
|
||||
for (auto &job : jobs)
|
||||
{
|
||||
//assert(job.id != -1ull);
|
||||
//std::cout << "Waking up " << job->finishedEvent.name << std::endl;
|
||||
job->state = Promise::State::SCHEDULED;
|
||||
jobQueue.push_back(job);
|
||||
jobQueue.add(job);
|
||||
jobQueueCV.notify_one();
|
||||
}
|
||||
}
|
||||
{
|
||||
std::scoped_lock lock(mainJobLock, waitingMainLock);
|
||||
std::list<MainPromise*> jobs = std::move(waitingMainJobs[event]);
|
||||
List<MainPromise*> jobs = std::move(waitingMainJobs[event]);
|
||||
waitingMainJobs.erase(event);
|
||||
for (auto &job : jobs)
|
||||
{
|
||||
//assert(job.id != -1ull);
|
||||
//std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
|
||||
job->state = MainPromise::State::SCHEDULED;
|
||||
mainJobs.push_back(job);
|
||||
mainJobs.add(job);
|
||||
mainJobCV.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
void ThreadPool::threadLoop(const bool mainThread)
|
||||
|
||||
void ThreadPool::mainLoop()
|
||||
{
|
||||
while (running.load())
|
||||
while(true)
|
||||
{
|
||||
if (mainThread)
|
||||
MainPromise* job;
|
||||
{
|
||||
MainPromise* job;
|
||||
std::unique_lock lock(mainJobLock);
|
||||
if(mainJobs.empty())
|
||||
{
|
||||
std::unique_lock lock(mainJobLock);
|
||||
if(mainJobs.empty())
|
||||
{
|
||||
mainJobCV.wait(lock);
|
||||
}
|
||||
if (!mainJobs.empty())
|
||||
{
|
||||
job = mainJobs.front();
|
||||
mainJobs.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
mainJobCV.wait(lock);
|
||||
}
|
||||
job = mainJobs.front();
|
||||
mainJobs.popFront();
|
||||
}
|
||||
job->resume();
|
||||
job->removeRef();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::threadLoop()
|
||||
{
|
||||
List<Promise*> localQueue;
|
||||
while (true)
|
||||
{
|
||||
[[likely]]
|
||||
if(!localQueue.empty())
|
||||
{
|
||||
Promise* job = localQueue.retrieve();
|
||||
job->resume();
|
||||
job->removeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
Promise* job;
|
||||
std::unique_lock lock(jobQueueLock);
|
||||
if (jobQueue.empty())
|
||||
{
|
||||
std::unique_lock lock(jobQueueLock);
|
||||
if (jobQueue.empty())
|
||||
{
|
||||
jobQueueCV.wait(lock);
|
||||
std::unique_lock lock2(numIdlingLock);
|
||||
numIdling++;
|
||||
numIdlingIncr.notify_one();
|
||||
}
|
||||
if (!jobQueue.empty())
|
||||
jobQueueCV.wait(lock);
|
||||
{
|
||||
job = jobQueue.front();
|
||||
jobQueue.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
std::unique_lock lock2(numIdlingLock);
|
||||
numIdling--;
|
||||
}
|
||||
}
|
||||
//std::cout << "Starting job " << job.id << std::endl;
|
||||
job->resume();
|
||||
job->removeRef();
|
||||
// take 1/numThreads jobs, maybe make this a parameter that
|
||||
// adjusts based on past workload
|
||||
uint32 numTaken = std::max(jobQueue.size() / workers.size(), 1ull);
|
||||
while (!jobQueue.empty() && localQueue.size() < numTaken)
|
||||
{
|
||||
localQueue.add(jobQueue.retrieve());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+91
-41
@@ -17,6 +17,7 @@ public:
|
||||
Event();
|
||||
Event(nullptr_t);
|
||||
Event(const std::string& name);
|
||||
Event(const std::source_location& location);
|
||||
~Event() = default;
|
||||
auto operator<=>(const Event& other) const
|
||||
{
|
||||
@@ -36,6 +37,19 @@ public:
|
||||
return flag->data;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const Event& event)
|
||||
{
|
||||
stream
|
||||
<< event.flag->location.file_name()
|
||||
<< "("
|
||||
<< event.flag->location.line()
|
||||
<< ":"
|
||||
<< event.flag->location.column()
|
||||
<< "): "
|
||||
<< event.flag->location.function_name();
|
||||
return stream;
|
||||
}
|
||||
|
||||
void raise();
|
||||
void reset();
|
||||
bool await_ready();
|
||||
@@ -43,17 +57,17 @@ public:
|
||||
constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h);
|
||||
constexpr void await_resume() {}
|
||||
private:
|
||||
std::string name;
|
||||
struct StateStore
|
||||
{
|
||||
std::mutex lock;
|
||||
std::string name;
|
||||
std::source_location location;
|
||||
bool data;
|
||||
};
|
||||
std::shared_ptr<StateStore> flag;
|
||||
friend class ThreadPool;
|
||||
};
|
||||
|
||||
extern std::atomic_uint64_t globalCounter;
|
||||
template<bool MainJob>
|
||||
struct JobBase;
|
||||
template<bool MainJob>
|
||||
@@ -70,8 +84,7 @@ struct JobPromiseBase
|
||||
JobPromiseBase(const std::source_location& location = std::source_location::current())
|
||||
{
|
||||
handle = std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this);
|
||||
id = globalCounter++;
|
||||
finishedEvent = Event(std::string(location.file_name()).append(": ").append(location.function_name()));
|
||||
finishedEvent = Event(location);
|
||||
}
|
||||
~JobPromiseBase()
|
||||
{}
|
||||
@@ -81,9 +94,10 @@ struct JobPromiseBase
|
||||
inline auto final_suspend() noexcept;
|
||||
|
||||
void return_void() noexcept {}
|
||||
void unhandled_exception() noexcept {
|
||||
std::cerr << "Unhandled exception! Exiting" << std::endl;
|
||||
exit(1);
|
||||
void unhandled_exception() {
|
||||
std::exception_ptr exception = std::current_exception();
|
||||
std::cerr << "Unhandled exception!" << std::endl;
|
||||
throw exception;
|
||||
};
|
||||
|
||||
void resume()
|
||||
@@ -165,16 +179,22 @@ struct JobPromiseBase
|
||||
}
|
||||
void removeRef()
|
||||
{
|
||||
if(--numRefs < 1 && done())
|
||||
if(--numRefs < 1)
|
||||
{
|
||||
handle.destroy();
|
||||
}
|
||||
if(done())
|
||||
{
|
||||
handle.destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex promiseLock;
|
||||
std::coroutine_handle<JobPromiseBase> handle;
|
||||
JobPromiseBase* continuation = nullptr;
|
||||
uint64 id;
|
||||
std::atomic_uint64_t numRefs = 0;
|
||||
Event finishedEvent;
|
||||
State state = State::READY;
|
||||
@@ -210,7 +230,7 @@ public:
|
||||
{
|
||||
if(promise)
|
||||
{
|
||||
promise->schedule();
|
||||
//promise->schedule();
|
||||
promise->removeRef();
|
||||
}
|
||||
}
|
||||
@@ -253,19 +273,25 @@ public:
|
||||
{
|
||||
return promise->done();
|
||||
}
|
||||
void finalize()
|
||||
{
|
||||
promise->finalize();
|
||||
}
|
||||
Event operator co_await() const
|
||||
{
|
||||
// the co_await operator keeps a reference to this, we it won't
|
||||
// the co_await operator keeps a reference to this, it won't
|
||||
// be scheduled from the destructor
|
||||
promise->schedule();
|
||||
return promise->finishedEvent;
|
||||
}
|
||||
static JobBase all() = delete;
|
||||
template<iterable Iterable>
|
||||
template<std::ranges::range Iterable>
|
||||
requires std::same_as<std::ranges::range_value_t<Iterable>, JobBase>
|
||||
static JobBase all(Iterable collection)
|
||||
{
|
||||
getGlobalThreadPool().scheduleBatch(collection);
|
||||
for(auto it : collection)
|
||||
{
|
||||
co_await it;
|
||||
}
|
||||
}
|
||||
template<std::ranges::range Iterable>
|
||||
static JobBase all(Iterable collection)
|
||||
{
|
||||
for(auto it : collection)
|
||||
@@ -278,14 +304,17 @@ public:
|
||||
{
|
||||
return JobBase::all(Array{jobs...});
|
||||
}
|
||||
template<std::invocable JobFunc, iterable IterableParams>
|
||||
static JobBase launchJobs(JobFunc&& func, IterableParams params)
|
||||
template<typename JobFunc, std::ranges::input_range Iterable>
|
||||
requires std::invocable<JobFunc, std::ranges::range_reference_t<Iterable>>
|
||||
static JobBase launchJobs(JobFunc&& func, Iterable params)
|
||||
{
|
||||
List<JobBase> jobs;
|
||||
Array<JobBase> jobs;
|
||||
for(auto&& param : params)
|
||||
{
|
||||
jobs.add(func(param));
|
||||
JobBase base = func(param);
|
||||
jobs.add(base);
|
||||
}
|
||||
getGlobalThreadPool().scheduleBatch(jobs);
|
||||
for(auto job : jobs)
|
||||
{
|
||||
co_await job;
|
||||
@@ -293,6 +322,7 @@ public:
|
||||
}
|
||||
private:
|
||||
JobPromiseBase<MainJob>* promise;
|
||||
friend class ThreadPool;
|
||||
};
|
||||
|
||||
using MainJob = JobBase<true>;
|
||||
@@ -305,32 +335,64 @@ class ThreadPool
|
||||
public:
|
||||
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
|
||||
virtual ~ThreadPool();
|
||||
void cleanup();
|
||||
void waitIdle();
|
||||
// Adds a job to the waiting queue for event
|
||||
void enqueueWaiting(Event& event, Promise* job);
|
||||
// Adds a job to the waiting queue for event
|
||||
void enqueueWaiting(Event& event, MainPromise* job);
|
||||
void scheduleJob(Promise* job);
|
||||
void scheduleJob(MainPromise* job);
|
||||
template<std::ranges::range Iterable>
|
||||
requires std::same_as<std::ranges::range_value_t<Iterable>, MainJob>
|
||||
void scheduleBatch(Iterable jobs)
|
||||
{
|
||||
std::scoped_lock lock(mainJobLock);
|
||||
for(auto job : jobs)
|
||||
{
|
||||
job.promise->addRef();
|
||||
job.promise->state = JobPromiseBase<true>::State::SCHEDULED;
|
||||
mainJobs.add(job.promise);
|
||||
}
|
||||
mainJobCV.notify_one();
|
||||
}
|
||||
template<std::ranges::range Iterable>
|
||||
requires std::same_as<std::ranges::range_value_t<Iterable>, Job>
|
||||
void scheduleBatch(Iterable jobs)
|
||||
{
|
||||
std::scoped_lock lock(jobQueueLock);
|
||||
for(auto job : jobs)
|
||||
{
|
||||
job.promise->addRef();
|
||||
job.promise->state = JobPromiseBase<false>::State::SCHEDULED;
|
||||
jobQueue.add(job.promise);
|
||||
}
|
||||
jobQueueCV.notify_all();
|
||||
}
|
||||
void notify(Event& event);
|
||||
void threadLoop(const bool isMainThread);
|
||||
void mainLoop();
|
||||
void threadLoop();
|
||||
private:
|
||||
std::atomic_bool running;
|
||||
std::vector<std::thread> workers;
|
||||
std::mutex numIdlingLock;
|
||||
std::condition_variable numIdlingIncr;
|
||||
uint32 numIdling;
|
||||
Array<std::thread> workers;
|
||||
|
||||
std::list<MainPromise*> mainJobs;
|
||||
List<MainPromise*> mainJobs;
|
||||
std::mutex mainJobLock;
|
||||
std::condition_variable mainJobCV;
|
||||
|
||||
std::list<Promise*> jobQueue;
|
||||
List<Promise*> jobQueue;
|
||||
std::mutex jobQueueLock;
|
||||
std::condition_variable jobQueueCV;
|
||||
|
||||
std::map<Event, std::list<MainPromise*>> waitingMainJobs;
|
||||
Map<Event, List<MainPromise*>> waitingMainJobs;
|
||||
std::mutex waitingMainLock;
|
||||
|
||||
std::map<Event, std::list<Promise*>> waitingJobs;
|
||||
Map<Event, List<Promise*>> waitingJobs;
|
||||
std::mutex waitingLock;
|
||||
|
||||
uint32 maxLocalQueueSize = 50;
|
||||
};
|
||||
|
||||
template<bool MainJob>
|
||||
@@ -349,18 +411,6 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept
|
||||
template<bool MainJob>
|
||||
inline auto JobPromiseBase<MainJob>::final_suspend() noexcept
|
||||
{
|
||||
/*struct JobAwaitable
|
||||
{
|
||||
constexpr bool await_ready() const noexcept { return false; }
|
||||
constexpr auto await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h) const noexcept
|
||||
{
|
||||
auto continuation = h.promise().continuation;
|
||||
h.destroy();
|
||||
|
||||
}
|
||||
constexpr void await_resume() const noexcept {}
|
||||
};
|
||||
return JobAwaitable{};*/
|
||||
markDone();
|
||||
return std::suspend_always{};
|
||||
}
|
||||
|
||||
@@ -32,15 +32,15 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx");
|
||||
|
||||
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka"));
|
||||
ayaka->addWorldTranslation(Vector(0, 0, 0));
|
||||
ayaka->setWorldScale(Vector(10, 10, 10));
|
||||
ayaka->setRelativeLocation(Vector(0, 0, 0));
|
||||
ayaka->setRelativeScale(Vector(10, 10, 10));
|
||||
//scene->addPrimitiveComponent(ayaka);
|
||||
|
||||
PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane"));
|
||||
plane->setWorldScale(Vector(100, 100, 100));
|
||||
plane->setRelativeScale(Vector(100, 100, 100));
|
||||
scene->addPrimitiveComponent(plane);
|
||||
|
||||
for(uint32 i = 0; i < 1; ++i)
|
||||
for(uint32 i = 0; i < 100000; ++i)
|
||||
{
|
||||
PMyComponent myComp = new MyComponent();
|
||||
PMyOtherComponent myOtherComp = new MyOtherComponent();
|
||||
@@ -97,32 +97,46 @@ void SceneView::prepareRender()
|
||||
|
||||
MainJob SceneView::render()
|
||||
{
|
||||
return MainJob::all(
|
||||
depthPrepass.beginFrame(),
|
||||
lightCullingPass.beginFrame(),
|
||||
basePass.beginFrame())
|
||||
return depthPrepass.beginFrame()
|
||||
.then(lightCullingPass.beginFrame())
|
||||
.then(basePass.beginFrame())
|
||||
.then(depthPrepass.render())
|
||||
.then(lightCullingPass.render())
|
||||
.then(basePass.render())
|
||||
.then(
|
||||
MainJob::all(
|
||||
depthPrepass.endFrame(),
|
||||
lightCullingPass.endFrame(),
|
||||
basePass.endFrame())
|
||||
);
|
||||
.then(depthPrepass.endFrame())
|
||||
.then(lightCullingPass.endFrame())
|
||||
.then(basePass.endFrame());
|
||||
}
|
||||
|
||||
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier)
|
||||
static float cameraSpeed = 1;
|
||||
|
||||
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier mod)
|
||||
{
|
||||
if((KeyModifierFlags)mod & (KeyModifierFlags)KeyModifier::MOD_SHIFT)
|
||||
{
|
||||
cameraSpeed = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
cameraSpeed = 1;
|
||||
}
|
||||
if(action != InputAction::RELEASE)
|
||||
{
|
||||
if(code == KeyCode::KEY_W)
|
||||
{
|
||||
activeCamera->getCameraComponent()->moveOrigin(1);
|
||||
activeCamera->getCameraComponent()->moveX(1);
|
||||
}
|
||||
if(code == KeyCode::KEY_S)
|
||||
{
|
||||
activeCamera->getCameraComponent()->moveOrigin(-1);
|
||||
activeCamera->getCameraComponent()->moveX(-1);
|
||||
}
|
||||
if(code == KeyCode::KEY_A)
|
||||
{
|
||||
activeCamera->getCameraComponent()->moveY(1);
|
||||
}
|
||||
if(code == KeyCode::KEY_D)
|
||||
{
|
||||
activeCamera->getCameraComponent()->moveY(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,7 +158,7 @@ void SceneView::mouseMoveCallback(double xPos, double yPos)
|
||||
|
||||
void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier)
|
||||
{
|
||||
if(button == MouseButton::MOUSE_BUTTON_1 && action != InputAction::RELEASE)
|
||||
if(button == MouseButton::MOUSE_BUTTON_2 && action != InputAction::RELEASE)
|
||||
{
|
||||
mouseDown = true;
|
||||
}
|
||||
|
||||
@@ -27,16 +27,14 @@ void Window::addView(PView view)
|
||||
MainJob Window::render()
|
||||
{
|
||||
gfxHandle->beginFrame();
|
||||
Array<MainJob> jobs;
|
||||
for(auto& windowView : views)
|
||||
{
|
||||
{
|
||||
std::scoped_lock lock(windowView->workerMutex);
|
||||
windowView->view->prepareRender();
|
||||
}
|
||||
jobs.add(windowView->view->render());
|
||||
co_await windowView->view->render();
|
||||
}
|
||||
co_await MainJob::all(jobs);
|
||||
gfxHandle->endFrame();
|
||||
if(owner->isActive())
|
||||
{
|
||||
|
||||
@@ -41,6 +41,6 @@ void WindowManager::notifyWindowClosed(PWindow window)
|
||||
windows.remove(windows.find(window));
|
||||
if(windows.empty())
|
||||
{
|
||||
getGlobalThreadPool().cleanup();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,9 +34,9 @@ int main()
|
||||
//PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
|
||||
//window->addView(inspectorView);
|
||||
sceneView->setFocused();
|
||||
|
||||
|
||||
window->render();
|
||||
|
||||
getGlobalThreadPool().threadLoop(true);
|
||||
getGlobalThreadPool().mainLoop();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
//#include <vld.h>
|
||||
#include <vld.h>
|
||||
#include "ThreadPool.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -12,7 +12,7 @@ namespace Seele
|
||||
}
|
||||
~GlobalFixture()
|
||||
{
|
||||
getGlobalThreadPool().cleanup();
|
||||
getGlobalThreadPool().waitIdle();
|
||||
}
|
||||
void setup()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "EngineTest.h"
|
||||
#include "ThreadPool.h"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(ThreadPool)
|
||||
|
||||
@@ -9,18 +12,21 @@ uint64 basicAwaitState = 0;
|
||||
Job basicAwaitFirst()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicAwaitState, 5);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicAwaitState = 10;
|
||||
co_return;
|
||||
}
|
||||
Job basicAwaitSecond()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicAwaitState, 15);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicAwaitState = 20;
|
||||
co_return;
|
||||
}
|
||||
Job basicAwaitThird()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicAwaitState, 25);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicAwaitState = 30;
|
||||
co_return;
|
||||
}
|
||||
@@ -48,18 +54,21 @@ uint64 basicThenState = 5;
|
||||
Job basicThenFirst()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicThenState, 5);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicThenState = 10;
|
||||
co_return;
|
||||
}
|
||||
Job basicThenSecond()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicThenState, 15);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicThenState = 20;
|
||||
co_return;
|
||||
}
|
||||
Job basicThenThird()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicThenState, 25);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicThenState = 30;
|
||||
co_return;
|
||||
}
|
||||
@@ -70,6 +79,7 @@ BOOST_AUTO_TEST_CASE(basic_thenchain)
|
||||
.then([]() -> Job
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicThenState, 10);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicThenState = 15;
|
||||
co_return;
|
||||
})
|
||||
@@ -77,6 +87,7 @@ BOOST_AUTO_TEST_CASE(basic_thenchain)
|
||||
.then([]() -> Job
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(basicThenState, 20);
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicThenState = 25;
|
||||
co_return;
|
||||
})
|
||||
@@ -92,11 +103,13 @@ uint64 basicAllState1 = 0;
|
||||
uint64 basicAllState2 = 0;
|
||||
Job basicAllFirst()
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicAllState1 = 10;
|
||||
co_return;
|
||||
}
|
||||
Job basicAllSecond()
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicAllState2 = 10;
|
||||
co_return;
|
||||
}
|
||||
@@ -112,10 +125,41 @@ BOOST_AUTO_TEST_CASE(basic_all)
|
||||
Job::all(basicAllFirst(), basicAllSecond()).then(basicAllThen());
|
||||
}
|
||||
|
||||
uint64 allThenState = 0;
|
||||
|
||||
Job allThenInitial()
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
allThenState = 10;
|
||||
co_return;
|
||||
}
|
||||
|
||||
Job allThenIntermediate()
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
BOOST_REQUIRE_EQUAL(allThenState, 10);
|
||||
allThenState = 20;
|
||||
co_return;
|
||||
}
|
||||
|
||||
Job allThenFinal()
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(allThenState, 20);
|
||||
co_return;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(all_then_interaction)
|
||||
{
|
||||
Job::all(allThenInitial())
|
||||
.then(allThenIntermediate())
|
||||
.then(Job::all(allThenFinal()));
|
||||
}
|
||||
|
||||
uint64 basicCallable = 0;
|
||||
|
||||
Job basicCallableFunc()
|
||||
{
|
||||
std::this_thread::sleep_for(500ms);
|
||||
basicCallable = 10;
|
||||
co_return;
|
||||
}
|
||||
@@ -130,4 +174,44 @@ BOOST_AUTO_TEST_CASE(basic_callable)
|
||||
});
|
||||
}
|
||||
|
||||
struct Payload
|
||||
{
|
||||
StaticArray<uint64, 1000> data;
|
||||
uint64 result = 0;
|
||||
};
|
||||
|
||||
Job worker(Payload& payload)
|
||||
{
|
||||
for(uint32 i = 0; i < 100000; ++i)
|
||||
{
|
||||
payload.result = std::accumulate(payload.data.begin(), payload.data.end(), (uint64)1, std::multiplies<uint64>());
|
||||
}
|
||||
co_return;
|
||||
}
|
||||
|
||||
Job launchStressTest()
|
||||
{
|
||||
Array<Payload> payloads(100);
|
||||
Array<Job> jobs;
|
||||
for(auto& payload : payloads)
|
||||
{
|
||||
for(uint64 i = 0; i < payload.data.size(); ++i)
|
||||
{
|
||||
payload.data[i] = i;
|
||||
}
|
||||
}
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Starting up" << std::endl;
|
||||
co_await Job::launchJobs(&worker, payloads);
|
||||
std::cout << "Finished waiting" << std::endl;
|
||||
auto endTime = std::chrono::high_resolution_clock::now();
|
||||
float delta = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime).count();
|
||||
std::cout << "Update took " << delta << " seconds";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(stress_test)
|
||||
{
|
||||
//launchStressTest();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user