From 4d5b8353529f12656f0acae8a3ffb99057188fc4 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 20 Jan 2016 16:43:09 +0100 Subject: [PATCH 01/49] WIP triangles vs. AABB. --- .../Schema/Entities/ModelCollisionTest.xml | 49 +++++++++ src/Engine/Collision/Collision.cpp | 99 ++++++++++++++++--- src/Engine/Collision/CollisionSystem.cpp | 63 ++++++------ 3 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 resources/Schema/Entities/ModelCollisionTest.xml diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml new file mode 100644 index 00000000..46746264 --- /dev/null +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.obj + + + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.obj + + + + + + + + + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index b30ae927..c351d9fa 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -199,30 +199,93 @@ bool RayVsModel(const Ray& ray, return hit; } -bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) +bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector) { - bool hit = false; - const glm::vec3& origin = box.Origin(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); + const glm::vec3& half = box.HalfSize(); - outResolutionVector.x = INFINITY; + const glm::vec3 triPos[] = { + v0, v1, v2 + }; - for (int i = 0; i < modelIndices.size(); ++i) { - glm::vec3 p = modelVertices[i].Position; + for (int ax = 0; ax < 3; ++ax) { + auto outsideMinPlane = glm::tvec3(false); + auto outsideMaxPlane = glm::tvec3(false); + for (int pos = 0; pos < 3; ++pos) { + outsideMinPlane[pos] = (min[ax] > triPos[pos][ax]); + outsideMaxPlane[pos] = (triPos[pos][ax] > max[ax]); + } + if (glm::all(outsideMinPlane) || glm::all(outsideMaxPlane)) { + return false; + } + } + return true; +} + +bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) +{ + bool hit = false; + for (int i = 0; i < modelIndices.size(); i += 3) { + glm::vec3 resVec; + hit = AABBvsTriangle( + box, + modelVertices[modelIndices[i]].Position, + modelVertices[modelIndices[i + 1]].Position, + modelVertices[modelIndices[i + 2]].Position, + resVec + ); + if (hit) { + break; + } + } + return hit; + //TODO: Remove old code. + + /* + auto hit = glm::tvec3(false); + const glm::vec3& origin = box.Origin(); + const glm::vec3& min = box.MinCorner(); + const glm::vec3& max = box.MaxCorner(); + const glm::vec3& half = box.HalfSize(); + + float minResolution = INFINITY; + outResolutionVector = glm::vec3(0.f); + //TODO: Don't need indices? Remove? + for (const auto& v : modelVertices) { + glm::vec3 p = v.Position; p = glm::vec3(modelMatrix * glm::vec4(p.x, p.y, p.z, 1)); - float distFromOrigin = glm::abs(origin.x - p.x); - float penetration = box.HalfSize().x - distFromOrigin; - if (penetration > 0 && penetration < glm::abs(outResolutionVector.x)) { - if (p.x > origin.x) { - outResolutionVector.x = -penetration; - } else { - outResolutionVector.x = penetration; + const glm::vec3 diffO = origin - p; + const glm::vec3 distO = glm::abs(diffO); + for (int axis = 0; axis < 3; ++axis) { + float penetration = half[axis] - distO[axis]; + if (penetration > 0){ + if (penetration < minResolution) { + minResolution = penetration; + outResolutionVector = glm::vec3(0.f); + if (p[axis] > origin[axis]) { + outResolutionVector[axis] = -penetration; + } else { + outResolutionVector[axis] = penetration; + } + } + hit[axis] = true; } - hit = true; } + + //float distFromOrigin = glm::abs(origin.x - p.x); + //float penetration = box.HalfSize().x - distFromOrigin; + //if (penetration > 0 && penetration < glm::abs(outResolutionVector.x)) { + // if (p.x > origin.x) { + // outResolutionVector.x = -penetration; + // } else { + // outResolutionVector.x = penetration; + // } + // hit = true; + //} + //glm::vec3 pLocal = origin - p; //for (int axis = 0; axis < 3; ++axis) { // if (p[axis] < min[axis] || p[axis] > max[axis]) { @@ -236,7 +299,13 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model //} } - return hit; + //for (int axis = 0; axis < 3; ++axis) { + // if (glm::isinf(outResolutionVector[axis])) { + // outResolutionVector[axis] = 0.f; + // } + //} + + return glm::all(hit);*/ } bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index d841c75e..58e48357 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -1,6 +1,7 @@ #include "Collision/Collision.h" #include "Collision/CollisionSystem.h" #include "Core/AABB.h" +#include "Rendering/Model.h" void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) { @@ -22,40 +23,42 @@ void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, Compo } // Collide against octree - std::vector octreeResult; - m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); - for (auto& boxB : octreeResult) { - glm::vec3 resolutionVector; - if (Collision::IsSameBoxProbably(boxA, boxB)) { - continue; - } - if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { - (glm::vec3&)cTransform["Position"] += resolutionVector; - cPhysics["Velocity"] = glm::vec3(0, 0, 0); - } - } - - // HACK: Temporarily collide against all collidable models since they're not in the octree yet - //auto otherCollidables = world->GetComponents("Model"); - //for (auto& cModel : *otherCollidables) { - // if (cModel.EntityID == entity) { - // continue; - // } - // if (!world->HasComponent(cModel.EntityID, "Collidable")) { - // continue; - // } - - // auto absPosition = RenderQueueFactory::AbsolutePosition(world, cModel.EntityID); - // auto absOrientation = RenderQueueFactory::AbsoluteOrientation(world, cModel.EntityID); - // auto absScale = RenderQueueFactory::AbsoluteScale(world, cModel.EntityID); - // glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); - - // auto model = ResourceManager::Load(cModel["Resource"]); + //std::vector octreeResult; + //m_Octree->BoxesInSameRegion(*boundingBox, octreeResult); + //for (auto& boxB : octreeResult) { // glm::vec3 resolutionVector; - // if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + // if (Collision::IsSameBoxProbably(boxA, boxB)) { + // continue; + // } + // if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { // (glm::vec3&)cTransform["Position"] += resolutionVector; + // cPhysics["Velocity"] = glm::vec3(0, 0, 0); // } //} + + // HACK: Temporarily collide against all collidable models since they're not in the octree yet + auto otherCollidables = world->GetComponents("Model"); + for (auto& cModel : *otherCollidables) { + if (cModel.EntityID == EntityID(entity)) { + continue; + } + if (!world->HasComponent(cModel.EntityID, "Collidable")) { + continue; + } + + auto absPosition = Transform::AbsolutePosition(world, cModel.EntityID); + auto absOrientation = Transform::AbsoluteOrientation(world, cModel.EntityID); + auto absScale = Transform::AbsoluteScale(world, cModel.EntityID); + glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); + + RawModel* model = ResourceManager::Load(cModel["Resource"]); + glm::vec3 resolutionVector; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + //TODO: remove Temp. + (glm::vec3&)cTransform["Position"] = glm::vec3(2, 2, 2); + //(glm::vec3&)cTransform["Position"] += resolutionVector; + } + } } bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) From de7c8e9234f89893265a6ce97a95b06268e6eb53 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Thu, 21 Jan 2016 17:10:36 +0100 Subject: [PATCH 02/49] WIP, collision detects too much, no resolving for most cases. --- include/Engine/Collision/Collision.h | 9 + include/Engine/Core/Transform.h | 1 + .../Schema/Entities/ModelCollisionTest.xml | 10 +- src/Engine/Collision/Collision.cpp | 256 ++++++++++++++++-- src/Engine/Collision/CollisionSystem.cpp | 6 +- src/Engine/Core/Transform.cpp | 4 + 6 files changed, 248 insertions(+), 38 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 148f688d..b32d190a 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -26,6 +26,15 @@ bool RayVsAABB(const Ray& ray, const AABB& box); //Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance]. bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); +//Return true if the ray hits the triangle, and the distance is less than outDistance. +bool RayVsTriangle(const Ray& ray, + const glm::vec3& v0, + const glm::vec3& v1, + const glm::vec3& v2, + float& outDistance, + float& outUCoord, + float& outVCoord, + bool trueOnNegativeDistance = false); //Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected. bool RayVsModel(const Ray& ray, const std::vector& modelVertices, diff --git a/include/Engine/Core/Transform.h b/include/Engine/Core/Transform.h index 474a7bdb..b004f047 100644 --- a/include/Engine/Core/Transform.h +++ b/include/Engine/Core/Transform.h @@ -11,6 +11,7 @@ glm::vec3 AbsolutePosition(World* world, EntityID entity); glm::quat AbsoluteOrientation(World* world, EntityID entity); glm::vec3 AbsoluteScale(World* world, EntityID entity); glm::mat4 ModelMatrix(EntityID entity, World* world); +glm::vec3 TransformPoint(const glm::vec3& point, const glm::mat4& matrix); } diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml index 46746264..fd26f0c5 100644 --- a/resources/Schema/Entities/ModelCollisionTest.xml +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -11,8 +11,8 @@ - - + + @@ -22,10 +22,10 @@ ../assets/Models/Core/UnitCube.obj + - - + @@ -39,7 +39,7 @@ ../assets/Models/Core/UnitCube.obj - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index c351d9fa..6794f5b9 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -146,6 +146,38 @@ bool RayVsModel(const Ray& ray, return false; } +bool RayVsTriangle(const Ray& ray, + const glm::vec3& v0, + const glm::vec3& v1, + const glm::vec3& v2, + float& outDistance, + float& outUCoord, + float& outVCoord, + bool trueOnNegativeDistance) +{ + glm::vec3 e1 = v1 - v0; //v1 - v0 + glm::vec3 e2 = v2 - v0; //v2 - v0 + glm::vec3 m = ray.Origin() - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + return false; + } + DetInv = 1.0f / DetInv; + float dist = glm::dot(e2, MxE1) * DetInv; + if (dist >= outDistance) { + return false; + } + outDistance = dist; + outUCoord = glm::dot(m, DxE2) * DetInv; + outVCoord = glm::dot(ray.Direction(), MxE1) * DetInv; + + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + //If u and v are positive, u+v <= 1, dist is positive, and less than closest. + return (0 <= (outUCoord + 0.001f) && 0 <= (outVCoord + 0.001f) && outUCoord + outVCoord <= 1 && (trueOnNegativeDistance || 0 <= dist)); +} + bool RayVsModel(const Ray& ray, const std::vector& modelVertices, const std::vector& modelIndices, @@ -157,26 +189,12 @@ bool RayVsModel(const Ray& ray, bool hit = false; for (int i = 0; i < modelIndices.size(); ++i) { glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin() - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; - } - DetInv = 1.0f / DetInv; - float dist = glm::dot(e2, MxE1) * DetInv; - if (dist >= outDistance) { - continue; - } - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction(), MxE1) * DetInv; - - //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem - //If u and v are positive, u+v <= 1, dist is positive, and less than closest. - if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) { + glm::vec3 v1 = modelVertices[modelIndices[++i]].Position; + glm::vec3 v2 = modelVertices[modelIndices[++i]].Position; + float dist; + float u; + float v; + if (RayVsTriangle(ray, v0, v1, v2, dist, u, v)) { outDistance = dist; outUCoord = u; outVCoord = v; @@ -199,29 +217,205 @@ bool RayVsModel(const Ray& ray, return hit; } +constexpr inline int squareOf(float x) +{ + return x * x; +} + +constexpr inline int signNonZero(float x) +{ + return x < 0 ? -1 : 1; +} + +inline glm::vec3 signNonZero(const glm::vec3& x) +{ + glm::vec3 r; + for (int i = 0; i < 3; ++i) { + r[i] = signNonZero(x[i]); + } + return r; +} + +bool lineIntersectsBox(const AABB& box, const glm::vec3& v0, const glm::vec3& v1) +{ + const glm::vec3 edgevec = v1 - v0; + glm::vec3 edgevec_signs = signNonZero(edgevec); + + for (int i = 0; i < 3; ++i) + edgevec_signs[i] = signNonZero(edgevec[i]); + + /* + * Test the three cube faces on the v1-ward side of the cube-- + * if v0 is outside any of their planes then there is no intersection. + * Also test the three cube faces on the v0-ward side of the cube-- + * if v1 is outside any of their planes then there is no intersection. + */ + + for (int i = 0; i < 3; ++i) + { + if (v0[i] * edgevec_signs[i] > .5) return false; + if (v1[i] * edgevec_signs[i] < -.5) return false; + } + + /* + * Okay, that's the six easy faces of the rhombic dodecahedron + * out of the way. Six more to go. + * The remaining six planes bound an infinite hexagonal prism + * joining the petrie polygons (skew hexagons) of the two cubes + * centered at the endpoints. + */ + + for (int i = 0; i < 3; ++i) + { + float rhomb_normal_dot_v0, rhomb_normal_dot_cubedge; + + int iplus1 = (i + 1) % 3; + int iplus2 = (i + 2) % 3; + +#ifdef THE_EASY_TO_UNDERSTAND_WAY + + { + real rhomb_normal[3], cubedge_midpoint[3]; + + /* + * rhomb_normal = VXV3(edgevec, unit vector in direction i), + * being cavalier about which direction it's facing + */ + rhomb_normal[i] = 0; + rhomb_normal[iplus1] = edgevec[iplus2]; + rhomb_normal[iplus2] = -edgevec[iplus1]; + + /* + * We now are describing a plane parallel to + * both segment and the cube edge in question. + * if |DOT3(rhomb_normal, an arbitrary point on the segment)| > + * |DOT3(rhomb_normal, an arbitrary point on the cube edge in question| + * then the origin is outside this pair of opposite faces. + * (This is equivalent to saying that the line + * containing the segment is "outside" (i.e. further away from the + * origin than) the line containing the cube edge. + */ + + cubedge_midpoint[i] = 0; + cubedge_midpoint[iplus1] = edgevec_signs[iplus1] * .5; + cubedge_midpoint[iplus2] = -edgevec_signs[iplus2] * .5; + + rhomb_normal_dot_v0 = DOT3(rhomb_normal, v0); + rhomb_normal_dot_cubedge = DOT3(rhomb_normal, cubedge_midpoint); + } + +#else /* the efficient way */ + + rhomb_normal_dot_v0 = edgevec[iplus2] * v0[iplus1] + - edgevec[iplus1] * v0[iplus2]; + + rhomb_normal_dot_cubedge = .5 * + (edgevec[iplus2] * edgevec_signs[iplus1] + + edgevec[iplus1] * edgevec_signs[iplus2]); + +#endif /* the efficient way */ + + if (squareOf(rhomb_normal_dot_v0) > squareOf(rhomb_normal_dot_cubedge)) + return false; /* origin is outside this pair of opposite planes */ + } + return true; +} + +bool vectorHasLength(const glm::vec3& vec) +{ + return glm::all(glm::lessThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); +} + bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector) { + //Check so we don't have a zero area triangle when calculating the normal. + glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); + if (vectorHasLength(triNormal)) { + return false; + } + const glm::vec3& origin = box.Origin(); + const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); - const glm::vec3& half = box.HalfSize(); const glm::vec3 triPos[] = { v0, v1, v2 }; + auto insideAllPlanes = glm::tvec3(false); + //All triangle vertex points. + //Check if the triangle is completely outside or inside the box. for (int ax = 0; ax < 3; ++ax) { auto outsideMinPlane = glm::tvec3(false); auto outsideMaxPlane = glm::tvec3(false); + auto insidePlanes = glm::tvec3(false); for (int pos = 0; pos < 3; ++pos) { outsideMinPlane[pos] = (min[ax] > triPos[pos][ax]); outsideMaxPlane[pos] = (triPos[pos][ax] > max[ax]); + insidePlanes[pos] = !(outsideMinPlane[pos] || outsideMaxPlane[pos]); } if (glm::all(outsideMinPlane) || glm::all(outsideMaxPlane)) { return false; } + insideAllPlanes[ax] = glm::all(insidePlanes); } - return true; + if (glm::all(insideAllPlanes)) { + outResolutionVector = glm::vec3(0.f); + LOG_DEBUG("Triangle collision inside"); + return true; //TODO: Resolve. + } + + glm::vec3 triPosInBoxSpace[3]; + for (int i = 0; i < 3; ++i) { + triPosInBoxSpace[i] = (triPos[i] - origin) / (2.0f * half); + } + //All triangle lines. + //Check if each line on the triangle intersects any plane on the box. + for (int l = 0; l < 3; ++l) { + if (lineIntersectsBox(box, triPosInBoxSpace[l], triPosInBoxSpace[(l + 1) % 3])) { + outResolutionVector = glm::vec3(0.f); + LOG_DEBUG("Triangle collision lines"); + return true; //TODO: Resolve. + } + } + + //None of the polygon's edges intersects the cube, finally, check if any of the four + //cube diagonals intersect the interior of the polygon. + //If the polygon does intersect any of the cube diagonals, it will + //intersect the cube diagonal that comes + //closest to being perpendicular to the plane of the polygon. + + triNormal = glm::normalize(triNormal); + glm::vec3 diagonal = signNonZero(triNormal) * half; +#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK +#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK + //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) + //The diagonal line contains all points P in P = origin + diagonal * t. + float t = glm::dot(triNormal, v0 - origin) / glm::dot(triNormal, diagonal); + + //If intersection point between plane and diagonal is not within the box. + if (glm::abs(t) > 1) { + return false; + } + //glm::vec3 intersection = origin + t * diagonal; +#endif + + //Check if intersection point is on the triangle. + Ray ray(origin, diagonal); + float dist = INFINITY, u, v; + if (RayVsTriangle(ray, v0, v1, v2, dist, u, v, true)) { +#ifndef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK + if (glm::abs(dist) > glm::length(diagonal)) { + return false; + } +#endif + float dist = glm::dot(triNormal, origin + diagonal - v0); + outResolutionVector = dist * triNormal; + LOG_DEBUG("Triangle collision corner"); + return true; + } + return false; } bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) @@ -229,15 +423,19 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model bool hit = false; for (int i = 0; i < modelIndices.size(); i += 3) { glm::vec3 resVec; - hit = AABBvsTriangle( + if (AABBvsTriangle( box, - modelVertices[modelIndices[i]].Position, - modelVertices[modelIndices[i + 1]].Position, - modelVertices[modelIndices[i + 2]].Position, + Transform::TransformPoint(modelVertices[modelIndices[i]].Position, modelMatrix), + Transform::TransformPoint(modelVertices[modelIndices[i + 1]].Position, modelMatrix), + Transform::TransformPoint(modelVertices[modelIndices[i + 2]].Position, modelMatrix), resVec - ); - if (hit) { - break; + )) + { + hit = true; + //If resolution distance is smaller than previous, and is non-zero. + if (glm::length(resVec) < glm::length(outResolutionVector) && vectorHasLength(resVec)) { + outResolutionVector = resVec; + } } } return hit; diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 58e48357..abddce1f 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -49,14 +49,12 @@ void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, Compo auto absPosition = Transform::AbsolutePosition(world, cModel.EntityID); auto absOrientation = Transform::AbsoluteOrientation(world, cModel.EntityID); auto absScale = Transform::AbsoluteScale(world, cModel.EntityID); - glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); + glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); RawModel* model = ResourceManager::Load(cModel["Resource"]); glm::vec3 resolutionVector; if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { - //TODO: remove Temp. - (glm::vec3&)cTransform["Position"] = glm::vec3(2, 2, 2); - //(glm::vec3&)cTransform["Position"] += resolutionVector; + (glm::vec3&)cTransform["Position"] += resolutionVector; } } } diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp index cbc405a3..054b1984 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -50,3 +50,7 @@ glm::mat4 Transform::ModelMatrix(EntityID entity, World* world) return modelMatrix; } +glm::vec3 Transform::TransformPoint(const glm::vec3& point, const glm::mat4& matrix) +{ + return glm::vec3(matrix * glm::vec4(point.x, point.y, point.z, 1)); +} \ No newline at end of file From 52765cc85bccfc3f4eaddefefcb404350fdc125f Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 22 Jan 2016 11:22:56 +0100 Subject: [PATCH 03/49] TriangleVsBox detection seems to work in all cases, but cannot resolve all cases yet. Also added default ctor for Ray and removed compilation errors in CollisionSystem. --- include/Engine/Core/Ray.h | 4 + src/Engine/Collision/Collision.cpp | 177 ++--------------------- src/Engine/Collision/CollisionSystem.cpp | 12 +- 3 files changed, 25 insertions(+), 168 deletions(-) diff --git a/include/Engine/Core/Ray.h b/include/Engine/Core/Ray.h index a234a488..03bfa391 100644 --- a/include/Engine/Core/Ray.h +++ b/include/Engine/Core/Ray.h @@ -7,6 +7,10 @@ class Ray { public: + Ray() + : m_Origin(glm::vec3(0.f)) + , m_Direction(glm::vec3(0, 0, 1)) + {} Ray(const glm::vec3& origin, const glm::vec3& dir) : m_Origin(origin) , m_Direction(glm::normalize(dir)) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 6794f5b9..d643e8cc 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -217,11 +217,6 @@ bool RayVsModel(const Ray& ray, return hit; } -constexpr inline int squareOf(float x) -{ - return x * x; -} - constexpr inline int signNonZero(float x) { return x < 0 ? -1 : 1; @@ -236,101 +231,17 @@ inline glm::vec3 signNonZero(const glm::vec3& x) return r; } -bool lineIntersectsBox(const AABB& box, const glm::vec3& v0, const glm::vec3& v1) -{ - const glm::vec3 edgevec = v1 - v0; - glm::vec3 edgevec_signs = signNonZero(edgevec); - - for (int i = 0; i < 3; ++i) - edgevec_signs[i] = signNonZero(edgevec[i]); - - /* - * Test the three cube faces on the v1-ward side of the cube-- - * if v0 is outside any of their planes then there is no intersection. - * Also test the three cube faces on the v0-ward side of the cube-- - * if v1 is outside any of their planes then there is no intersection. - */ - - for (int i = 0; i < 3; ++i) - { - if (v0[i] * edgevec_signs[i] > .5) return false; - if (v1[i] * edgevec_signs[i] < -.5) return false; - } - - /* - * Okay, that's the six easy faces of the rhombic dodecahedron - * out of the way. Six more to go. - * The remaining six planes bound an infinite hexagonal prism - * joining the petrie polygons (skew hexagons) of the two cubes - * centered at the endpoints. - */ - - for (int i = 0; i < 3; ++i) - { - float rhomb_normal_dot_v0, rhomb_normal_dot_cubedge; - - int iplus1 = (i + 1) % 3; - int iplus2 = (i + 2) % 3; - -#ifdef THE_EASY_TO_UNDERSTAND_WAY - - { - real rhomb_normal[3], cubedge_midpoint[3]; - - /* - * rhomb_normal = VXV3(edgevec, unit vector in direction i), - * being cavalier about which direction it's facing - */ - rhomb_normal[i] = 0; - rhomb_normal[iplus1] = edgevec[iplus2]; - rhomb_normal[iplus2] = -edgevec[iplus1]; - - /* - * We now are describing a plane parallel to - * both segment and the cube edge in question. - * if |DOT3(rhomb_normal, an arbitrary point on the segment)| > - * |DOT3(rhomb_normal, an arbitrary point on the cube edge in question| - * then the origin is outside this pair of opposite faces. - * (This is equivalent to saying that the line - * containing the segment is "outside" (i.e. further away from the - * origin than) the line containing the cube edge. - */ - - cubedge_midpoint[i] = 0; - cubedge_midpoint[iplus1] = edgevec_signs[iplus1] * .5; - cubedge_midpoint[iplus2] = -edgevec_signs[iplus2] * .5; - - rhomb_normal_dot_v0 = DOT3(rhomb_normal, v0); - rhomb_normal_dot_cubedge = DOT3(rhomb_normal, cubedge_midpoint); - } - -#else /* the efficient way */ - - rhomb_normal_dot_v0 = edgevec[iplus2] * v0[iplus1] - - edgevec[iplus1] * v0[iplus2]; - - rhomb_normal_dot_cubedge = .5 * - (edgevec[iplus2] * edgevec_signs[iplus1] + - edgevec[iplus1] * edgevec_signs[iplus2]); - -#endif /* the efficient way */ - - if (squareOf(rhomb_normal_dot_v0) > squareOf(rhomb_normal_dot_cubedge)) - return false; /* origin is outside this pair of opposite planes */ - } - return true; -} bool vectorHasLength(const glm::vec3& vec) { - return glm::all(glm::lessThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); + return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); } bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector) { //Check so we don't have a zero area triangle when calculating the normal. glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); - if (vectorHasLength(triNormal)) { + if (!vectorHasLength(triNormal)) { return false; } @@ -366,14 +277,15 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c return true; //TODO: Resolve. } - glm::vec3 triPosInBoxSpace[3]; - for (int i = 0; i < 3; ++i) { - triPosInBoxSpace[i] = (triPos[i] - origin) / (2.0f * half); - } + Ray ray; //All triangle lines. //Check if each line on the triangle intersects any plane on the box. for (int l = 0; l < 3; ++l) { - if (lineIntersectsBox(box, triPosInBoxSpace[l], triPosInBoxSpace[(l + 1) % 3])) { + glm::vec3 edge = triPos[(l + 1) % 3] - triPos[l]; + ray.SetOrigin(triPos[l]); + ray.SetDirection(edge); + float dist; + if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) { outResolutionVector = glm::vec3(0.f); LOG_DEBUG("Triangle collision lines"); return true; //TODO: Resolve. @@ -402,7 +314,8 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c #endif //Check if intersection point is on the triangle. - Ray ray(origin, diagonal); + ray.SetOrigin(origin); + ray.SetDirection(diagonal); float dist = INFINITY, u, v; if (RayVsTriangle(ray, v0, v1, v2, dist, u, v, true)) { #ifndef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK @@ -421,6 +334,7 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) { bool hit = false; + outResolutionVector = glm::vec3(INFINITY); for (int i = 0; i < modelIndices.size(); i += 3) { glm::vec3 resVec; if (AABBvsTriangle( @@ -438,72 +352,11 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model } } } - return hit; - //TODO: Remove old code. - - /* - auto hit = glm::tvec3(false); - const glm::vec3& origin = box.Origin(); - const glm::vec3& min = box.MinCorner(); - const glm::vec3& max = box.MaxCorner(); - const glm::vec3& half = box.HalfSize(); - - float minResolution = INFINITY; - outResolutionVector = glm::vec3(0.f); - //TODO: Don't need indices? Remove? - for (const auto& v : modelVertices) { - glm::vec3 p = v.Position; - p = glm::vec3(modelMatrix * glm::vec4(p.x, p.y, p.z, 1)); - - const glm::vec3 diffO = origin - p; - const glm::vec3 distO = glm::abs(diffO); - for (int axis = 0; axis < 3; ++axis) { - float penetration = half[axis] - distO[axis]; - if (penetration > 0){ - if (penetration < minResolution) { - minResolution = penetration; - outResolutionVector = glm::vec3(0.f); - if (p[axis] > origin[axis]) { - outResolutionVector[axis] = -penetration; - } else { - outResolutionVector[axis] = penetration; - } - } - hit[axis] = true; - } - } - - //float distFromOrigin = glm::abs(origin.x - p.x); - //float penetration = box.HalfSize().x - distFromOrigin; - //if (penetration > 0 && penetration < glm::abs(outResolutionVector.x)) { - // if (p.x > origin.x) { - // outResolutionVector.x = -penetration; - // } else { - // outResolutionVector.x = penetration; - // } - // hit = true; - //} - - //glm::vec3 pLocal = origin - p; - //for (int axis = 0; axis < 3; ++axis) { - // if (p[axis] < min[axis] || p[axis] > max[axis]) { - // continue; - // } - - // if (glm::abs(pLocal[axis]) < box.HalfSize()[axis]) { - // outResolutionVector[axis] = (glm::sign(pLocal[axis]) * box.HalfSize()[axis]) - pLocal[axis]; - // hit = true; - // } - //} + //TODO: Unnecessary later, remove it. + if (glm::any(glm::isinf(outResolutionVector))) { + outResolutionVector = glm::vec3(0, 0, 0); } - - //for (int axis = 0; axis < 3; ++axis) { - // if (glm::isinf(outResolutionVector[axis])) { - // outResolutionVector[axis] = 0.f; - // } - //} - - return glm::all(hit);*/ + return hit; } bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 84608fbd..657cc90b 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -37,18 +37,18 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c //} // HACK: Temporarily collide against all collidable models since they're not in the octree yet - auto otherCollidables = world->GetComponents("Model"); + auto otherCollidables = m_World->GetComponents("Model"); for (auto& cModel : *otherCollidables) { - if (cModel.EntityID == EntityID(entity)) { + if (cModel.EntityID == entity.ID) { continue; } - if (!world->HasComponent(cModel.EntityID, "Collidable")) { + if (!m_World->HasComponent(cModel.EntityID, "Collidable")) { continue; } - auto absPosition = Transform::AbsolutePosition(world, cModel.EntityID); - auto absOrientation = Transform::AbsoluteOrientation(world, cModel.EntityID); - auto absScale = Transform::AbsoluteScale(world, cModel.EntityID); + auto absPosition = Transform::AbsolutePosition(m_World, cModel.EntityID); + auto absOrientation = Transform::AbsoluteOrientation(m_World, cModel.EntityID); + auto absScale = Transform::AbsoluteScale(m_World, cModel.EntityID); glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); RawModel* model = ResourceManager::Load(cModel["Resource"]); From 3955e1d60c1d388b39599c5eaa3c343d064bac85 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 22 Jan 2016 13:46:09 +0100 Subject: [PATCH 04/49] Can resolve collision when AABB corners cut through triangle. At least two more cases left to resolve. --- .../Schema/Entities/ModelCollisionTest.xml | 35 ++++++++++++++----- src/Engine/Collision/Collision.cpp | 8 ++--- src/Engine/Collision/CollisionSystem.cpp | 8 ++++- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml index fd26f0c5..f7a547f5 100644 --- a/resources/Schema/Entities/ModelCollisionTest.xml +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -2,7 +2,9 @@ - + + + @@ -11,8 +13,8 @@ - - + + @@ -21,25 +23,40 @@ - ../assets/Models/Core/UnitCube.obj - + ../assets/Models/Core/UnitQuad.obj + - + + + - + + + + + ../assets/Models/Core/UnitQuad.obj + + + + + + + + + - ../assets/Models/Core/UnitCube.obj + - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d643e8cc..d174eb86 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -299,7 +299,7 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c //closest to being perpendicular to the plane of the polygon. triNormal = glm::normalize(triNormal); - glm::vec3 diagonal = signNonZero(triNormal) * half; + glm::vec3 diagonal = -signNonZero(triNormal) * half; #define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK #ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) @@ -323,9 +323,9 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c return false; } #endif - float dist = glm::dot(triNormal, origin + diagonal - v0); - outResolutionVector = dist * triNormal; - LOG_DEBUG("Triangle collision corner"); + //Distance between triangle plane, and the diagonal corner, multiplied by the normal. + //Signed distance, positive if on the same side as the normal. + outResolutionVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; return true; } return false; diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 657cc90b..11d2a836 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -51,7 +51,13 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c auto absScale = Transform::AbsoluteScale(m_World, cModel.EntityID); glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); - RawModel* model = ResourceManager::Load(cModel["Resource"]); + RawModel* model; + try { + model = ResourceManager::Load(cModel["Resource"]); + } catch (const std::exception&) { + continue; + } + glm::vec3 resolutionVector; if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; From 1670fb4e48f4e9aa215512a7238ec49898074ba3 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 22 Jan 2016 14:45:50 +0100 Subject: [PATCH 05/49] Moved triangle vs ray code to method. --- include/Engine/Collision/Collision.h | 6 ++++ src/Engine/Collision/Collision.cpp | 54 +++++++++++++++++----------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index b32d190a..4e764905 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -26,6 +26,12 @@ bool RayVsAABB(const Ray& ray, const AABB& box); //Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance]. bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); +//Return true if the ray hits the triangle. +bool RayVsTriangle(const Ray& ray, + const glm::vec3& v0, + const glm::vec3& v1, + const glm::vec3& v2, + bool trueOnNegativeDistance = false); //Return true if the ray hits the triangle, and the distance is less than outDistance. bool RayVsTriangle(const Ray& ray, const glm::vec3& v0, diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d174eb86..d44c97be 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -116,30 +116,41 @@ bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation) return glm::all(axisesIntersecting); } +bool RayVsTriangle(const Ray& ray, + const glm::vec3& v0, + const glm::vec3& v1, + const glm::vec3& v2, + bool trueOnNegativeDistance) +{ + glm::vec3 e1 = v1 - v0; //v1 - v0 + glm::vec3 e2 = v2 - v0; //v2 - v0 + glm::vec3 m = ray.Origin() - v0; + glm::vec3 MxE1 = glm::cross(m, e1); + glm::vec3 DxE2 = glm::cross(ray.Direction(), e2); + float DetInv = glm::dot(e1, DxE2); + if (std::abs(DetInv) < FLT_EPSILON) { + return false; + } + DetInv = 1.0f / DetInv; + float u = glm::dot(m, DxE2) * DetInv; + float v = glm::dot(ray.Direction(), MxE1) * DetInv; + //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem + if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { + return false; + } + //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. + return trueOnNegativeDistance || 0 <= glm::dot(e2, MxE1) * DetInv; +} + bool RayVsModel(const Ray& ray, const std::vector& modelVertices, const std::vector& modelIndices) { for (int i = 0; i < modelIndices.size(); ++i) { glm::vec3 v0 = modelVertices[modelIndices[i]].Position; - glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0 - glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0 - glm::vec3 m = ray.Origin() - v0; - glm::vec3 MxE1 = glm::cross(m, e1); - glm::vec3 DxE2 = glm::cross(ray.Direction(), e2); - float DetInv = glm::dot(e1, DxE2); - if (std::abs(DetInv) < FLT_EPSILON) { - continue; - } - DetInv = 1.0f / DetInv; - float u = glm::dot(m, DxE2) * DetInv; - float v = glm::dot(ray.Direction(), MxE1) * DetInv; - //u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem - if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) { - continue; - } - //Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit. - if (0 <= glm::dot(e2, MxE1) * DetInv) { + glm::vec3 v1 = modelVertices[modelIndices[++i]].Position; + glm::vec3 v2 = modelVertices[modelIndices[++i]].Position; + if (RayVsTriangle(ray, v0, v1, v2)) { return true; } } @@ -300,7 +311,7 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c triNormal = glm::normalize(triNormal); glm::vec3 diagonal = -signNonZero(triNormal) * half; -#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK +#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //TODO: We should probably performance test with this on/off. #ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) //The diagonal line contains all points P in P = origin + diagonal * t. @@ -310,15 +321,16 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c if (glm::abs(t) > 1) { return false; } - //glm::vec3 intersection = origin + t * diagonal; #endif //Check if intersection point is on the triangle. ray.SetOrigin(origin); ray.SetDirection(diagonal); +#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK + if (RayVsTriangle(ray, v0, v1, v2, true)) { +#else float dist = INFINITY, u, v; if (RayVsTriangle(ray, v0, v1, v2, dist, u, v, true)) { -#ifndef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK if (glm::abs(dist) > glm::length(diagonal)) { return false; } From 3974c649ab8297a8dbf4750643f474f761fa9182 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sat, 23 Jan 2016 10:45:50 +0100 Subject: [PATCH 06/49] WIP on ModelBoxCollision. Octree works in Release mode. --- include/Engine/Collision/CollisionSystem.h | 7 -- include/Engine/Core/Octree.h | 2 +- .../Schema/Entities/ModelCollisionTest.xml | 6 +- src/Engine/Collision/Collision.cpp | 86 +++++++++++++------ src/Engine/Collision/CollisionSystem.cpp | 13 --- src/Engine/Core/Octree.cpp | 5 -- 6 files changed, 64 insertions(+), 55 deletions(-) diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index 5f15a3d5..93ec3d76 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -17,20 +17,13 @@ public: : System(world, eventBroker) , PureSystem("Collidable") , m_Octree(octree) - , zPress(false) { - //TODO: Debug stuff, remove later. - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); } virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: Octree* m_Octree; - bool zPress; - - EventRelay m_EKeyUp; - bool OnKeyUp(const Events::KeyUp &event); }; #endif \ No newline at end of file diff --git a/include/Engine/Core/Octree.h b/include/Engine/Core/Octree.h index bbd27b3c..907d5736 100644 --- a/include/Engine/Core/Octree.h +++ b/include/Engine/Core/Octree.h @@ -111,7 +111,7 @@ struct Child std::vector& m_StaticObjectsRef; std::vector& m_DynamicObjectsRef; - inline bool hasChildren() const; + inline bool hasChildren() const { return m_Children[0] != nullptr; } int childIndexContainingPoint(const glm::vec3& point) const; std::vector childIndicesContainingBox(const AABB& box) const; }; diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml index f7a547f5..f2a78549 100644 --- a/resources/Schema/Entities/ModelCollisionTest.xml +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -23,7 +23,7 @@ - ../assets/Models/Core/UnitQuad.obj + ../assets/Models/Core/Tri.obj @@ -36,11 +36,11 @@ - ../assets/Models/Core/UnitQuad.obj + ../assets/Models/Core/Tri.obj - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d44c97be..f040ccd5 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -248,7 +248,12 @@ bool vectorHasLength(const glm::vec3& vec) return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); } -bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outResolutionVector) +bool AABBvsTriangle(const AABB& box, + const glm::vec3& v0, + const glm::vec3& v1, + const glm::vec3& v2, + glm::vec3& outVector, + int& lineHit) { //Check so we don't have a zero area triangle when calculating the normal. glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); @@ -283,23 +288,22 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c insideAllPlanes[ax] = glm::all(insidePlanes); } if (glm::all(insideAllPlanes)) { - outResolutionVector = glm::vec3(0.f); - LOG_DEBUG("Triangle collision inside"); - return true; //TODO: Resolve. + return false; //If a triangle is completely inside the box, we call it a non-intersection. } + triNormal = glm::normalize(triNormal); Ray ray; - //All triangle lines. - //Check if each line on the triangle intersects any plane on the box. + //All triangle edges. + //Check if any edge on the triangle intersects the box. for (int l = 0; l < 3; ++l) { glm::vec3 edge = triPos[(l + 1) % 3] - triPos[l]; ray.SetOrigin(triPos[l]); ray.SetDirection(edge); float dist; if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) { - outResolutionVector = glm::vec3(0.f); - LOG_DEBUG("Triangle collision lines"); - return true; //TODO: Resolve. + outVector = triNormal; + lineHit = l; + return true; } } @@ -309,7 +313,6 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c //intersect the cube diagonal that comes //closest to being perpendicular to the plane of the polygon. - triNormal = glm::normalize(triNormal); glm::vec3 diagonal = -signNonZero(triNormal) * half; #define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //TODO: We should probably performance test with this on/off. #ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK @@ -337,7 +340,7 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c #endif //Distance between triangle plane, and the diagonal corner, multiplied by the normal. //Signed distance, positive if on the same side as the normal. - outResolutionVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; + outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; return true; } return false; @@ -345,28 +348,59 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, c bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) { + struct Triangle + { + glm::vec3 v0, v1, v2; + }; bool hit = false; - outResolutionVector = glm::vec3(INFINITY); + bool cornerHitTODO = false; + outResolutionVector = glm::vec3(0.f); + std::vector hitTriangles; + std::vector hitNormals; for (int i = 0; i < modelIndices.size(); i += 3) { - glm::vec3 resVec; - if (AABBvsTriangle( - box, - Transform::TransformPoint(modelVertices[modelIndices[i]].Position, modelMatrix), - Transform::TransformPoint(modelVertices[modelIndices[i + 1]].Position, modelMatrix), - Transform::TransformPoint(modelVertices[modelIndices[i + 2]].Position, modelMatrix), - resVec - )) + glm::vec3 outVec; + glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); + int lineHit = -1; + if (AABBvsTriangle(box, v0, v1, v2, outVec, lineHit)) { hit = true; - //If resolution distance is smaller than previous, and is non-zero. - if (glm::length(resVec) < glm::length(outResolutionVector) && vectorHasLength(resVec)) { - outResolutionVector = resVec; + if (lineHit == -1) { + outResolutionVector += outVec; + //TODO: We might be able to return here instead, having only convex geometry. + cornerHitTODO = true; + //return true; + } + else { + const glm::vec3 triPos[] = { + v0, v1, v2 + }; + glm::vec3 edge = triPos[(lineHit + 1) % 3] - triPos[lineHit]; + hitTriangles.push_back({v0, v1, v2}); + hitNormals.push_back(outVec); } } } - //TODO: Unnecessary later, remove it. - if (glm::any(glm::isinf(outResolutionVector))) { - outResolutionVector = glm::vec3(0, 0, 0); + if (hitTriangles.size() > 0) { + if (cornerHitTODO) { + LOG_DEBUG("Both edges and corners was hit on the same model."); + return true; + } + for (const glm::vec3& norm : hitNormals) { + outResolutionVector += norm; + } + //Normalize. + outResolutionVector /= hitNormals.size(); + const glm::vec3& origin = box.Origin(); + const glm::vec3& half = box.HalfSize(); + float maxDist = -10; + for (const Triangle& tri : hitTriangles) { + float d = glm::dot(outResolutionVector, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); + maxDist = std::max(maxDist, d); + } + glm::vec3 tmp = glm::clamp(2.0f * outResolutionVector, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); + outResolutionVector *= maxDist + glm::length(tmp * half); } return hit; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 11d2a836..452a73ef 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -17,11 +17,6 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c ComponentWrapper& cTransform = entity["Transform"]; AABB& boxA = *boundingBox; - //Press 'Z' to enable/disable collision. - if (zPress) { - return; - } - // Collide against octree //std::vector octreeResult; //m_Octree->ObjectsInSameRegion(*boundingBox, octreeResult); @@ -64,11 +59,3 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c } } } - -bool CollisionSystem::OnKeyUp(const Events::KeyUp & event) -{ - if (event.KeyCode == GLFW_KEY_Z) { - zPress = !zPress; - } - return false; -} diff --git a/src/Engine/Core/Octree.cpp b/src/Engine/Core/Octree.cpp index d7feba45..f6e358c8 100644 --- a/src/Engine/Core/Octree.cpp +++ b/src/Engine/Core/Octree.cpp @@ -276,9 +276,4 @@ std::vector Child::childIndicesContainingBox(const AABB& box) const } } -inline bool Child::hasChildren() const -{ - return m_Children[0] != nullptr; -} - } \ No newline at end of file From 71404c882819a10a4016cf95b032f67736911d11 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sat, 23 Jan 2016 14:01:54 +0100 Subject: [PATCH 07/49] Special case for collision vs ground (upward facing) triangles. --- .../Schema/Entities/CollisionTestLevel.xml | 186 ++++++------------ src/Engine/Collision/Collision.cpp | 92 ++++++--- src/Engine/Collision/CollisionSystem.cpp | 1 + 3 files changed, 134 insertions(+), 145 deletions(-) diff --git a/resources/Schema/Entities/CollisionTestLevel.xml b/resources/Schema/Entities/CollisionTestLevel.xml index d5e932c2..76a3b6e6 100644 --- a/resources/Schema/Entities/CollisionTestLevel.xml +++ b/resources/Schema/Entities/CollisionTestLevel.xml @@ -1,122 +1,66 @@ - + + - - - - - - - Models/DummyScene.obj - - - - - - - - - - - Models/Core/UnitSphere.obj - - - - - - - - - - - Models/RotationWidgetX.obj - - - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitRaptor.obj - - - - - - - - - - - - 20 - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - - Models/Core/UnitCube.obj - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + ../assets\Models\Test/ObstacleCourse.obj + + + + + + + + + + + 0.46000027656555176 + + + + + + + + + + + + + ../assets\Models\Core\UnitCube.obj + + + false + + + + + + + + + + + + + + ../assets\Models\Core\colorbox.obj + + + + + + + + + + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index f040ccd5..d134a5d8 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -4,6 +4,7 @@ #include "Engine/GLM.h" #include "Core/World.h" #include "Rendering/Model.h" +#include "imgui/imgui.h" namespace Collision { @@ -248,12 +249,21 @@ bool vectorHasLength(const glm::vec3& vec) return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); } +enum BoxTriHit +{ + Line0 = 0, + Line1, + Line2, + Ground, + Corner +}; + bool AABBvsTriangle(const AABB& box, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, glm::vec3& outVector, - int& lineHit) + BoxTriHit& outHit) { //Check so we don't have a zero area triangle when calculating the normal. glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); @@ -266,6 +276,23 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); + //Check if normal faces upwards, and if so, just push the box upwards on collision. + triNormal = glm::normalize(triNormal); + if (triNormal.y > 0.5f || true) { + //TODO: Optimize calculation since x, z is 0. + //Ray ray(glm::vec3(origin.x, origin.y + half.y, origin.z), glm::vec3(0, -1, 0)); + //float dist = INFINITY, u, v; + //if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < 2.0f * half.y) { + Ray ray(origin, glm::vec3(0, -1, 0)); + float dist = INFINITY, u, v; + if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < half.y) { + outVector = glm::vec3(0, half.y - dist, 0); + outHit = Ground; + return true; + } + //return false; //TODO: Uncomment? + } + const glm::vec3 triPos[] = { v0, v1, v2 }; @@ -291,7 +318,6 @@ bool AABBvsTriangle(const AABB& box, return false; //If a triangle is completely inside the box, we call it a non-intersection. } - triNormal = glm::normalize(triNormal); Ray ray; //All triangle edges. //Check if any edge on the triangle intersects the box. @@ -302,7 +328,7 @@ bool AABBvsTriangle(const AABB& box, float dist; if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) { outVector = triNormal; - lineHit = l; + outHit = (BoxTriHit)l; return true; } } @@ -341,6 +367,7 @@ bool AABBvsTriangle(const AABB& box, //Distance between triangle plane, and the diagonal corner, multiplied by the normal. //Signed distance, positive if on the same side as the normal. outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; + outHit = Corner; return true; } return false; @@ -348,6 +375,7 @@ bool AABBvsTriangle(const AABB& box, bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) { + AABB newBox = box; struct Triangle { glm::vec3 v0, v1, v2; @@ -362,45 +390,61 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - int lineHit = -1; - if (AABBvsTriangle(box, v0, v1, v2, outVec, lineHit)) + BoxTriHit hitCase; + if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase)) { hit = true; - if (lineHit == -1) { - outResolutionVector += outVec; - //TODO: We might be able to return here instead, having only convex geometry. - cornerHitTODO = true; - //return true; - } - else { - const glm::vec3 triPos[] = { - v0, v1, v2 - }; - glm::vec3 edge = triPos[(lineHit + 1) % 3] - triPos[lineHit]; + switch (hitCase) { + case Collision::Line0: + case Collision::Line1: + case Collision::Line2: + //TODO: Resolve. + //const glm::vec3 triPos[] = { + // v0, v1, v2 + //}; + //glm::vec3 edge = triPos[(hitCase + 1) % 3] - triPos[hitCase]; hitTriangles.push_back({v0, v1, v2}); hitNormals.push_back(outVec); + ImGui::Text("triangle edge collision."); + break; + case Collision::Corner: + //TODO: We might be able to return here instead, having only convex geometry. + cornerHitTODO = true; + //outResolutionVector += outVec; + //return true; + ImGui::Text("triangle corner collision."); + outResolutionVector += outVec; + newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); + break; + case Collision::Ground: + default: + outResolutionVector += outVec; + newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); + ImGui::Text("triangle ground collision."); + break; } } } if (hitTriangles.size() > 0) { if (cornerHitTODO) { - LOG_DEBUG("Both edges and corners was hit on the same model."); + ImGui::Text("Both edges and corners was hit on the same model."); return true; } + glm::vec3 lineResolve(0.f); for (const glm::vec3& norm : hitNormals) { - outResolutionVector += norm; + lineResolve += norm; } //Normalize. - outResolutionVector /= hitNormals.size(); - const glm::vec3& origin = box.Origin(); - const glm::vec3& half = box.HalfSize(); + lineResolve /= hitNormals.size(); + const glm::vec3& origin = newBox.Origin(); + const glm::vec3& half = newBox.HalfSize(); float maxDist = -10; for (const Triangle& tri : hitTriangles) { - float d = glm::dot(outResolutionVector, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); + float d = glm::dot(lineResolve, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); maxDist = std::max(maxDist, d); } - glm::vec3 tmp = glm::clamp(2.0f * outResolutionVector, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); - outResolutionVector *= maxDist + glm::length(tmp * half); + glm::vec3 tmp = glm::clamp(2.0f * lineResolve, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); + outResolutionVector += lineResolve * (maxDist + glm::length(tmp * half)); } return hit; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 452a73ef..20854c12 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -56,6 +56,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::vec3 resolutionVector; if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; + cPhysics["Velocity"] = glm::vec3(0, 0, 0); } } } From 6eeb3ea5248e2a0acfa72d81f65363deb24a7038 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sat, 23 Jan 2016 17:50:35 +0100 Subject: [PATCH 08/49] WIP, Bug fix + nitpicks + optimizations. --- resources/Schema/Entities/CollisionTestLevel.xml | 3 ++- src/Engine/Collision/Collision.cpp | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/resources/Schema/Entities/CollisionTestLevel.xml b/resources/Schema/Entities/CollisionTestLevel.xml index 76a3b6e6..5c029cf3 100644 --- a/resources/Schema/Entities/CollisionTestLevel.xml +++ b/resources/Schema/Entities/CollisionTestLevel.xml @@ -42,7 +42,8 @@ - + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index d134a5d8..2b4b989e 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -278,8 +278,8 @@ bool AABBvsTriangle(const AABB& box, //Check if normal faces upwards, and if so, just push the box upwards on collision. triNormal = glm::normalize(triNormal); - if (triNormal.y > 0.5f || true) { - //TODO: Optimize calculation since x, z is 0. + if (triNormal.y > 0.5f) { + //TODO: Optimize calculation since x, z is 0, y is -1. //Ray ray(glm::vec3(origin.x, origin.y + half.y, origin.z), glm::vec3(0, -1, 0)); //float dist = INFINITY, u, v; //if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < 2.0f * half.y) { @@ -290,7 +290,7 @@ bool AABBvsTriangle(const AABB& box, outHit = Ground; return true; } - //return false; //TODO: Uncomment? + return false; } const glm::vec3 triPos[] = { @@ -300,7 +300,8 @@ bool AABBvsTriangle(const AABB& box, auto insideAllPlanes = glm::tvec3(false); //All triangle vertex points. //Check if the triangle is completely outside or inside the box. - for (int ax = 0; ax < 3; ++ax) { + //First test x, then z, lastly y, since y is least likely to result in a early false. + for (int ax : { 0, 2, 1 }) { auto outsideMinPlane = glm::tvec3(false); auto outsideMaxPlane = glm::tvec3(false); auto insidePlanes = glm::tvec3(false); @@ -385,14 +386,13 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model outResolutionVector = glm::vec3(0.f); std::vector hitTriangles; std::vector hitNormals; - for (int i = 0; i < modelIndices.size(); i += 3) { + for (int i = 0; i < modelIndices.size(); ) { glm::vec3 outVec; glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); BoxTriHit hitCase; - if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase)) - { + if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase)) { hit = true; switch (hitCase) { case Collision::Line0: @@ -403,7 +403,7 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model // v0, v1, v2 //}; //glm::vec3 edge = triPos[(hitCase + 1) % 3] - triPos[hitCase]; - hitTriangles.push_back({v0, v1, v2}); + hitTriangles.push_back({ v0, v1, v2 }); hitNormals.push_back(outVec); ImGui::Text("triangle edge collision."); break; From e6224a4e96ab9d9d67c43810353098207927213d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sat, 23 Jan 2016 18:31:27 +0100 Subject: [PATCH 09/49] WIP (not working), attempt at separating axis theorem stuff. --- src/Engine/Collision/Collision.cpp | 96 +++++------------------------- 1 file changed, 15 insertions(+), 81 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 2b4b989e..911b87bc 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -275,103 +275,37 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); - - //Check if normal faces upwards, and if so, just push the box upwards on collision. - triNormal = glm::normalize(triNormal); - if (triNormal.y > 0.5f) { - //TODO: Optimize calculation since x, z is 0, y is -1. - //Ray ray(glm::vec3(origin.x, origin.y + half.y, origin.z), glm::vec3(0, -1, 0)); - //float dist = INFINITY, u, v; - //if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < 2.0f * half.y) { - Ray ray(origin, glm::vec3(0, -1, 0)); - float dist = INFINITY, u, v; - if (RayVsTriangle(ray, v0, v1, v2, dist, u, v) && dist < half.y) { - outVector = glm::vec3(0, half.y - dist, 0); - outHit = Ground; - return true; - } - return false; - } - const glm::vec3 triPos[] = { v0, v1, v2 }; - auto insideAllPlanes = glm::tvec3(false); - //All triangle vertex points. - //Check if the triangle is completely outside or inside the box. - //First test x, then z, lastly y, since y is least likely to result in a early false. - for (int ax : { 0, 2, 1 }) { - auto outsideMinPlane = glm::tvec3(false); - auto outsideMaxPlane = glm::tvec3(false); - auto insidePlanes = glm::tvec3(false); - for (int pos = 0; pos < 3; ++pos) { - outsideMinPlane[pos] = (min[ax] > triPos[pos][ax]); - outsideMaxPlane[pos] = (triPos[pos][ax] > max[ax]); - insidePlanes[pos] = !(outsideMinPlane[pos] || outsideMaxPlane[pos]); - } - if (glm::all(outsideMinPlane) || glm::all(outsideMaxPlane)) { - return false; - } - insideAllPlanes[ax] = glm::all(insidePlanes); - } - if (glm::all(insideAllPlanes)) { - return false; //If a triangle is completely inside the box, we call it a non-intersection. + for (int axis : {1, 0, 2}) { + //2D Triangle. + //for axis=0,1,2: 2d point takes from xy,xz,yx. + int dim1 = axis == 2 ? 0 : 1; //0,0,1 + int dim2 = axis == 0 ? 1 : 2; //1,2,2 + glm::vec2 t0(triPos[0][dim1], triPos[0][dim2]); + glm::vec2 t1(triPos[1][dim1], triPos[1][dim2]); + glm::vec2 t2(triPos[2][dim1], triPos[2][dim2]); + //Project tri, + //Project box, + //if projections don't overlap, return false. } - Ray ray; - //All triangle edges. - //Check if any edge on the triangle intersects the box. - for (int l = 0; l < 3; ++l) { - glm::vec3 edge = triPos[(l + 1) % 3] - triPos[l]; - ray.SetOrigin(triPos[l]); - ray.SetDirection(edge); - float dist; - if (RayVsAABB(ray, box, dist) && dist <= glm::length(edge)) { - outVector = triNormal; - outHit = (BoxTriHit)l; - return true; - } - } - - //None of the polygon's edges intersects the cube, finally, check if any of the four - //cube diagonals intersect the interior of the polygon. //If the polygon does intersect any of the cube diagonals, it will //intersect the cube diagonal that comes //closest to being perpendicular to the plane of the polygon. - + triNormal = glm::normalize(triNormal); glm::vec3 diagonal = -signNonZero(triNormal) * half; -#define EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //TODO: We should probably performance test with this on/off. -#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) //The diagonal line contains all points P in P = origin + diagonal * t. float t = glm::dot(triNormal, v0 - origin) / glm::dot(triNormal, diagonal); - - //If intersection point between plane and diagonal is not within the box. + //If intersection point between plane and diagonal is within the box. if (glm::abs(t) > 1) { return false; } -#endif - - //Check if intersection point is on the triangle. - ray.SetOrigin(origin); - ray.SetDirection(diagonal); -#ifdef EARLY_OUT_OR_MAYBE_JUST_EXTRA_WORK - if (RayVsTriangle(ray, v0, v1, v2, true)) { -#else - float dist = INFINITY, u, v; - if (RayVsTriangle(ray, v0, v1, v2, dist, u, v, true)) { - if (glm::abs(dist) > glm::length(diagonal)) { - return false; - } -#endif - //Distance between triangle plane, and the diagonal corner, multiplied by the normal. - //Signed distance, positive if on the same side as the normal. - outVector = -glm::dot(triNormal, origin + diagonal - v0) * triNormal; - outHit = Corner; - return true; - } - return false; + //TODO: Resolve it. + return true; } bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) From 910b3d10e4b18f20a1e1ed32430e077d3f351943 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sun, 24 Jan 2016 15:32:10 +0100 Subject: [PATCH 10/49] WIP (false collisions), collision method expanded, not working. --- .../Schema/Entities/ModelCollisionTest.xml | 7 +- src/Engine/Collision/Collision.cpp | 184 +++++++++--------- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/resources/Schema/Entities/ModelCollisionTest.xml b/resources/Schema/Entities/ModelCollisionTest.xml index f2a78549..c4a3f81b 100644 --- a/resources/Schema/Entities/ModelCollisionTest.xml +++ b/resources/Schema/Entities/ModelCollisionTest.xml @@ -27,9 +27,8 @@ - - - + + @@ -56,7 +55,7 @@ - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 911b87bc..48a6a1e3 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -249,24 +249,70 @@ bool vectorHasLength(const glm::vec3& vec) return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); } -enum BoxTriHit +bool AARectangleVsTriangle(const glm::vec2& boxMin, + const glm::vec2& boxMax, + const std::array& triPos) { - Line0 = 0, - Line1, - Line2, - Ground, - Corner -}; + //Project along box normals (coordinate axes, since it's axis-aligned). + for (int ax = 0; ax < 2; ++ax) { + float minTri = INFINITY; + float maxTri = -INFINITY; + for (const glm::vec2& t : triPos) { + minTri = std::min(t[ax], minTri); + maxTri = std::max(t[ax], maxTri); + } + if (minTri > boxMax[ax] || maxTri < boxMin[ax]) { + return false; + } + } + //Project along triangle normals. + //Put edges into normal vector, make normals in the loop. + std::array triNormals = { + triPos[1] - triPos[0], + triPos[2] - triPos[1], + triPos[0] - triPos[2] + }; + std::array boxPos = { + boxMax, + glm::vec2(boxMax.x, boxMin.y), + glm::vec2(boxMin.x, boxMax.y), + boxMin + }; + for (auto& normal : triNormals) { + //Rotate edge to a normal. + normal = glm::vec2(-normal.y, normal.x); + //Project triangle onto the normal. + float minTri = INFINITY; + float maxTri = -INFINITY; + for (const glm::vec2& point : triPos) { + float dot = glm::dot(normal, point); + minTri = std::min(dot, minTri); + maxTri = std::max(dot, maxTri); + } + //Project box onto the normal. + float minBox = INFINITY; + float maxBox = -INFINITY; + for (const glm::vec2& point : boxPos) { + float dot = glm::dot(normal, point); + minBox = std::min(dot, minTri); + maxBox = std::max(dot, maxTri); + } + if (maxBox < minTri || minBox > maxTri) { + return false; + } + } + return true; +} + +//An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } +constexpr std::array, 3> DimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); bool AABBvsTriangle(const AABB& box, - const glm::vec3& v0, - const glm::vec3& v1, - const glm::vec3& v2, - glm::vec3& outVector, - BoxTriHit& outHit) + const std::array& triPos, + glm::vec3& outVector) { //Check so we don't have a zero area triangle when calculating the normal. - glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0); + glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); if (!vectorHasLength(triNormal)) { return false; } @@ -275,111 +321,69 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); - const glm::vec3 triPos[] = { - v0, v1, v2 - }; - - for (int axis : {1, 0, 2}) { + glm::tvec3 axisHit(false, false, false); + int i = 0; + for (std::pair dim : DimensionPairs) { //2D Triangle. //for axis=0,1,2: 2d point takes from xy,xz,yx. - int dim1 = axis == 2 ? 0 : 1; //0,0,1 - int dim2 = axis == 0 ? 1 : 2; //1,2,2 - glm::vec2 t0(triPos[0][dim1], triPos[0][dim2]); - glm::vec2 t1(triPos[1][dim1], triPos[1][dim2]); - glm::vec2 t2(triPos[2][dim1], triPos[2][dim2]); - //Project tri, - //Project box, + //Project triangle. + std::array t2D = { + glm::vec2(triPos[0][dim.first], triPos[0][dim.second]), + glm::vec2(triPos[1][dim.first], triPos[1][dim.second]), + glm::vec2(triPos[2][dim.first], triPos[2][dim.second]) + }; + //Project box. + glm::vec2 boxMin(min[dim.first], min[dim.second]); + glm::vec2 boxMax(max[dim.first], max[dim.second]); //if projections don't overlap, return false. + if (!AARectangleVsTriangle(boxMin, boxMax, t2D)) { + //return false; + } else { + axisHit[i] = true; + ImGui::Text("Triangle collision: Box axis %s", i == 0 ? "y" : i == 1 ? "z" : "x"); + } + ++i; } - //If the polygon does intersect any of the cube diagonals, it will + //If the triangle does intersect any of the cube diagonals, it will //intersect the cube diagonal that comes - //closest to being perpendicular to the plane of the polygon. + //closest to being perpendicular to the plane of the triangle. triNormal = glm::normalize(triNormal); glm::vec3 diagonal = -signNonZero(triNormal) * half; //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) //The diagonal line contains all points P in P = origin + diagonal * t. - float t = glm::dot(triNormal, v0 - origin) / glm::dot(triNormal, diagonal); + float t = glm::dot(triNormal, triPos[0] - origin) / glm::dot(triNormal, diagonal); //If intersection point between plane and diagonal is within the box. if (glm::abs(t) > 1) { return false; + } else { + ImGui::Text("Triangle collision: Triangle axis."); + return glm::all(axisHit); } //TODO: Resolve it. + outVector = glm::vec3(0.f); return true; } bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) { AABB newBox = box; - struct Triangle - { - glm::vec3 v0, v1, v2; - }; bool hit = false; - bool cornerHitTODO = false; outResolutionVector = glm::vec3(0.f); - std::vector hitTriangles; - std::vector hitNormals; for (int i = 0; i < modelIndices.size(); ) { + std::array triVertices = { + Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) + }; glm::vec3 outVec; - glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - BoxTriHit hitCase; - if (AABBvsTriangle(newBox, v0, v1, v2, outVec, hitCase)) { + if (AABBvsTriangle(newBox, triVertices, outVec)) { + ImGui::Text("Triangle collision: True."); hit = true; - switch (hitCase) { - case Collision::Line0: - case Collision::Line1: - case Collision::Line2: - //TODO: Resolve. - //const glm::vec3 triPos[] = { - // v0, v1, v2 - //}; - //glm::vec3 edge = triPos[(hitCase + 1) % 3] - triPos[hitCase]; - hitTriangles.push_back({ v0, v1, v2 }); - hitNormals.push_back(outVec); - ImGui::Text("triangle edge collision."); - break; - case Collision::Corner: - //TODO: We might be able to return here instead, having only convex geometry. - cornerHitTODO = true; - //outResolutionVector += outVec; - //return true; - ImGui::Text("triangle corner collision."); - outResolutionVector += outVec; - newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); - break; - case Collision::Ground: - default: - outResolutionVector += outVec; - newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); - ImGui::Text("triangle ground collision."); - break; - } + outResolutionVector += outVec; + newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); } } - if (hitTriangles.size() > 0) { - if (cornerHitTODO) { - ImGui::Text("Both edges and corners was hit on the same model."); - return true; - } - glm::vec3 lineResolve(0.f); - for (const glm::vec3& norm : hitNormals) { - lineResolve += norm; - } - //Normalize. - lineResolve /= hitNormals.size(); - const glm::vec3& origin = newBox.Origin(); - const glm::vec3& half = newBox.HalfSize(); - float maxDist = -10; - for (const Triangle& tri : hitTriangles) { - float d = glm::dot(lineResolve, 0.333f * (tri.v0 + tri.v1 + tri.v2) - origin); - maxDist = std::max(maxDist, d); - } - glm::vec3 tmp = glm::clamp(2.0f * lineResolve, glm::vec3(-1, -1, -1), glm::vec3(1, 1, 1)); - outResolutionVector += lineResolve * (maxDist + glm::length(tmp * half)); - } return hit; } From f1343e2f82b14a74710b8b01f5e1926851c9967d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Sun, 24 Jan 2016 21:08:42 +0100 Subject: [PATCH 11/49] Collision may be working, kind of. --- src/Engine/Collision/Collision.cpp | 69 +++++++++++++++++++----------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 48a6a1e3..41ca2155 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -243,16 +243,19 @@ inline glm::vec3 signNonZero(const glm::vec3& x) return r; } - -bool vectorHasLength(const glm::vec3& vec) +template +bool vectorHasLength(const T& vec) { - return glm::any(glm::greaterThan(glm::abs(vec), glm::vec3(0.0001f, 0.0001f, 0.0001f))); + return glm::any(glm::greaterThan(glm::abs(vec), T(0.0001f))); } -bool AARectangleVsTriangle(const glm::vec2& boxMin, +bool rectangleVsTriangle(const glm::vec2& boxMin, const glm::vec2& boxMax, - const std::array& triPos) + const std::array& triPos, + glm::vec2& resolutionDirection, + float& resolutionDistance) { + resolutionDistance = INFINITY; //Project along box normals (coordinate axes, since it's axis-aligned). for (int ax = 0; ax < 2; ++ax) { float minTri = INFINITY; @@ -264,6 +267,12 @@ bool AARectangleVsTriangle(const glm::vec2& boxMin, if (minTri > boxMax[ax] || maxTri < boxMin[ax]) { return false; } + float push = std::min(maxTri - boxMin[ax], boxMax[ax] - minTri); + if (push < resolutionDistance) { + resolutionDistance = push; + resolutionDirection[1 - ax] = 0.f; + resolutionDirection[ax] = resolutionDistance; + } } //Project along triangle normals. //Put edges into normal vector, make normals in the loop. @@ -279,6 +288,9 @@ bool AARectangleVsTriangle(const glm::vec2& boxMin, boxMin }; for (auto& normal : triNormals) { + if (!vectorHasLength(normal)) { + continue; + } //Rotate edge to a normal. normal = glm::vec2(-normal.y, normal.x); //Project triangle onto the normal. @@ -294,18 +306,24 @@ bool AARectangleVsTriangle(const glm::vec2& boxMin, float maxBox = -INFINITY; for (const glm::vec2& point : boxPos) { float dot = glm::dot(normal, point); - minBox = std::min(dot, minTri); - maxBox = std::max(dot, maxTri); + minBox = std::min(dot, minBox); + maxBox = std::max(dot, maxBox); } if (maxBox < minTri || minBox > maxTri) { return false; } + //Here: maxBox > minTri && minBox < maxTri + float push = std::min(maxTri - minBox, maxBox - minTri); + if (push < resolutionDistance) { + resolutionDistance = push; + resolutionDirection = resolutionDistance * glm::normalize(normal); + } } return true; } //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } -constexpr std::array, 3> DimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); +constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); bool AABBvsTriangle(const AABB& box, const std::array& triPos, @@ -321,11 +339,11 @@ bool AABBvsTriangle(const AABB& box, const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); - glm::tvec3 axisHit(false, false, false); - int i = 0; - for (std::pair dim : DimensionPairs) { + float minimumTranslation = INFINITY; + + //For each projection in xy-, xz-, and yx-planes. + for (std::pair dim : dimensionPairs) { //2D Triangle. - //for axis=0,1,2: 2d point takes from xy,xz,yx. //Project triangle. std::array t2D = { glm::vec2(triPos[0][dim.first], triPos[0][dim.second]), @@ -335,33 +353,35 @@ bool AABBvsTriangle(const AABB& box, //Project box. glm::vec2 boxMin(min[dim.first], min[dim.second]); glm::vec2 boxMax(max[dim.first], max[dim.second]); + glm::vec2 resolutionVector; + float resolutionDist; //if projections don't overlap, return false. - if (!AARectangleVsTriangle(boxMin, boxMax, t2D)) { - //return false; - } else { - axisHit[i] = true; - ImGui::Text("Triangle collision: Box axis %s", i == 0 ? "y" : i == 1 ? "z" : "x"); + if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist)) { + return false; + } else if (resolutionDist < minimumTranslation) { + outVector = glm::vec3(0.f); + outVector[dim.first] = resolutionVector.x; + outVector[dim.second] = resolutionVector.y; + minimumTranslation = resolutionDist; } - ++i; } //If the triangle does intersect any of the cube diagonals, it will //intersect the cube diagonal that comes //closest to being perpendicular to the plane of the triangle. triNormal = glm::normalize(triNormal); - glm::vec3 diagonal = -signNonZero(triNormal) * half; + glm::vec3 diagonal = signNonZero(triNormal) * half; //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) //The diagonal line contains all points P in P = origin + diagonal * t. float t = glm::dot(triNormal, triPos[0] - origin) / glm::dot(triNormal, diagonal); //If intersection point between plane and diagonal is within the box. if (glm::abs(t) > 1) { return false; - } else { - ImGui::Text("Triangle collision: Triangle axis."); - return glm::all(axisHit); } - //TODO: Resolve it. - outVector = glm::vec3(0.f); + glm::vec3 cornerResolution = (1+t) * diagonal; + if (glm::length(cornerResolution) < minimumTranslation) { + outVector = cornerResolution; + } return true; } @@ -378,7 +398,6 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model }; glm::vec3 outVec; if (AABBvsTriangle(newBox, triVertices, outVec)) { - ImGui::Text("Triangle collision: True."); hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); From 3389b965eb888a8a5c8ebe33a91da574568a3d09 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 25 Jan 2016 10:55:05 +0100 Subject: [PATCH 12/49] Test on game level v1. --- .../Schema/Entities/LevelCollisionTest.xml | 43 ++++++++++++++++++ src/Engine/Collision/Collision.cpp | 44 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 resources/Schema/Entities/LevelCollisionTest.xml diff --git a/resources/Schema/Entities/LevelCollisionTest.xml b/resources/Schema/Entities/LevelCollisionTest.xml new file mode 100644 index 00000000..0feb9a11 --- /dev/null +++ b/resources/Schema/Entities/LevelCollisionTest.xml @@ -0,0 +1,43 @@ + + + + + + + ../assets\Models/MapVersion1.obj + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.obj + + + false + + + + + + + + + + + + + + + + + + + + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 41ca2155..7e9edb31 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -403,6 +403,50 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); } } + + //outResolutionVector = glm::vec3(INFINITY); + //std::stack testBoxes; + //std::stack resolveIndices; + //std::stack resolveVectors; + //resolveVectors.push(glm::vec3(0.f)); + //resolveIndices.push(0); + //testBoxes.push(box); + //do { + // int i = resolveIndices.top(); + // resolveIndices.pop(); + // while (i < modelIndices.size()) { + // std::array triVertices = { + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) + // }; + // glm::vec3 outVec; + // bool test = AABBvsTriangle(testBoxes.top(), triVertices, outVec); + // if (test) { + // hit = true; + // //emplace? + // resolveIndices.push(i); + // testBoxes.push(AABB::FromOriginSize(box.Origin() + outVec, box.Size())); + // resolveVectors.top() += outVec; + // } + // } + // testBoxes.pop(); + // resolveVectors.push(glm::vec3(0.f)); + //} while (!resolveIndices.empty()); + //if (hit) { + // if (!resolveVectors.empty()) { + // while (!resolveVectors.empty()) { + // if (glm::length2(resolveVectors.top()) < glm::length2(outResolutionVector)) { + // outResolutionVector = resolveVectors.top(); + // } + // resolveVectors.pop(); + // } + // } else { + // //TODO: This won't happen. + // ImGui::Text("Collision, but not resolved."); + // } + // return true; + //} return hit; } From 6ea490e215775c1e11ae0b7bdee39396f83b543b Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 27 Jan 2016 10:34:26 +0100 Subject: [PATCH 13/49] Tried a horrible recursive method, extreme framedrop. --- include/Engine/Collision/Collision.h | 1 + .../Schema/Entities/LevelCollisionTest.xml | 6 +- src/Engine/Collision/Collision.cpp | 62 +++++++++++++++++-- src/Engine/Collision/CollisionSystem.cpp | 12 ++-- 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 4e764905..6e2d679e 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -65,6 +65,7 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, + const glm::vec3& boxVelocity, glm::vec3& outResolutionVector); //Return true if the boxes are intersecting. diff --git a/resources/Schema/Entities/LevelCollisionTest.xml b/resources/Schema/Entities/LevelCollisionTest.xml index 0feb9a11..ce0fe405 100644 --- a/resources/Schema/Entities/LevelCollisionTest.xml +++ b/resources/Schema/Entities/LevelCollisionTest.xml @@ -6,9 +6,7 @@ ../assets\Models/MapVersion1.obj - - - + @@ -24,7 +22,7 @@ - + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 7e9edb31..96d908ff 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -327,11 +327,14 @@ constexpr std::array, 3> dimensionPairs({ std::pair& triPos, + const glm::vec3& boxVelocity, glm::vec3& outVector) { //Check so we don't have a zero area triangle when calculating the normal. + //Also, don't check a triangle facing away from the player. + //Less checks, and we should be able to walk out from models if we are trapped inside. glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); - if (!vectorHasLength(triNormal)) { + if (!vectorHasLength(triNormal) || glm::dot(triNormal, boxVelocity) > 0) { return false; } @@ -385,10 +388,18 @@ bool AABBvsTriangle(const AABB& box, return true; } -bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& outResolutionVector) +bool AABBvsTriangles(const AABB& box, + const std::vector& modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix, + const glm::vec3& boxVelocity, + glm::vec3& outResolutionVector, + int startIndex, + int recursiveDepth) { - AABB newBox = box; bool hit = false; + + AABB newBox = box; outResolutionVector = glm::vec3(0.f); for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { @@ -397,13 +408,38 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) }; glm::vec3 outVec; - if (AABBvsTriangle(newBox, triVertices, outVec)) { + if (AABBvsTriangle(newBox, triVertices, boxVelocity, outVec)) { hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); } } + //outResolutionVector = glm::vec3(INFINITY); + //if (recursiveDepth > 2) { + // return true; + //} + //for (int i = startIndex; i < modelIndices.size(); ) { + // std::array triVertices = { + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), + // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) + // }; + // glm::vec3 outVec; + // if (AABBvsTriangle(box, triVertices, boxVelocity, outVec) && glm::length2(outVec) < glm::length2(outResolutionVector)) { + // hit = true; + // glm::vec3 potentialResolution = outVec; + // const AABB& resolvedBox = AABB::FromOriginSize(box.Origin() + potentialResolution, box.Size()); + // if (AABBvsTriangles(resolvedBox, modelVertices, modelIndices, modelMatrix, boxVelocity, outVec, i, recursiveDepth+1)) { + // potentialResolution += outVec; + // if (glm::length2(potentialResolution) > glm::length2(outResolutionVector)) { + // continue; + // } + // } + // outResolutionVector = potentialResolution; + // } + //} + //outResolutionVector = glm::vec3(INFINITY); //std::stack testBoxes; //std::stack resolveIndices; @@ -449,6 +485,24 @@ bool AABBvsTriangles(const AABB& box, const std::vector& model //} return hit; } +bool AABBvsTriangles(const AABB& box, + const std::vector& modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix, + const glm::vec3& boxVelocity, + glm::vec3& outResolutionVector) +{ + return AABBvsTriangles( + box, + modelVertices, + modelIndices, + modelMatrix, + boxVelocity, + outResolutionVector, + 0, + 0 + ); +} bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) { diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 20854c12..612d0707 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -41,11 +41,6 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } - auto absPosition = Transform::AbsolutePosition(m_World, cModel.EntityID); - auto absOrientation = Transform::AbsoluteOrientation(m_World, cModel.EntityID); - auto absScale = Transform::AbsoluteScale(m_World, cModel.EntityID); - glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); - RawModel* model; try { model = ResourceManager::Load(cModel["Resource"]); @@ -53,8 +48,13 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } + auto absPosition = Transform::AbsolutePosition(m_World, cModel.EntityID); + auto absOrientation = Transform::AbsoluteOrientation(m_World, cModel.EntityID); + auto absScale = Transform::AbsoluteScale(m_World, cModel.EntityID); + glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); + glm::vec3 resolutionVector; - if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, (glm::vec3&)cPhysics["Velocity"], resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; cPhysics["Velocity"] = glm::vec3(0, 0, 0); } From 5cdf6db3404904ca799bed8d65e880739d4a6d26 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 27 Jan 2016 14:46:45 +0100 Subject: [PATCH 14/49] Modified HealthSystem so it actually publishes the DeathEvent. Modified EPlayerHealthPickup. Fixed 2 tests. Started work on PlayerDeathSystem --- include/Engine/Core/EPlayerDamage.h | 1 + include/Engine/Core/EPlayerHealthPickup.h | 4 +- include/Game/Systems/HealthSystem.h | 2 +- include/Game/Systems/PlayerDeathSystem.h | 39 ++++++++ resources/Schema/Entities/GameMap.xml | 4 +- src/Game/Game.cpp | 2 + src/Game/Systems/HealthSystem.cpp | 45 ++------- src/Game/Systems/PlayerDeathSystem.cpp | 116 ++++++++++++++++++++++ src/Tests/CollisionTest.cpp | 2 +- src/Tests/HealthSystemTest.cpp | 4 +- 10 files changed, 176 insertions(+), 43 deletions(-) create mode 100644 include/Game/Systems/PlayerDeathSystem.h create mode 100644 src/Game/Systems/PlayerDeathSystem.cpp diff --git a/include/Engine/Core/EPlayerDamage.h b/include/Engine/Core/EPlayerDamage.h index a7e135ce..8ba3907e 100644 --- a/include/Engine/Core/EPlayerDamage.h +++ b/include/Engine/Core/EPlayerDamage.h @@ -9,6 +9,7 @@ namespace Events struct PlayerDamage : Event { + //NOTE: this struct is missing information on what the damageSource is EntityWrapper Player; double Damage; }; diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h index f3158f92..46ed76db 100644 --- a/include/Engine/Core/EPlayerHealthPickup.h +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -2,15 +2,15 @@ #define EPlayerHealthPickup_h__ #include "EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { struct PlayerHealthPickup : Event { + EntityWrapper Player; double HealthAmount; - EntityID PlayerHealedID; }; } diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 3b069349..46f24630 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -26,7 +26,7 @@ private: EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; - bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); + bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e); //vector which will keep track of health changes std::vector> m_DeltaHealthVector; diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h new file mode 100644 index 00000000..3f7268ca --- /dev/null +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -0,0 +1,39 @@ +#ifndef PlayerDeathSystem_h__ +#define PlayerDeathSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "Systems/SpawnerSystem.h" +#include "Events/ESpawnerSpawn.h" +#include "Core/EPlayerSpawned.h" +#include "Rendering/ESetCamera.h" +#include "Core/ConfigFile.h" + +#include "Core/EPlayerDeath.h" +//tests +#include "Core/EPlayerDamage.h" + +class PlayerDeathSystem : public ImpureSystem +{ +public: + PlayerDeathSystem(World* world, EventBroker* eventBroker); + + virtual void Update(double dt) override; + +private: + struct SpawnRequest + { + int PlayerID; + ComponentInfo::EnumType Team; + }; + + bool m_NetworkEnabled = false; + std::vector m_SpawnRequests; + std::map m_PlayerEntities; + + EventRelay m_OnInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_OnPlayerDeath; + bool OnPlayerDeath(Events::PlayerDeath& e); +}; +#endif \ No newline at end of file diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 97fd3f4d..b37f702d 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -139,7 +139,7 @@ - + @@ -201,7 +201,7 @@ - + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d13d62d4..b0c10a74 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -7,6 +7,7 @@ #include "Systems/PlayerMovementSystem.h" #include "Systems/SpawnerSystem.h" #include "Systems/PlayerSpawnSystem.h" +#include "Systems/PlayerDeathSystem.h" #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" #include "Game/Systems/WeaponSystem.h" @@ -86,6 +87,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 9e118070..26d38c69 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -11,38 +11,6 @@ HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker) void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) - double maxHealth = (double)component["MaxHealth"]; - - //process the DeltaHealthVector and change the entitys health accordingly - for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) - { - auto deltaHP = m_DeltaHealthVector[i - 1]; - //if we have a healthchange for the current player and health is greater than 0, then apply it - if (std::get<0>(deltaHP) == component.EntityID && (double)component["Health"] > 0.0f) { - //get the deltaHP value from the tuple and make sure you dont get more than maxHealth - double newHealth = std::min((double)component["Health"] + (double)std::get<1>(deltaHP), maxHealth); - component["Health"] = newHealth; - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); - //check if health is <= 0 - if ((double)component["Health"] <= 0.0f) { - component["Health"] = 0.0; - //publish death event - Events::PlayerDeath e; - e.PlayerID = component.EntityID; - m_EventBroker->Publish(e); - //clear the remaining hpDeltas for the dead player - for (size_t j = m_DeltaHealthVector.size(); j > 0; j--) - { - if (std::get<0>(m_DeltaHealthVector[j - 1]) == component.EntityID) - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1); - } - //delete the player and break the loop - m_World->DeleteEntity(entity.ID); - break; - } - } - } } bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) @@ -52,16 +20,23 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) health -= e.Damage; if (health <= 0.0) { + Events::PlayerDeath ePlayerDeath; + ePlayerDeath.PlayerID = e.Player.ID; + m_EventBroker->Publish(ePlayerDeath); + m_World->DeleteEntity(e.Player.ID); } return true; } -bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) +bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e) { - //save the changed HP to a vector. it will be taken care of in UpdateComponent - m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount)); + ComponentWrapper cHealth = e.Player["Health"]; + double& health = cHealth["Health"]; + //NOTE: its possible to get more than MaxHealth health + health += e.HealthAmount; + return true; } diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp new file mode 100644 index 00000000..dcee3a92 --- /dev/null +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -0,0 +1,116 @@ +#include "Systems/PlayerDeathSystem.h" + +PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) +{ + EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerDeathSystem::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); + m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); +} + +void PlayerDeathSystem::Update(double dt) +{ + auto playerSpawns = m_World->GetComponents("PlayerSpawn"); + if (playerSpawns == nullptr) { + return; + } + + for (auto& req : m_SpawnRequests) { + for (auto& cPlayerSpawn : *playerSpawns) { + EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); + if (!spawner.HasComponent("Spawner")) { + continue; + } + + // If the spawner has a team affiliation, check it + if (spawner.HasComponent("Team")) { + if ((int)spawner["Team"]["Team"] != req.Team) { + continue; + } + } + + // Spawn the player! + EntityWrapper player = SpawnerSystem::Spawn(spawner); + // Set the player team affiliation + player["Team"]["Team"] = req.Team; + + // Publish a PlayerSpawned event + Events::PlayerSpawned e; + e.PlayerID = req.PlayerID; + e.Player = player; + e.Spawner = spawner; + m_EventBroker->Publish(e); + + } + } + m_SpawnRequests.clear(); +} + +bool PlayerDeathSystem::OnInputCommand(const Events::InputCommand& e) +{ + //testing: Jump -> playerdamage + if (e.Command != "Jump") { + return false; + } + + // 0 = released + if (e.Value != 0) { + return false; + } + + auto players = m_World->GetComponents("Player"); + + for (auto& cPlayer : *players) { + EntityWrapper player(m_World, cPlayer.EntityID); + Events::PlayerDamage e; + e.Player = player; + e.Damage = 50; + m_EventBroker->Publish(e); + } + + + + return true; +} + +bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) +{ + //// When a player is actually spawned (since the actual spawning is handled on the server) + + //// Check if a player already exists + //if (m_PlayerEntities.count(e.PlayerID) != 0) { + // // TODO: Disallow infinite respawning here + // m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); + //} + + //// Store the player for future reference + //m_PlayerEntities[e.PlayerID] = e.Player; + + //// Set the camera to the correct entity + //EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera"); + //if (cameraEntity.Valid()) { + // Events::SetCamera e; + // e.CameraEntity = cameraEntity; + // m_EventBroker->Publish(e); + //} + + //// HACK: Set the player model color to team color + //EntityWrapper playerModel = e.Player.FirstChildByName("PlayerModel"); + //if (playerModel.Valid() && e.Player.HasComponent("Team")) { + // ComponentWrapper cTeam = e.Player["Team"]; + // ComponentWrapper cModel = playerModel["Model"]; + // if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Red")) { + // cModel["Color"] = glm::vec3(1.f, 0.f, 0.f); + // } else if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Blue")) { + // cModel["Color"] = glm::vec3(0.f, 0.25f, 1.f); + // } + //} + + //// TODO: Set the player name to whatever + //EntityWrapper playerName = e.Player.FirstChildByName("PlayerName"); + //if (playerName.Valid()) { + // playerName["Text"]["Content"] = e.PlayerName; + //} + + return true; +} \ No newline at end of file diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 67b6ce19..6cb6c88b 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -29,7 +29,7 @@ void RayTest(std::string fileName) { Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0)); //using a - here, else we have to init the renderingsystem + //here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); BOOST_REQUIRE(unitBox != nullptr); diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index bdd9ba4b..6a434a9a 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -69,8 +69,8 @@ GameHealthSystemTest::GameHealthSystemTest() m_EventBroker->Publish(e3); //damage player with 50 Events::PlayerDamage e; - e.DamageAmount = 50.0f; - e.PlayerDamagedID = healthsID; + e.Damage = 50.0f; +// e.PlayerDamagedID = healthsID; m_EventBroker->Publish(e); //heal some other player with 40 Events::PlayerHealthPickup e2; From 7497ff39d2e3d73ed4a3d34b8345236e575b6cf9 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 27 Jan 2016 18:00:31 +0100 Subject: [PATCH 15/49] Simon added Copy method to ComponentWrapper. Its being used in PlayerDeathSystem to copy model,animation,transform. TODO: 3rd person camera, cleanup, tests --- include/Engine/Core/ComponentWrapper.h | 5 ++ include/Engine/Core/EPlayerDeath.h | 3 +- src/Game/Systems/HealthSystem.cpp | 4 +- src/Game/Systems/PlayerDeathSystem.cpp | 69 +++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index f09bbfe3..1ca0347d 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -43,6 +43,11 @@ struct ComponentWrapper // Specialization for string literals template void SetField(std::string name, const char(&value)[N]) { Field(name) = std::string(value); } + + void Copy(ComponentWrapper& destination) + { + memcpy(destination.Data, this->Data, Info.Stride); + } struct SubscriptProxy { diff --git a/include/Engine/Core/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h index 00ede5ed..53dfd013 100644 --- a/include/Engine/Core/EPlayerDeath.h +++ b/include/Engine/Core/EPlayerDeath.h @@ -2,7 +2,7 @@ #define EPlayerDeath_h__ #include "EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { @@ -12,6 +12,7 @@ struct PlayerDeath : Event //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system EntityID KilledBy; EntityID PlayerID; + EntityWrapper Player; std::string KilledByWhat; }; diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 26d38c69..102a4be6 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -22,9 +22,9 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) if (health <= 0.0) { Events::PlayerDeath ePlayerDeath; ePlayerDeath.PlayerID = e.Player.ID; + ePlayerDeath.Player = e.Player; m_EventBroker->Publish(ePlayerDeath); - - m_World->DeleteEntity(e.Player.ID); + //m_World->DeleteEntity(e.Player.ID); } return true; diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index dcee3a92..ab20dbce 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -112,5 +112,72 @@ bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) // playerName["Text"]["Content"] = e.PlayerName; //} + //m_World->DeleteEntity(e.Player.ID); + + //koppla till en kamera modell för att explodera den + + auto cameras = m_World->GetComponents("Camera"); + + for (auto& someCamera : *cameras) { + EntityWrapper entity = EntityWrapper(m_World, someCamera.EntityID); + auto cameraID = entity.ID; + auto modelID = entity.FirstChildByName("HUD"); + auto weapID = entity.FirstChildByName("Weapon").ID; + + // auto modelID = m_World->GetComponent(e.PlayerID, "Camera"); + ComponentWrapper& explosionEffect = m_World->AttachComponent(weapID, "ExplosionEffect"); + ComponentWrapper& lifeTime = m_World->AttachComponent(weapID, "Lifetime"); + (glm::vec3)explosionEffect["ExplosionOrigin"] = glm::vec3(0, 0, 0); + //explosionEffect["ExplosionOrigin"] = e.Player["Transform"]["Position"]; + (double)explosionEffect["TimeSinceDeath"] = 0.0; + (double)explosionEffect["ExplosionDuration"] = 2.0; + explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); + (bool)explosionEffect["Randomness"] = false; + (double)explosionEffect["RandomnessScalar"] = 1.0; + (glm::vec2)explosionEffect["Velocity"] = glm::vec2(1, 1); + (bool)explosionEffect["ColorByDistance"] = false; + (bool)explosionEffect["ExponentialAccelaration"] = false; + lifeTime["Lifetime"] = 2.0; + } + + + auto t = e.Player.FirstChildByName("PlayerModel"); + auto playerEntityModel = t["Model"]; + auto playerEntityAnimation = t["Animation"]; + auto playerEntityTransform = t["Transform"]; + //auto playerEntityModel = e.Player["PlayerModel"]; +// ComponentWrapper& playerEntityModel = e.Player.FirstChildByName("PlayerModel"); + + auto newEntity = m_World->CreateEntity(); + ComponentWrapper& newEntityModel = m_World->AttachComponent(newEntity, "Model"); + ComponentWrapper& newAnimationModel = m_World->AttachComponent(newEntity, "Animation"); + ComponentWrapper& newTransformModel = m_World->AttachComponent(newEntity, "Transform"); + + //ComponentWrapper& playerEntityModel = m_World->GetComponent(e.PlayerID, "PlayerModel"); + playerEntityModel.Copy(newEntityModel); + playerEntityAnimation.Copy(newAnimationModel); + playerEntityTransform.Copy(newTransformModel); + newAnimationModel["Speed"] = (double)0.0; + auto t2 = e.Player["Transform"]["Position"]; + newTransformModel["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; + newTransformModel["Scale"] = glm::vec3(5, 5, 5); + //auto tr = m_World->GetComponent(newEntityModel.EntityID, "Transform"); + //tr["Position"] = glm::vec3(0, 50, 0); + + ComponentWrapper& explosionEffect = m_World->AttachComponent(newEntityModel.EntityID, "ExplosionEffect"); + ComponentWrapper& lifeTime = m_World->AttachComponent(newEntityModel.EntityID, "Lifetime"); + (glm::vec3)explosionEffect["ExplosionOrigin"] = (glm::vec3)e.Player["Transform"]["Position"]; + //explosionEffect["ExplosionOrigin"] = e.Player["Transform"]["Position"]; + (double)explosionEffect["TimeSinceDeath"] = 0.0; + (double)explosionEffect["ExplosionDuration"] = 8.0; + explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); + (bool)explosionEffect["Randomness"] = false; + (double)explosionEffect["RandomnessScalar"] = 1.0; + (glm::vec2)explosionEffect["Velocity"] = glm::vec2(1, 1); + (bool)explosionEffect["ColorByDistance"] = false; + (bool)explosionEffect["ExponentialAccelaration"] = false; + lifeTime["Lifetime"] = 8.0; + return true; -} \ No newline at end of file +} +//on deathanim done -> del entity From df05f1909b08b37a3e02d86e1a73730d6b2b7f5a Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 28 Jan 2016 11:43:38 +0100 Subject: [PATCH 16/49] Completed the code to trigger the 3rd person camera on death. Cleaned up PlayerDeathSystem. Fixed HealthSystemTest. Removed the test for PlayerDeathSystem --- include/Game/Systems/PlayerDeathSystem.h | 18 +-- src/Game/Systems/HealthSystem.cpp | 2 +- src/Game/Systems/PlayerDeathSystem.cpp | 191 +++++------------------ src/Tests/HealthSystemTest.cpp | 22 ++- 4 files changed, 52 insertions(+), 181 deletions(-) diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index 3f7268ca..c59aea03 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -3,15 +3,11 @@ #include "Core/System.h" #include "Input/EInputCommand.h" -#include "Systems/SpawnerSystem.h" -#include "Events/ESpawnerSpawn.h" -#include "Core/EPlayerSpawned.h" +#include "GLM.h" #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" #include "Core/EPlayerDeath.h" -//tests -#include "Core/EPlayerDamage.h" class PlayerDeathSystem : public ImpureSystem { @@ -21,18 +17,6 @@ public: virtual void Update(double dt) override; private: - struct SpawnRequest - { - int PlayerID; - ComponentInfo::EnumType Team; - }; - - bool m_NetworkEnabled = false; - std::vector m_SpawnRequests; - std::map m_PlayerEntities; - - EventRelay m_OnInputCommand; - bool OnInputCommand(const Events::InputCommand& e); EventRelay m_OnPlayerDeath; bool OnPlayerDeath(Events::PlayerDeath& e); }; diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 102a4be6..1b747046 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -24,7 +24,7 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) ePlayerDeath.PlayerID = e.Player.ID; ePlayerDeath.Player = e.Player; m_EventBroker->Publish(ePlayerDeath); - //m_World->DeleteEntity(e.Player.ID); + //Note: we will delete the entity in PlayerDeathSystem } return true; diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index ab20dbce..7085a23f 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -3,181 +3,72 @@ PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) : System(m_World, eventBroker) { - EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerDeathSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); - m_NetworkEnabled = ResourceManager::Load("Config.ini")->Get("Networking.StartNetwork", false); } void PlayerDeathSystem::Update(double dt) { - auto playerSpawns = m_World->GetComponents("PlayerSpawn"); - if (playerSpawns == nullptr) { - return; - } - - for (auto& req : m_SpawnRequests) { - for (auto& cPlayerSpawn : *playerSpawns) { - EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); - if (!spawner.HasComponent("Spawner")) { - continue; - } - - // If the spawner has a team affiliation, check it - if (spawner.HasComponent("Team")) { - if ((int)spawner["Team"]["Team"] != req.Team) { - continue; - } - } - - // Spawn the player! - EntityWrapper player = SpawnerSystem::Spawn(spawner); - // Set the player team affiliation - player["Team"]["Team"] = req.Team; - - // Publish a PlayerSpawned event - Events::PlayerSpawned e; - e.PlayerID = req.PlayerID; - e.Player = player; - e.Spawner = spawner; - m_EventBroker->Publish(e); - - } - } - m_SpawnRequests.clear(); -} - -bool PlayerDeathSystem::OnInputCommand(const Events::InputCommand& e) -{ - //testing: Jump -> playerdamage - if (e.Command != "Jump") { - return false; - } - - // 0 = released - if (e.Value != 0) { - return false; - } - - auto players = m_World->GetComponents("Player"); - - for (auto& cPlayer : *players) { - EntityWrapper player(m_World, cPlayer.EntityID); - Events::PlayerDamage e; - e.Player = player; - e.Damage = 50; - m_EventBroker->Publish(e); - } - - - - return true; } bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) { - //// When a player is actually spawned (since the actual spawning is handled on the server) - - //// Check if a player already exists - //if (m_PlayerEntities.count(e.PlayerID) != 0) { - // // TODO: Disallow infinite respawning here - // m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); - //} - - //// Store the player for future reference - //m_PlayerEntities[e.PlayerID] = e.Player; - - //// Set the camera to the correct entity - //EntityWrapper cameraEntity = e.Player.FirstChildByName("Camera"); - //if (cameraEntity.Valid()) { - // Events::SetCamera e; - // e.CameraEntity = cameraEntity; - // m_EventBroker->Publish(e); - //} - - //// HACK: Set the player model color to team color - //EntityWrapper playerModel = e.Player.FirstChildByName("PlayerModel"); - //if (playerModel.Valid() && e.Player.HasComponent("Team")) { - // ComponentWrapper cTeam = e.Player["Team"]; - // ComponentWrapper cModel = playerModel["Model"]; - // if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Red")) { - // cModel["Color"] = glm::vec3(1.f, 0.f, 0.f); - // } else if ((ComponentInfo::EnumType)cTeam["Team"] == cTeam["Team"].Enum("Blue")) { - // cModel["Color"] = glm::vec3(0.f, 0.25f, 1.f); - // } - //} - - //// TODO: Set the player name to whatever - //EntityWrapper playerName = e.Player.FirstChildByName("PlayerName"); - //if (playerName.Valid()) { - // playerName["Text"]["Content"] = e.PlayerName; - //} - - //m_World->DeleteEntity(e.Player.ID); - - //koppla till en kamera modell för att explodera den - - auto cameras = m_World->GetComponents("Camera"); - - for (auto& someCamera : *cameras) { - EntityWrapper entity = EntityWrapper(m_World, someCamera.EntityID); - auto cameraID = entity.ID; - auto modelID = entity.FirstChildByName("HUD"); - auto weapID = entity.FirstChildByName("Weapon").ID; - - // auto modelID = m_World->GetComponent(e.PlayerID, "Camera"); - ComponentWrapper& explosionEffect = m_World->AttachComponent(weapID, "ExplosionEffect"); - ComponentWrapper& lifeTime = m_World->AttachComponent(weapID, "Lifetime"); - (glm::vec3)explosionEffect["ExplosionOrigin"] = glm::vec3(0, 0, 0); - //explosionEffect["ExplosionOrigin"] = e.Player["Transform"]["Position"]; - (double)explosionEffect["TimeSinceDeath"] = 0.0; - (double)explosionEffect["ExplosionDuration"] = 2.0; - explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); - (bool)explosionEffect["Randomness"] = false; - (double)explosionEffect["RandomnessScalar"] = 1.0; - (glm::vec2)explosionEffect["Velocity"] = glm::vec2(1, 1); - (bool)explosionEffect["ColorByDistance"] = false; - (bool)explosionEffect["ExponentialAccelaration"] = false; - lifeTime["Lifetime"] = 2.0; - } - - - auto t = e.Player.FirstChildByName("PlayerModel"); - auto playerEntityModel = t["Model"]; - auto playerEntityAnimation = t["Animation"]; - auto playerEntityTransform = t["Transform"]; - //auto playerEntityModel = e.Player["PlayerModel"]; -// ComponentWrapper& playerEntityModel = e.Player.FirstChildByName("PlayerModel"); + //current components for player that we need + auto playerModelEWrapper = e.Player.FirstChildByName("PlayerModel"); + auto playerEntityModel = playerModelEWrapper["Model"]; + auto playerEntityAnimation = playerModelEWrapper["Animation"]; + auto playerEntityTransform = playerModelEWrapper["Transform"]; + //create new entity with those components + //graphics bug: model must have an animationcomponent to be able to display it auto newEntity = m_World->CreateEntity(); ComponentWrapper& newEntityModel = m_World->AttachComponent(newEntity, "Model"); ComponentWrapper& newAnimationModel = m_World->AttachComponent(newEntity, "Animation"); ComponentWrapper& newTransformModel = m_World->AttachComponent(newEntity, "Transform"); - - //ComponentWrapper& playerEntityModel = m_World->GetComponent(e.PlayerID, "PlayerModel"); playerEntityModel.Copy(newEntityModel); playerEntityAnimation.Copy(newAnimationModel); playerEntityTransform.Copy(newTransformModel); - newAnimationModel["Speed"] = (double)0.0; - auto t2 = e.Player["Transform"]["Position"]; - newTransformModel["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; - newTransformModel["Scale"] = glm::vec3(5, 5, 5); - //auto tr = m_World->GetComponent(newEntityModel.EntityID, "Transform"); - //tr["Position"] = glm::vec3(0, 50, 0); - ComponentWrapper& explosionEffect = m_World->AttachComponent(newEntityModel.EntityID, "ExplosionEffect"); - ComponentWrapper& lifeTime = m_World->AttachComponent(newEntityModel.EntityID, "Lifetime"); + //change the animation speed and make sure the explosioneffect spawns at the players position + newAnimationModel["Speed"] = (double)0.0; + newEntityModel["Color"] = glm::vec4(1, 0, 0, 1); + newTransformModel["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; + newTransformModel["Scale"] = glm::vec3(1, 1, 1); + + //add the explosion with a lifetime + ComponentWrapper& explosionEffect = m_World->AttachComponent(newEntity, "ExplosionEffect"); + ComponentWrapper& lifeTime = m_World->AttachComponent(newEntity, "Lifetime"); (glm::vec3)explosionEffect["ExplosionOrigin"] = (glm::vec3)e.Player["Transform"]["Position"]; - //explosionEffect["ExplosionOrigin"] = e.Player["Transform"]["Position"]; (double)explosionEffect["TimeSinceDeath"] = 0.0; (double)explosionEffect["ExplosionDuration"] = 8.0; - explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); + (glm::vec4)explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); (bool)explosionEffect["Randomness"] = false; (double)explosionEffect["RandomnessScalar"] = 1.0; - (glm::vec2)explosionEffect["Velocity"] = glm::vec2(1, 1); + (glm::vec2)explosionEffect["Velocity"] = glm::vec2(0.1f, 0.1f); (bool)explosionEffect["ColorByDistance"] = false; (bool)explosionEffect["ExponentialAccelaration"] = false; - lifeTime["Lifetime"] = 8.0; + lifeTime["Lifetime"] = (double)8.0; + //create a camera (with lifetime) slightly above the player and look down at the player + auto cameraEntity = m_World->CreateEntity(); + ComponentWrapper& thirdPersonCameraLifeTime = m_World->AttachComponent(cameraEntity, "Lifetime"); + ComponentWrapper& thirdPersonCamera = m_World->AttachComponent(cameraEntity, "Camera"); + ComponentWrapper& thirdPersonCameraTransform = m_World->AttachComponent(cameraEntity, "Transform"); + auto pos = (glm::vec3)e.Player["Transform"]["Position"]; + pos.y += 10.0f; + thirdPersonCameraTransform["Position"] = (glm::vec3)pos; + //http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ + thirdPersonCameraTransform["Orientation"] = glm::vec3(-0.7f, 1.46f, 0.8f); + thirdPersonCamera["FOV"] = 120.0; + thirdPersonCamera["NearClip"] = 0.1; + thirdPersonCamera["FarClip"] = 10000.0; + thirdPersonCameraLifeTime["Lifetime"] = (double)1.0; + + //set 3rd person camera + Events::SetCamera eSetCamera; + eSetCamera.CameraEntity = EntityWrapper(m_World, cameraEntity); + m_EventBroker->Publish(eSetCamera); + + //on deathanim done -> del entity + m_World->DeleteEntity(e.Player.ID); return true; } -//on deathanim done -> del entity diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 6a434a9a..280b8d14 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -54,36 +54,32 @@ GameHealthSystemTest::GameHealthSystemTest() //The Test //create entity which has transform,player,model,health in it. i.e. is a player EntityID playerID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); healthsID = playerID; - double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"]; + + EntityID playerID2 = m_World->CreateEntity(); + ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); + ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); //heal player with 40 Events::PlayerHealthPickup e3; e3.HealthAmount = 40.0f; - e3.PlayerHealedID = healthsID; + e3.Player = EntityWrapper(m_World, player.EntityID); m_EventBroker->Publish(e3); + //damage player with 50 Events::PlayerDamage e; e.Damage = 50.0f; -// e.PlayerDamagedID = healthsID; + e.Player = EntityWrapper(m_World, player.EntityID); m_EventBroker->Publish(e); + //heal some other player with 40 Events::PlayerHealthPickup e2; e2.HealthAmount = 40.0f; - e2.PlayerHealedID = healthsID + 1; + e2.Player = EntityWrapper(m_World, player2.EntityID); m_EventBroker->Publish(e2); - EntityID playerID2 = m_World->CreateEntity(); - ComponentWrapper transform2 = m_World->AttachComponent(playerID2, "Transform"); - ComponentWrapper model2 = m_World->AttachComponent(playerID2, "Model"); - model2["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere - ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); - ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); //END TEST } From 7987d4b27cabe927d75da234a0e201ec502b66ac Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 29 Jan 2016 12:06:14 +0100 Subject: [PATCH 17/49] Added AssaultDash and all its logic, including a doubletapkey. Doubletapkey could be made more generic. --- include/Game/Systems/PlayerMovementSystem.h | 16 +++++++ src/Game/Systems/PlayerMovementSystem.cpp | 52 +++++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index f39740ec..554d174e 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -20,4 +20,20 @@ private: EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(Events::PlayerSpawned& e); + + double m_AssaultDashDoubleTapDeltaTime = 0.0f; + double m_AssaultDashCoolDownTimer = 0.0f; + double m_AssaultDashCoolDownMaxTimer = 3.0f; + ImGuiKey m_AssaultDashDoubleTapLastKey = ImGuiKey_Escape; + const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; + enum class AssaultDashDirection { + Left, + Right, + None + }; + AssaultDashDirection m_AssaultDashTapDirection = AssaultDashDirection::None; + bool m_AssaultDashDoubleTapped = false; + bool m_PlayerIsDashing = false; + + void assaultDashCheck(glm::vec3 controllerMovement, double dt, bool isJumping); }; \ No newline at end of file diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 6eab02c5..fe28ff8e 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -1,6 +1,6 @@ #include "Systems/PlayerMovementSystem.h" -PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker) +PlayerMovementSystem::PlayerMovementSystem(World* world, EventBroker* eventBroker) : System(world, eventBroker) , PureSystem("Player") { @@ -41,7 +41,9 @@ void PlayerMovementSystem::Update(double dt) if (player.HasComponent("Physics")) { ComponentWrapper cPhysics = player["Physics"]; - + //Assault Dash Check - + //TODO: check if playerclass is assault! + assaultDashCheck(controller->Movement(), dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); float wishSpeed; if (controller->Crouching()) { @@ -71,12 +73,15 @@ void PlayerMovementSystem::Update(double dt) static float surfaceFriction = 5.f; ImGui::InputFloat("surfaceFriction", &surfaceFriction); float accelerationSpeed = actualAccel * (float)dt * wishSpeed * surfaceFriction; - accelerationSpeed = glm::min(accelerationSpeed, addSpeed); + //if doubleTapped do Assault Dash - but only boost maximum 50.0f + float doubleTapDashBoost = m_AssaultDashDoubleTapped ? 20.0f : 1.0f; + accelerationSpeed = glm::min(doubleTapDashBoost*glm::min(accelerationSpeed, addSpeed), 50.0f); velocity += accelerationSpeed * wishDirection; ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); } - if (controller->Jumping() && !controller->Crouching() && velocity.y == 0.f) { + //you cant jump and dash at the same time - since there is no friction in the air and we would thus dash much further in the air + if (!m_PlayerIsDashing && controller->Jumping() && !controller->Crouching() && velocity.y == 0.f) { velocity.y += 4.f; } @@ -95,6 +100,7 @@ void PlayerMovementSystem::Update(double dt) ComponentWrapper cAnimation = playerModel["Animation"]; float movementLength = glm::length(groundVelocity); + //TODO: add assault dash animation here if (glm::length(controller->Movement()) > 0.f) { if (controller->Crouching()) { cAnimation["Name"] = "Crouch Walk"; @@ -158,3 +164,41 @@ bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) return true; } +void PlayerMovementSystem::assaultDashCheck(glm::vec3 controllerMovement, double dt, bool isJumping) { + m_AssaultDashDoubleTapDeltaTime += dt; + m_AssaultDashCoolDownTimer -= dt; + //cooldown = m_AssaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) + if (m_AssaultDashCoolDownTimer > (m_AssaultDashCoolDownMaxTimer - 0.25f)) { + m_PlayerIsDashing = true; + } else { + m_PlayerIsDashing = false; + } + //reset the DoubleTapped state in case we recently doubleTapped + if (m_AssaultDashDoubleTapped) { + m_AssaultDashDoubleTapped = false; + } + //Assault Dash logic: tap left or right twice within 0.5sec to activate the doubletap-dash + if (controllerMovement.x > 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { + if (m_AssaultDashDoubleTapLastKey != ImGuiKey_RightArrow && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer + && m_AssaultDashTapDirection == AssaultDashDirection::Right && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + } + m_AssaultDashDoubleTapLastKey = ImGuiKey_RightArrow; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashTapDirection = AssaultDashDirection::Right; + } else if (controllerMovement.x < 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { + if (m_AssaultDashDoubleTapLastKey != ImGuiKey_LeftArrow && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer + && m_AssaultDashTapDirection == AssaultDashDirection::Left && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + } + m_AssaultDashDoubleTapLastKey = ImGuiKey_LeftArrow; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashTapDirection = AssaultDashDirection::Left; + } else { + m_AssaultDashDoubleTapLastKey = ImGuiKey_Escape; + } +} From 76274c326e66beeae725b6638fd46b1d2814e364 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 1 Feb 2016 13:34:39 +0100 Subject: [PATCH 18/49] Fixed going through flat large triangles. Velocity affected by collision. --- include/Engine/Collision/Collision.h | 2 +- .../Schema/Entities/CollisionSpawnTest.xml | 164 ++++++++++++++ resources/Schema/Entities/GameMap.xml | 1 + .../Schema/Entities/LevelCollisionTest.xml | 4 +- src/Engine/Collision/Collision.cpp | 203 +++++++++--------- src/Engine/Collision/CollisionSystem.cpp | 5 +- 6 files changed, 267 insertions(+), 112 deletions(-) create mode 100644 resources/Schema/Entities/CollisionSpawnTest.xml diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index b8625b73..dfc71496 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -66,7 +66,7 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, - const glm::vec3& boxVelocity, + glm::vec3& boxVelocity, glm::vec3& outResolutionVector); //Return true if the boxes are intersecting. diff --git a/resources/Schema/Entities/CollisionSpawnTest.xml b/resources/Schema/Entities/CollisionSpawnTest.xml new file mode 100644 index 00000000..331beae6 --- /dev/null +++ b/resources/Schema/Entities/CollisionSpawnTest.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + ../assets/Models/Test/ObstacleCourse.mesh + + + + + + + + + + + 0.46000027656555176 + + + + + + + + + + + + + ../assets/Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 97fd3f4d..e206d31f 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -8,6 +8,7 @@ + Models\MapVersion1.mesh diff --git a/resources/Schema/Entities/LevelCollisionTest.xml b/resources/Schema/Entities/LevelCollisionTest.xml index ce0fe405..3c3f3bab 100644 --- a/resources/Schema/Entities/LevelCollisionTest.xml +++ b/resources/Schema/Entities/LevelCollisionTest.xml @@ -4,7 +4,7 @@ - ../assets\Models/MapVersion1.obj + ../assets/Models/MapVersion1.mesh @@ -15,7 +15,7 @@ - ../assets/Models/Core/UnitCube.obj + ../assets/Models/Core/UnitCube.mesh false diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 96d908ff..8134bab7 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -253,8 +253,10 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, const glm::vec2& boxMax, const std::array& triPos, glm::vec2& resolutionDirection, - float& resolutionDistance) + float& resolutionDistance, + bool& pushedFromTriNormal) { + pushedFromTriNormal = false; resolutionDistance = INFINITY; //Project along box normals (coordinate axes, since it's axis-aligned). for (int ax = 0; ax < 2; ++ax) { @@ -264,14 +266,20 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, minTri = std::min(t[ax], minTri); maxTri = std::max(t[ax], maxTri); } - if (minTri > boxMax[ax] || maxTri < boxMin[ax]) { + if (boxMax[ax] <= minTri || maxTri <= boxMin[ax]) { return false; } - float push = std::min(maxTri - boxMin[ax], boxMax[ax] - minTri); - if (push < resolutionDistance) { - resolutionDistance = push; + + //Here: maxBox > minTri && minBox < maxTri + //Left is negative. + float leftRes = minTri - boxMax[ax]; + float rightRes = maxTri - boxMin[ax]; + float push = rightRes < -leftRes ? rightRes : leftRes; + float absPush = abs(push); + if (absPush < resolutionDistance) { + resolutionDistance = absPush; resolutionDirection[1 - ax] = 0.f; - resolutionDirection[ax] = resolutionDistance; + resolutionDirection[ax] = push; } } //Project along triangle normals. @@ -292,7 +300,7 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, continue; } //Rotate edge to a normal. - normal = glm::vec2(-normal.y, normal.x); + normal = glm::normalize(glm::vec2(-normal.y, normal.x)); //Project triangle onto the normal. float minTri = INFINITY; float maxTri = -INFINITY; @@ -309,14 +317,20 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, minBox = std::min(dot, minBox); maxBox = std::max(dot, maxBox); } - if (maxBox < minTri || minBox > maxTri) { + if (maxBox <= minTri || maxTri <= minBox) { return false; } + //Here: maxBox > minTri && minBox < maxTri - float push = std::min(maxTri - minBox, maxBox - minTri); - if (push < resolutionDistance) { - resolutionDistance = push; - resolutionDirection = resolutionDistance * glm::normalize(normal); + //Left is negative. + float leftRes = minTri - maxBox; + float rightRes = maxTri - minBox; + float push = rightRes < -leftRes ? rightRes : leftRes; + float absPush = abs(push); + if (absPush < resolutionDistance) { + resolutionDistance = absPush; + resolutionDirection = push * normal; + pushedFromTriNormal = true; } } return true; @@ -326,18 +340,26 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); bool AABBvsTriangle(const AABB& box, - const std::array& triPos, - const glm::vec3& boxVelocity, + const std::array& triPos, + const glm::vec3& wantDirection, + glm::vec3& boxVelocity, glm::vec3& outVector) { //Check so we don't have a zero area triangle when calculating the normal. //Also, don't check a triangle facing away from the player. //Less checks, and we should be able to walk out from models if we are trapped inside. glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); - if (!vectorHasLength(triNormal) || glm::dot(triNormal, boxVelocity) > 0) { + if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0) && vectorHasLength(boxVelocity)) { return false; } + enum BoxTriResolveCase + { + Vertex, + Line, + Corner + } resolveCase; + const glm::vec3& origin = box.Origin(); const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); @@ -358,14 +380,16 @@ bool AABBvsTriangle(const AABB& box, glm::vec2 boxMax(max[dim.first], max[dim.second]); glm::vec2 resolutionVector; float resolutionDist; + bool pushedFromTriangleLine; //if projections don't overlap, return false. - if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist)) { + if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist, pushedFromTriangleLine)) { return false; } else if (resolutionDist < minimumTranslation) { outVector = glm::vec3(0.f); outVector[dim.first] = resolutionVector.x; outVector[dim.second] = resolutionVector.y; minimumTranslation = resolutionDist; + resolveCase = pushedFromTriangleLine ? Line : Vertex; } } @@ -384,6 +408,56 @@ bool AABBvsTriangle(const AABB& box, glm::vec3 cornerResolution = (1+t) * diagonal; if (glm::length(cornerResolution) < minimumTranslation) { outVector = cornerResolution; + resolveCase = Corner; + } + + bool groundCollision = triNormal.y > 0.5f; + //ImGui::Text(groundCollision ? "Ground" : "Slope"); + + glm::vec3 projNorm; + switch (resolveCase) { + case Vertex: + { + int maxD = 0; + float maxResolution = 0.f; + for (int d = 0; d < 3; ++d) { + float resolve = glm::abs(outVector[d]); + if (resolve > maxResolution) { + maxResolution = resolve; + maxD = d; + } + } + boxVelocity[maxD] = 0.f; + return true; + } + case Line: + projNorm = glm::normalize(outVector); + break; + case Corner: + projNorm = triNormal; + break; + default: + break; + } + + //Project the velocity onto the normal of the hit line/face. + //w = v - *n, |n|==1. + boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + if (groundCollision) { + float len = glm::length2(boxVelocity); + if (len > 0.0001f) { + len = glm::sqrt(len); + boxVelocity = len * glm::normalize(wantDirection); + } + + len = glm::length(outVector); + float ang = glm::half_pi() - glm::acos(outVector.y / len); + if (len > 0.0000001f && ang > 0.0000001f) { + //ImGui::Text("ang=%f, len=%f, acos=%f, outY=%f", ang, len, glm::acos(outVector.y / len), outVector.y); + outVector.x = 0; + outVector.y = len / glm::sin(ang); + outVector.z = 0; + } } return true; } @@ -392,15 +466,16 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelVertices, const std::vector& modelIndices, const glm::mat4& modelMatrix, - const glm::vec3& boxVelocity, - glm::vec3& outResolutionVector, - int startIndex, - int recursiveDepth) + glm::vec3& boxVelocity, + glm::vec3& outResolutionVector) { bool hit = false; AABB newBox = box; outResolutionVector = glm::vec3(0.f); + glm::vec3 wantDirection(boxVelocity); + wantDirection.y = 0; + wantDirection = glm::normalize(wantDirection); for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), @@ -408,101 +483,15 @@ bool AABBvsTriangles(const AABB& box, Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) }; glm::vec3 outVec; - if (AABBvsTriangle(newBox, triVertices, boxVelocity, outVec)) { + if (AABBvsTriangle(newBox, triVertices, wantDirection, boxVelocity, outVec)) { hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); } } - //outResolutionVector = glm::vec3(INFINITY); - //if (recursiveDepth > 2) { - // return true; - //} - //for (int i = startIndex; i < modelIndices.size(); ) { - // std::array triVertices = { - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) - // }; - // glm::vec3 outVec; - // if (AABBvsTriangle(box, triVertices, boxVelocity, outVec) && glm::length2(outVec) < glm::length2(outResolutionVector)) { - // hit = true; - // glm::vec3 potentialResolution = outVec; - // const AABB& resolvedBox = AABB::FromOriginSize(box.Origin() + potentialResolution, box.Size()); - // if (AABBvsTriangles(resolvedBox, modelVertices, modelIndices, modelMatrix, boxVelocity, outVec, i, recursiveDepth+1)) { - // potentialResolution += outVec; - // if (glm::length2(potentialResolution) > glm::length2(outResolutionVector)) { - // continue; - // } - // } - // outResolutionVector = potentialResolution; - // } - //} - - //outResolutionVector = glm::vec3(INFINITY); - //std::stack testBoxes; - //std::stack resolveIndices; - //std::stack resolveVectors; - //resolveVectors.push(glm::vec3(0.f)); - //resolveIndices.push(0); - //testBoxes.push(box); - //do { - // int i = resolveIndices.top(); - // resolveIndices.pop(); - // while (i < modelIndices.size()) { - // std::array triVertices = { - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), - // Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) - // }; - // glm::vec3 outVec; - // bool test = AABBvsTriangle(testBoxes.top(), triVertices, outVec); - // if (test) { - // hit = true; - // //emplace? - // resolveIndices.push(i); - // testBoxes.push(AABB::FromOriginSize(box.Origin() + outVec, box.Size())); - // resolveVectors.top() += outVec; - // } - // } - // testBoxes.pop(); - // resolveVectors.push(glm::vec3(0.f)); - //} while (!resolveIndices.empty()); - //if (hit) { - // if (!resolveVectors.empty()) { - // while (!resolveVectors.empty()) { - // if (glm::length2(resolveVectors.top()) < glm::length2(outResolutionVector)) { - // outResolutionVector = resolveVectors.top(); - // } - // resolveVectors.pop(); - // } - // } else { - // //TODO: This won't happen. - // ImGui::Text("Collision, but not resolved."); - // } - // return true; - //} return hit; } -bool AABBvsTriangles(const AABB& box, - const std::vector& modelVertices, - const std::vector& modelIndices, - const glm::mat4& modelMatrix, - const glm::vec3& boxVelocity, - glm::vec3& outResolutionVector) -{ - return AABBvsTriangles( - box, - modelVertices, - modelIndices, - modelMatrix, - boxVelocity, - outResolutionVector, - 0, - 0 - ); -} bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon) { diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 8d43534c..81e76410 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -54,9 +54,10 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::mat4 modelMatrix = glm::translate(absPosition) * glm::toMat4(absOrientation) * glm::scale(absScale); glm::vec3 resolutionVector; - if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, (glm::vec3&)cPhysics["Velocity"], resolutionVector)) { + glm::vec3 newVelocity = (glm::vec3)cPhysics["Velocity"]; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, newVelocity, resolutionVector)) { (glm::vec3&)cTransform["Position"] += resolutionVector; - cPhysics["Velocity"] = glm::vec3(0, 0, 0); + cPhysics["Velocity"] = newVelocity; } } } From 3cfbbbbf54c0365bb0244d1f7289970cea4efddb Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 1 Feb 2016 16:13:48 +0100 Subject: [PATCH 19/49] CollisionSystem now utilizes Octree for collision detection. --- resources/Schema/Components/AABB.xsd | 4 +-- resources/Schema/Entities/GameMap.xml | 3 ++ src/Engine/Collision/CollisionSystem.cpp | 44 +++++++++++------------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/resources/Schema/Components/AABB.xsd b/resources/Schema/Components/AABB.xsd index daa633a6..7dec510f 100644 --- a/resources/Schema/Components/AABB.xsd +++ b/resources/Schema/Components/AABB.xsd @@ -7,10 +7,10 @@ - Middle point of the bounding box + Middle point of the bounding box, in model space - Size of the bounding box + Size of the bounding box, in model space diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index e206d31f..4d0a2716 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -8,6 +8,9 @@ + + + Models\MapVersion1.mesh diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 382238e7..846d38a7 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -1,6 +1,7 @@ #include "Collision/Collision.h" #include "Collision/CollisionSystem.h" #include "Core/AABB.h" +#include "Rendering/Model.h" void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { @@ -25,33 +26,28 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c continue; } - if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { + if (boxB.Entity.HasComponent("Model") && Collision::AABBVsAABB(boxA, boxB)) { + //Here we know boxB is a entity with Collideable, AABB, and Model. + RawModel* model; + try { + model = ResourceManager::Load(boxB.Entity["Model"]["Resource"]); + } catch (const std::exception&) { + continue; + } + + glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity); + + glm::vec3 newVelocity = (glm::vec3)cPhysics["Velocity"]; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, newVelocity, resolutionVector)) { + (glm::vec3&)cTransform["Position"] += resolutionVector; + cPhysics["Velocity"] = newVelocity; + } + } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { + //Enter here if boxB has no Model. (glm::vec3&)cTransform["Position"] += resolutionVector; if (resolutionVector.y > 0) { ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; } } } - - // HACK: Temporarily collide against all collidable models since they're not in the octree yet - //auto otherCollidables = world->GetComponents("Model"); - //for (auto& cModel : *otherCollidables) { - // if (cModel.EntityID == entity) { - // continue; - // } - // if (!world->HasComponent(cModel.EntityID, "Collidable")) { - // continue; - // } - - // auto absPosition = RenderQueueFactory::AbsolutePosition(world, cModel.EntityID); - // auto absOrientation = RenderQueueFactory::AbsoluteOrientation(world, cModel.EntityID); - // auto absScale = RenderQueueFactory::AbsoluteScale(world, cModel.EntityID); - // glm::mat4 modelMatrix = glm::translate(absPosition); // *glm::toMat4(absOrientation) * glm::scale(absScale); - - // auto model = ResourceManager::Load(cModel["Resource"]); - // glm::vec3 resolutionVector; - // if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) { - // (glm::vec3&)cTransform["Position"] += resolutionVector; - // } - //} -} \ No newline at end of file +} From 5a45f778e68498933486e77a5b2108170318938d Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 1 Feb 2016 17:01:58 +0100 Subject: [PATCH 20/49] Fixed so players don't teleport to (NaN, NaN, NaN) on spawning. --- include/Engine/Core/MemoryPool.h | 2 +- src/Engine/Collision/Collision.cpp | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index 3a1cc069..f4073294 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -102,7 +102,7 @@ public: m_ExtraMemory.push_back((char*)malloc(m_Stride)); //We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead. if (!DisableMemoryPool::Value) { - LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size()); + LOG_DEBUG("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size()); } return m_ExtraMemory.back(); } diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 67ed6c99..a17e347c 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -412,7 +412,6 @@ bool AABBvsTriangle(const AABB& box, } bool groundCollision = triNormal.y > 0.5f; - //ImGui::Text(groundCollision ? "Ground" : "Slope"); glm::vec3 projNorm; switch (resolveCase) { @@ -446,14 +445,12 @@ bool AABBvsTriangle(const AABB& box, if (groundCollision) { float len = glm::length2(boxVelocity); if (len > 0.0001f) { - len = glm::sqrt(len); - boxVelocity = len * glm::normalize(wantDirection); + boxVelocity = glm::sqrt(len) * wantDirection; } len = glm::length(outVector); float ang = glm::half_pi() - glm::acos(outVector.y / len); if (len > 0.0000001f && ang > 0.0000001f) { - //ImGui::Text("ang=%f, len=%f, acos=%f, outY=%f", ang, len, glm::acos(outVector.y / len), outVector.y); outVector.x = 0; outVector.y = len / glm::sin(ang); outVector.z = 0; @@ -475,7 +472,9 @@ bool AABBvsTriangles(const AABB& box, outResolutionVector = glm::vec3(0.f); glm::vec3 wantDirection(boxVelocity); wantDirection.y = 0; - wantDirection = glm::normalize(wantDirection); + if (vectorHasLength(wantDirection)) { + wantDirection = glm::normalize(wantDirection); + } for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), From 30b1dab7640406c180de7f2ce5ef6c53de0319b4 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Mon, 1 Feb 2016 18:06:28 +0100 Subject: [PATCH 21/49] More efficient collision resolution case + comments. --- src/Engine/Collision/Collision.cpp | 43 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index a17e347c..edb6c9a9 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -336,6 +336,11 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, return true; } +constexpr float SlopeConstant(float degrees) +{ + return (1.0 - degrees / 90.f); +} + //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); @@ -355,9 +360,11 @@ bool AABBvsTriangle(const AABB& box, enum BoxTriResolveCase { - Vertex, - Line, - Corner + ResolveDimX, + ResolveDimY, + ResolveDimZ, + Line, //Box edge colliding with triangle line. + Corner //Box corner colliding with the triangle face. } resolveCase; const glm::vec3& origin = box.Origin(); @@ -389,7 +396,9 @@ bool AABBvsTriangle(const AABB& box, outVector[dim.first] = resolutionVector.x; outVector[dim.second] = resolutionVector.y; minimumTranslation = resolutionDist; - resolveCase = pushedFromTriangleLine ? Line : Vertex; + //If we pushed away from triangle line (edge), or if we + //move the player along one coordinate axis (pick the dimension that isn't zero). + resolveCase = pushedFromTriangleLine ? Line : static_cast((abs(outVector[dim.first]) < 0.0001f) ? dim.second : dim.first); } } @@ -411,22 +420,15 @@ bool AABBvsTriangle(const AABB& box, resolveCase = Corner; } - bool groundCollision = triNormal.y > 0.5f; - glm::vec3 projNorm; switch (resolveCase) { - case Vertex: + case ResolveDimX: + case ResolveDimY: + case ResolveDimZ: { - int maxD = 0; - float maxResolution = 0.f; - for (int d = 0; d < 3; ++d) { - float resolve = glm::abs(outVector[d]); - if (resolve > maxResolution) { - maxResolution = resolve; - maxD = d; - } - } - boxVelocity[maxD] = 0.f; + //If we get here, the resolution is along one coordinate axis. + //set velocity to 0 in that dimension. + boxVelocity[resolveCase] = 0.f; return true; } case Line: @@ -442,12 +444,17 @@ bool AABBvsTriangle(const AABB& box, //Project the velocity onto the normal of the hit line/face. //w = v - *n, |n|==1. boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; - if (groundCollision) { + //If the collision was not on steep wall or similarly (e.g. walking on the ground), do special treatment. + //Magic value that makes condition correspond to: + //if the angle between horizon and the collision surface is less than 45 degrees. + if (projNorm.y > SlopeConstant(45.0f)) { + //Make sure the player keeps moving in their desired direction, just slower. float len = glm::length2(boxVelocity); if (len > 0.0001f) { boxVelocity = glm::sqrt(len) * wantDirection; } + //Ensure that the player always is moved upwards, instead of sliding down. len = glm::length(outVector); float ang = glm::half_pi() - glm::acos(outVector.y / len); if (len > 0.0000001f && ang > 0.0000001f) { From 563fd4082e090cb46e5eebc23095a2c86154e323 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 2 Feb 2016 12:10:39 +0100 Subject: [PATCH 22/49] Updated movement test for model collisions --- resources/Schema/Entities/MovementTest.xml | 67 ++-------------------- 1 file changed, 5 insertions(+), 62 deletions(-) diff --git a/resources/Schema/Entities/MovementTest.xml b/resources/Schema/Entities/MovementTest.xml index 1378f623..f5197830 100644 --- a/resources/Schema/Entities/MovementTest.xml +++ b/resources/Schema/Entities/MovementTest.xml @@ -6,22 +6,6 @@ - - - - - - Models/Core/UnitCube.mesh - - false - - - - - - - - @@ -81,6 +65,10 @@ + + + + Models/Test/ObstacleCourse.mesh @@ -88,51 +76,6 @@ - - - - - - Models/Core/UnitCube.mesh - false - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - false - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - false - - - - - - - - @@ -197,7 +140,7 @@ - + From 6a3f585fb921e10f23513cebf98de645822115d7 Mon Sep 17 00:00:00 2001 From: Jocke Date: Tue, 2 Feb 2016 13:26:15 +0100 Subject: [PATCH 23/49] Fixed warnings associated with Network.cpp, Client.cpp, Server.cpp and Packet.cpp. BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT': macro redefinition was fixed by https://svn.boost.org/trac/boost/ticket/11539 --- include/Engine/Network/Client.h | 4 ++-- include/Engine/Network/Network.h | 2 +- include/Engine/Network/NetworkData.h | 16 ++++++++-------- include/Engine/Network/Packet.h | 18 +++++++++--------- include/Engine/Network/Server.h | 8 ++++---- include/Game/Systems/InterpolationSystem.h | 2 +- src/Engine/Network/Client.cpp | 6 +++--- src/Engine/Network/Network.cpp | 10 +++++----- src/Engine/Network/Packet.cpp | 6 +++--- src/Engine/Network/Server.cpp | 16 ++++++++-------- src/Game/Systems/InterpolationSystem.cpp | 6 +++--- 11 files changed, 47 insertions(+), 47 deletions(-) diff --git a/include/Engine/Network/Client.h b/include/Engine/Network/Client.h index 4f1baa67..7d1d5bba 100644 --- a/include/Engine/Network/Client.h +++ b/include/Engine/Network/Client.h @@ -36,7 +36,7 @@ private: boost::asio::ip::udp::socket m_Socket; // Sending message to server logic - int bytesRead = -1; + size_t bytesRead = 0; char readBuf[INPUTSIZE] = { 0 }; // Packet loss logic @@ -69,7 +69,7 @@ private: // Private member functions void readFromServer(); - int receive(char* data); + size_t receive(char* data); void send(Packet& packet); void connect(); void disconnect(); diff --git a/include/Engine/Network/Network.h b/include/Engine/Network/Network.h index e1e64fc1..874e3377 100644 --- a/include/Engine/Network/Network.h +++ b/include/Engine/Network/Network.h @@ -29,7 +29,7 @@ protected: unsigned int m_SaveDataIntervalMs = 1000; std::clock_t m_SaveDataTimer; unsigned int m_MaxConnections; - unsigned int m_TimeoutMs; + double m_TimeoutMs; void saveToFile(); void updateNetworkData(); void initialize(); diff --git a/include/Engine/Network/NetworkData.h b/include/Engine/Network/NetworkData.h index 87f7a215..85db36de 100644 --- a/include/Engine/Network/NetworkData.h +++ b/include/Engine/Network/NetworkData.h @@ -3,16 +3,16 @@ #include struct NetworkData { - unsigned int TotalTime = 0; - unsigned int TotalDataReceived = 0; - unsigned int TotalDataSent = 0; - unsigned int AmountOfMessagesReceived = 0; + double TotalTime = 0; + size_t TotalDataReceived = 0; + size_t TotalDataSent = 0; + size_t AmountOfMessagesReceived = 0; unsigned int AmountOfMessagesSent = 0; // Interval based - unsigned int DataReceivedThisInterval = 0; - unsigned int DataSentThisInterval = 0; + size_t DataReceivedThisInterval = 0; + size_t DataSentThisInterval = 0; // pair: first=reveived, second=send - std::vector> BandwidthBytes; + std::vector> BandwidthBytes; }; -#endif +#endif \ No newline at end of file diff --git a/include/Engine/Network/Packet.h b/include/Engine/Network/Packet.h index d38ddf58..009d8563 100644 --- a/include/Engine/Network/Packet.h +++ b/include/Engine/Network/Packet.h @@ -13,7 +13,7 @@ public: // arg2: PacketID for identifying packet loss. Packet(MessageType type, unsigned int& packetID); // Used to create packet from already existing data buffer. - Packet(char* data, const int sizeOfPacket); + Packet(char* data, const size_t sizeOfPacket); Packet(MessageType type); ~Packet(); void Init(MessageType type, unsigned int& packetID); @@ -51,18 +51,18 @@ public: std::string ReadString(); char* ReadData(int SizeOfData); void ChangePacketID(unsigned int& packetID); - int Size() { return m_Offset; }; + size_t Size() { return m_Offset; }; char* Data() { return m_Data; }; - unsigned int DataReadSize() { return m_ReturnDataOffset; } - unsigned int MaxSize() { return m_MaxPacketSize; } - unsigned int HeaderSize() { return m_HeaderSize; } + size_t DataReadSize() { return m_ReturnDataOffset; } + size_t MaxSize() { return m_MaxPacketSize; } + size_t HeaderSize() { return m_HeaderSize; } private: char* m_Data; - unsigned int m_ReturnDataOffset = 0; - int m_Offset = 0; - unsigned int m_MaxPacketSize = 512; - unsigned int m_HeaderSize = 0; + size_t m_ReturnDataOffset = 0; + size_t m_Offset = 0; + size_t m_MaxPacketSize = 512; + size_t m_HeaderSize = 0; void resizeData(); }; diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index 11f983a9..90b9e922 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -36,14 +36,14 @@ private: std::map m_ConnectedPlayers; // HACK: Fix INPUTSIZE char readBuffer[INPUTSIZE] = { 0 }; - int bytesRead = 0; + size_t bytesRead = 0; // time for previouse message std::clock_t previousePingMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock(); std::clock_t timOutTimer = std::clock(); // How often we send messages (milliseconds) - int pingIntervalMs; - int snapshotInterval; + float pingIntervalMs; + float snapshotInterval; int checkTimeOutInterval = 100; int m_NextPlayerID = 0; @@ -59,7 +59,7 @@ private: PacketID m_PreviousPacketID = 0; // Private member functions - int receive(char* data); + size_t receive(char* data); void readFromClients(); void send(PlayerID player, Packet& packet); void send(Packet& packet); diff --git a/include/Game/Systems/InterpolationSystem.h b/include/Game/Systems/InterpolationSystem.h index 1e345c91..96236f62 100644 --- a/include/Game/Systems/InterpolationSystem.h +++ b/include/Game/Systems/InterpolationSystem.h @@ -23,7 +23,7 @@ class InterpolationSystem : public PureSystem glm::vec3 Position; glm::vec3 Scale; glm::quat Orientation; - double interpolationTime; + float interpolationTime; }; public: InterpolationSystem(World* world, EventBroker* eventBroker); diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 6c43cc8b..f4631e98 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -258,11 +258,11 @@ void Client::parseSnapshot(Packet& packet) } } -int Client::receive(char* data) +size_t Client::receive(char* data) { boost::system::error_code error; - int bytesReceived = m_Socket.receive_from(boost + size_t bytesReceived = m_Socket.receive_from(boost ::asio::buffer((void*)data, INPUTSIZE), m_ReceiverEndpoint, 0, error); @@ -390,7 +390,7 @@ void Client::identifyPacketLoss() bool Client::hasServerTimedOut() { // Time in ms - float timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); + double timeSincePing = 1000 * (std::clock() - m_StartPingTime) / static_cast(CLOCKS_PER_SEC); if (timeSincePing > m_TimeoutMs) { // Clear everything and go to menu. LOG_INFO("Server has timed out, returning to menu, Beep Boop."); diff --git a/src/Engine/Network/Network.cpp b/src/Engine/Network/Network.cpp index f4dcd1a2..f43e5d83 100644 --- a/src/Engine/Network/Network.cpp +++ b/src/Engine/Network/Network.cpp @@ -26,10 +26,10 @@ void Network::saveToFile() outfile << "Total messages received," + std::to_string(m_NetworkData.AmountOfMessagesReceived) + "\n"; outfile << "Total messages sent," + std::to_string(m_NetworkData.AmountOfMessagesSent) + "\n"; - float messagesReceivedPerSec = (float)m_NetworkData.AmountOfMessagesReceived / (m_NetworkData.TotalTime / 1000); - float messagesSentPerSec = (float)m_NetworkData.AmountOfMessagesSent / (m_NetworkData.TotalTime / 1000); - float dataReceivedPerSec = (float)m_NetworkData.TotalDataReceived / (m_NetworkData.TotalTime / 1000); - float dataSentPerSec = (float)m_NetworkData.TotalDataSent / (m_NetworkData.TotalTime / 1000); + double messagesReceivedPerSec = m_NetworkData.AmountOfMessagesReceived / (m_NetworkData.TotalTime / 1000); + double messagesSentPerSec = m_NetworkData.AmountOfMessagesSent / (m_NetworkData.TotalTime / 1000); + double dataReceivedPerSec = m_NetworkData.TotalDataReceived / (m_NetworkData.TotalTime / 1000); + double dataSentPerSec = m_NetworkData.TotalDataSent / (m_NetworkData.TotalTime / 1000); outfile << "Avarage messages received / s: " + std::to_string(messagesReceivedPerSec) + "\n"; outfile << "Avarage messages sents / s: " + std::to_string(messagesSentPerSec) + "\n"; outfile << "Avarage data received B/s: " + std::to_string(dataReceivedPerSec) + "\n"; @@ -52,7 +52,7 @@ void Network::updateNetworkData() if (m_SaveDataIntervalMs < (1000 * (currentTime - m_SaveDataTimer) / (double)CLOCKS_PER_SEC)) { // Set values m_NetworkData.TotalTime += (1000 * (currentTime - m_SaveDataTimer) / (double)CLOCKS_PER_SEC); - m_NetworkData.BandwidthBytes.push_back(std::pair(m_NetworkData.DataReceivedThisInterval, m_NetworkData.DataSentThisInterval)); + m_NetworkData.BandwidthBytes.push_back(std::pair(m_NetworkData.DataReceivedThisInterval, m_NetworkData.DataSentThisInterval)); // Reset interval stuff m_SaveDataTimer = std::clock(); m_NetworkData.DataSentThisInterval = 0; diff --git a/src/Engine/Network/Packet.cpp b/src/Engine/Network/Packet.cpp index d40a1b32..21226a07 100644 --- a/src/Engine/Network/Packet.cpp +++ b/src/Engine/Network/Packet.cpp @@ -7,7 +7,7 @@ Packet::Packet(MessageType type, unsigned int& packetID) } // Create message -Packet::Packet(char* data, const int sizeOfPacket) +Packet::Packet(char* data, const size_t sizeOfPacket) { // Resize message m_MaxPacketSize = sizeOfPacket; @@ -45,7 +45,7 @@ void Packet::Init(MessageType type, unsigned int & packetID) void Packet::WriteString(const std::string& str) { // Message, add one extra byte for null terminator - int sizeOfString = str.size() + 1; + size_t sizeOfString = str.size() + 1; if (m_Offset + sizeOfString > m_MaxPacketSize) { //LOG_WARNING("Package::WriteString(): Data size in packet exceeded maximum package size. New size is %i bytes\n", m_MaxPacketSize*2); resizeData(); @@ -82,7 +82,7 @@ char * Packet::ReadData(int SizeOfData) //LOG_WARNING("packet ReadData(): Oh no! You are trying to remove things outside my memory kingdom"); return nullptr; } - unsigned int oldReturnDataOffset = m_ReturnDataOffset; + size_t oldReturnDataOffset = m_ReturnDataOffset; m_ReturnDataOffset += SizeOfData; return (m_Data + oldReturnDataOffset); } diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index adf810aa..962081cc 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -4,7 +4,7 @@ Server::Server() : m_Socket(m_IOService, boost::asio::ip::udp::endpoint(boost::a { Network::initialize(); ConfigFile* config = ResourceManager::Load("Config.ini"); - snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05); + snapshotInterval = 1000 * config->Get("Networking.SnapshotInterval", 0.05f); pingIntervalMs = config->Get("Networking.PingIntervalMs", 1000); } @@ -43,7 +43,7 @@ void Server::readFromClients() bytesRead = receive(readBuffer); Packet packet(readBuffer, bytesRead); parseMessageType(packet); - } catch (const std::exception& err) { + } catch (const std::exception&) { //LOG_ERROR("%i: Read from client crashed %s", m_PacketID, err.what()); } } @@ -103,9 +103,9 @@ void Server::parseMessageType(Packet& packet) } } -int Server::receive(char * data) +size_t Server::receive(char * data) { - unsigned int length = m_Socket.receive_from( + size_t length = m_Socket.receive_from( boost::asio::buffer((void*)data , INPUTSIZE) , m_ReceiverEndpoint, 0); @@ -121,7 +121,7 @@ int Server::receive(char * data) void Server::send(PlayerID player, Packet& packet) { try { - int bytesSent = m_Socket.send_to( + size_t bytesSent = m_Socket.send_to( boost::asio::buffer(packet.Data(), packet.Size()), m_ConnectedPlayers[player].Endpoint, 0); @@ -131,7 +131,7 @@ void Server::send(PlayerID player, Packet& packet) m_NetworkData.DataSentThisInterval += packet.Size(); m_NetworkData.AmountOfMessagesSent++; } - } catch (const boost::system::system_error& e) { + } catch (const boost::system::system_error&) { // TODO: Clean up invalid endpoints out of m_ConnectedPlayers later m_ConnectedPlayers[player].Endpoint = boost::asio::ip::udp::endpoint(); } @@ -231,12 +231,12 @@ void Server::sendPing() void Server::checkForTimeOuts() { - int startPing = 1000 * m_StartPingTime + double startPing = 1000 * m_StartPingTime / static_cast(CLOCKS_PER_SEC); for (int i = 0; i < m_ConnectedPlayers.size(); i++) { if (m_ConnectedPlayers[i].Endpoint.address() != boost::asio::ip::address()) { - int stopPing = 1000 * m_ConnectedPlayers[i].StopTime / + double stopPing = 1000 * m_ConnectedPlayers[i].StopTime / static_cast(CLOCKS_PER_SEC); if (startPing > stopPing + m_TimeoutMs) { LOG_INFO("User %i timed out!", i); diff --git a/src/Game/Systems/InterpolationSystem.cpp b/src/Game/Systems/InterpolationSystem.cpp index bfb6952a..f2de710d 100644 --- a/src/Game/Systems/InterpolationSystem.cpp +++ b/src/Game/Systems/InterpolationSystem.cpp @@ -5,7 +5,7 @@ InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker) , PureSystem("Transform") { ConfigFile* config = ResourceManager::Load("Config.ini"); - m_SnapshotInterval = config->Get("Networking.SnapshotInterval", 0.05); + m_SnapshotInterval = config->Get("Networking.SnapshotInterval", 0.05f); EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate); EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &InterpolationSystem::OnPlayerSpawned); } @@ -18,9 +18,9 @@ void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrappe } if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map - m_NextTransform[transform.EntityID].interpolationTime += dt; + m_NextTransform[transform.EntityID].interpolationTime += static_cast(dt); Transform sTransform = m_NextTransform[transform.EntityID]; - double time = sTransform.interpolationTime; + float time = sTransform.interpolationTime; if (time > m_SnapshotInterval) { if (m_LastReceivedTransform.find(transform.EntityID) != m_LastReceivedTransform.end()) { m_NextTransform[transform.EntityID] = m_LastReceivedTransform[transform.EntityID]; From 5e472cd69c9a24bc090211c7c15daf10ea6ee0bc Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 2 Feb 2016 17:18:12 +0100 Subject: [PATCH 24/49] DeathExplosion is now an XML file, changed PlayerDeathSystem accordingly. The effect should show as soon as the explosioneffect-fix is merged into master. TODO: remove the test --- include/Engine/Core/EPlayerDeath.h | 2 - include/Game/Systems/PlayerDeathSystem.h | 8 ++ .../PlayerDeathExplosionWithCamera.xml | 48 +++++++++ src/Game/Systems/HealthSystem.cpp | 1 - src/Game/Systems/PlayerDeathSystem.cpp | 102 +++++++++--------- src/Tests/CapturePointTest.cpp | 8 +- 6 files changed, 114 insertions(+), 55 deletions(-) create mode 100644 resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml diff --git a/include/Engine/Core/EPlayerDeath.h b/include/Engine/Core/EPlayerDeath.h index 53dfd013..363745a6 100644 --- a/include/Engine/Core/EPlayerDeath.h +++ b/include/Engine/Core/EPlayerDeath.h @@ -10,8 +10,6 @@ namespace Events struct PlayerDeath : Event { //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system - EntityID KilledBy; - EntityID PlayerID; EntityWrapper Player; std::string KilledByWhat; }; diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index c59aea03..4734947e 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -7,7 +7,11 @@ #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" +#include "Core/EntityFile.h" +#include "Core/EntityFileParser.h" + #include "Core/EPlayerDeath.h" +#include "Core/EPlayerDamage.h" class PlayerDeathSystem : public ImpureSystem { @@ -19,5 +23,9 @@ public: private: EventRelay m_OnPlayerDeath; bool OnPlayerDeath(Events::PlayerDeath& e); + + EventRelay m_OnInputCommand; + bool OnInputCommand(const Events::InputCommand& e); + }; #endif \ No newline at end of file diff --git a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml new file mode 100644 index 00000000..bdebbfe7 --- /dev/null +++ b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml @@ -0,0 +1,48 @@ + + + + + + Hold Pos + + 0 + + + 8 + + + 0 + 8 + + + + Models/AssaultAnimated.mesh + + true + + + + + + + + + + + 1 + + + 120 + 0.1 + 10000 + + + + + + + + + + + diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 1b747046..18a15828 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -21,7 +21,6 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) if (health <= 0.0) { Events::PlayerDeath ePlayerDeath; - ePlayerDeath.PlayerID = e.Player.ID; ePlayerDeath.Player = e.Player; m_EventBroker->Publish(ePlayerDeath); //Note: we will delete the entity in PlayerDeathSystem diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index 7085a23f..d57caefc 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -3,69 +3,75 @@ PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) : System(m_World, eventBroker) { + EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerDeathSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); } +bool PlayerDeathSystem::OnInputCommand(const Events::InputCommand& e) +{ + //testing: Jump > playerdamage + if (e.Command != "Jump") { + return false; + + } + + // 0 = released + if (e.Value != 0) { + return false; + + } + + auto players = m_World->GetComponents("Player"); + + for (auto& cPlayer : *players) { + EntityWrapper player(m_World, cPlayer.EntityID); + Events::PlayerDamage e; + e.Player = player; + e.Damage = 50; + m_EventBroker->Publish(e); + + } + + + + return true; +} + void PlayerDeathSystem::Update(double dt) { } bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) { - //current components for player that we need - auto playerModelEWrapper = e.Player.FirstChildByName("PlayerModel"); - auto playerEntityModel = playerModelEWrapper["Model"]; - auto playerEntityAnimation = playerModelEWrapper["Animation"]; - auto playerEntityTransform = playerModelEWrapper["Transform"]; + //LOAD THE XML + auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); - //create new entity with those components - //graphics bug: model must have an animationcomponent to be able to display it - auto newEntity = m_World->CreateEntity(); - ComponentWrapper& newEntityModel = m_World->AttachComponent(newEntity, "Model"); - ComponentWrapper& newAnimationModel = m_World->AttachComponent(newEntity, "Animation"); - ComponentWrapper& newTransformModel = m_World->AttachComponent(newEntity, "Transform"); - playerEntityModel.Copy(newEntityModel); - playerEntityAnimation.Copy(newAnimationModel); - playerEntityTransform.Copy(newTransformModel); + EntityFileParser parser(deathEffect); + EntityID deathEffectID = parser.MergeEntities(m_World); + EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); + + //current components for player that we need + auto playerModelEW = e.Player.FirstChildByName("PlayerModel"); + auto playerEntityModel = playerModelEW["Model"]; + auto playerEntityTransform = playerModelEW["Transform"]; + + //copy the data from player to new playermodel + playerEntityModel.Copy(deathEffectEW["Model"]); + playerEntityTransform.Copy(deathEffectEW["Transform"]); //change the animation speed and make sure the explosioneffect spawns at the players position - newAnimationModel["Speed"] = (double)0.0; - newEntityModel["Color"] = glm::vec4(1, 0, 0, 1); - newTransformModel["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; - newTransformModel["Scale"] = glm::vec3(1, 1, 1); - - //add the explosion with a lifetime - ComponentWrapper& explosionEffect = m_World->AttachComponent(newEntity, "ExplosionEffect"); - ComponentWrapper& lifeTime = m_World->AttachComponent(newEntity, "Lifetime"); - (glm::vec3)explosionEffect["ExplosionOrigin"] = (glm::vec3)e.Player["Transform"]["Position"]; - (double)explosionEffect["TimeSinceDeath"] = 0.0; - (double)explosionEffect["ExplosionDuration"] = 8.0; - (glm::vec4)explosionEffect["EndColor"] = glm::vec4(0, 0, 0, 1); - (bool)explosionEffect["Randomness"] = false; - (double)explosionEffect["RandomnessScalar"] = 1.0; - (glm::vec2)explosionEffect["Velocity"] = glm::vec2(0.1f, 0.1f); - (bool)explosionEffect["ColorByDistance"] = false; - (bool)explosionEffect["ExponentialAccelaration"] = false; - lifeTime["Lifetime"] = (double)8.0; - - //create a camera (with lifetime) slightly above the player and look down at the player - auto cameraEntity = m_World->CreateEntity(); - ComponentWrapper& thirdPersonCameraLifeTime = m_World->AttachComponent(cameraEntity, "Lifetime"); - ComponentWrapper& thirdPersonCamera = m_World->AttachComponent(cameraEntity, "Camera"); - ComponentWrapper& thirdPersonCameraTransform = m_World->AttachComponent(cameraEntity, "Transform"); - auto pos = (glm::vec3)e.Player["Transform"]["Position"]; - pos.y += 10.0f; - thirdPersonCameraTransform["Position"] = (glm::vec3)pos; //http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ - thirdPersonCameraTransform["Orientation"] = glm::vec3(-0.7f, 1.46f, 0.8f); - thirdPersonCamera["FOV"] = 120.0; - thirdPersonCamera["NearClip"] = 0.1; - thirdPersonCamera["FarClip"] = 10000.0; - thirdPersonCameraLifeTime["Lifetime"] = (double)1.0; + auto playerPosition = (glm::vec3)e.Player["Transform"]["Position"]; + deathEffectEW["Transform"]["Position"] = playerPosition; + deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = playerPosition; - //set 3rd person camera + //camera (with lifetime) slightly above the player and looking down at the player + //camera will be positioned just above the player + glm::vec3 cameraPosition = glm::vec3(0, 10, 0); + auto cam = deathEffectEW.FirstChildByName("Camera"); + cam["Transform"]["Position"] = cameraPosition; Events::SetCamera eSetCamera; - eSetCamera.CameraEntity = EntityWrapper(m_World, cameraEntity); + eSetCamera.CameraEntity = cam; m_EventBroker->Publish(eSetCamera); //on deathanim done -> del entity diff --git a/src/Tests/CapturePointTest.cpp b/src/Tests/CapturePointTest.cpp index ffb01030..2c7bf430 100644 --- a/src/Tests/CapturePointTest.cpp +++ b/src/Tests/CapturePointTest.cpp @@ -255,14 +255,14 @@ void CapturePointTest::TestSetup8() } void CapturePointTest::DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject) { Events::TriggerTouch touchEvent; - touchEvent.Entity = whoDidSomething; - touchEvent.Trigger = onWhatObject; + touchEvent.Entity = EntityWrapper(m_World, whoDidSomething); + touchEvent.Trigger = EntityWrapper(m_World, onWhatObject); m_EventBroker->Publish(touchEvent); } void CapturePointTest::DoLeaveEvent(EntityID whoDidSomething, EntityID onWhatObject) { Events::TriggerLeave leaveEvent; - leaveEvent.Entity = whoDidSomething; - leaveEvent.Trigger = onWhatObject; + leaveEvent.Entity = EntityWrapper(m_World, whoDidSomething); + leaveEvent.Trigger = EntityWrapper(m_World, onWhatObject); m_EventBroker->Publish(leaveEvent); } void CapturePointTest::TestSuccess1() { From affcc5305bc032b27eb3e50ac222144a0820bfc3 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 2 Feb 2016 17:19:59 +0100 Subject: [PATCH 25/49] Collision affects velocity correctly, no wierd ice cream sliding along walls. --- src/Engine/Collision/Collision.cpp | 48 +++++++++++++++++++----------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index edb6c9a9..81949cb5 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -344,9 +344,10 @@ constexpr float SlopeConstant(float degrees) //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); +//TODO: Prefer to move in y - if the resolution is small enough, value in physics comp. +//TODO: Walking down slopes correctly. bool AABBvsTriangle(const AABB& box, const std::array& triPos, - const glm::vec3& wantDirection, glm::vec3& boxVelocity, glm::vec3& outVector) { @@ -354,7 +355,7 @@ bool AABBvsTriangle(const AABB& box, //Also, don't check a triangle facing away from the player. //Less checks, and we should be able to walk out from models if we are trapped inside. glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); - if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0) && vectorHasLength(boxVelocity)) { + if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0)) { return false; } @@ -428,40 +429,56 @@ bool AABBvsTriangle(const AABB& box, { //If we get here, the resolution is along one coordinate axis. //set velocity to 0 in that dimension. + //projNorm = glm::vec3(0.f); + //projNorm[resolveCase] = 1; + //ImGui::Text(("Axis " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); boxVelocity[resolveCase] = 0.f; return true; } case Line: projNorm = glm::normalize(outVector); + //ImGui::Text(("Line " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); break; case Corner: projNorm = triNormal; + //ImGui::Text(("Corner " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); break; default: break; } - //Project the velocity onto the normal of the hit line/face. - //w = v - *n, |n|==1. - boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; //If the collision was not on steep wall or similarly (e.g. walking on the ground), do special treatment. //Magic value that makes condition correspond to: //if the angle between horizon and the collision surface is less than 45 degrees. if (projNorm.y > SlopeConstant(45.0f)) { - //Make sure the player keeps moving in their desired direction, just slower. - float len = glm::length2(boxVelocity); - if (len > 0.0001f) { - boxVelocity = glm::sqrt(len) * wantDirection; - } - //Ensure that the player always is moved upwards, instead of sliding down. - len = glm::length(outVector); + //Also zero the vertical velocity. + float len = glm::length(outVector); float ang = glm::half_pi() - glm::acos(outVector.y / len); if (len > 0.0000001f && ang > 0.0000001f) { outVector.x = 0; outVector.y = len / glm::sin(ang); outVector.z = 0; + boxVelocity.y = 0.f; } + } else if (projNorm.y > 0) { + //Enter here if the triangle is a steep slope, and it is not facing downwards. + //Project the velocity onto the normal of the hit line/face. + //w = v - *n, |n|==1. + boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + + //Ensure that the player will be pushed in the xz-plane. + //glm::vec3 moveDir(outVector); + //moveDir.y = 0; + //if (vectorHasLength(moveDir)) { + // moveDir = glm::normalize(moveDir); + // float len = glm::length(outVector); + // float dotMoveOut = moveDir.x * outVector.x + moveDir.z * outVector.z; + // float ang = glm::half_pi() - glm::acos(dotMoveOut / len); + // if (len > 0.0000001f && ang > 0.0000001f) { + // outVector = (len / glm::sin(ang)) * moveDir; + // } + //} } return true; } @@ -477,11 +494,6 @@ bool AABBvsTriangles(const AABB& box, AABB newBox = box; outResolutionVector = glm::vec3(0.f); - glm::vec3 wantDirection(boxVelocity); - wantDirection.y = 0; - if (vectorHasLength(wantDirection)) { - wantDirection = glm::normalize(wantDirection); - } for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), @@ -489,7 +501,7 @@ bool AABBvsTriangles(const AABB& box, Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) }; glm::vec3 outVec; - if (AABBvsTriangle(newBox, triVertices, wantDirection, boxVelocity, outVec)) { + if (AABBvsTriangle(newBox, triVertices, boxVelocity, outVec)) { hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); From 214dad2afc23be62a5fee10e71374667daa32830 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 2 Feb 2016 17:25:59 +0100 Subject: [PATCH 26/49] Removed commented code. --- src/Engine/Collision/Collision.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 81949cb5..083af229 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -429,19 +429,14 @@ bool AABBvsTriangle(const AABB& box, { //If we get here, the resolution is along one coordinate axis. //set velocity to 0 in that dimension. - //projNorm = glm::vec3(0.f); - //projNorm[resolveCase] = 1; - //ImGui::Text(("Axis " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); boxVelocity[resolveCase] = 0.f; return true; } case Line: projNorm = glm::normalize(outVector); - //ImGui::Text(("Line " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); break; case Corner: projNorm = triNormal; - //ImGui::Text(("Corner " + std::string(projNorm.y > SlopeConstant(45.0f) ? "Ground" : "Slope") + "collision proj=(%f,%f,%f)").c_str(), projNorm.x, projNorm.y, projNorm.z); break; default: break; @@ -466,19 +461,6 @@ bool AABBvsTriangle(const AABB& box, //Project the velocity onto the normal of the hit line/face. //w = v - *n, |n|==1. boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; - - //Ensure that the player will be pushed in the xz-plane. - //glm::vec3 moveDir(outVector); - //moveDir.y = 0; - //if (vectorHasLength(moveDir)) { - // moveDir = glm::normalize(moveDir); - // float len = glm::length(outVector); - // float dotMoveOut = moveDir.x * outVector.x + moveDir.z * outVector.z; - // float ang = glm::half_pi() - glm::acos(dotMoveOut / len); - // if (len > 0.0000001f && ang > 0.0000001f) { - // outVector = (len / glm::sin(ang)) * moveDir; - // } - //} } return true; } From 2961f198b3e71546405343e34f7fa0e4a7175b4c Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 3 Feb 2016 11:48:22 +0100 Subject: [PATCH 27/49] PlayerDeathSystem is now working well. Changed so the model is oriented correctly. Changed so camera is behind the player. Copied the current animation and froze it. --- .../PlayerDeathExplosionWithCamera.xml | 5 ++- src/Game/Systems/PlayerDeathSystem.cpp | 37 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml index bdebbfe7..ff33476d 100644 --- a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml +++ b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml @@ -8,12 +8,13 @@ 0 - 8 + 4 0 - 8 + 4 + Models/AssaultAnimated.mesh diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index d57caefc..d6680928 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -43,38 +43,39 @@ void PlayerDeathSystem::Update(double dt) bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) { - //LOAD THE XML + //load the explosioneffect XML auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); EntityFileParser parser(deathEffect); EntityID deathEffectID = parser.MergeEntities(m_World); EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); - - //current components for player that we need - auto playerModelEW = e.Player.FirstChildByName("PlayerModel"); - auto playerEntityModel = playerModelEW["Model"]; - auto playerEntityTransform = playerModelEW["Transform"]; - //copy the data from player to new playermodel + //components that we need from player + auto playerCamera = e.Player.FirstChildByName("Camera"); + auto playerEntityModel = e.Player.FirstChildByName("PlayerModel")["Model"]; + auto playerEntityAnimation = e.Player.FirstChildByName("PlayerModel")["Animation"]; + + //copy the data from player to explisioneffectmodel playerEntityModel.Copy(deathEffectEW["Model"]); - playerEntityTransform.Copy(deathEffectEW["Transform"]); + playerEntityAnimation.Copy(deathEffectEW["Animation"]); + //freeze the animation + deathEffectEW["Animation"]["Speed"] = 0.0; - //change the animation speed and make sure the explosioneffect spawns at the players position - //http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ - auto playerPosition = (glm::vec3)e.Player["Transform"]["Position"]; - deathEffectEW["Transform"]["Position"] = playerPosition; - deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = playerPosition; + //copy the models position,orientation + deathEffectEW["Transform"]["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; + deathEffectEW["Transform"]["Orientation"] = (glm::vec3)e.Player["Transform"]["Orientation"]; + //effect,camera is relative to playersPosition + deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 0, 0); - //camera (with lifetime) slightly above the player and looking down at the player - //camera will be positioned just above the player - glm::vec3 cameraPosition = glm::vec3(0, 10, 0); + //camera (with lifetime) behind the player auto cam = deathEffectEW.FirstChildByName("Camera"); - cam["Transform"]["Position"] = cameraPosition; + cam["Transform"]["Position"] = glm::vec3(0, 2.5f, 1.8f); + cam["Transform"]["Orientation"] = glm::vec3(5.655f, 0, 0); Events::SetCamera eSetCamera; eSetCamera.CameraEntity = cam; m_EventBroker->Publish(eSetCamera); - //on deathanim done -> del entity + //done -> del entity m_World->DeleteEntity(e.Player.ID); return true; } From 9d3171540df1d0acd04174a564459ab13b4ae4b6 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 3 Feb 2016 11:54:14 +0100 Subject: [PATCH 28/49] AssaultDashCheck is now in FirstPersonInputController instead. TODO: config option, shift button, forward/backward dash --- .../Engine/Input/FirstPersonInputController.h | 62 +++++++++++++++++++ include/Game/Systems/PlayerMovementSystem.h | 15 ----- src/Game/Systems/PlayerMovementSystem.cpp | 44 +------------ 3 files changed, 65 insertions(+), 56 deletions(-) diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index d4c9071c..1efe4b75 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -25,6 +25,10 @@ public: virtual bool OnCommand(const Events::InputCommand& e) override; virtual void Reset(); + void AssaultDashCheck(double dt, bool isJumping); + virtual bool AssaultDashDoubleTapped() const { return m_AssaultDashDoubleTapped; } + virtual bool PlayerIsDashing() const { return m_PlayerIsDashing; } + protected: const int m_PlayerID; bool m_MouseLocked = false; @@ -33,6 +37,23 @@ protected: bool m_Jumping = false; bool m_DoubleJumping = false; bool m_Crouching = false; + //assault dash enum + enum class AssaultDashDirection { + Left, + Right, + Forward, + Backward, + None + }; + //assault dash membervariables + double m_AssaultDashDoubleTapDeltaTime = 0.0f; + double m_AssaultDashCoolDownTimer = 0.0f; + double m_AssaultDashCoolDownMaxTimer = 3.0f; + AssaultDashDirection m_AssaultDashDoubleTapLastKey = AssaultDashDirection::None; + const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; + AssaultDashDirection m_AssaultDashTapDirection = AssaultDashDirection::None; + bool m_AssaultDashDoubleTapped = false; + bool m_PlayerIsDashing = false; EventRelay m_ELockMouse; bool OnLockMouse(const Events::LockMouse& e); @@ -129,4 +150,45 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou return true; } +template +void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping) { + auto controllerMovement = Movement(); + m_AssaultDashDoubleTapDeltaTime += dt; + m_AssaultDashCoolDownTimer -= dt; + //cooldown = m_AssaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) + if (m_AssaultDashCoolDownTimer > (m_AssaultDashCoolDownMaxTimer - 0.25f)) { + m_PlayerIsDashing = true; + } else { + m_PlayerIsDashing = false; + } + //reset the DoubleTapped state in case we recently doubleTapped + if (m_AssaultDashDoubleTapped) { + m_AssaultDashDoubleTapped = false; + } + //Assault Dash logic: tap left or right twice within 0.5sec to activate the doubletap-dash + if (controllerMovement.x > 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { + if (m_AssaultDashDoubleTapLastKey != AssaultDashDirection::Right && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer + && m_AssaultDashTapDirection == AssaultDashDirection::Right && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + } + m_AssaultDashDoubleTapLastKey = AssaultDashDirection::Right; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashTapDirection = AssaultDashDirection::Right; + } else if (controllerMovement.x < 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { + if (m_AssaultDashDoubleTapLastKey != AssaultDashDirection::Left && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer + && m_AssaultDashTapDirection == AssaultDashDirection::Left && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + } + m_AssaultDashDoubleTapLastKey = AssaultDashDirection::Left; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashTapDirection = AssaultDashDirection::Left; + } else { + m_AssaultDashDoubleTapLastKey = AssaultDashDirection::None; + } +} + #endif \ No newline at end of file diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 554d174e..34862e90 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -21,19 +21,4 @@ private: EventRelay m_EPlayerSpawned; bool OnPlayerSpawned(Events::PlayerSpawned& e); - double m_AssaultDashDoubleTapDeltaTime = 0.0f; - double m_AssaultDashCoolDownTimer = 0.0f; - double m_AssaultDashCoolDownMaxTimer = 3.0f; - ImGuiKey m_AssaultDashDoubleTapLastKey = ImGuiKey_Escape; - const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; - enum class AssaultDashDirection { - Left, - Right, - None - }; - AssaultDashDirection m_AssaultDashTapDirection = AssaultDashDirection::None; - bool m_AssaultDashDoubleTapped = false; - bool m_PlayerIsDashing = false; - - void assaultDashCheck(glm::vec3 controllerMovement, double dt, bool isJumping); }; \ No newline at end of file diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index c3eb1c84..70bbafb0 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -43,7 +43,7 @@ void PlayerMovementSystem::Update(double dt) ComponentWrapper cPhysics = player["Physics"]; //Assault Dash Check - //TODO: check if playerclass is assault! - assaultDashCheck(controller->Movement(), dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); float wishSpeed; if (controller->Crouching()) { @@ -74,14 +74,14 @@ void PlayerMovementSystem::Update(double dt) ImGui::InputFloat("surfaceFriction", &surfaceFriction); float accelerationSpeed = actualAccel * (float)dt * wishSpeed * surfaceFriction; //if doubleTapped do Assault Dash - but only boost maximum 50.0f - float doubleTapDashBoost = m_AssaultDashDoubleTapped ? 20.0f : 1.0f; + float doubleTapDashBoost = controller->AssaultDashDoubleTapped() ? 20.0f : 1.0f; accelerationSpeed = glm::min(doubleTapDashBoost*glm::min(accelerationSpeed, addSpeed), 50.0f); velocity += accelerationSpeed * wishDirection; ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); } //you cant jump and dash at the same time - since there is no friction in the air and we would thus dash much further in the air - if (!m_PlayerIsDashing && controller->Jumping() && !controller->Crouching() && (velocity.y == 0.f || !controller->DoubleJumping())) { + if (!controller->PlayerIsDashing() && controller->Jumping() && !controller->Crouching() && (velocity.y == 0.f || !controller->DoubleJumping())) { if (velocity.y == 0.f) { controller->SetDoubleJumping(false); } @@ -170,41 +170,3 @@ bool PlayerMovementSystem::OnPlayerSpawned(Events::PlayerSpawned& e) return true; } -void PlayerMovementSystem::assaultDashCheck(glm::vec3 controllerMovement, double dt, bool isJumping) { - m_AssaultDashDoubleTapDeltaTime += dt; - m_AssaultDashCoolDownTimer -= dt; - //cooldown = m_AssaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) - if (m_AssaultDashCoolDownTimer > (m_AssaultDashCoolDownMaxTimer - 0.25f)) { - m_PlayerIsDashing = true; - } else { - m_PlayerIsDashing = false; - } - //reset the DoubleTapped state in case we recently doubleTapped - if (m_AssaultDashDoubleTapped) { - m_AssaultDashDoubleTapped = false; - } - //Assault Dash logic: tap left or right twice within 0.5sec to activate the doubletap-dash - if (controllerMovement.x > 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { - if (m_AssaultDashDoubleTapLastKey != ImGuiKey_RightArrow && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer - && m_AssaultDashTapDirection == AssaultDashDirection::Right && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { - m_AssaultDashDoubleTapped = true; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; - } - m_AssaultDashDoubleTapLastKey = ImGuiKey_RightArrow; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashTapDirection = AssaultDashDirection::Right; - } else if (controllerMovement.x < 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { - if (m_AssaultDashDoubleTapLastKey != ImGuiKey_LeftArrow && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer - && m_AssaultDashTapDirection == AssaultDashDirection::Left && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { - m_AssaultDashDoubleTapped = true; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; - } - m_AssaultDashDoubleTapLastKey = ImGuiKey_LeftArrow; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashTapDirection = AssaultDashDirection::Left; - } else { - m_AssaultDashDoubleTapLastKey = ImGuiKey_Escape; - } -} From b56824786ce1c01f429b9f2309423bb1021a929e Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 3 Feb 2016 16:16:06 +0100 Subject: [PATCH 29/49] Revert "Merge pull request #75 from teamfisk/NormalSpecularMapping" This reverts commit 192de8078250ffc612c3d3642c484579959315bf, reversing changes made to 24aac6a00d27940de6a596ef0360f1ae9271aa78. --- assets | 2 +- .../Rendering/DrawColorCorrectionPass.h | 4 +- include/Engine/Rendering/RenderQueue.h | 4 - include/Engine/Rendering/Util/GLError.h | 2 +- resources/Schema/Components.xsd | 1 - resources/Schema/Components/SceneLight.xml | 7 - resources/Schema/Components/SceneLight.xsd | 25 - resources/Schema/Entities/AssetPedistal.xml | 51 - resources/Schema/Entities/EditorTestWorld.xml | 196 +-- .../Schema/Entities/EditorWidgetTranslate.xml | 9 + resources/Schema/Entities/Player.xml | 17 +- .../Schema/Entities/QualityAssurance.xml | 1558 ----------------- resources/Schema/Entities/RayBlue.xml | 3 +- resources/Schema/Entities/RayRed.xml | 3 +- resources/Schema/Entities/SoundEmitter.xml | 24 - .../Entities/SpawnPointClusterWithModels.xml | 68 - .../Entities/SpawnerWithPlayerModel.xml | 16 - resources/Schema/Types/Entity.xsd | 1 - .../Shaders/DrawColorCorrection.frag.glsl | 4 +- resources/Shaders/ExplosionEffect.geom.glsl | 28 +- resources/Shaders/ForwardPlus.frag.glsl | 15 +- resources/Shaders/ForwardPlus.vert.glsl | 4 +- src/Engine/Editor/EditorRenderSystem.cpp | 8 +- .../Rendering/DrawColorCorrectionPass.cpp | 10 +- src/Engine/Rendering/DrawFinalPass.cpp | 70 +- src/Engine/Rendering/FrameBuffer.cpp | 7 + src/Engine/Rendering/PickingPass.cpp | 8 +- src/Engine/Rendering/RenderSystem.cpp | 9 +- src/Engine/Rendering/Renderer.cpp | 4 +- 29 files changed, 137 insertions(+), 2021 deletions(-) delete mode 100644 resources/Schema/Components/SceneLight.xml delete mode 100644 resources/Schema/Components/SceneLight.xsd delete mode 100644 resources/Schema/Entities/AssetPedistal.xml delete mode 100644 resources/Schema/Entities/QualityAssurance.xml delete mode 100644 resources/Schema/Entities/SoundEmitter.xml delete mode 100644 resources/Schema/Entities/SpawnPointClusterWithModels.xml delete mode 100644 resources/Schema/Entities/SpawnerWithPlayerModel.xml diff --git a/assets b/assets index c4898d82..091ad5c0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c4898d8281b5584d89b1caf14dab8e5fac120321 +Subproject commit 091ad5c01bf7b6ef5501fc907fc610576a4a45ea diff --git a/include/Engine/Rendering/DrawColorCorrectionPass.h b/include/Engine/Rendering/DrawColorCorrectionPass.h index fcde73d7..e9a7e281 100644 --- a/include/Engine/Rendering/DrawColorCorrectionPass.h +++ b/include/Engine/Rendering/DrawColorCorrectionPass.h @@ -7,7 +7,6 @@ #include "ShaderProgram.h" //#include "Util/UnorderedMapVec2.h" #include "Texture.h" -#include "imgui/imgui.h" class DrawColorCorrectionPass { @@ -17,13 +16,14 @@ public: void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure); + void Draw(GLuint sceneTexture, GLuint bloomTexture); private: const IRenderer* m_Renderer; ShaderProgram* m_ColorCorrectionProgram; Model* m_ScreenQuad; + GLfloat m_Exposure; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index af9d928e..57371146 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -26,7 +26,6 @@ struct RenderScene std::list> DirectionalLightJobs; Rectangle Viewport; bool ClearDepth = false; - glm::vec4 AmbientColor; void Clear() { @@ -41,9 +40,6 @@ struct RenderScene struct RenderFrame { public: - //TODO: Getters - GLfloat Gamma = 2.2f; - GLfloat Exposure = 1.f; void Add(RenderScene &scene) { diff --git a/include/Engine/Rendering/Util/GLError.h b/include/Engine/Rendering/Util/GLError.h index 2b244e1c..754623d1 100644 --- a/include/Engine/Rendering/Util/GLError.h +++ b/include/Engine/Rendering/Util/GLError.h @@ -9,7 +9,7 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig GLenum error = glGetError(); if (error != GL_NO_ERROR) { - _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s\nError code: %i, %s\n", info, error, gluErrorString(error)); + _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s, %i, %s", info, error, gluErrorString(error)); return true; } diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index bb1fd770..ab46b0ea 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -11,7 +11,6 @@ - diff --git a/resources/Schema/Components/SceneLight.xml b/resources/Schema/Components/SceneLight.xml deleted file mode 100644 index 80b6b9f4..00000000 --- a/resources/Schema/Components/SceneLight.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - true - 2.2 - 1 - \ No newline at end of file diff --git a/resources/Schema/Components/SceneLight.xsd b/resources/Schema/Components/SceneLight.xsd deleted file mode 100644 index 9f8a9705..00000000 --- a/resources/Schema/Components/SceneLight.xsd +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - Some settings for the scene lighting - - - - - Color of the ambient light - - - Wether the ambient light should be applied or not - - - Gamma correction for the scene - - - The exposure of the camera - - - - - \ No newline at end of file diff --git a/resources/Schema/Entities/AssetPedistal.xml b/resources/Schema/Entities/AssetPedistal.xml deleted file mode 100644 index 728a3028..00000000 --- a/resources/Schema/Entities/AssetPedistal.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/AssaultWeaponBlue.mesh - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 4727c777..9565e2d4 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -2,9 +2,7 @@ - - - + @@ -20,7 +18,7 @@ - + @@ -40,27 +38,18 @@ Models/DirectionalLightWidget.mesh - 1 + 1.0499999523162842 - + - - true - - - 5.0498686575577523 - 5 - - 3 - Models/Assault.mesh @@ -73,26 +62,11 @@ - Models/AssaultWeaponRed.mesh - true + Models/SecondaryWeapon.mesh - - - - - - - - - - Models/DefenderGunRed.mesh - true - false - - - - + + @@ -111,7 +85,7 @@ Run - + 1 @@ -127,7 +101,7 @@ Walk - + 1 @@ -173,6 +147,70 @@ + + + + Models/NormalMapSphere.mesh + + + + + + + + + + + Models/SpecularMapSphere.mesh + + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + + + + + Models/IncandescenceMapSphere.mesh + + + + + + + @@ -189,7 +227,7 @@ - + @@ -246,94 +284,8 @@ - - - - 1 - - - - - - - - - - - Models/NormalMapSphere.mesh - - - - - - - - - - - Models/SpecularMapSphere.mesh - - - - - - - - - - 1 - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 3 - 1.1399998664855957 - - - - - - - - - - - - - - - - Models/IncandescenceMapSphere.mesh - - - - - - - - - - - - - 1.3999999761581421 - - - - - diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index c6dba4d9..d4ed5e76 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -84,6 +84,15 @@ + + + + + + + + + diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index d365c0ee..e81ec5aa 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -2,12 +2,12 @@ + - @@ -20,7 +20,7 @@ - + @@ -101,19 +101,12 @@ - - true - - 3.7999999523162842 - - true - - Models/AssaultWeaponRed.mesh + Models/AssaultWeapon.mesh - + @@ -148,7 +141,7 @@ Hold Pos - + 1 diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml deleted file mode 100644 index e057cf38..00000000 --- a/resources/Schema/Entities/QualityAssurance.xml +++ /dev/null @@ -1,1558 +0,0 @@ - - - - - - - - - - - - - - - - Models/Core/UnitPlane.mesh - - - - - - - - - - - 90 - - - - - - - - - - - - 1 - - - - - - - - - - - Audio/crosscounter.wav - true - - - - - - - - - - SoundEmitter - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Sound Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - 0.80000001192092896 - - - Models/DirectionalLightWidget.mesh - - - 1 - - - - - - - - - - - - - - - - - - - - - Run - - 1 - - - models/AssaultAnimated.mesh - - - - - - - - - - - Walk - - 1 - - - models/AssaultAnimated.mesh - - - - - - - - - Animation test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Run - - 1 - - - Models/AssaultAnimated.mesh - - - - - - - - - - - - - - - - - - - - - - - - models/NormSpecIncdMapSphere.mesh - - - - - - - - - 1 - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 3 - 1.1399998664855957 - - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 5.0100002288818359 - 0.69999998807907104 - - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 4 - 0.80000001192092896 - - - - - - - - - - - - - - 1 - - - - - - - - - - - Models/NormalMapSphere.mesh - - - - - - - - - - - Models/SpecularMapSphere.mesh - - - - - - - - - - 1 - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 3 - 1.1399998664855957 - - - - - - - - - - - - - - - - Models/IncandescenceMapSphere.mesh - - - - - - - - - - - - - TextureMap's Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - 1.3999999761581421 - - - - - - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - - - Spawn Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - true - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - true - - - - - - - - - - - - Models/Core/UnitRaptor.mesh - - true - - - - - - - - - - - Models/Assault.mesh - - true - - - - - - - - - - - - Models/Core/UnitCube.mesh - - true - - - - - - - - - - - - - Transparency Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/AssaultWeaponBlue.mesh - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/AssaultWeaponRed.mesh - - - - - - - - - - - - - - - - Asset Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/SecondaryWeapon.mesh - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/AssualtSoft.mesh - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/DefenderGunBlue.mesh - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/DefenderGunRed.mesh - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Models/Assualt.mesh - - - - - - - - - - - - - - - - - - - - - - - - CapturePoint Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - Models/CapturePoint.mesh - - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - true - - - - - - - - - - - - - - - - - - Red team home point - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Models/CapturePoint.mesh - - - - - - - - - - - 1 - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - RedMiddle Point - Fonts/DroidSans.ttf - - - - - - - - - - - - - - - Models/CapturePoint.mesh - - - - - - - - - 2 - - - Models/Core/UnitCube.mesh - true - - - - - - - - - - - - - - Middle Point - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Models/CapturePoint.mesh - - - - - - - - - - - -12.033302729641917 - 3 - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - BlueMiddle Point - Fonts/DroidSans.ttf - - - - - - - - - - - - - - - Models/CapturePoint.mesh - - - - - - - - - - - - - - 4 - - - Models/Core/UnitCube.mesh - - true - - - - - - - - - - - - - - - - - - Blue team home point - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Models/Test/ObstacleCourse.mesh - - - - - - - - - - - Collision Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - Models/Core/UnitCube.mesh - - - - - - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - true - - 0.75008034908941568 - 3.7999999523162842 - - true - - - Models/AssaultWeaponBlue.mesh - true - - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - - - 1.1999860997035228 - - - Models/Assault.mesh - true - - - - - - - - - - - - - - - Models/Core/UnitCylinder.mesh - - - - - - - - - - - - - - - - - - - - 0.5 - - - - - - - - - - - Walk - - 1 - - - true - - - 0.68343188336345406 - - true - - - Models/AssaultAnimated.mesh - true - - - - - - - - - - - - - - - ExplosionEffect Test - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - - - - - - - - Remember to pick random entities. - Fonts/DroidSans.ttf,64 - - - - - - - - - - - - - - diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 4a0bb9d4..3b985a7e 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -7,8 +7,7 @@ Models/CylinderBullet.mesh - - true + diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml index e69df489..df563476 100644 --- a/resources/Schema/Entities/RayRed.xml +++ b/resources/Schema/Entities/RayRed.xml @@ -7,8 +7,7 @@ Models/CylinderBullet.mesh - - true + diff --git a/resources/Schema/Entities/SoundEmitter.xml b/resources/Schema/Entities/SoundEmitter.xml deleted file mode 100644 index 39b4c750..00000000 --- a/resources/Schema/Entities/SoundEmitter.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - SoundEmitter - Fonts/DroidSans.ttf,64 - - - - - - - - - - diff --git a/resources/Schema/Entities/SpawnPointClusterWithModels.xml b/resources/Schema/Entities/SpawnPointClusterWithModels.xml deleted file mode 100644 index 9c42d0e4..00000000 --- a/resources/Schema/Entities/SpawnPointClusterWithModels.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - Schema/Entities/Player.xml - - - - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - - - Models/Assault.mesh - - - - - - - - - - diff --git a/resources/Schema/Entities/SpawnerWithPlayerModel.xml b/resources/Schema/Entities/SpawnerWithPlayerModel.xml deleted file mode 100644 index 1274eefa..00000000 --- a/resources/Schema/Entities/SpawnerWithPlayerModel.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Models/Assault.mesh - - - - - - - - - diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 028af9e6..99b90caa 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -31,7 +31,6 @@ - diff --git a/resources/Shaders/DrawColorCorrection.frag.glsl b/resources/Shaders/DrawColorCorrection.frag.glsl index 91ace0c7..8d13992a 100644 --- a/resources/Shaders/DrawColorCorrection.frag.glsl +++ b/resources/Shaders/DrawColorCorrection.frag.glsl @@ -3,7 +3,6 @@ layout (binding = 0) uniform sampler2D SceneTexture; layout (binding = 1) uniform sampler2D BloomTexture; uniform float Exposure; -uniform float Gamma; in VertexData{ vec2 TextureCoordinate; @@ -13,6 +12,7 @@ out vec4 fragmentColor; void main() { + const float gamma = 2.2; vec4 hdrColor = texture(SceneTexture, Input.TextureCoordinate); vec4 bloomColor = texture(BloomTexture, Input.TextureCoordinate); hdrColor += bloomColor; @@ -21,7 +21,7 @@ void main() vec3 result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); //gamme correction - result = pow(result, vec3(1.0 / Gamma)); + result = pow(result, vec3(1.0 / gamma)); fragmentColor = vec4(result, 1.0); //fragmentColor = hdrColor; diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index 44b44aa6..cb91b545 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -17,21 +17,15 @@ uniform bool ExponentialAccelaration; in VertexData{ vec3 Position; vec3 Normal; - vec3 Tangent; - vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; - float ExplosionPercentageElapsed; }Input[]; out VertexData{ vec3 Position; vec3 Normal; - vec3 Tangent; - vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; - float ExplosionPercentageElapsed; }Output; layout(triangles) in; @@ -120,17 +114,12 @@ void main() { // calculate the max distance (s) the triangle will move float s = (randomVelocity.x * ExplosionDuration) + (0.5 * a * pow(ExplosionDuration, 2)); - float te = (length(triangleCenter2ExplosionRadius) / s); - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = te; - + Output.ExplosionColor = EndColor * (length(triangleCenter2ExplosionRadius) / s); } else { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; - + Output.ExplosionColor = EndColor * timePercetage; } // for every vertex on the triangle... @@ -143,8 +132,6 @@ void main() Output.Normal = Input[i].Normal; Output.Position = Input[i].Position; Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; // convert to model space for the gravity to always be in -y vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); @@ -167,14 +154,11 @@ void main() // if explosion color should be affected by distance instead of time... if (ColorByDistance == true) { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = 0.0; + Output.ExplosionColor = vec4(0.0); } else { - Output.ExplosionColor = EndColor; - Output.ExplosionPercentageElapsed = timePercetage; - + Output.ExplosionColor = EndColor * timePercetage; } // for every vertex on the triangle... @@ -184,9 +168,7 @@ void main() Output.Normal = Input[i].Normal; Output.Position = Input[i].Position; Output.TextureCoordinate = Input[i].TextureCoordinate; - Output.Tangent = Input[i].Tangent; - Output.BiTangent = Input[i].BiTangent; - + // no change in position, pass through vertex gl_Position = gl_in[i].gl_Position; EmitVertex(); diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index c09e0438..de672dd1 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -7,13 +7,13 @@ uniform vec4 Color; uniform vec4 DiffuseColor; uniform vec2 ScreenDimensions; uniform vec4 FillColor; -uniform vec4 AmbientColor; uniform float FillPercentage; layout (binding = 0) uniform sampler2D DiffuseTexture; layout (binding = 1) uniform sampler2D NormalMapTexture; layout (binding = 2) uniform sampler2D SpecularMapTexture; layout (binding = 3) uniform sampler2D GlowMapTexture; + #define TILE_SIZE 16 struct LightSource { @@ -55,12 +55,13 @@ in VertexData{ vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; - float ExplosionPercentageElapsed; }Input; out vec4 sceneColor; out vec4 bloomColor; +vec4 scene_ambient = vec4(0.3,0.3,0.3,1); + struct LightResult { vec4 Diffuse; vec4 Specular; @@ -119,7 +120,6 @@ void main() vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate); vec4 position = V * M * vec4(Input.Position, 1.0); vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, NormalMapTexture); - normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); vec4 viewVec = normalize(-position); @@ -128,7 +128,7 @@ void main() tilePos.y = int(gl_FragCoord.y/TILE_SIZE); LightResult totalLighting; - totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); + totalLighting.Diffuse = scene_ambient; int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); int start = int(LightGrids.Data[currentTile].Start); @@ -150,9 +150,8 @@ void main() totalLighting.Specular += light_result.Specular; } - vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); - color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); - //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + + vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; @@ -161,7 +160,7 @@ void main() color_result += FillColor; } sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); - color_result += glowTexel*3; + color_result += glowTexel; bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 3b3e931c..1a7cca12 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -20,7 +20,6 @@ out VertexData{ vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; - float ExplosionPercentageElapsed; }Output; void main() @@ -42,6 +41,5 @@ void main() Output.Normal = vec3(M * vec4(Normal, 0.0)); Output.Tangent = vec3(M * vec4(Tangent, 0.0)); Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); - Output.ExplosionColor = vec4(1.0); - Output.ExplosionPercentageElapsed = 0.0; + Output.ExplosionColor = vec4(0.0); } \ No newline at end of file diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 4d65e9d3..67b09a21 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -23,12 +23,6 @@ void EditorRenderSystem::Update(double dt) scene.Camera = m_EditorCamera; scene.Viewport = Rectangle(1920, 1080); - auto cSceneLight = m_World->GetComponents("SceneLight"); - if (cSceneLight != nullptr) { - //these are hardcoded since they want special light treatment and a component just for widgets is stupid. - scene.AmbientColor = glm::vec4(0.8, 0.8, 0.8, 1.0); - } - auto models = m_World->GetComponents("Model"); if (models != nullptr) { for (auto& cModel : *models) { @@ -55,7 +49,7 @@ void EditorRenderSystem::Update(double dt) glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); for (auto matGroup : model->MaterialGroups()) { std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f); - if (cModel["Transparent"]) { + if(cModel["Transparent"]) { scene.TransparentObjects.push_back(modelJob); } else { scene.OpaqueObjects.push_back(modelJob); diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index 45401bce..ba9efe3e 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -5,8 +5,7 @@ DrawColorCorrectionPass::DrawColorCorrectionPass(IRenderer* renderer) m_Renderer = renderer; m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); - - //m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting. + m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting. InitializeShaderPrograms(); } @@ -20,16 +19,15 @@ void DrawColorCorrectionPass::InitializeShaderPrograms() m_ColorCorrectionProgram->Link(); } -void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure) +void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); GLERROR("DrawScreenQuadPass::Draw: Pre"); DrawScreenQuadPassState state = DrawScreenQuadPassState(); m_ColorCorrectionProgram->Bind(); - //glClear(GL_COLOR_BUFFER_BIT); - glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Exposure"), exposure); - glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Gamma"), gamma); + glClear(GL_COLOR_BUFFER_BIT); + glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Exposure"), m_Exposure); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sceneTexture); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 8247797e..aa9da9a1 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -44,7 +44,6 @@ void DrawFinalPass::InitializeShaderPrograms() m_ForwardPlusProgram->BindFragDataLocation(0, "sceneColor"); m_ForwardPlusProgram->BindFragDataLocation(1, "bloomColor"); m_ForwardPlusProgram->Link(); - GLERROR("Creating forward+ program"); m_ExplosionEffectProgram = ResourceManager::Load("#ExplosionEffectProgram"); m_ExplosionEffectProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); @@ -54,12 +53,11 @@ void DrawFinalPass::InitializeShaderPrograms() m_ExplosionEffectProgram->BindFragDataLocation(0, "sceneColor"); m_ExplosionEffectProgram->BindFragDataLocation(1, "bloomColor"); m_ExplosionEffectProgram->Link(); - GLERROR("Creating explosion program"); } void DrawFinalPass::Draw(RenderScene& scene) { - GLERROR("Pre"); + GLERROR("DrawFinalPass::Draw: Pre"); DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); if (scene.ClearDepth) { @@ -67,12 +65,12 @@ void DrawFinalPass::Draw(RenderScene& scene) } DrawModelRenderQueues(scene.OpaqueObjects, scene); - GLERROR("OpaqueObjects"); + GLERROR("DrawFinalPass::Draw: OpaqueObjects"); DrawModelRenderQueues(scene.TransparentObjects, scene); - GLERROR("TransparentObjects"); + GLERROR("DrawFinalPass::Draw: TransparentObjects"); + GLERROR("DrawFinalPass::Draw: END"); delete state; - GLERROR("END"); } @@ -113,9 +111,7 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm: void DrawFinalPass::DrawModelRenderQueues(std::list>& job, RenderScene& scene) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); - GLERROR("forwardHandle"); GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); - GLERROR("explosionHandle"); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); @@ -126,21 +122,10 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& auto explosionEffectJob = std::dynamic_pointer_cast(job); if(explosionEffectJob) { //Bind program - if(GLERROR("Prebind")) { - continue; - } m_ExplosionEffectProgram->Bind(); - if(GLERROR("BindProgram")) { - continue; - } - - glDisable(GL_CULL_FACE); //Bind uniforms BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); - if(GLERROR("BindExplosionUniforms")) { - continue; - } if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { @@ -149,23 +134,13 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } } - if(GLERROR("Animation")) { - continue; - } //bind textures BindExplosionTextures(explosionEffectJob); - if(GLERROR("BindExplosionTextures")) { - continue; - } //draw glBindVertexArray(explosionEffectJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); - glEnable(GL_CULL_FACE); - if(GLERROR("explosion effect end")) { - continue; - } } else { auto modelJob = std::dynamic_pointer_cast(job); @@ -192,9 +167,7 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); - if(GLERROR("models end")) { - continue; - } + GLERROR("DrawFinalPass::Model: END"); } } } @@ -203,46 +176,36 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor)); glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness); - glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar); glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity)); glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance); glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration); - - glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); - glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); - glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); - glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); - GLERROR("END"); + glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); } void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); - glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); - - GLERROR("END"); } @@ -254,22 +217,7 @@ void DrawFinalPass::BindExplosionTextures(std::shared_ptr& j } else { glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); } - glActiveTexture(GL_TEXTURE1); - if (job->NormalTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); - } - - glActiveTexture(GL_TEXTURE2); - if (job->SpecularTexture != nullptr) { - glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture); - } else { - glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); - } - - glActiveTexture(GL_TEXTURE3); if (job->IncandescenceTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); } else { diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index 9677f50e..b7e908cc 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -54,6 +54,13 @@ void FrameBuffer::Generate() case GL_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); + if ( (*it)->m_Attachment != GL_COLOR_ATTACHMENT0 || + (*it)->m_Attachment != GL_COLOR_ATTACHMENT1 || + (*it)->m_Attachment != GL_DEPTH_ATTACHMENT || + (*it)->m_Attachment != GL_STENCIL_ATTACHMENT) //TODO: Viktor: Fixa detta + { + LOG_ERROR("RenderBuffer Attachment not valid."); + } break; } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index abc79f2e..792539f8 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -75,9 +75,9 @@ void PickingPass::Draw(RenderScene& scene) m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); if (m_ColorCounter[0] > 255) { m_ColorCounter[0] = 0; - m_ColorCounter[1] += 1; + m_ColorCounter[1] += 5; } else { - m_ColorCounter[0] += 1; + m_ColorCounter[0] += 50; } } @@ -121,9 +121,9 @@ void PickingPass::Draw(RenderScene& scene) m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); if (m_ColorCounter[0] > 255) { m_ColorCounter[0] = 0; - m_ColorCounter[1] += 1; + m_ColorCounter[1] += 5; } else { - m_ColorCounter[0] += 1; + m_ColorCounter[0] += 50; } } diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index eaecf99e..a0912a45 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -240,17 +240,10 @@ void RenderSystem::Update(double dt) m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera)); } + RenderScene scene; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); - - auto cSceneLight = m_World->GetComponents("SceneLight"); - if (cSceneLight != nullptr && cSceneLight->begin() != cSceneLight->end()) { - m_RenderFrame->Gamma = (double)(*cSceneLight->begin())["Gamma"]; - m_RenderFrame->Exposure = (double)(*cSceneLight->begin())["Exposure"]; - scene.AmbientColor = (glm::vec4)(*cSceneLight->begin())["AmbientColor"]; - } - fillModels(scene.OpaqueObjects, scene.TransparentObjects); fillPointLights(scene.PointLightJobs, m_World); fillDirectionalLights(scene.DirectionalLightJobs, m_World); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index a63e02a0..bec86b4a 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -119,8 +119,8 @@ void Renderer::Draw(RenderFrame& frame) } m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); - if (m_DebugTextureToDraw == 0) { - m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure); + if(m_DebugTextureToDraw == 0) { + m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture()); } if (m_DebugTextureToDraw == 1) { m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTexture()); From bd2da7bc9f88f8e9f27bfbeaa2c1cff210e0cdb4 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 3 Feb 2016 16:30:00 +0100 Subject: [PATCH 30/49] Revert "Revert "Merge pull request #75 from teamfisk/NormalSpecularMapping"" This reverts commit b56824786ce1c01f429b9f2309423bb1021a929e. --- assets | 2 +- .../Rendering/DrawColorCorrectionPass.h | 4 +- include/Engine/Rendering/RenderQueue.h | 4 + include/Engine/Rendering/Util/GLError.h | 2 +- resources/Schema/Components.xsd | 1 + resources/Schema/Components/SceneLight.xml | 7 + resources/Schema/Components/SceneLight.xsd | 25 + resources/Schema/Entities/AssetPedistal.xml | 51 + resources/Schema/Entities/EditorTestWorld.xml | 196 ++- .../Schema/Entities/EditorWidgetTranslate.xml | 9 - resources/Schema/Entities/Player.xml | 17 +- .../Schema/Entities/QualityAssurance.xml | 1558 +++++++++++++++++ resources/Schema/Entities/RayBlue.xml | 3 +- resources/Schema/Entities/RayRed.xml | 3 +- resources/Schema/Entities/SoundEmitter.xml | 24 + .../Entities/SpawnPointClusterWithModels.xml | 68 + .../Entities/SpawnerWithPlayerModel.xml | 16 + resources/Schema/Types/Entity.xsd | 1 + .../Shaders/DrawColorCorrection.frag.glsl | 4 +- resources/Shaders/ExplosionEffect.geom.glsl | 28 +- resources/Shaders/ForwardPlus.frag.glsl | 15 +- resources/Shaders/ForwardPlus.vert.glsl | 4 +- src/Engine/Editor/EditorRenderSystem.cpp | 8 +- .../Rendering/DrawColorCorrectionPass.cpp | 10 +- src/Engine/Rendering/DrawFinalPass.cpp | 86 +- src/Engine/Rendering/FrameBuffer.cpp | 7 - src/Engine/Rendering/PickingPass.cpp | 8 +- src/Engine/Rendering/RenderSystem.cpp | 9 +- src/Engine/Rendering/Renderer.cpp | 4 +- 29 files changed, 2029 insertions(+), 145 deletions(-) create mode 100644 resources/Schema/Components/SceneLight.xml create mode 100644 resources/Schema/Components/SceneLight.xsd create mode 100644 resources/Schema/Entities/AssetPedistal.xml create mode 100644 resources/Schema/Entities/QualityAssurance.xml create mode 100644 resources/Schema/Entities/SoundEmitter.xml create mode 100644 resources/Schema/Entities/SpawnPointClusterWithModels.xml create mode 100644 resources/Schema/Entities/SpawnerWithPlayerModel.xml diff --git a/assets b/assets index 091ad5c0..c4898d82 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 091ad5c01bf7b6ef5501fc907fc610576a4a45ea +Subproject commit c4898d8281b5584d89b1caf14dab8e5fac120321 diff --git a/include/Engine/Rendering/DrawColorCorrectionPass.h b/include/Engine/Rendering/DrawColorCorrectionPass.h index e9a7e281..fcde73d7 100644 --- a/include/Engine/Rendering/DrawColorCorrectionPass.h +++ b/include/Engine/Rendering/DrawColorCorrectionPass.h @@ -7,6 +7,7 @@ #include "ShaderProgram.h" //#include "Util/UnorderedMapVec2.h" #include "Texture.h" +#include "imgui/imgui.h" class DrawColorCorrectionPass { @@ -16,14 +17,13 @@ public: void InitializeFrameBuffers(); void InitializeShaderPrograms(); - void Draw(GLuint sceneTexture, GLuint bloomTexture); + void Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure); private: const IRenderer* m_Renderer; ShaderProgram* m_ColorCorrectionProgram; Model* m_ScreenQuad; - GLfloat m_Exposure; }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index 57371146..af9d928e 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -26,6 +26,7 @@ struct RenderScene std::list> DirectionalLightJobs; Rectangle Viewport; bool ClearDepth = false; + glm::vec4 AmbientColor; void Clear() { @@ -40,6 +41,9 @@ struct RenderScene struct RenderFrame { public: + //TODO: Getters + GLfloat Gamma = 2.2f; + GLfloat Exposure = 1.f; void Add(RenderScene &scene) { diff --git a/include/Engine/Rendering/Util/GLError.h b/include/Engine/Rendering/Util/GLError.h index 754623d1..2b244e1c 100644 --- a/include/Engine/Rendering/Util/GLError.h +++ b/include/Engine/Rendering/Util/GLError.h @@ -9,7 +9,7 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig GLenum error = glGetError(); if (error != GL_NO_ERROR) { - _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s, %i, %s", info, error, gluErrorString(error)); + _LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s\nError code: %i, %s\n", info, error, gluErrorString(error)); return true; } diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index ab46b0ea..bb1fd770 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -11,6 +11,7 @@ + diff --git a/resources/Schema/Components/SceneLight.xml b/resources/Schema/Components/SceneLight.xml new file mode 100644 index 00000000..80b6b9f4 --- /dev/null +++ b/resources/Schema/Components/SceneLight.xml @@ -0,0 +1,7 @@ + + + + true + 2.2 + 1 + \ No newline at end of file diff --git a/resources/Schema/Components/SceneLight.xsd b/resources/Schema/Components/SceneLight.xsd new file mode 100644 index 00000000..9f8a9705 --- /dev/null +++ b/resources/Schema/Components/SceneLight.xsd @@ -0,0 +1,25 @@ + + + + + + Some settings for the scene lighting + + + + + Color of the ambient light + + + Wether the ambient light should be applied or not + + + Gamma correction for the scene + + + The exposure of the camera + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/AssetPedistal.xml b/resources/Schema/Entities/AssetPedistal.xml new file mode 100644 index 00000000..728a3028 --- /dev/null +++ b/resources/Schema/Entities/AssetPedistal.xml @@ -0,0 +1,51 @@ + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssaultWeaponBlue.mesh + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 9565e2d4..4727c777 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -2,7 +2,9 @@ - + + + @@ -18,7 +20,7 @@ - + @@ -38,18 +40,27 @@ Models/DirectionalLightWidget.mesh - 1.0499999523162842 + 1 - + + + true + + + 5.0498686575577523 + 5 + + 3 + Models/Assault.mesh @@ -62,11 +73,26 @@ - Models/SecondaryWeapon.mesh + Models/AssaultWeaponRed.mesh + true - - + + + + + + + + + + Models/DefenderGunRed.mesh + true + false + + + + @@ -85,7 +111,7 @@ Run - + 1 @@ -101,7 +127,7 @@ Walk - + 1 @@ -147,70 +173,6 @@ - - - - Models/NormalMapSphere.mesh - - - - - - - - - - - Models/SpecularMapSphere.mesh - - - - - - - - - - 1 - - - - - - - - - - - Models/Core/UnitSphere.mesh - - - - 3 - 1.1399998664855957 - - - - - - - - - - - - - - - - Models/IncandescenceMapSphere.mesh - - - - - - - @@ -227,7 +189,7 @@ - + @@ -284,8 +246,94 @@ + + + + 1 + + + + + + + + + + + Models/NormalMapSphere.mesh + + + + + + + + + + + Models/SpecularMapSphere.mesh + + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + + + + + Models/IncandescenceMapSphere.mesh + + + + + + + + + + + + + 1.3999999761581421 + + + + + diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index d4ed5e76..c6dba4d9 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -84,15 +84,6 @@ - - - - - - - - - diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index e81ec5aa..d365c0ee 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -2,12 +2,12 @@ - + @@ -20,7 +20,7 @@ - + @@ -101,12 +101,19 @@ + + true + + 3.7999999523162842 + + true + - Models/AssaultWeapon.mesh + Models/AssaultWeaponRed.mesh - + @@ -141,7 +148,7 @@ Hold Pos - + 1 diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml new file mode 100644 index 00000000..e057cf38 --- /dev/null +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -0,0 +1,1558 @@ + + + + + + + + + + + + + + + + Models/Core/UnitPlane.mesh + + + + + + + + + + + 90 + + + + + + + + + + + + 1 + + + + + + + + + + + Audio/crosscounter.wav + true + + + + + + + + + + SoundEmitter + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Sound Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + 0.80000001192092896 + + + Models/DirectionalLightWidget.mesh + + + 1 + + + + + + + + + + + + + + + + + + + + + Run + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + + + + Walk + + 1 + + + models/AssaultAnimated.mesh + + + + + + + + + Animation test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Run + + 1 + + + Models/AssaultAnimated.mesh + + + + + + + + + + + + + + + + + + + + + + + + models/NormSpecIncdMapSphere.mesh + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 5.0100002288818359 + 0.69999998807907104 + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 4 + 0.80000001192092896 + + + + + + + + + + + + + + 1 + + + + + + + + + + + Models/NormalMapSphere.mesh + + + + + + + + + + + Models/SpecularMapSphere.mesh + + + + + + + + + + 1 + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + 3 + 1.1399998664855957 + + + + + + + + + + + + + + + + Models/IncandescenceMapSphere.mesh + + + + + + + + + + + + + TextureMap's Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + 1.3999999761581421 + + + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + + + Spawn Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + true + + + + + + + + + + + + Models/Core/UnitRaptor.mesh + + true + + + + + + + + + + + Models/Assault.mesh + + true + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + Transparency Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssaultWeaponBlue.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssaultWeaponRed.mesh + + + + + + + + + + + + + + + + Asset Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/SecondaryWeapon.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/AssualtSoft.mesh + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/DefenderGunBlue.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/DefenderGunRed.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Models/Assualt.mesh + + + + + + + + + + + + + + + + + + + + + + + + CapturePoint Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + + + + + + Red team home point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + 1 + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + RedMiddle Point + Fonts/DroidSans.ttf + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + 2 + + + Models/Core/UnitCube.mesh + true + + + + + + + + + + + + + + Middle Point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + -12.033302729641917 + 3 + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + BlueMiddle Point + Fonts/DroidSans.ttf + + + + + + + + + + + + + + + Models/CapturePoint.mesh + + + + + + + + + + + + + + 4 + + + Models/Core/UnitCube.mesh + + true + + + + + + + + + + + + + + + + + + Blue team home point + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Test/ObstacleCourse.mesh + + + + + + + + + + + Collision Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + true + + 0.75008034908941568 + 3.7999999523162842 + + true + + + Models/AssaultWeaponBlue.mesh + true + + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + + + 1.1999860997035228 + + + Models/Assault.mesh + true + + + + + + + + + + + + + + + Models/Core/UnitCylinder.mesh + + + + + + + + + + + + + + + + + + + + 0.5 + + + + + + + + + + + Walk + + 1 + + + true + + + 0.68343188336345406 + + true + + + Models/AssaultAnimated.mesh + true + + + + + + + + + + + + + + + ExplosionEffect Test + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Remember to pick random entities. + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/RayBlue.xml b/resources/Schema/Entities/RayBlue.xml index 3b985a7e..4a0bb9d4 100644 --- a/resources/Schema/Entities/RayBlue.xml +++ b/resources/Schema/Entities/RayBlue.xml @@ -7,7 +7,8 @@ Models/CylinderBullet.mesh - + + true diff --git a/resources/Schema/Entities/RayRed.xml b/resources/Schema/Entities/RayRed.xml index df563476..e69df489 100644 --- a/resources/Schema/Entities/RayRed.xml +++ b/resources/Schema/Entities/RayRed.xml @@ -7,7 +7,8 @@ Models/CylinderBullet.mesh - + + true diff --git a/resources/Schema/Entities/SoundEmitter.xml b/resources/Schema/Entities/SoundEmitter.xml new file mode 100644 index 00000000..39b4c750 --- /dev/null +++ b/resources/Schema/Entities/SoundEmitter.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + SoundEmitter + Fonts/DroidSans.ttf,64 + + + + + + + + + + diff --git a/resources/Schema/Entities/SpawnPointClusterWithModels.xml b/resources/Schema/Entities/SpawnPointClusterWithModels.xml new file mode 100644 index 00000000..9c42d0e4 --- /dev/null +++ b/resources/Schema/Entities/SpawnPointClusterWithModels.xml @@ -0,0 +1,68 @@ + + + + + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + + + Models/Assault.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/SpawnerWithPlayerModel.xml b/resources/Schema/Entities/SpawnerWithPlayerModel.xml new file mode 100644 index 00000000..1274eefa --- /dev/null +++ b/resources/Schema/Entities/SpawnerWithPlayerModel.xml @@ -0,0 +1,16 @@ + + + + + + + Models/Assault.mesh + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 99b90caa..028af9e6 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -31,6 +31,7 @@ + diff --git a/resources/Shaders/DrawColorCorrection.frag.glsl b/resources/Shaders/DrawColorCorrection.frag.glsl index 8d13992a..91ace0c7 100644 --- a/resources/Shaders/DrawColorCorrection.frag.glsl +++ b/resources/Shaders/DrawColorCorrection.frag.glsl @@ -3,6 +3,7 @@ layout (binding = 0) uniform sampler2D SceneTexture; layout (binding = 1) uniform sampler2D BloomTexture; uniform float Exposure; +uniform float Gamma; in VertexData{ vec2 TextureCoordinate; @@ -12,7 +13,6 @@ out vec4 fragmentColor; void main() { - const float gamma = 2.2; vec4 hdrColor = texture(SceneTexture, Input.TextureCoordinate); vec4 bloomColor = texture(BloomTexture, Input.TextureCoordinate); hdrColor += bloomColor; @@ -21,7 +21,7 @@ void main() vec3 result = vec3(1.0) - exp(-hdrColor.rgb * Exposure); //gamme correction - result = pow(result, vec3(1.0 / gamma)); + result = pow(result, vec3(1.0 / Gamma)); fragmentColor = vec4(result, 1.0); //fragmentColor = hdrColor; diff --git a/resources/Shaders/ExplosionEffect.geom.glsl b/resources/Shaders/ExplosionEffect.geom.glsl index cb91b545..44b44aa6 100644 --- a/resources/Shaders/ExplosionEffect.geom.glsl +++ b/resources/Shaders/ExplosionEffect.geom.glsl @@ -17,15 +17,21 @@ uniform bool ExponentialAccelaration; in VertexData{ vec3 Position; vec3 Normal; + vec3 Tangent; + vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; + float ExplosionPercentageElapsed; }Input[]; out VertexData{ vec3 Position; vec3 Normal; + vec3 Tangent; + vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; + float ExplosionPercentageElapsed; }Output; layout(triangles) in; @@ -114,12 +120,17 @@ void main() { // calculate the max distance (s) the triangle will move float s = (randomVelocity.x * ExplosionDuration) + (0.5 * a * pow(ExplosionDuration, 2)); + float te = (length(triangleCenter2ExplosionRadius) / s); - Output.ExplosionColor = EndColor * (length(triangleCenter2ExplosionRadius) / s); + Output.ExplosionColor = EndColor; + Output.ExplosionPercentageElapsed = te; + } else { - Output.ExplosionColor = EndColor * timePercetage; + Output.ExplosionColor = EndColor; + Output.ExplosionPercentageElapsed = timePercetage; + } // for every vertex on the triangle... @@ -132,6 +143,8 @@ void main() Output.Normal = Input[i].Normal; Output.Position = Input[i].Position; Output.TextureCoordinate = Input[i].TextureCoordinate; + Output.Tangent = Input[i].Tangent; + Output.BiTangent = Input[i].BiTangent; // convert to model space for the gravity to always be in -y vec4 ExplodedPositionInModelSpace = M * vec4(ExplodedPosition, 1.0); @@ -154,11 +167,14 @@ void main() // if explosion color should be affected by distance instead of time... if (ColorByDistance == true) { - Output.ExplosionColor = vec4(0.0); + Output.ExplosionColor = EndColor; + Output.ExplosionPercentageElapsed = 0.0; } else { - Output.ExplosionColor = EndColor * timePercetage; + Output.ExplosionColor = EndColor; + Output.ExplosionPercentageElapsed = timePercetage; + } // for every vertex on the triangle... @@ -168,7 +184,9 @@ void main() Output.Normal = Input[i].Normal; Output.Position = Input[i].Position; Output.TextureCoordinate = Input[i].TextureCoordinate; - + Output.Tangent = Input[i].Tangent; + Output.BiTangent = Input[i].BiTangent; + // no change in position, pass through vertex gl_Position = gl_in[i].gl_Position; EmitVertex(); diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index de672dd1..c09e0438 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -7,13 +7,13 @@ uniform vec4 Color; uniform vec4 DiffuseColor; uniform vec2 ScreenDimensions; uniform vec4 FillColor; +uniform vec4 AmbientColor; uniform float FillPercentage; layout (binding = 0) uniform sampler2D DiffuseTexture; layout (binding = 1) uniform sampler2D NormalMapTexture; layout (binding = 2) uniform sampler2D SpecularMapTexture; layout (binding = 3) uniform sampler2D GlowMapTexture; - #define TILE_SIZE 16 struct LightSource { @@ -55,13 +55,12 @@ in VertexData{ vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; + float ExplosionPercentageElapsed; }Input; out vec4 sceneColor; out vec4 bloomColor; -vec4 scene_ambient = vec4(0.3,0.3,0.3,1); - struct LightResult { vec4 Diffuse; vec4 Specular; @@ -120,6 +119,7 @@ void main() vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate); vec4 position = V * M * vec4(Input.Position, 1.0); vec4 normal = V * CalcNormalMappedValue(Input.Normal, Input.Tangent, Input.BiTangent, Input.TextureCoordinate, NormalMapTexture); + normal = normalize(normal); //vec4 normal = normalize(V * vec4(Input.Normal, 0.0)); vec4 viewVec = normalize(-position); @@ -128,7 +128,7 @@ void main() tilePos.y = int(gl_FragCoord.y/TILE_SIZE); LightResult totalLighting; - totalLighting.Diffuse = scene_ambient; + totalLighting.Diffuse = vec4(AmbientColor.rgb, 1.0); int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * int(ScreenDimensions.x/TILE_SIZE))); int start = int(LightGrids.Data[currentTile].Start); @@ -150,8 +150,9 @@ void main() totalLighting.Specular += light_result.Specular; } - - vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; + vec4 color_result = mix((Color * diffuseTexel * DiffuseColor), Input.ExplosionColor, Input.ExplosionPercentageElapsed); + color_result = color_result * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)); + //vec4 color_result = (DiffuseColor + Input.ExplosionColor) * (totalLighting.Diffuse + (totalLighting.Specular * specularTexel)) * diffuseTexel * Color; float pos = ((P * vec4(Input.Position, 1)).y + 1.0)/2.0; @@ -160,7 +161,7 @@ void main() color_result += FillColor; } sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); - color_result += glowTexel; + color_result += glowTexel*3; bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); diff --git a/resources/Shaders/ForwardPlus.vert.glsl b/resources/Shaders/ForwardPlus.vert.glsl index 1a7cca12..3b3e931c 100644 --- a/resources/Shaders/ForwardPlus.vert.glsl +++ b/resources/Shaders/ForwardPlus.vert.glsl @@ -20,6 +20,7 @@ out VertexData{ vec3 BiTangent; vec2 TextureCoordinate; vec4 ExplosionColor; + float ExplosionPercentageElapsed; }Output; void main() @@ -41,5 +42,6 @@ void main() Output.Normal = vec3(M * vec4(Normal, 0.0)); Output.Tangent = vec3(M * vec4(Tangent, 0.0)); Output.BiTangent = vec3(M * vec4(BiTangent, 0.0)); - Output.ExplosionColor = vec4(0.0); + Output.ExplosionColor = vec4(1.0); + Output.ExplosionPercentageElapsed = 0.0; } \ No newline at end of file diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 67b09a21..4d65e9d3 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -23,6 +23,12 @@ void EditorRenderSystem::Update(double dt) scene.Camera = m_EditorCamera; scene.Viewport = Rectangle(1920, 1080); + auto cSceneLight = m_World->GetComponents("SceneLight"); + if (cSceneLight != nullptr) { + //these are hardcoded since they want special light treatment and a component just for widgets is stupid. + scene.AmbientColor = glm::vec4(0.8, 0.8, 0.8, 1.0); + } + auto models = m_World->GetComponents("Model"); if (models != nullptr) { for (auto& cModel : *models) { @@ -49,7 +55,7 @@ void EditorRenderSystem::Update(double dt) glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); for (auto matGroup : model->MaterialGroups()) { std::shared_ptr modelJob = std::make_shared(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f); - if(cModel["Transparent"]) { + if (cModel["Transparent"]) { scene.TransparentObjects.push_back(modelJob); } else { scene.OpaqueObjects.push_back(modelJob); diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index ba9efe3e..45401bce 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -5,7 +5,8 @@ DrawColorCorrectionPass::DrawColorCorrectionPass(IRenderer* renderer) m_Renderer = renderer; m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.mesh"); - m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting. + + //m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting. InitializeShaderPrograms(); } @@ -19,15 +20,16 @@ void DrawColorCorrectionPass::InitializeShaderPrograms() m_ColorCorrectionProgram->Link(); } -void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture) +void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLfloat gamma, GLfloat exposure) { //glBindFramebuffer(GL_FRAMEBUFFER, 0); GLERROR("DrawScreenQuadPass::Draw: Pre"); DrawScreenQuadPassState state = DrawScreenQuadPassState(); m_ColorCorrectionProgram->Bind(); - glClear(GL_COLOR_BUFFER_BIT); - glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Exposure"), m_Exposure); + //glClear(GL_COLOR_BUFFER_BIT); + glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Exposure"), exposure); + glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Gamma"), gamma); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sceneTexture); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index aa9da9a1..8247797e 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -44,6 +44,7 @@ void DrawFinalPass::InitializeShaderPrograms() m_ForwardPlusProgram->BindFragDataLocation(0, "sceneColor"); m_ForwardPlusProgram->BindFragDataLocation(1, "bloomColor"); m_ForwardPlusProgram->Link(); + GLERROR("Creating forward+ program"); m_ExplosionEffectProgram = ResourceManager::Load("#ExplosionEffectProgram"); m_ExplosionEffectProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/ForwardPlus.vert.glsl"))); @@ -53,11 +54,12 @@ void DrawFinalPass::InitializeShaderPrograms() m_ExplosionEffectProgram->BindFragDataLocation(0, "sceneColor"); m_ExplosionEffectProgram->BindFragDataLocation(1, "bloomColor"); m_ExplosionEffectProgram->Link(); + GLERROR("Creating explosion program"); } void DrawFinalPass::Draw(RenderScene& scene) { - GLERROR("DrawFinalPass::Draw: Pre"); + GLERROR("Pre"); DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle()); if (scene.ClearDepth) { @@ -65,12 +67,12 @@ void DrawFinalPass::Draw(RenderScene& scene) } DrawModelRenderQueues(scene.OpaqueObjects, scene); - GLERROR("DrawFinalPass::Draw: OpaqueObjects"); + GLERROR("OpaqueObjects"); DrawModelRenderQueues(scene.TransparentObjects, scene); - GLERROR("DrawFinalPass::Draw: TransparentObjects"); + GLERROR("TransparentObjects"); - GLERROR("DrawFinalPass::Draw: END"); delete state; + GLERROR("END"); } @@ -111,7 +113,9 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm: void DrawFinalPass::DrawModelRenderQueues(std::list>& job, RenderScene& scene) { GLuint forwardHandle = m_ForwardPlusProgram->GetHandle(); + GLERROR("forwardHandle"); GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle(); + GLERROR("explosionHandle"); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); @@ -122,10 +126,21 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& auto explosionEffectJob = std::dynamic_pointer_cast(job); if(explosionEffectJob) { //Bind program + if(GLERROR("Prebind")) { + continue; + } m_ExplosionEffectProgram->Bind(); + if(GLERROR("BindProgram")) { + continue; + } + + glDisable(GL_CULL_FACE); //Bind uniforms BindExplosionUniforms(explosionHandle, explosionEffectJob, scene); + if(GLERROR("BindExplosionUniforms")) { + continue; + } if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) { @@ -134,13 +149,23 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0])); } } + if(GLERROR("Animation")) { + continue; + } //bind textures BindExplosionTextures(explosionEffectJob); + if(GLERROR("BindExplosionTextures")) { + continue; + } //draw glBindVertexArray(explosionEffectJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, explosionEffectJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, explosionEffectJob->EndIndex - explosionEffectJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(explosionEffectJob->StartIndex*sizeof(unsigned int))); + glEnable(GL_CULL_FACE); + if(GLERROR("explosion effect end")) { + continue; + } } else { auto modelJob = std::dynamic_pointer_cast(job); @@ -167,7 +192,9 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& glBindVertexArray(modelJob->Model->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex*sizeof(unsigned int))); - GLERROR("DrawFinalPass::Model: END"); + if(GLERROR("models end")) { + continue; + } } } } @@ -176,36 +203,46 @@ void DrawFinalPass::DrawModelRenderQueues(std::list>& void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) { + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); - glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); glUniform1f(glGetUniformLocation(shaderHandle, "TimeSinceDeath"), job->TimeSinceDeath); glUniform1f(glGetUniformLocation(shaderHandle, "ExplosionDuration"), job->ExplosionDuration); glUniform4fv(glGetUniformLocation(shaderHandle, "EndColor"), 1, glm::value_ptr(job->EndColor)); glUniform1i(glGetUniformLocation(shaderHandle, "Randomness"), job->Randomness); + glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); glUniform1f(glGetUniformLocation(shaderHandle, "RandomnessScalar"), job->RandomnessScalar); glUniform2fv(glGetUniformLocation(shaderHandle, "Velocity"), 1, glm::value_ptr(job->Velocity)); glUniform1i(glGetUniformLocation(shaderHandle, "ColorByDistance"), job->ColorByDistance); glUniform1i(glGetUniformLocation(shaderHandle, "ExponentialAccelaration"), job->ExponentialAccelaration); - glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); - glUniform1fv(glGetUniformLocation(shaderHandle, "RandomNumbers"), 50, job->RandomNumbers.data()); -} -void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) -{ - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); - - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); + glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("END"); +} + +void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr& job, RenderScene& scene) +{ + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(job->Matrix)); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); + + glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + + glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(job->Color)); + glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(job->DiffuseColor)); + glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(job->FillColor)); + glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), job->FillPercentage); + glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + + GLERROR("END"); } @@ -217,7 +254,22 @@ void DrawFinalPass::BindExplosionTextures(std::shared_ptr& j } else { glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); } + glActiveTexture(GL_TEXTURE1); + if (job->NormalTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->NormalTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_NeutralNormalTexture->m_Texture); + } + + glActiveTexture(GL_TEXTURE2); + if (job->SpecularTexture != nullptr) { + glBindTexture(GL_TEXTURE_2D, job->SpecularTexture->m_Texture); + } else { + glBindTexture(GL_TEXTURE_2D, m_GreyTexture->m_Texture); + } + + glActiveTexture(GL_TEXTURE3); if (job->IncandescenceTexture != nullptr) { glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture); } else { diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index b7e908cc..9677f50e 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -54,13 +54,6 @@ void FrameBuffer::Generate() case GL_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle); GLERROR("FrameBuffer generate: glFramebufferRenderbuffer"); - if ( (*it)->m_Attachment != GL_COLOR_ATTACHMENT0 || - (*it)->m_Attachment != GL_COLOR_ATTACHMENT1 || - (*it)->m_Attachment != GL_DEPTH_ATTACHMENT || - (*it)->m_Attachment != GL_STENCIL_ATTACHMENT) //TODO: Viktor: Fixa detta - { - LOG_ERROR("RenderBuffer Attachment not valid."); - } break; } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 792539f8..abc79f2e 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -75,9 +75,9 @@ void PickingPass::Draw(RenderScene& scene) m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); if (m_ColorCounter[0] > 255) { m_ColorCounter[0] = 0; - m_ColorCounter[1] += 5; + m_ColorCounter[1] += 1; } else { - m_ColorCounter[0] += 50; + m_ColorCounter[0] += 1; } } @@ -121,9 +121,9 @@ void PickingPass::Draw(RenderScene& scene) m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); if (m_ColorCounter[0] > 255) { m_ColorCounter[0] = 0; - m_ColorCounter[1] += 5; + m_ColorCounter[1] += 1; } else { - m_ColorCounter[0] += 50; + m_ColorCounter[0] += 1; } } diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index a0912a45..eaecf99e 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -240,10 +240,17 @@ void RenderSystem::Update(double dt) m_Camera->SetOrientation(Transform::AbsoluteOrientation(m_CurrentCamera)); } - RenderScene scene; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); + + auto cSceneLight = m_World->GetComponents("SceneLight"); + if (cSceneLight != nullptr && cSceneLight->begin() != cSceneLight->end()) { + m_RenderFrame->Gamma = (double)(*cSceneLight->begin())["Gamma"]; + m_RenderFrame->Exposure = (double)(*cSceneLight->begin())["Exposure"]; + scene.AmbientColor = (glm::vec4)(*cSceneLight->begin())["AmbientColor"]; + } + fillModels(scene.OpaqueObjects, scene.TransparentObjects); fillPointLights(scene.PointLightJobs, m_World); fillDirectionalLights(scene.DirectionalLightJobs, m_World); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index bec86b4a..a63e02a0 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -119,8 +119,8 @@ void Renderer::Draw(RenderFrame& frame) } m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); - if(m_DebugTextureToDraw == 0) { - m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture()); + if (m_DebugTextureToDraw == 0) { + m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), frame.Gamma, frame.Exposure); } if (m_DebugTextureToDraw == 1) { m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTexture()); From 7b5a2a538815c632da5713ba3a68c5861d2f97df Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 3 Feb 2016 17:30:46 +0100 Subject: [PATCH 31/49] Dashing now works great both with shift and doubletap. Added Dash Component. Changed default Player.xml to have a Dash Component. Disabled Sprint. You can now disable DoubleTapToDash in Input.Ini. Added command "SpecialAbility". --- .../Editor/EditorCameraInputController.h | 7 +- .../Engine/Input/FirstPersonInputController.h | 98 ++++++++++++++----- resources/Schema/Components.xsd | 1 + resources/Schema/Components/Dash.xml | 4 + resources/Schema/Components/Dash.xsd | 18 ++++ resources/Schema/Entities/Player.xml | 1 + src/Game/Systems/PlayerMovementSystem.cpp | 13 ++- 7 files changed, 108 insertions(+), 34 deletions(-) create mode 100644 resources/Schema/Components/Dash.xml create mode 100644 resources/Schema/Components/Dash.xsd diff --git a/include/Engine/Editor/EditorCameraInputController.h b/include/Engine/Editor/EditorCameraInputController.h index 4c139e01..6c5e8b14 100644 --- a/include/Engine/Editor/EditorCameraInputController.h +++ b/include/Engine/Editor/EditorCameraInputController.h @@ -55,11 +55,12 @@ public: } } - if (e.Command == "Sprint") { + //this is just temp here, the sprint ability. it will have a component check later + if (e.Command == "SpecialAbility") { if (e.Value > 0) { - m_SpeedMultiplier *= 2.f; + //m_SpeedMultiplier *= 2.f; } else { - m_SpeedMultiplier /= 2.f; + //m_SpeedMultiplier /= 2.f; } } diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 1efe4b75..4e964d19 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -4,6 +4,7 @@ #include "../GLM.h" #include "../Core/InputController.h" #include "../Core/ELockMouse.h" +#include "InputHandler.h" template class FirstPersonInputController : public InputController @@ -48,12 +49,18 @@ protected: //assault dash membervariables double m_AssaultDashDoubleTapDeltaTime = 0.0f; double m_AssaultDashCoolDownTimer = 0.0f; - double m_AssaultDashCoolDownMaxTimer = 3.0f; + double m_AssaultDashCoolDownMaxTimer = 2.0f; AssaultDashDirection m_AssaultDashDoubleTapLastKey = AssaultDashDirection::None; const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; - AssaultDashDirection m_AssaultDashTapDirection = AssaultDashDirection::None; + std::string m_AssaultDashTapDirection = ""; bool m_AssaultDashDoubleTapped = false; bool m_PlayerIsDashing = false; + bool m_ShiftDashing = true; + bool m_ValidDoubleTap = false; + + //specialabilitys + bool m_MovementKeyDown = false; + bool m_SpecialAbilityKeyDown = false; EventRelay m_ELockMouse; bool OnLockMouse(const Events::LockMouse& e); @@ -125,6 +132,22 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm } } + if (e.Command == "Forward" || e.Command == "Right") { + //if value = 0 then you have just released this key + if (e.Value > 0 || e.Value < 0) { + m_MovementKeyDown = true; + //if you pressed the same key within m_AssaultDashDoubleTapSensitivityTimer then you have doubletapped it + if (m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer && m_AssaultDashTapDirection == e.Command) { + m_ValidDoubleTap = true; + } + } else { + m_MovementKeyDown = false; + //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer + m_AssaultDashTapDirection = e.Command; + m_AssaultDashDoubleTapDeltaTime = 0.f; + } + } + if (e.Command == "Jump") { m_Jumping = e.Value > 0; } @@ -133,6 +156,19 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm m_Crouching = e.Value > 0; } + if (e.Command == "SpecialAbility") { + if (e.Value > 0) { + m_SpecialAbilityKeyDown = true; + } else { + m_SpecialAbilityKeyDown = false; + } + } + if (m_SpecialAbilityKeyDown && m_MovementKeyDown) { + m_ShiftDashing = true; + } else { + m_ShiftDashing = false; + } + return true; } @@ -152,7 +188,6 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou template void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping) { - auto controllerMovement = Movement(); m_AssaultDashDoubleTapDeltaTime += dt; m_AssaultDashCoolDownTimer -= dt; //cooldown = m_AssaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) @@ -161,34 +196,43 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool } else { m_PlayerIsDashing = false; } - //reset the DoubleTapped state in case we recently doubleTapped + + //dashing with shift + if (m_ShiftDashing && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { + //player is dashing with shift + //the wanted-direction is set in playermovement already so we dont need to check what direction we want to dash in! + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + //moving to the side has priority + return; + } + + //dashing with doubletap - check if doubletap to dash enabled + if (ResourceManager::Load("Input.ini")->Get("Keyboard.DoubleTapToDash", false)) { + return; + } + + //reset the DoubleTapped state in case we recently doubleTapped (doubletap will only happen during 1 frame) if (m_AssaultDashDoubleTapped) { m_AssaultDashDoubleTapped = false; } - //Assault Dash logic: tap left or right twice within 0.5sec to activate the doubletap-dash - if (controllerMovement.x > 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { - if (m_AssaultDashDoubleTapLastKey != AssaultDashDirection::Right && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer - && m_AssaultDashTapDirection == AssaultDashDirection::Right && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { - m_AssaultDashDoubleTapped = true; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; - } - m_AssaultDashDoubleTapLastKey = AssaultDashDirection::Right; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashTapDirection = AssaultDashDirection::Right; - } else if (controllerMovement.x < 0 && controllerMovement.y == 0.f && controllerMovement.z == 0.f) { - if (m_AssaultDashDoubleTapLastKey != AssaultDashDirection::Left && m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer - && m_AssaultDashTapDirection == AssaultDashDirection::Left && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { - m_AssaultDashDoubleTapped = true; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; - } - m_AssaultDashDoubleTapLastKey = AssaultDashDirection::Left; - m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashTapDirection = AssaultDashDirection::Left; - } else { - m_AssaultDashDoubleTapLastKey = AssaultDashDirection::None; + + //check if we have received a valid doubletap + if (!m_ValidDoubleTap) { + return; } + m_ValidDoubleTap = false; + + if (!(m_AssaultDashCoolDownTimer <= 0.0f && !isJumping)) { + //if we cant dash at the moment, then just reset the tap-sensitivity-timer + m_AssaultDashDoubleTapDeltaTime = 0.f; + return; + } + //ok, we have a valid tap, lets do it + m_AssaultDashDoubleTapped = true; + m_AssaultDashDoubleTapDeltaTime = 0.f; + m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; } #endif \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index bb1fd770..17278f14 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -30,4 +30,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xml b/resources/Schema/Components/Dash.xml new file mode 100644 index 00000000..084f9620 --- /dev/null +++ b/resources/Schema/Components/Dash.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xsd b/resources/Schema/Components/Dash.xsd new file mode 100644 index 00000000..68b64b0c --- /dev/null +++ b/resources/Schema/Components/Dash.xsd @@ -0,0 +1,18 @@ + + + + + + + + A dash component for one of the classes + + + + + Yada + + + + + \ No newline at end of file diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index d365c0ee..3029e9f7 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -6,6 +6,7 @@ + diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 70bbafb0..4fe3da2d 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -43,8 +43,14 @@ void PlayerMovementSystem::Update(double dt) ComponentWrapper cPhysics = player["Physics"]; //Assault Dash Check - //TODO: check if playerclass is assault! - controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); + if (player.HasComponent("Dash")) { + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); + } glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); + //this makes sure you can only dash in the 4 directions: forw,backw,left,right + if (controller->AssaultDashDoubleTapped() && controller->Movement().z != 0 && controller->Movement().x != 0) { + wishDirection = glm::vec3(controller->Movement().x, 0, 0)* glm::inverse(glm::quat(ori)); + } float wishSpeed; if (controller->Crouching()) { wishSpeed = playerCrouchSpeed; @@ -74,7 +80,7 @@ void PlayerMovementSystem::Update(double dt) ImGui::InputFloat("surfaceFriction", &surfaceFriction); float accelerationSpeed = actualAccel * (float)dt * wishSpeed * surfaceFriction; //if doubleTapped do Assault Dash - but only boost maximum 50.0f - float doubleTapDashBoost = controller->AssaultDashDoubleTapped() ? 20.0f : 1.0f; + float doubleTapDashBoost = controller->AssaultDashDoubleTapped() ? 40.0f : 1.0f; accelerationSpeed = glm::min(doubleTapDashBoost*glm::min(accelerationSpeed, addSpeed), 50.0f); velocity += accelerationSpeed * wishDirection; ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); @@ -84,8 +90,7 @@ void PlayerMovementSystem::Update(double dt) if (!controller->PlayerIsDashing() && controller->Jumping() && !controller->Crouching() && (velocity.y == 0.f || !controller->DoubleJumping())) { if (velocity.y == 0.f) { controller->SetDoubleJumping(false); - } - else { + } else { controller->SetDoubleJumping(true); } velocity.y += 4.f; From 1bd4aa91ff70275f1a3cd38e66c184841617f985 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 3 Feb 2016 17:45:37 +0100 Subject: [PATCH 32/49] Oops! Readded "Sprint" command. Removed some unnecessary variables in FirstPersonInputController. Fixed bug where you couldnt dash right away as the game started. --- .../Engine/Editor/EditorCameraInputController.h | 7 +++---- .../Engine/Input/FirstPersonInputController.h | 17 ++++------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/include/Engine/Editor/EditorCameraInputController.h b/include/Engine/Editor/EditorCameraInputController.h index 6c5e8b14..4c139e01 100644 --- a/include/Engine/Editor/EditorCameraInputController.h +++ b/include/Engine/Editor/EditorCameraInputController.h @@ -55,12 +55,11 @@ public: } } - //this is just temp here, the sprint ability. it will have a component check later - if (e.Command == "SpecialAbility") { + if (e.Command == "Sprint") { if (e.Value > 0) { - //m_SpeedMultiplier *= 2.f; + m_SpeedMultiplier *= 2.f; } else { - //m_SpeedMultiplier /= 2.f; + m_SpeedMultiplier /= 2.f; } } diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index 4e964d19..de4f1226 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -38,24 +38,15 @@ protected: bool m_Jumping = false; bool m_DoubleJumping = false; bool m_Crouching = false; - //assault dash enum - enum class AssaultDashDirection { - Left, - Right, - Forward, - Backward, - None - }; //assault dash membervariables - double m_AssaultDashDoubleTapDeltaTime = 0.0f; - double m_AssaultDashCoolDownTimer = 0.0f; - double m_AssaultDashCoolDownMaxTimer = 2.0f; - AssaultDashDirection m_AssaultDashDoubleTapLastKey = AssaultDashDirection::None; + double m_AssaultDashDoubleTapDeltaTime = 0.0; + double m_AssaultDashCoolDownTimer = 0.0; + double m_AssaultDashCoolDownMaxTimer = 2.0; const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; std::string m_AssaultDashTapDirection = ""; bool m_AssaultDashDoubleTapped = false; bool m_PlayerIsDashing = false; - bool m_ShiftDashing = true; + bool m_ShiftDashing = false; bool m_ValidDoubleTap = false; //specialabilitys From 0bbaf1d57678e6e7745d4fe55466b3330a2f2afe Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 4 Feb 2016 10:04:44 +0100 Subject: [PATCH 33/49] Oops! Removed DebugCode... --- include/Game/Systems/PlayerDeathSystem.h | 5 ---- src/Game/Systems/PlayerDeathSystem.cpp | 31 ------------------------ 2 files changed, 36 deletions(-) diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index 4734947e..7d989dbf 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -11,7 +11,6 @@ #include "Core/EntityFileParser.h" #include "Core/EPlayerDeath.h" -#include "Core/EPlayerDamage.h" class PlayerDeathSystem : public ImpureSystem { @@ -23,9 +22,5 @@ public: private: EventRelay m_OnPlayerDeath; bool OnPlayerDeath(Events::PlayerDeath& e); - - EventRelay m_OnInputCommand; - bool OnInputCommand(const Events::InputCommand& e); - }; #endif \ No newline at end of file diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index d6680928..f7fe1ab5 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -3,40 +3,9 @@ PlayerDeathSystem::PlayerDeathSystem(World* m_World, EventBroker* eventBroker) : System(m_World, eventBroker) { - EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerDeathSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_OnPlayerDeath, &PlayerDeathSystem::OnPlayerDeath); } -bool PlayerDeathSystem::OnInputCommand(const Events::InputCommand& e) -{ - //testing: Jump > playerdamage - if (e.Command != "Jump") { - return false; - - } - - // 0 = released - if (e.Value != 0) { - return false; - - } - - auto players = m_World->GetComponents("Player"); - - for (auto& cPlayer : *players) { - EntityWrapper player(m_World, cPlayer.EntityID); - Events::PlayerDamage e; - e.Player = player; - e.Damage = 50; - m_EventBroker->Publish(e); - - } - - - - return true; -} - void PlayerDeathSystem::Update(double dt) { } From 03a16b46b568ee8079c615559b1a3e2d311855cf Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 4 Feb 2016 10:28:28 +0100 Subject: [PATCH 34/49] Dash component now has the dash-maxCoolDownVariable in it. --- .../Engine/Input/FirstPersonInputController.h | 17 +++++++++-------- resources/Schema/Components/Dash.xml | 2 +- resources/Schema/Components/Dash.xsd | 4 ++-- src/Game/Systems/PlayerMovementSystem.cpp | 5 ++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index de4f1226..fa9af852 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -26,7 +26,7 @@ public: virtual bool OnCommand(const Events::InputCommand& e) override; virtual void Reset(); - void AssaultDashCheck(double dt, bool isJumping); + void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer); virtual bool AssaultDashDoubleTapped() const { return m_AssaultDashDoubleTapped; } virtual bool PlayerIsDashing() const { return m_PlayerIsDashing; } @@ -38,10 +38,11 @@ protected: bool m_Jumping = false; bool m_DoubleJumping = false; bool m_Crouching = false; - //assault dash membervariables + //assault dash membervariables - needed to calculate the doubletap- and dashlogic double m_AssaultDashDoubleTapDeltaTime = 0.0; double m_AssaultDashCoolDownTimer = 0.0; - double m_AssaultDashCoolDownMaxTimer = 2.0; + //i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable), + //and its very unlikely that someone wants to change that value const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; std::string m_AssaultDashTapDirection = ""; bool m_AssaultDashDoubleTapped = false; @@ -178,11 +179,11 @@ bool FirstPersonInputController::OnLockMouse(const Events::LockMou } template -void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping) { +void FirstPersonInputController::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer) { m_AssaultDashDoubleTapDeltaTime += dt; m_AssaultDashCoolDownTimer -= dt; - //cooldown = m_AssaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) - if (m_AssaultDashCoolDownTimer > (m_AssaultDashCoolDownMaxTimer - 0.25f)) { + //cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work) + if (m_AssaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) { m_PlayerIsDashing = true; } else { m_PlayerIsDashing = false; @@ -192,7 +193,7 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool if (m_ShiftDashing && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) { //player is dashing with shift //the wanted-direction is set in playermovement already so we dont need to check what direction we want to dash in! - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; //moving to the side has priority @@ -223,7 +224,7 @@ void FirstPersonInputController::AssaultDashCheck(double dt, bool //ok, we have a valid tap, lets do it m_AssaultDashDoubleTapped = true; m_AssaultDashDoubleTapDeltaTime = 0.f; - m_AssaultDashCoolDownTimer = m_AssaultDashCoolDownMaxTimer; + m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer; } #endif \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xml b/resources/Schema/Components/Dash.xml index 084f9620..fbd255a6 100644 --- a/resources/Schema/Components/Dash.xml +++ b/resources/Schema/Components/Dash.xml @@ -1,4 +1,4 @@ - true + 2.0 \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xsd b/resources/Schema/Components/Dash.xsd index 68b64b0c..ca6fc366 100644 --- a/resources/Schema/Components/Dash.xsd +++ b/resources/Schema/Components/Dash.xsd @@ -9,8 +9,8 @@ - - Yada + + This is the cooldown on dash diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 4fe3da2d..c65a961e 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -41,10 +41,9 @@ void PlayerMovementSystem::Update(double dt) if (player.HasComponent("Physics")) { ComponentWrapper cPhysics = player["Physics"]; - //Assault Dash Check - - //TODO: check if playerclass is assault! + //Assault Dash Check if (player.HasComponent("Dash")) { - controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f); + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["Dash"]["CoolDownMaxTimer"]); } glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); //this makes sure you can only dash in the 4 directions: forw,backw,left,right From 035c79564b2e129e16cefef4c6d527bb9cf75b98 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 4 Feb 2016 11:41:21 +0100 Subject: [PATCH 35/49] Changed Dash name to DashAbility. Fixed dash bug where you could do two different keys to dash. --- include/Engine/Input/FirstPersonInputController.h | 11 ++++++++--- resources/Schema/Components.xsd | 2 +- .../Schema/Components/{Dash.xml => DashAbility.xml} | 2 +- .../Schema/Components/{Dash.xsd => DashAbility.xsd} | 2 +- resources/Schema/Entities/Player.xml | 4 +++- src/Game/Systems/PlayerMovementSystem.cpp | 4 ++-- 6 files changed, 16 insertions(+), 9 deletions(-) rename resources/Schema/Components/{Dash.xml => DashAbility.xml} (78%) rename resources/Schema/Components/{Dash.xsd => DashAbility.xsd} (94%) diff --git a/include/Engine/Input/FirstPersonInputController.h b/include/Engine/Input/FirstPersonInputController.h index fa9af852..2bbd768d 100644 --- a/include/Engine/Input/FirstPersonInputController.h +++ b/include/Engine/Input/FirstPersonInputController.h @@ -45,6 +45,7 @@ protected: //and its very unlikely that someone wants to change that value const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f; std::string m_AssaultDashTapDirection = ""; + std::string m_CurrentDirectionVector = ""; bool m_AssaultDashDoubleTapped = false; bool m_PlayerIsDashing = false; bool m_ShiftDashing = false; @@ -125,17 +126,21 @@ bool FirstPersonInputController::OnCommand(const Events::InputComm } if (e.Command == "Forward" || e.Command == "Right") { + if (e.Value != 0) { + m_CurrentDirectionVector = e.Command == "Right" ? (e.Value > 0 ? "Right" : "Left") : (e.Value > 0 ? "Forward" : "Backward"); + } //if value = 0 then you have just released this key - if (e.Value > 0 || e.Value < 0) { + if (e.Value != 0) { m_MovementKeyDown = true; //if you pressed the same key within m_AssaultDashDoubleTapSensitivityTimer then you have doubletapped it - if (m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer && m_AssaultDashTapDirection == e.Command) { + if (m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer && m_AssaultDashTapDirection == m_CurrentDirectionVector) { m_ValidDoubleTap = true; } } else { + //== 0 m_MovementKeyDown = false; //you have just released the key, store what key it was and reset the doubletap-sensitivity-timer - m_AssaultDashTapDirection = e.Command; + m_AssaultDashTapDirection = m_CurrentDirectionVector; m_AssaultDashDoubleTapDeltaTime = 0.f; } } diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 17278f14..265a3cc5 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -30,5 +30,5 @@ - + \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xml b/resources/Schema/Components/DashAbility.xml similarity index 78% rename from resources/Schema/Components/Dash.xml rename to resources/Schema/Components/DashAbility.xml index fbd255a6..25b9e19a 100644 --- a/resources/Schema/Components/Dash.xml +++ b/resources/Schema/Components/DashAbility.xml @@ -1,4 +1,4 @@ - + 2.0 \ No newline at end of file diff --git a/resources/Schema/Components/Dash.xsd b/resources/Schema/Components/DashAbility.xsd similarity index 94% rename from resources/Schema/Components/Dash.xsd rename to resources/Schema/Components/DashAbility.xsd index ca6fc366..4273cc71 100644 --- a/resources/Schema/Components/Dash.xsd +++ b/resources/Schema/Components/DashAbility.xsd @@ -3,7 +3,7 @@ - + A dash component for one of the classes diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index 3029e9f7..fe24adcc 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -6,7 +6,9 @@ - + + 2.0 + diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index c65a961e..3224f579 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -42,8 +42,8 @@ void PlayerMovementSystem::Update(double dt) if (player.HasComponent("Physics")) { ComponentWrapper cPhysics = player["Physics"]; //Assault Dash Check - if (player.HasComponent("Dash")) { - controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["Dash"]["CoolDownMaxTimer"]); + if (player.HasComponent("DashAbility")) { + controller->AssaultDashCheck(dt, ((glm::vec3)cPhysics["Velocity"]).y != 0.0f, player["DashAbility"]["CoolDownMaxTimer"]); } glm::vec3 wishDirection = controller->Movement() * glm::inverse(glm::quat(ori)); //this makes sure you can only dash in the 4 directions: forw,backw,left,right From c87e4d4fd6f05d8e257da9588836d0252c59a5e4 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 4 Feb 2016 11:53:11 +0100 Subject: [PATCH 36/49] Added mutex to resource manager cache reading to avoid a potential race condition. We hope this is the actual bug we saw. --- include/Engine/Core/ResourceManager.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/include/Engine/Core/ResourceManager.h b/include/Engine/Core/ResourceManager.h index 10529819..b994b5cf 100644 --- a/include/Engine/Core/ResourceManager.h +++ b/include/Engine/Core/ResourceManager.h @@ -200,13 +200,16 @@ static T* ResourceManager::Load(const std::string& resourceName, Resource* paren } //If resource has already been cached and completely loaded. - it = m_ResourceCache.find(cacheKey); - if (it != m_ResourceCache.end()) { - if (it->second != nullptr) { - return static_cast(it->second); - } else { - //Don't return null on failure, exception instead. - throw Resource::FailedLoadingException(); + { + boost::lock_guard guard(m_Mutex); + it = m_ResourceCache.find(cacheKey); + if (it != m_ResourceCache.end()) { + if (it->second != nullptr) { + return static_cast(it->second); + } else { + //Don't return null on failure, exception instead. + throw Resource::FailedLoadingException(); + } } } From 6990e473b3c2d481cee2cd4b5a784051eb386603 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 4 Feb 2016 11:53:35 +0100 Subject: [PATCH 37/49] Adding a clear here makes AMD drivers NOT crash for some reason. We're fixing the symptom but not the underlying cause. --- src/Engine/Rendering/DrawColorCorrectionPass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Rendering/DrawColorCorrectionPass.cpp b/src/Engine/Rendering/DrawColorCorrectionPass.cpp index 45401bce..95de26e2 100644 --- a/src/Engine/Rendering/DrawColorCorrectionPass.cpp +++ b/src/Engine/Rendering/DrawColorCorrectionPass.cpp @@ -27,7 +27,7 @@ void DrawColorCorrectionPass::Draw(GLuint sceneTexture, GLuint bloomTexture, GLf DrawScreenQuadPassState state = DrawScreenQuadPassState(); m_ColorCorrectionProgram->Bind(); - //glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Exposure"), exposure); glUniform1f(glGetUniformLocation(m_ColorCorrectionProgram->GetHandle(), "Gamma"), gamma); From 6a23a987b36e4f0785b4ea07a3455781c8135a3c Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 4 Feb 2016 17:43:45 +0100 Subject: [PATCH 38/49] Started PickupSpawnSystem, added 2 events and a system --- include/Engine/Core/EPickupSpawned.h | 18 ++++++++++++++++++ include/Engine/Core/EPickupTaken.h | 19 +++++++++++++++++++ include/Game/Systems/PickupSpawnSystem.h | 17 +++++++++++++++++ resources/Schema/Components.xsd | 1 + resources/Schema/Components/PickupSpawn.xml | 2 ++ resources/Schema/Components/PickupSpawn.xsd | 11 +++++++++++ src/Game/Systems/PickupSpawnSystem.cpp | 1 + 7 files changed, 69 insertions(+) create mode 100644 include/Engine/Core/EPickupSpawned.h create mode 100644 include/Engine/Core/EPickupTaken.h create mode 100644 include/Game/Systems/PickupSpawnSystem.h create mode 100644 resources/Schema/Components/PickupSpawn.xml create mode 100644 resources/Schema/Components/PickupSpawn.xsd create mode 100644 src/Game/Systems/PickupSpawnSystem.cpp diff --git a/include/Engine/Core/EPickupSpawned.h b/include/Engine/Core/EPickupSpawned.h new file mode 100644 index 00000000..acb6776e --- /dev/null +++ b/include/Engine/Core/EPickupSpawned.h @@ -0,0 +1,18 @@ +#ifndef EPickupSpawned_h__ +#define EPickupSpawned_h__ + +#include "Core/Event.h" +#include "Core/EntityWrapper.h" + +namespace Events +{ + +struct PickupSpawned : Event +{ + EntityID PickupID; + EntityWrapper Spawner; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/EPickupTaken.h b/include/Engine/Core/EPickupTaken.h new file mode 100644 index 00000000..e06fd974 --- /dev/null +++ b/include/Engine/Core/EPickupTaken.h @@ -0,0 +1,19 @@ +#ifndef EPickupTaken_h__ +#define EPickupTaken_h__ + +#include "Core/Event.h" +#include "Core/EntityWrapper.h" + +namespace Events +{ + +struct PickupTaken : Event +{ + EntityID PickupID; + EntityWrapper Spawner; + EntityWrapper Player; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h new file mode 100644 index 00000000..99dad0aa --- /dev/null +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -0,0 +1,17 @@ +#ifndef PickupSpawnSystem_h__ +#define PickupSpawnSystem_h__ + +#include "Core/System.h" +#include "Input/EInputCommand.h" +#include "Systems/SpawnerSystem.h" +#include "Events/ESpawnerSpawn.h" +#include "Core/EPlayerSpawned.h" +#include "Rendering/ESetCamera.h" +#include "Core/ConfigFile.h" +#include "Core/EPickupSpawned.h" + +class PickupSpawnSystem : public ImpureSystem +{ + +}; +#endif diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index ab46b0ea..445d96e7 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -29,4 +29,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/PickupSpawn.xml b/resources/Schema/Components/PickupSpawn.xml new file mode 100644 index 00000000..f8ce1225 --- /dev/null +++ b/resources/Schema/Components/PickupSpawn.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/PickupSpawn.xsd b/resources/Schema/Components/PickupSpawn.xsd new file mode 100644 index 00000000..7ab90407 --- /dev/null +++ b/resources/Schema/Components/PickupSpawn.xsd @@ -0,0 +1,11 @@ + + + + + + + + Combined with a Spawner, defines a spawn point for a pickup + + + diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp new file mode 100644 index 00000000..3b758764 --- /dev/null +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -0,0 +1 @@ +#include "Systems/PickupSpawnSystem.h" From d61e6050938b751f82b7bfd1b58cd1f5628bf358 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 5 Feb 2016 10:56:34 +0100 Subject: [PATCH 39/49] Can walk up "stair-steps". Cleanup WIP. Better performance in RectanglevsTriangle check. Added IsOnGround flag and VerticalStepHeight in Physics. Lotsa commented code saved for historical reasons, remove later. --- include/Engine/Collision/Collision.h | 2 + resources/Schema/Components/Physics.xml | 2 + resources/Schema/Components/Physics.xsd | 4 + src/Engine/Collision/Collision.cpp | 226 +++++++++++++++++----- src/Engine/Collision/CollisionSystem.cpp | 30 ++- src/Game/Systems/PlayerMovementSystem.cpp | 18 +- 6 files changed, 221 insertions(+), 61 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 183c800c..6e4858b2 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -68,6 +68,8 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, + float verticalStepHeight, + bool& isOnGround, glm::vec3& outResolutionVector); //Return true if the boxes are intersecting. diff --git a/resources/Schema/Components/Physics.xml b/resources/Schema/Components/Physics.xml index 9d1638fb..6cb73c75 100644 --- a/resources/Schema/Components/Physics.xml +++ b/resources/Schema/Components/Physics.xml @@ -2,4 +2,6 @@ true + false + 0.33 diff --git a/resources/Schema/Components/Physics.xsd b/resources/Schema/Components/Physics.xsd index 72037f48..7fed1fb5 100644 --- a/resources/Schema/Components/Physics.xsd +++ b/resources/Schema/Components/Physics.xsd @@ -13,6 +13,10 @@ m/s^2 + + + The largest height of a "stair-step" that can be walked over + diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 083af229..7bb0d3c4 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -238,7 +238,7 @@ inline glm::vec3 signNonZero(const glm::vec3& x) { glm::vec3 r; for (int i = 0; i < 3; ++i) { - r[i] = signNonZero(x[i]); + r[i] = (float)signNonZero(x[i]); } return r; } @@ -253,11 +253,11 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, const glm::vec2& boxMax, const std::array& triPos, glm::vec2& resolutionDirection, - float& resolutionDistance, + float& resolutionDistanceSq, bool& pushedFromTriNormal) { pushedFromTriNormal = false; - resolutionDistance = INFINITY; + resolutionDistanceSq = INFINITY; //Project along box normals (coordinate axes, since it's axis-aligned). for (int ax = 0; ax < 2; ++ax) { float minTri = INFINITY; @@ -275,9 +275,11 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, float leftRes = minTri - boxMax[ax]; float rightRes = maxTri - boxMin[ax]; float push = rightRes < -leftRes ? rightRes : leftRes; - float absPush = abs(push); - if (absPush < resolutionDistance) { - resolutionDistance = absPush; + float absPushSq = abs(push); + absPushSq *= absPushSq; + + if (absPushSq < resolutionDistanceSq) { + resolutionDistanceSq = absPushSq; resolutionDirection[1 - ax] = 0.f; resolutionDirection[ax] = push; } @@ -326,9 +328,11 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, float leftRes = minTri - maxBox; float rightRes = maxTri - minBox; float push = rightRes < -leftRes ? rightRes : leftRes; - float absPush = abs(push); - if (absPush < resolutionDistance) { - resolutionDistance = absPush; + float absPushSq = abs(push); + absPushSq *= absPushSq; + + if (absPushSq < resolutionDistanceSq) { + resolutionDistanceSq = absPushSq; resolutionDirection = push * normal; pushedFromTriNormal = true; } @@ -338,26 +342,35 @@ bool rectangleVsTriangle(const glm::vec2& boxMin, constexpr float SlopeConstant(float degrees) { - return (1.0 - degrees / 90.f); + return (1.0f - degrees / 90.f); +} + +//Returns true if the angle between horizon and the collision surface is less than 45 degrees. +constexpr bool FaceIsGround(float faceNormalY) +{ + //TODO: Perhaps the 45 degrees could be saved in a component or in the config.. + return faceNormalY > SlopeConstant(45.0f); } //An array containing 3 int pairs { 0, 2 }, { 0, 1 }, { 1, 2 } constexpr std::array, 3> dimensionPairs({ std::pair(0, 2), std::pair(0, 1), std::pair(1, 2) }); -//TODO: Prefer to move in y - if the resolution is small enough, value in physics comp. -//TODO: Walking down slopes correctly. bool AABBvsTriangle(const AABB& box, const std::array& triPos, + const glm::vec3& originalBoxVelocity, + float verticalStepHeight, + bool& isOnGround, glm::vec3& boxVelocity, - glm::vec3& outVector) + glm::vec3& outResolution) { //Check so we don't have a zero area triangle when calculating the normal. //Also, don't check a triangle facing away from the player. //Less checks, and we should be able to walk out from models if we are trapped inside. glm::vec3 triNormal = glm::cross(triPos[1] - triPos[0], triPos[2] - triPos[0]); - if (!vectorHasLength(triNormal) || (glm::dot(triNormal, boxVelocity) > 0)) { + if (!vectorHasLength(triNormal) || (glm::dot(triNormal, originalBoxVelocity) > 0)) { return false; } + triNormal = glm::normalize(triNormal); enum BoxTriResolveCase { @@ -366,13 +379,29 @@ bool AABBvsTriangle(const AABB& box, ResolveDimZ, Line, //Box edge colliding with triangle line. Corner //Box corner colliding with the triangle face. - } resolveCase; + }; + struct Resolution + { + Resolution() + : DistanceSq(INFINITY) + , Vector(0.f) + {} + BoxTriResolveCase Case; + float DistanceSq; + glm::vec3 Vector; + }; + //The smallest resolution that solves the collision. + Resolution resolveShortest; + //The smallest resolution that solves the collision, that resolves upwards. + Resolution resolveUpwards; + //If player stands on the ground and collides with a ground triangle, + //we might step up onto it if the step is small enough. + bool canStairStepUp = isOnGround && FaceIsGround(triNormal.y); const glm::vec3& origin = box.Origin(); const glm::vec3& half = box.HalfSize(); const glm::vec3& min = box.MinCorner(); const glm::vec3& max = box.MaxCorner(); - float minimumTranslation = INFINITY; //For each projection in xy-, xz-, and yx-planes. for (std::pair dim : dimensionPairs) { @@ -392,21 +421,35 @@ bool AABBvsTriangle(const AABB& box, //if projections don't overlap, return false. if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist, pushedFromTriangleLine)) { return false; - } else if (resolutionDist < minimumTranslation) { - outVector = glm::vec3(0.f); - outVector[dim.first] = resolutionVector.x; - outVector[dim.second] = resolutionVector.y; - minimumTranslation = resolutionDist; - //If we pushed away from triangle line (edge), or if we - //move the player along one coordinate axis (pick the dimension that isn't zero). - resolveCase = pushedFromTriangleLine ? Line : static_cast((abs(outVector[dim.first]) < 0.0001f) ? dim.second : dim.first); + } else { + //Overwrite the smallest resolution if this is smaller. + if (resolutionDist < resolveShortest.DistanceSq) { + resolveShortest.Vector = glm::vec3(0.f); + resolveShortest.Vector[dim.first] = resolutionVector.x; + resolveShortest.Vector[dim.second] = resolutionVector.y; + resolveShortest.DistanceSq = resolutionDist; + //If we pushed away from triangle line (edge), or if we + //move the player along one coordinate axis (pick the dimension that isn't zero). + resolveShortest.Case = pushedFromTriangleLine ? Line : static_cast((abs(resolveShortest.Vector[dim.first]) < 0.0001f) ? dim.second : dim.first); + } + //Overwrite the smallest upward resolution if this is smaller, and resolves upwards. + constexpr int yAxis = 1; + bool resIsUpwardsIn3D = dim.first == yAxis && resolutionVector.x > 0 || dim.second == yAxis && resolutionVector.y > 0; + if (canStairStepUp && resIsUpwardsIn3D && resolutionDist < resolveUpwards.DistanceSq) { + resolveUpwards.Vector = glm::vec3(0.f); + resolveUpwards.Vector[dim.first] = resolutionVector.x; + resolveUpwards.Vector[dim.second] = resolutionVector.y; + resolveUpwards.DistanceSq = resolutionDist; + //If we pushed away from triangle line (edge), or if we + //move the player along one coordinate axis (pick the dimension that isn't zero). + resolveUpwards.Case = pushedFromTriangleLine ? Line : static_cast((abs(resolveUpwards.Vector[dim.first]) < 0.0001f) ? dim.second : dim.first); + } } } //If the triangle does intersect any of the cube diagonals, it will //intersect the cube diagonal that comes //closest to being perpendicular to the plane of the triangle. - triNormal = glm::normalize(triNormal); glm::vec3 diagonal = signNonZero(triNormal) * half; //The triangle plane contains all points P in dot(triNormal, P) == dot(triNormal, v0) //The diagonal line contains all points P in P = origin + diagonal * t. @@ -416,24 +459,62 @@ bool AABBvsTriangle(const AABB& box, return false; } glm::vec3 cornerResolution = (1+t) * diagonal; - if (glm::length(cornerResolution) < minimumTranslation) { - outVector = cornerResolution; - resolveCase = Corner; + //Overwrite the smallest resolution if this is smaller. + float lenSq = glm::length2(cornerResolution); + if (lenSq < resolveShortest.DistanceSq) { + resolveShortest.Vector = cornerResolution; + resolveShortest.Case = Corner; + } + if (canStairStepUp && cornerResolution.y > 0 && lenSq < resolveUpwards.DistanceSq) { + resolveUpwards.Vector = cornerResolution; + resolveUpwards.Case = Corner; + resolveUpwards.DistanceSq = lenSq; } - glm::vec3 projNorm; - switch (resolveCase) { - case ResolveDimX: + //Force the resolution upwards if it is smaller than the threshold verticalStepHeight. + //Else take the shortest resolution. + bool takeUp = resolveUpwards.Vector.y > 0 && resolveUpwards.Vector.y < verticalStepHeight; + Resolution& bestResolve = takeUp ? resolveUpwards : resolveShortest; + outResolution = bestResolve.Vector; + + //TODO: Debug stuff. + std::string dbg; + switch (bestResolve.Case) { case ResolveDimY: + case ResolveDimX: + case ResolveDimZ: + dbg = "Axis"; + break; + case Line: + dbg = "Line"; + break; + case Corner: + dbg = "Corner"; + break; + default: + break; + } + std::string outs = (takeUp ? "Resolve upwards " : "Resolve normal ") + dbg; + //TODO: End debug stuff. + + glm::vec3 projNorm; + switch (bestResolve.Case) { + case ResolveDimY: + boxVelocity.y = 0.f; + if (outResolution.y > 0) + isOnGround = true; + case ResolveDimX: case ResolveDimZ: { //If we get here, the resolution is along one coordinate axis. - //set velocity to 0 in that dimension. - boxVelocity[resolveCase] = 0.f; + //set velocity to 0 in y if it is along y-axis. + outs += isOnGround ? " ground" : " air"; + ImGui::Text(outs.c_str()); + LOG_INFO(outs.c_str()); return true; } case Line: - projNorm = glm::normalize(outVector); + projNorm = glm::normalize(outResolution); break; case Corner: projNorm = triNormal; @@ -442,26 +523,64 @@ bool AABBvsTriangle(const AABB& box, break; } - //If the collision was not on steep wall or similarly (e.g. walking on the ground), do special treatment. - //Magic value that makes condition correspond to: - //if the angle between horizon and the collision surface is less than 45 degrees. - if (projNorm.y > SlopeConstant(45.0f)) { + isOnGround = false; + //If the collision was not on steep wall or similarly (e.g. walking on the ground), force resolution in y only. + if (FaceIsGround(projNorm.y)) { //Ensure that the player always is moved upwards, instead of sliding down. //Also zero the vertical velocity. - float len = glm::length(outVector); - float ang = glm::half_pi() - glm::acos(outVector.y / len); + float len = glm::length(outResolution); + float ang = glm::half_pi() - glm::acos(outResolution.y / len); if (len > 0.0000001f && ang > 0.0000001f) { - outVector.x = 0; - outVector.y = len / glm::sin(ang); - outVector.z = 0; - boxVelocity.y = 0.f; + outResolution.x = 0; + outResolution.y = len / glm::sin(ang); + outResolution.z = 0; } - } else if (projNorm.y > 0) { - //Enter here if the triangle is a steep slope, and it is not facing downwards. //Project the velocity onto the normal of the hit line/face. //w = v - *n, |n|==1. - boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + glm::vec3 projVel = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + if (abs(originalBoxVelocity.x) < 0.001f && abs(originalBoxVelocity.z) < 0.001f) { + boxVelocity.y = 0.f; + } else { + boxVelocity.y = std::min(projVel.y, 0.f); + } + + isOnGround = true; + } else if (projNorm.y > 0) { + //Enter here if the triangle is a steep slope, and it is not facing downwards. + //Ensure that the player will be pushed in the xz-plane. + //glm::vec3 moveDir(outResolution); + //moveDir.y = 0; + //if (vectorHasLength(moveDir)) { + // moveDir = glm::normalize(moveDir); + // float len = glm::length(outResolution); + // float dotMoveOut = moveDir.x * outResolution.x + moveDir.z * outResolution.z; + // float ang = glm::half_pi() - glm::acos(dotMoveOut / len); + // if (len > 0.0000001f && ang > 0.0000001f) { + // outResolution = (len / glm::sin(ang)) * moveDir; + // } + //} + //Project the velocity onto the normal of the hit line/face. + //w = v - *n, |n|==1. + //TODO: What do we want.. +#if 0 //Walk up steep walls. + glm::vec3 projVel = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + boxVelocity.y = std::min(projVel.y, 0.f); + isOnGround = true; +#elif 1 //"ice cream"-effect, air resistance + projected velocity. + if (!isOnGround) { + boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + } + isOnGround = false; +#elif 0 //"ice cream"-effect, ground friction (full control) + projected velocity. + if (!isOnGround) { + boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; + } + isOnGround = true; +#endif } + outs += isOnGround ? " ground" : " air"; + ImGui::Text(outs.c_str()); + LOG_INFO(outs.c_str()); return true; } @@ -470,12 +589,16 @@ bool AABBvsTriangles(const AABB& box, const std::vector& modelIndices, const glm::mat4& modelMatrix, glm::vec3& boxVelocity, + float verticalStepHeight, + bool& isOnGround, glm::vec3& outResolutionVector) { bool hit = false; + bool everHitTheGround = false; AABB newBox = box; outResolutionVector = glm::vec3(0.f); + glm::vec3 originalBoxVelocity(boxVelocity); for (int i = 0; i < modelIndices.size(); ) { std::array triVertices = { Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix), @@ -483,13 +606,20 @@ bool AABBvsTriangles(const AABB& box, Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix) }; glm::vec3 outVec; - if (AABBvsTriangle(newBox, triVertices, boxVelocity, outVec)) { + bool collideWithGround = isOnGround; + if (AABBvsTriangle(newBox, triVertices, originalBoxVelocity, verticalStepHeight, collideWithGround, boxVelocity, outVec)) { hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); + if (collideWithGround) { + everHitTheGround = isOnGround = true; + } } } + if (!everHitTheGround) { + isOnGround = false; + } return hit; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 846d38a7..e5c194d6 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -37,15 +37,33 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::mat4 modelMatrix = Transform::ModelMatrix(boxB.Entity); - glm::vec3 newVelocity = (glm::vec3)cPhysics["Velocity"]; - if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, newVelocity, resolutionVector)) { - (glm::vec3&)cTransform["Position"] += resolutionVector; - cPhysics["Velocity"] = newVelocity; - } + glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; + bool isOnGround = (bool)cPhysics["IsOnGround"]; + //glm::vec3 gravity = glm::vec3(0, 9.82f * dt, 0); + //TODO: glm::abs(inOutVelocity - gravity) doesn't work, because of velocity projection on ground normal. + //if (!isOnGround || glm::any(glm::greaterThan(glm::abs(inOutVelocity - gravity), glm::vec3(0.0001f)))) { + float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + glm::vec3 pos = (glm::vec3)cTransform["Position"] + resolutionVector; + //Hack: Force the position to be at discrete values after collision, removes jittering. + //constexpr float discreteValue = 1.0e2f; + //pos = glm::vec3(glm::ivec3(discreteValue * pos)) / discreteValue; + //pos = glm::round(discreteValue * pos) / discreteValue; + (glm::vec3&)cTransform["Position"] = pos; + cPhysics["Velocity"] = inOutVelocity; + (bool)cPhysics["IsOnGround"] = isOnGround; + } else { + (bool)cPhysics["IsOnGround"] = false; + } + //} else { + // (glm::vec3&)cTransform["Position"] -= gravity; + // cPhysics["Velocity"] = glm::vec3(0.f); + //} } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { //Enter here if boxB has no Model. (glm::vec3&)cTransform["Position"] += resolutionVector; - if (resolutionVector.y > 0) { + (bool)cPhysics["IsOnGround"] = resolutionVector.y > 0; + if ((bool)cPhysics["IsOnGround"]){ ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; } } diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 6eab02c5..92ddf549 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -50,11 +50,13 @@ void PlayerMovementSystem::Update(double dt) wishSpeed = playerMovementSpeed; } glm::vec3& velocity = cPhysics["Velocity"]; - ImGui::Text("velocity: (%f, %f, %f)", velocity.x, velocity.y, velocity.z); + bool isOnGround = (bool)cPhysics["IsOnGround"]; + ImGui::Text(isOnGround ? "On ground" : "In air"); + ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); glm::vec3 groundVelocity(0.f, 0.f, 0.f); - groundVelocity.x = glm::dot(velocity, glm::vec3(1.f, 0.f, 0.f)); - groundVelocity.z = glm::dot(velocity, glm::vec3(0.f, 0.f, 1.f)); - ImGui::Text("groundVelocity: (%f, %f, %f) |%f|", groundVelocity.x, groundVelocity.y, groundVelocity.z, glm::length(wishDirection)); + groundVelocity.x = velocity.x; + groundVelocity.z = velocity.z; + ImGui::Text("groundVelocity: (%f, %f, %f) |%f|", groundVelocity.x, groundVelocity.y, groundVelocity.z, glm::length(groundVelocity)); ImGui::Text("wishDirection: (%f, %f, %f) |%f|", wishDirection.x, wishDirection.y, wishDirection.z, glm::length(wishDirection)); float currentSpeedProj = glm::dot(groundVelocity, wishDirection); float addSpeed = wishSpeed - currentSpeedProj; @@ -67,7 +69,7 @@ void PlayerMovementSystem::Update(double dt) ImGui::InputFloat("accel", &accel); static float airAccel = 0.5f; ImGui::InputFloat("airAccel", &airAccel); - float actualAccel = (velocity.y != 0) ? airAccel : accel; + float actualAccel = isOnGround ? accel : airAccel; static float surfaceFriction = 5.f; ImGui::InputFloat("surfaceFriction", &surfaceFriction); float accelerationSpeed = actualAccel * (float)dt * wishSpeed * surfaceFriction; @@ -76,7 +78,8 @@ void PlayerMovementSystem::Update(double dt) ImGui::Text("velocity: (%f, %f, %f) |%f|", velocity.x, velocity.y, velocity.z, glm::length(velocity)); } - if (controller->Jumping() && !controller->Crouching() && velocity.y == 0.f) { + if (controller->Jumping() && !controller->Crouching() && isOnGround) { + (bool)cPhysics["IsOnGround"] = false; velocity.y += 4.f; } @@ -128,6 +131,7 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp ComponentWrapper& cPhysics = entity["Physics"]; glm::vec3& velocity = cPhysics["Velocity"]; + bool isOnGround = (bool)cPhysics["IsOnGround"]; // Ground friction float speed = glm::length(velocity); @@ -135,7 +139,7 @@ void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapp ImGui::InputFloat("groundFriction", &groundFriction); static float airFriction = 0.f; ImGui::InputFloat("airFriction", &airFriction); - float friction = (velocity.y != 0) ? airFriction : groundFriction; + float friction = isOnGround ? groundFriction : airFriction; if (speed > 0) { float drop = speed * friction * (float)dt; float multiplier = glm::max(speed - drop, 0.f) / speed; From 4fe9e4f1c3586bb346684fe245a92a05adcae68a Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 5 Feb 2016 14:38:08 +0100 Subject: [PATCH 40/49] Debug cleanup and some bug fixes. --- src/Engine/Collision/Collision.cpp | 68 ++---------------------- src/Engine/Collision/CollisionSystem.cpp | 28 +++------- 2 files changed, 13 insertions(+), 83 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 7bb0d3c4..533fdc9b 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -459,7 +459,7 @@ bool AABBvsTriangle(const AABB& box, return false; } glm::vec3 cornerResolution = (1+t) * diagonal; - //Overwrite the smallest resolution if this is smaller. + //Overwrite the smallest resolution if cornerResolution is smaller. float lenSq = glm::length2(cornerResolution); if (lenSq < resolveShortest.DistanceSq) { resolveShortest.Vector = cornerResolution; @@ -477,26 +477,6 @@ bool AABBvsTriangle(const AABB& box, Resolution& bestResolve = takeUp ? resolveUpwards : resolveShortest; outResolution = bestResolve.Vector; - //TODO: Debug stuff. - std::string dbg; - switch (bestResolve.Case) { - case ResolveDimY: - case ResolveDimX: - case ResolveDimZ: - dbg = "Axis"; - break; - case Line: - dbg = "Line"; - break; - case Corner: - dbg = "Corner"; - break; - default: - break; - } - std::string outs = (takeUp ? "Resolve upwards " : "Resolve normal ") + dbg; - //TODO: End debug stuff. - glm::vec3 projNorm; switch (bestResolve.Case) { case ResolveDimY: @@ -505,14 +485,9 @@ bool AABBvsTriangle(const AABB& box, isOnGround = true; case ResolveDimX: case ResolveDimZ: - { //If we get here, the resolution is along one coordinate axis. //set velocity to 0 in y if it is along y-axis. - outs += isOnGround ? " ground" : " air"; - ImGui::Text(outs.c_str()); - LOG_INFO(outs.c_str()); return true; - } case Line: projNorm = glm::normalize(outResolution); break; @@ -523,11 +498,9 @@ bool AABBvsTriangle(const AABB& box, break; } - isOnGround = false; //If the collision was not on steep wall or similarly (e.g. walking on the ground), force resolution in y only. if (FaceIsGround(projNorm.y)) { //Ensure that the player always is moved upwards, instead of sliding down. - //Also zero the vertical velocity. float len = glm::length(outResolution); float ang = glm::half_pi() - glm::acos(outResolution.y / len); if (len > 0.0000001f && ang > 0.0000001f) { @@ -535,52 +508,21 @@ bool AABBvsTriangle(const AABB& box, outResolution.y = len / glm::sin(ang); outResolution.z = 0; } + //Also zero the vertical velocity, if it is positive, else project it onto the normal. //Project the velocity onto the normal of the hit line/face. //w = v - *n, |n|==1. - glm::vec3 projVel = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; - if (abs(originalBoxVelocity.x) < 0.001f && abs(originalBoxVelocity.z) < 0.001f) { - boxVelocity.y = 0.f; - } else { - boxVelocity.y = std::min(projVel.y, 0.f); - } - + boxVelocity.y = std::min(boxVelocity.y - glm::dot(boxVelocity, projNorm) * projNorm.y, 0.f); isOnGround = true; - } else if (projNorm.y > 0) { + } else { //Enter here if the triangle is a steep slope, and it is not facing downwards. - //Ensure that the player will be pushed in the xz-plane. - //glm::vec3 moveDir(outResolution); - //moveDir.y = 0; - //if (vectorHasLength(moveDir)) { - // moveDir = glm::normalize(moveDir); - // float len = glm::length(outResolution); - // float dotMoveOut = moveDir.x * outResolution.x + moveDir.z * outResolution.z; - // float ang = glm::half_pi() - glm::acos(dotMoveOut / len); - // if (len > 0.0000001f && ang > 0.0000001f) { - // outResolution = (len / glm::sin(ang)) * moveDir; - // } - //} //Project the velocity onto the normal of the hit line/face. //w = v - *n, |n|==1. - //TODO: What do we want.. -#if 0 //Walk up steep walls. - glm::vec3 projVel = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; - boxVelocity.y = std::min(projVel.y, 0.f); - isOnGround = true; -#elif 1 //"ice cream"-effect, air resistance + projected velocity. + //"ice cream"-effect, air resistance + projected velocity. if (!isOnGround) { boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; } isOnGround = false; -#elif 0 //"ice cream"-effect, ground friction (full control) + projected velocity. - if (!isOnGround) { - boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; - } - isOnGround = true; -#endif } - outs += isOnGround ? " ground" : " air"; - ImGui::Text(outs.c_str()); - LOG_INFO(outs.c_str()); return true; } diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index e5c194d6..b5d7a1f0 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -39,26 +39,14 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c glm::vec3 inOutVelocity = (glm::vec3)cPhysics["Velocity"]; bool isOnGround = (bool)cPhysics["IsOnGround"]; - //glm::vec3 gravity = glm::vec3(0, 9.82f * dt, 0); - //TODO: glm::abs(inOutVelocity - gravity) doesn't work, because of velocity projection on ground normal. - //if (!isOnGround || glm::any(glm::greaterThan(glm::abs(inOutVelocity - gravity), glm::vec3(0.0001f)))) { - float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; - if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { - glm::vec3 pos = (glm::vec3)cTransform["Position"] + resolutionVector; - //Hack: Force the position to be at discrete values after collision, removes jittering. - //constexpr float discreteValue = 1.0e2f; - //pos = glm::vec3(glm::ivec3(discreteValue * pos)) / discreteValue; - //pos = glm::round(discreteValue * pos) / discreteValue; - (glm::vec3&)cTransform["Position"] = pos; - cPhysics["Velocity"] = inOutVelocity; - (bool)cPhysics["IsOnGround"] = isOnGround; - } else { - (bool)cPhysics["IsOnGround"] = false; - } - //} else { - // (glm::vec3&)cTransform["Position"] -= gravity; - // cPhysics["Velocity"] = glm::vec3(0.f); - //} + float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"]; + if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) { + (glm::vec3&)cTransform["Position"] += resolutionVector; + cPhysics["Velocity"] = inOutVelocity; + (bool)cPhysics["IsOnGround"] = isOnGround; + } else { + (bool)cPhysics["IsOnGround"] = false; + } } else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) { //Enter here if boxB has no Model. (glm::vec3&)cTransform["Position"] += resolutionVector; From 428dca003daf6daa38d81e67a3a1c29727f42094 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 5 Feb 2016 14:40:50 +0100 Subject: [PATCH 41/49] Tiny bug fix. --- src/Engine/Collision/Collision.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 533fdc9b..fe4eb5e0 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -521,7 +521,6 @@ bool AABBvsTriangle(const AABB& box, if (!isOnGround) { boxVelocity = boxVelocity - glm::dot(boxVelocity, projNorm) * projNorm; } - isOnGround = false; } return true; } From fe6fd0bbe35005f87f32dbd3853193423229c748 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 5 Feb 2016 15:15:04 +0100 Subject: [PATCH 42/49] PickupSpawnSystem now spawns a new HealthPickup after the respawnTimer is up. Added HealthPickup.xml entity. Event PickupSpawned now gets published when a new HealthPickup spawns. Player now gains health as he picks up the HealthPickup. --- include/Engine/Core/EPickupSpawned.h | 2 +- include/Engine/Core/EPickupTaken.h | 19 -- include/Game/Systems/PickupSpawnSystem.h | 16 ++ resources/Schema/Components.xsd | 2 +- resources/Schema/Components/HealthPickup.xml | 4 + resources/Schema/Components/HealthPickup.xsd | 18 ++ resources/Schema/Components/PickupSpawn.xml | 2 - resources/Schema/Components/PickupSpawn.xsd | 11 - resources/Schema/Entities/CapturePoint.xml | 2 +- resources/Schema/Entities/HealthPickup.xml | 18 ++ .../Schema/Entities/HealthPickupTest.xml | 257 ++++++++++++++++++ src/Game/Game.cpp | 2 + src/Game/Systems/PickupSpawnSystem.cpp | 50 ++++ 13 files changed, 368 insertions(+), 35 deletions(-) delete mode 100644 include/Engine/Core/EPickupTaken.h create mode 100644 resources/Schema/Components/HealthPickup.xml create mode 100644 resources/Schema/Components/HealthPickup.xsd delete mode 100644 resources/Schema/Components/PickupSpawn.xml delete mode 100644 resources/Schema/Components/PickupSpawn.xsd create mode 100644 resources/Schema/Entities/HealthPickup.xml create mode 100644 resources/Schema/Entities/HealthPickupTest.xml diff --git a/include/Engine/Core/EPickupSpawned.h b/include/Engine/Core/EPickupSpawned.h index acb6776e..dc3bc632 100644 --- a/include/Engine/Core/EPickupSpawned.h +++ b/include/Engine/Core/EPickupSpawned.h @@ -10,7 +10,7 @@ namespace Events struct PickupSpawned : Event { EntityID PickupID; - EntityWrapper Spawner; + EntityWrapper Pickup; }; } diff --git a/include/Engine/Core/EPickupTaken.h b/include/Engine/Core/EPickupTaken.h deleted file mode 100644 index e06fd974..00000000 --- a/include/Engine/Core/EPickupTaken.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef EPickupTaken_h__ -#define EPickupTaken_h__ - -#include "Core/Event.h" -#include "Core/EntityWrapper.h" - -namespace Events -{ - -struct PickupTaken : Event -{ - EntityID PickupID; - EntityWrapper Spawner; - EntityWrapper Player; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index 99dad0aa..8ae07265 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -9,9 +9,25 @@ #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" #include "Core/EPickupSpawned.h" +#include "Core/EPlayerHealthPickup.h"; +#include "Engine/Collision/ETrigger.h" + +#include "Common.h" +#include class PickupSpawnSystem : public ImpureSystem { +public: + PickupSpawnSystem(World* world, EventBroker* eventBroker); + + virtual void Update(double dt) override; + +private: + EventRelay m_ETriggerTouch; + bool OnTriggerTouch(Events::TriggerTouch& e); + + std::vector> m_ETriggerTouchVector; + }; #endif diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 445d96e7..996475cf 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -29,5 +29,5 @@ - + \ No newline at end of file diff --git a/resources/Schema/Components/HealthPickup.xml b/resources/Schema/Components/HealthPickup.xml new file mode 100644 index 00000000..e9d0a23d --- /dev/null +++ b/resources/Schema/Components/HealthPickup.xml @@ -0,0 +1,4 @@ + + + 3 + \ No newline at end of file diff --git a/resources/Schema/Components/HealthPickup.xsd b/resources/Schema/Components/HealthPickup.xsd new file mode 100644 index 00000000..db9661a7 --- /dev/null +++ b/resources/Schema/Components/HealthPickup.xsd @@ -0,0 +1,18 @@ + + + + + + + + A Health Pickup + + + + + The respawn timer for a health pickup + + + + + diff --git a/resources/Schema/Components/PickupSpawn.xml b/resources/Schema/Components/PickupSpawn.xml deleted file mode 100644 index f8ce1225..00000000 --- a/resources/Schema/Components/PickupSpawn.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/resources/Schema/Components/PickupSpawn.xsd b/resources/Schema/Components/PickupSpawn.xsd deleted file mode 100644 index 7ab90407..00000000 --- a/resources/Schema/Components/PickupSpawn.xsd +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - Combined with a Spawner, defines a spawn point for a pickup - - - diff --git a/resources/Schema/Entities/CapturePoint.xml b/resources/Schema/Entities/CapturePoint.xml index 9b3c5036..9f33c4de 100644 --- a/resources/Schema/Entities/CapturePoint.xml +++ b/resources/Schema/Entities/CapturePoint.xml @@ -5,7 +5,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh diff --git a/resources/Schema/Entities/HealthPickup.xml b/resources/Schema/Entities/HealthPickup.xml new file mode 100644 index 00000000..f1b787f6 --- /dev/null +++ b/resources/Schema/Entities/HealthPickup.xml @@ -0,0 +1,18 @@ + + + + + + + + Models/Core/UnitSphere.mesh + + + + + + + + + + diff --git a/resources/Schema/Entities/HealthPickupTest.xml b/resources/Schema/Entities/HealthPickupTest.xml new file mode 100644 index 00000000..6a368006 --- /dev/null +++ b/resources/Schema/Entities/HealthPickupTest.xml @@ -0,0 +1,257 @@ + + + + + + + + + + + + Models\MapVersion1.mesh + + + + + + + + + 2 + + + Models/DirectionalLightWidget.mesh + false + + + + + + + + + + + + + 8 + 2.7999999523162842 + + + + + + + + + + + 8 + 2.7999999523162842 + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitCube.mesh + false + + + Schema/Entities/Player.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Models/Core/UnitSphere.mesh + + + + + + + + + + + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index f5afcaeb..9e803e9e 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -10,6 +10,7 @@ #include "Systems/PlayerSpawnSystem.h" #include "Core/EntityFileWriter.h" #include "Game/Systems/CapturePointSystem.h" +#include "Game/Systems/PickupSpawnSystem.h" #include "Game/Systems/WeaponSystem.h" #include "Game/Systems/PlayerHUD.h" #include "Game/Systems/LifetimeSystem.h" @@ -91,6 +92,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index 3b758764..28f0ca86 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -1 +1,51 @@ #include "Systems/PickupSpawnSystem.h" + +PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) +{ + EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &PickupSpawnSystem::OnTriggerTouch); +} + +void PickupSpawnSystem::Update(double dt) +{ + for (auto &healthPickupPosition : m_ETriggerTouchVector) { + //set the double timer value (1) + std::get<1>(healthPickupPosition) -= dt; + if (std::get<1>(healthPickupPosition) < 0) { + //spawn and delete the vector item + auto entityFile = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); + EntityFileParser parser(entityFile); + EntityID healthPickupID = parser.MergeEntities(m_World); + + //let the world know a pickup has spawned (graphics effects, etc) + Events::PickupSpawned ePickupSpawned; + ePickupSpawned.PickupID = healthPickupID; + ePickupSpawned.Pickup = EntityWrapper(m_World, healthPickupID); + m_EventBroker->Publish(ePickupSpawned); + + //erase the current element (healthPickupPosition) + m_ETriggerTouchVector.erase(std::remove(m_ETriggerTouchVector.begin(), m_ETriggerTouchVector.end(),healthPickupPosition), m_ETriggerTouchVector.end()); + break; + } + } +} + + +bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e) +{ + if (!e.Trigger.HasComponent("HealthPickup")) { + return false; + } + //personEntered = e.Entity, thingEntered = e.Trigger + Events::PlayerHealthPickup ePlayerHealthPickup; + ePlayerHealthPickup.HealthAmount = 30.0f; + ePlayerHealthPickup.PlayerHealedID = e.Entity.ID; + m_EventBroker->Publish(ePlayerHealthPickup); + + //copy the position to a vector -> respawntimer in ["HealthPickup"]["RespawnTimer"] + m_ETriggerTouchVector.push_back(std::make_tuple((glm::vec3)e.Trigger["Transform"]["Position"], e.Trigger["HealthPickup"]["RespawnTimer"])); + + //delete the healthpickup + m_World->DeleteEntity(e.Trigger.ID); + return true; +} From 7641ba49c751427fd419cafc59f86ab7a4b62052 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 5 Feb 2016 15:16:24 +0100 Subject: [PATCH 43/49] Weapon doesn't explode in first person. --- resources/Schema/Entities/Player.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index fe24adcc..384ffb80 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -104,13 +104,6 @@ - - true - - 3.7999999523162842 - - true - Models/AssaultWeaponRed.mesh From 254239751188f582215b47cc287508723ca0998e Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 5 Feb 2016 15:35:51 +0100 Subject: [PATCH 44/49] Miscellaneous small fixes: For Tests, CapturePoint xml file, HealthSystem, DashAbility xml file. --- include/Engine/Core/EPlayerHealthPickup.h | 12 +++--- include/Game/Systems/HealthSystem.h | 2 +- resources/Schema/Components/DashAbility.xml | 4 +- resources/Schema/Entities/CapturePoint.xml | 2 +- resources/Schema/Entities/Player.xml | 7 ---- src/Game/Systems/HealthSystem.cpp | 41 +++------------------ src/Tests/CapturePointTest.cpp | 8 ++-- src/Tests/CollisionTest.cpp | 2 +- src/Tests/HealthSystemTest.cpp | 26 ++++++------- 9 files changed, 32 insertions(+), 72 deletions(-) diff --git a/include/Engine/Core/EPlayerHealthPickup.h b/include/Engine/Core/EPlayerHealthPickup.h index f3158f92..7d44e544 100644 --- a/include/Engine/Core/EPlayerHealthPickup.h +++ b/include/Engine/Core/EPlayerHealthPickup.h @@ -2,16 +2,16 @@ #define EPlayerHealthPickup_h__ #include "EventBroker.h" -#include "../Core/Entity.h" +#include "../Core/EntityWrapper.h" namespace Events { -struct PlayerHealthPickup : Event -{ - double HealthAmount; - EntityID PlayerHealedID; -}; + struct PlayerHealthPickup : Event + { + EntityWrapper Player; + double HealthAmount; + }; } diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 3b069349..46f24630 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -26,7 +26,7 @@ private: EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; - bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e); + bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e); //vector which will keep track of health changes std::vector> m_DeltaHealthVector; diff --git a/resources/Schema/Components/DashAbility.xml b/resources/Schema/Components/DashAbility.xml index 25b9e19a..a313c447 100644 --- a/resources/Schema/Components/DashAbility.xml +++ b/resources/Schema/Components/DashAbility.xml @@ -1,4 +1,4 @@ - + 2.0 - \ No newline at end of file + \ No newline at end of file diff --git a/resources/Schema/Entities/CapturePoint.xml b/resources/Schema/Entities/CapturePoint.xml index 9b3c5036..9f33c4de 100644 --- a/resources/Schema/Entities/CapturePoint.xml +++ b/resources/Schema/Entities/CapturePoint.xml @@ -5,7 +5,7 @@ - C:\Users\123456\Workspace\TacticalZ\assets\Models\Core\UnitSphere.mesh + Models/Core/UnitSphere.mesh diff --git a/resources/Schema/Entities/Player.xml b/resources/Schema/Entities/Player.xml index fe24adcc..384ffb80 100644 --- a/resources/Schema/Entities/Player.xml +++ b/resources/Schema/Entities/Player.xml @@ -104,13 +104,6 @@ - - true - - 3.7999999523162842 - - true - Models/AssaultWeaponRed.mesh diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 9e118070..91cae148 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -11,38 +11,6 @@ HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker) void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { - //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) - double maxHealth = (double)component["MaxHealth"]; - - //process the DeltaHealthVector and change the entitys health accordingly - for (size_t i = m_DeltaHealthVector.size(); i > 0; i--) - { - auto deltaHP = m_DeltaHealthVector[i - 1]; - //if we have a healthchange for the current player and health is greater than 0, then apply it - if (std::get<0>(deltaHP) == component.EntityID && (double)component["Health"] > 0.0f) { - //get the deltaHP value from the tuple and make sure you dont get more than maxHealth - double newHealth = std::min((double)component["Health"] + (double)std::get<1>(deltaHP), maxHealth); - component["Health"] = newHealth; - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1); - //check if health is <= 0 - if ((double)component["Health"] <= 0.0f) { - component["Health"] = 0.0; - //publish death event - Events::PlayerDeath e; - e.PlayerID = component.EntityID; - m_EventBroker->Publish(e); - //clear the remaining hpDeltas for the dead player - for (size_t j = m_DeltaHealthVector.size(); j > 0; j--) - { - if (std::get<0>(m_DeltaHealthVector[j - 1]) == component.EntityID) - m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1); - } - //delete the player and break the loop - m_World->DeleteEntity(entity.ID); - break; - } - } - } } bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) @@ -58,10 +26,13 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) return true; } -bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e) +bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e) { - //save the changed HP to a vector. it will be taken care of in UpdateComponent - m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerHealedID, e.HealthAmount)); + ComponentWrapper cHealth = e.Player["Health"]; + double& health = cHealth["Health"]; + //NOTE: its possible to get more than MaxHealth health + health += e.HealthAmount; + return true; } diff --git a/src/Tests/CapturePointTest.cpp b/src/Tests/CapturePointTest.cpp index ffb01030..2c7bf430 100644 --- a/src/Tests/CapturePointTest.cpp +++ b/src/Tests/CapturePointTest.cpp @@ -255,14 +255,14 @@ void CapturePointTest::TestSetup8() } void CapturePointTest::DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject) { Events::TriggerTouch touchEvent; - touchEvent.Entity = whoDidSomething; - touchEvent.Trigger = onWhatObject; + touchEvent.Entity = EntityWrapper(m_World, whoDidSomething); + touchEvent.Trigger = EntityWrapper(m_World, onWhatObject); m_EventBroker->Publish(touchEvent); } void CapturePointTest::DoLeaveEvent(EntityID whoDidSomething, EntityID onWhatObject) { Events::TriggerLeave leaveEvent; - leaveEvent.Entity = whoDidSomething; - leaveEvent.Trigger = onWhatObject; + leaveEvent.Entity = EntityWrapper(m_World, whoDidSomething); + leaveEvent.Trigger = EntityWrapper(m_World, onWhatObject); m_EventBroker->Publish(leaveEvent); } void CapturePointTest::TestSuccess1() { diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 67b6ce19..6cb6c88b 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -29,7 +29,7 @@ void RayTest(std::string fileName) { Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0)); //using a - here, else we have to init the renderingsystem + //here, else we have to init the renderingsystem ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); BOOST_REQUIRE(unitBox != nullptr); diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index bdd9ba4b..36608f8f 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -48,42 +48,38 @@ GameHealthSystemTest::GameHealthSystemTest() fp.MergeEntities(m_World); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_World,m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); m_SystemPipeline->AddSystem(0); //The Test //create entity which has transform,player,model,health in it. i.e. is a player EntityID playerID = m_World->CreateEntity(); - ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform"); - ComponentWrapper model = m_World->AttachComponent(playerID, "Model"); - model["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); healthsID = playerID; - double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"]; + + EntityID playerID2 = m_World->CreateEntity(); + ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); + ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); //heal player with 40 Events::PlayerHealthPickup e3; e3.HealthAmount = 40.0f; - e3.PlayerHealedID = healthsID; + e3.Player = EntityWrapper(m_World, player.EntityID); m_EventBroker->Publish(e3); + //damage player with 50 Events::PlayerDamage e; - e.DamageAmount = 50.0f; - e.PlayerDamagedID = healthsID; + e.Damage = 50.0f; + e.Player = EntityWrapper(m_World, player.EntityID); m_EventBroker->Publish(e); + //heal some other player with 40 Events::PlayerHealthPickup e2; e2.HealthAmount = 40.0f; - e2.PlayerHealedID = healthsID + 1; + e2.Player = EntityWrapper(m_World, player2.EntityID); m_EventBroker->Publish(e2); - EntityID playerID2 = m_World->CreateEntity(); - ComponentWrapper transform2 = m_World->AttachComponent(playerID2, "Transform"); - ComponentWrapper model2 = m_World->AttachComponent(playerID2, "Model"); - model2["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere - ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); - ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); //END TEST } From 66f442f1afbe6e6a0ce76bb461d1d20fdd19368a Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 5 Feb 2016 16:13:59 +0100 Subject: [PATCH 45/49] Added HealthGain to HealthPickup component. Changed PickupSpawnSystem so it copies the values from the old to the new entity. --- include/Game/Systems/PickupSpawnSystem.h | 14 +++-------- resources/Schema/Components/HealthPickup.xml | 1 + resources/Schema/Components/HealthPickup.xsd | 3 +++ .../Schema/Entities/HealthPickupTest.xml | 14 ----------- src/Game/Systems/PickupSpawnSystem.cpp | 25 +++++++++++++------ 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index 8ae07265..fbb2f082 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -2,16 +2,12 @@ #define PickupSpawnSystem_h__ #include "Core/System.h" -#include "Input/EInputCommand.h" -#include "Systems/SpawnerSystem.h" -#include "Events/ESpawnerSpawn.h" -#include "Core/EPlayerSpawned.h" -#include "Rendering/ESetCamera.h" -#include "Core/ConfigFile.h" +#include "Core/Transform.h" +#include "Core/ResourceManager.h" +#include "Core/EntityFileParser.h" #include "Core/EPickupSpawned.h" #include "Core/EPlayerHealthPickup.h"; #include "Engine/Collision/ETrigger.h" - #include "Common.h" #include @@ -26,8 +22,6 @@ private: EventRelay m_ETriggerTouch; bool OnTriggerTouch(Events::TriggerTouch& e); - std::vector> m_ETriggerTouchVector; - - + std::vector> m_ETriggerTouchVector; }; #endif diff --git a/resources/Schema/Components/HealthPickup.xml b/resources/Schema/Components/HealthPickup.xml index e9d0a23d..1c9ee0f4 100644 --- a/resources/Schema/Components/HealthPickup.xml +++ b/resources/Schema/Components/HealthPickup.xml @@ -1,4 +1,5 @@ 3 + 30 \ No newline at end of file diff --git a/resources/Schema/Components/HealthPickup.xsd b/resources/Schema/Components/HealthPickup.xsd index db9661a7..c5fae00f 100644 --- a/resources/Schema/Components/HealthPickup.xsd +++ b/resources/Schema/Components/HealthPickup.xsd @@ -12,6 +12,9 @@ The respawn timer for a health pickup + + How much health the player will get when he picks the healthPickup up + diff --git a/resources/Schema/Entities/HealthPickupTest.xml b/resources/Schema/Entities/HealthPickupTest.xml index 6a368006..97fd3f4d 100644 --- a/resources/Schema/Entities/HealthPickupTest.xml +++ b/resources/Schema/Entities/HealthPickupTest.xml @@ -238,20 +238,6 @@ - - - - - - Models/Core/UnitSphere.mesh - - - - - - - - diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index 28f0ca86..558aef14 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -9,9 +9,9 @@ PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker) void PickupSpawnSystem::Update(double dt) { for (auto &healthPickupPosition : m_ETriggerTouchVector) { - //set the double timer value (1) - std::get<1>(healthPickupPosition) -= dt; - if (std::get<1>(healthPickupPosition) < 0) { + //set the double timer value (value 3) + std::get<3>(healthPickupPosition) -= dt; + if (std::get<3>(healthPickupPosition) < 0) { //spawn and delete the vector item auto entityFile = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); EntityFileParser parser(entityFile); @@ -23,8 +23,14 @@ void PickupSpawnSystem::Update(double dt) ePickupSpawned.Pickup = EntityWrapper(m_World, healthPickupID); m_EventBroker->Publish(ePickupSpawned); + //set values from the old entity to the new entity + auto& newHealthPickupEntity = EntityWrapper(m_World, healthPickupID); + newHealthPickupEntity["Transform"]["Position"] = std::get<0>(healthPickupPosition); + newHealthPickupEntity["HealthPickup"]["HealthGain"] = std::get<1>(healthPickupPosition); + newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = std::get<2>(healthPickupPosition); + //erase the current element (healthPickupPosition) - m_ETriggerTouchVector.erase(std::remove(m_ETriggerTouchVector.begin(), m_ETriggerTouchVector.end(),healthPickupPosition), m_ETriggerTouchVector.end()); + m_ETriggerTouchVector.erase(std::remove(m_ETriggerTouchVector.begin(), m_ETriggerTouchVector.end(), healthPickupPosition), m_ETriggerTouchVector.end()); break; } } @@ -38,12 +44,17 @@ bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e) } //personEntered = e.Entity, thingEntered = e.Trigger Events::PlayerHealthPickup ePlayerHealthPickup; - ePlayerHealthPickup.HealthAmount = 30.0f; + ePlayerHealthPickup.HealthAmount = e.Trigger["HealthPickup"]["HealthGain"]; ePlayerHealthPickup.PlayerHealedID = e.Entity.ID; m_EventBroker->Publish(ePlayerHealthPickup); - //copy the position to a vector -> respawntimer in ["HealthPickup"]["RespawnTimer"] - m_ETriggerTouchVector.push_back(std::make_tuple((glm::vec3)e.Trigger["Transform"]["Position"], e.Trigger["HealthPickup"]["RespawnTimer"])); + //copy position, healthgain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object) + //we need to copy all values since each value can be different for each healthPickup + m_ETriggerTouchVector.push_back(std::make_tuple( + (glm::vec3)e.Trigger["Transform"]["Position"], + e.Trigger["HealthPickup"]["HealthGain"], + e.Trigger["HealthPickup"]["RespawnTimer"], + e.Trigger["HealthPickup"]["RespawnTimer"])); //delete the healthpickup m_World->DeleteEntity(e.Trigger.ID); From 59bdc614f2b28991b91cc1f2b0f871cefb28a1f4 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 5 Feb 2016 17:34:19 +0100 Subject: [PATCH 46/49] Put SpecialAbility on left shift, and Sprint on left shift in DefaultInput. --- resources/DefaultInput.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index a3f7d166..589dfb3f 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -13,7 +13,8 @@ A=Right,-1 R=Reload Space=Jump LeftControl=Crouch -LeftShift=Sprint +RightShift=Sprint +LeftShift=SpecialAbility F1=ToggleEditor C=ConnectToServer N=SwitchToServer From 4103c878ec69399e256ab13c302ef5bb3390dabf Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Fri, 5 Feb 2016 18:05:46 +0100 Subject: [PATCH 47/49] Refactoring: Changed HealthPickupSystem to use a struct instead. Removed the Id in EPickupSpawned --- include/Engine/Core/EPickupSpawned.h | 1 - include/Game/Systems/PickupSpawnSystem.h | 10 +++- resources/Schema/Entities/HealthPickup.xml | 2 +- .../Schema/Entities/HealthPickupTest.xml | 51 +++++++++++++++++++ src/Game/Systems/PickupSpawnSystem.cpp | 24 ++++----- 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/include/Engine/Core/EPickupSpawned.h b/include/Engine/Core/EPickupSpawned.h index dc3bc632..9f85913a 100644 --- a/include/Engine/Core/EPickupSpawned.h +++ b/include/Engine/Core/EPickupSpawned.h @@ -9,7 +9,6 @@ namespace Events struct PickupSpawned : Event { - EntityID PickupID; EntityWrapper Pickup; }; diff --git a/include/Game/Systems/PickupSpawnSystem.h b/include/Game/Systems/PickupSpawnSystem.h index fbb2f082..24cee2b9 100644 --- a/include/Game/Systems/PickupSpawnSystem.h +++ b/include/Game/Systems/PickupSpawnSystem.h @@ -6,7 +6,7 @@ #include "Core/ResourceManager.h" #include "Core/EntityFileParser.h" #include "Core/EPickupSpawned.h" -#include "Core/EPlayerHealthPickup.h"; +#include "Core/EPlayerHealthPickup.h" #include "Engine/Collision/ETrigger.h" #include "Common.h" #include @@ -22,6 +22,12 @@ private: EventRelay m_ETriggerTouch; bool OnTriggerTouch(Events::TriggerTouch& e); - std::vector> m_ETriggerTouchVector; + struct NewHealthPickup { + glm::vec3 Pos; + double HealthGain; + double RespawnTimer; + double DecreaseThisRespawnTimer; + }; + std::vector m_ETriggerTouchVector; }; #endif diff --git a/resources/Schema/Entities/HealthPickup.xml b/resources/Schema/Entities/HealthPickup.xml index f1b787f6..dfc6f938 100644 --- a/resources/Schema/Entities/HealthPickup.xml +++ b/resources/Schema/Entities/HealthPickup.xml @@ -8,7 +8,7 @@ Models/Core/UnitSphere.mesh - + diff --git a/resources/Schema/Entities/HealthPickupTest.xml b/resources/Schema/Entities/HealthPickupTest.xml index 97fd3f4d..2980fb51 100644 --- a/resources/Schema/Entities/HealthPickupTest.xml +++ b/resources/Schema/Entities/HealthPickupTest.xml @@ -238,6 +238,57 @@ + + + + + 1 + 22 + + + Models/Core/UnitSphere.mesh + + + + + + + + + + + + + 1 + 22 + + + Models/Core/UnitSphere.mesh + + + + + + + + + + + + + 4 + 44 + + + Models/Core/UnitSphere.mesh + + + + + + + + diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index 558aef14..783f7a62 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -8,10 +8,12 @@ PickupSpawnSystem::PickupSpawnSystem(World* m_World, EventBroker* eventBroker) void PickupSpawnSystem::Update(double dt) { - for (auto &healthPickupPosition : m_ETriggerTouchVector) { + for (auto it = m_ETriggerTouchVector.begin(); it != m_ETriggerTouchVector.end(); ++it) + { + auto& healthPickupPosition = *it; //set the double timer value (value 3) - std::get<3>(healthPickupPosition) -= dt; - if (std::get<3>(healthPickupPosition) < 0) { + healthPickupPosition.DecreaseThisRespawnTimer -= dt; + if (healthPickupPosition.DecreaseThisRespawnTimer < 0) { //spawn and delete the vector item auto entityFile = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); EntityFileParser parser(entityFile); @@ -19,18 +21,17 @@ void PickupSpawnSystem::Update(double dt) //let the world know a pickup has spawned (graphics effects, etc) Events::PickupSpawned ePickupSpawned; - ePickupSpawned.PickupID = healthPickupID; ePickupSpawned.Pickup = EntityWrapper(m_World, healthPickupID); m_EventBroker->Publish(ePickupSpawned); //set values from the old entity to the new entity auto& newHealthPickupEntity = EntityWrapper(m_World, healthPickupID); - newHealthPickupEntity["Transform"]["Position"] = std::get<0>(healthPickupPosition); - newHealthPickupEntity["HealthPickup"]["HealthGain"] = std::get<1>(healthPickupPosition); - newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = std::get<2>(healthPickupPosition); + newHealthPickupEntity["Transform"]["Position"] = healthPickupPosition.Pos; + newHealthPickupEntity["HealthPickup"]["HealthGain"] = healthPickupPosition.HealthGain; + newHealthPickupEntity["HealthPickup"]["RespawnTimer"] = healthPickupPosition.RespawnTimer; //erase the current element (healthPickupPosition) - m_ETriggerTouchVector.erase(std::remove(m_ETriggerTouchVector.begin(), m_ETriggerTouchVector.end(), healthPickupPosition), m_ETriggerTouchVector.end()); + m_ETriggerTouchVector.erase(it); break; } } @@ -50,11 +51,8 @@ bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e) //copy position, healthgain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object) //we need to copy all values since each value can be different for each healthPickup - m_ETriggerTouchVector.push_back(std::make_tuple( - (glm::vec3)e.Trigger["Transform"]["Position"], - e.Trigger["HealthPickup"]["HealthGain"], - e.Trigger["HealthPickup"]["RespawnTimer"], - e.Trigger["HealthPickup"]["RespawnTimer"])); + m_ETriggerTouchVector.push_back({ (glm::vec3)e.Trigger["Transform"]["Position"] ,e.Trigger["HealthPickup"]["HealthGain"], + e.Trigger["HealthPickup"]["RespawnTimer"],e.Trigger["HealthPickup"]["RespawnTimer"] }); //delete the healthpickup m_World->DeleteEntity(e.Trigger.ID); From ce228541689d695c7a09ef96527dc572a874193e Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Mon, 8 Feb 2016 11:22:28 +0100 Subject: [PATCH 48/49] HealthPickups are now based on a percentage of player maxhealth. You can no longer pickup healthpacks if you are at max health. You can no longer gain more than maxHealth. --- include/Game/Systems/HealthSystem.h | 1 + resources/Schema/Components/HealthPickup.xsd | 2 +- src/Game/Systems/HealthSystem.cpp | 4 ++-- src/Game/Systems/PickupSpawnSystem.cpp | 10 ++++++++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 46f24630..61456d5d 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -12,6 +12,7 @@ #include #include +#include class HealthSystem : public PureSystem { diff --git a/resources/Schema/Components/HealthPickup.xsd b/resources/Schema/Components/HealthPickup.xsd index c5fae00f..bf3b327c 100644 --- a/resources/Schema/Components/HealthPickup.xsd +++ b/resources/Schema/Components/HealthPickup.xsd @@ -13,7 +13,7 @@ The respawn timer for a health pickup - How much health the player will get when he picks the healthPickup up + How much percent max-health the player will get when he picks the healthPickup up diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 91cae148..94d98222 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -18,7 +18,7 @@ bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) ComponentWrapper cHealth = e.Player["Health"]; double& health = cHealth["Health"]; health -= e.Damage; - + if (health <= 0.0) { m_World->DeleteEntity(e.Player.ID); } @@ -30,8 +30,8 @@ bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e) { ComponentWrapper cHealth = e.Player["Health"]; double& health = cHealth["Health"]; - //NOTE: its possible to get more than MaxHealth health health += e.HealthAmount; + health = std::min(health, (double)cHealth["MaxHealth"]); return true; } diff --git a/src/Game/Systems/PickupSpawnSystem.cpp b/src/Game/Systems/PickupSpawnSystem.cpp index 783f7a62..e9f201c1 100644 --- a/src/Game/Systems/PickupSpawnSystem.cpp +++ b/src/Game/Systems/PickupSpawnSystem.cpp @@ -43,10 +43,16 @@ bool PickupSpawnSystem::OnTriggerTouch(Events::TriggerTouch& e) if (!e.Trigger.HasComponent("HealthPickup")) { return false; } + double healthGiven = 0.01*(double)e.Trigger["HealthPickup"]["HealthGain"] * (double)e.Entity["Health"]["MaxHealth"]; + //cant pick up healthpacks if you are already at MaxHealth + if ((double)e.Entity["Health"]["Health"] >= (double)e.Entity["Health"]["MaxHealth"]) { + return false; + } + //personEntered = e.Entity, thingEntered = e.Trigger Events::PlayerHealthPickup ePlayerHealthPickup; - ePlayerHealthPickup.HealthAmount = e.Trigger["HealthPickup"]["HealthGain"]; - ePlayerHealthPickup.PlayerHealedID = e.Entity.ID; + ePlayerHealthPickup.HealthAmount = healthGiven; + ePlayerHealthPickup.Player = e.Entity; m_EventBroker->Publish(ePlayerHealthPickup); //copy position, healthgain, respawntimer (twice since one of the values will be counted down to 0, the other will be set in the new object) From 99cbdd3c1e668b85603ed3fa07d5f9f84ff6f7fa Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 8 Feb 2016 11:39:29 +0100 Subject: [PATCH 49/49] Player death effect fixes --- include/Game/Systems/PlayerDeathSystem.h | 3 ++ include/Game/Systems/PlayerSpawnSystem.h | 1 + .../PlayerDeathExplosionWithCamera.xml | 30 +++++++---------- src/Game/Systems/PlayerDeathSystem.cpp | 33 +++++++++++-------- src/Game/Systems/PlayerSpawnSystem.cpp | 4 ++- 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/include/Game/Systems/PlayerDeathSystem.h b/include/Game/Systems/PlayerDeathSystem.h index 7d989dbf..988dad57 100644 --- a/include/Game/Systems/PlayerDeathSystem.h +++ b/include/Game/Systems/PlayerDeathSystem.h @@ -22,5 +22,8 @@ public: private: EventRelay m_OnPlayerDeath; bool OnPlayerDeath(Events::PlayerDeath& e); + + void createDeathEffect(EntityWrapper player); + }; #endif \ No newline at end of file diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index b0ff1d79..f5aa7b82 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -3,6 +3,7 @@ #include "Systems/SpawnerSystem.h" #include "Events/ESpawnerSpawn.h" #include "Core/EPlayerSpawned.h" +#include "Core/EPlayerDeath.h" #include "Rendering/ESetCamera.h" #include "Core/ConfigFile.h" diff --git a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml index ff33476d..8a9f5e5b 100644 --- a/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml +++ b/resources/Schema/Entities/PlayerDeathExplosionWithCamera.xml @@ -4,17 +4,18 @@ Hold Pos - - 0 - 4 + 2.5 - 0 - 4 - - + true + + + true + 3 + + true Models/AssaultAnimated.mesh @@ -22,24 +23,17 @@ true - + - - 1 - - - 120 - 0.1 - 10000 - + - - + + diff --git a/src/Game/Systems/PlayerDeathSystem.cpp b/src/Game/Systems/PlayerDeathSystem.cpp index f7fe1ab5..60c31ce5 100644 --- a/src/Game/Systems/PlayerDeathSystem.cpp +++ b/src/Game/Systems/PlayerDeathSystem.cpp @@ -11,18 +11,31 @@ void PlayerDeathSystem::Update(double dt) } bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) +{ + if (!e.Player.Valid()) { + return false; + } + + createDeathEffect(e.Player); + + // Delete player + m_World->DeleteEntity(e.Player.ID); + + return true; +} + +void PlayerDeathSystem::createDeathEffect(EntityWrapper player) { //load the explosioneffect XML auto deathEffect = ResourceManager::Load("Schema/Entities/PlayerDeathExplosionWithCamera.xml"); - EntityFileParser parser(deathEffect); EntityID deathEffectID = parser.MergeEntities(m_World); EntityWrapper deathEffectEW = EntityWrapper(m_World, deathEffectID); //components that we need from player - auto playerCamera = e.Player.FirstChildByName("Camera"); - auto playerEntityModel = e.Player.FirstChildByName("PlayerModel")["Model"]; - auto playerEntityAnimation = e.Player.FirstChildByName("PlayerModel")["Animation"]; + auto playerCamera = player.FirstChildByName("Camera"); + auto playerEntityModel = player.FirstChildByName("PlayerModel")["Model"]; + auto playerEntityAnimation = player.FirstChildByName("PlayerModel")["Animation"]; //copy the data from player to explisioneffectmodel playerEntityModel.Copy(deathEffectEW["Model"]); @@ -31,20 +44,14 @@ bool PlayerDeathSystem::OnPlayerDeath(Events::PlayerDeath& e) deathEffectEW["Animation"]["Speed"] = 0.0; //copy the models position,orientation - deathEffectEW["Transform"]["Position"] = (glm::vec3)e.Player["Transform"]["Position"]; - deathEffectEW["Transform"]["Orientation"] = (glm::vec3)e.Player["Transform"]["Orientation"]; + deathEffectEW["Transform"]["Position"] = (glm::vec3)player["Transform"]["Position"]; + deathEffectEW["Transform"]["Orientation"] = (glm::vec3)player["Transform"]["Orientation"]; //effect,camera is relative to playersPosition - deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 0, 0); + //deathEffectEW["ExplosionEffect"]["ExplosionOrigin"] = glm::vec3(0, 0, 0); //camera (with lifetime) behind the player auto cam = deathEffectEW.FirstChildByName("Camera"); - cam["Transform"]["Position"] = glm::vec3(0, 2.5f, 1.8f); - cam["Transform"]["Orientation"] = glm::vec3(5.655f, 0, 0); Events::SetCamera eSetCamera; eSetCamera.CameraEntity = cam; m_EventBroker->Publish(eSetCamera); - - //done -> del entity - m_World->DeleteEntity(e.Player.ID); - return true; } diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 7db6e8ff..5f46cce3 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -75,7 +75,9 @@ bool PlayerSpawnSystem::OnPlayerSpawned(Events::PlayerSpawned& e) // Check if a player already exists if (m_PlayerEntities.count(e.PlayerID) != 0) { // TODO: Disallow infinite respawning here - m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); + if (m_PlayerEntities[e.PlayerID].Valid()) { + m_World->DeleteEntity(m_PlayerEntities[e.PlayerID].ID); + } } // Store the player for future reference