Merge branch 'master' into BoxModelCollision
# Conflicts: # include/Engine/Collision/CollisionSystem.h # src/Engine/Collision/CollisionSystem.cpp
This commit is contained in:
@@ -8,7 +8,7 @@ void CollidableOctreeSystem::Update(double dt)
|
||||
void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
{
|
||||
if (entity.HasComponent("AABB")) {
|
||||
boost::optional<AABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
|
||||
boost::optional<EntityAABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
|
||||
if (absoluteAABB) {
|
||||
m_Octree->AddDynamicObject(*absoluteAABB);
|
||||
}
|
||||
|
||||
@@ -493,20 +493,6 @@ bool AABBvsTriangles(const AABB& box,
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon)
|
||||
{
|
||||
const glm::vec3& ma1 = first.MaxCorner();
|
||||
const glm::vec3& ma2 = second.MaxCorner();
|
||||
const glm::vec3& mi1 = first.MinCorner();
|
||||
const glm::vec3& mi2 = second.MinCorner();
|
||||
return (std::abs(ma1.x - ma2.x) < epsilon) &&
|
||||
(std::abs(mi1.x - mi2.x) < epsilon) &&
|
||||
(std::abs(ma1.z - ma2.z) < epsilon) &&
|
||||
(std::abs(mi1.z - mi2.z) < epsilon) &&
|
||||
(std::abs(ma1.y - ma2.y) < epsilon) &&
|
||||
(std::abs(mi1.y - mi2.y) < epsilon);
|
||||
}
|
||||
|
||||
bool attachAABBComponentFromModel(World* world, EntityID id)
|
||||
{
|
||||
if (!world->HasComponent(id, "Model")) {
|
||||
@@ -537,7 +523,7 @@ bool attachAABBComponentFromModel(World* world, EntityID id)
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::optional<AABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
{
|
||||
if (!entity.HasComponent("AABB")) {
|
||||
return boost::none;
|
||||
@@ -548,7 +534,11 @@ boost::optional<AABB> EntityAbsoluteAABB(EntityWrapper& entity)
|
||||
glm::vec3 absScale = Transform::AbsoluteScale(entity.World, entity.ID);
|
||||
glm::vec3 origin = absPosition + (glm::vec3)cAABB["Origin"];
|
||||
glm::vec3 size = (glm::vec3)cAABB["Size"] * absScale;
|
||||
return AABB::FromOriginSize(origin, size);
|
||||
|
||||
EntityAABB aabb = EntityAABB::FromOriginSize(origin, size);
|
||||
aabb.Entity = entity;
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#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)
|
||||
{
|
||||
@@ -10,54 +9,49 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
|
||||
}
|
||||
ComponentWrapper& cPhysics = entity["Physics"];
|
||||
|
||||
boost::optional<AABB> boundingBox = Collision::EntityAbsoluteAABB(entity);
|
||||
boost::optional<EntityAABB> boundingBox = Collision::EntityAbsoluteAABB(entity);
|
||||
if (!boundingBox) {
|
||||
return;
|
||||
}
|
||||
ComponentWrapper& cTransform = entity["Transform"];
|
||||
AABB& boxA = *boundingBox;
|
||||
|
||||
// Collide against octree
|
||||
//std::vector<AABB> octreeResult;
|
||||
//m_Octree->ObjectsInSameRegion(*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;
|
||||
// ((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
|
||||
// }
|
||||
//}
|
||||
|
||||
// HACK: Temporarily collide against all collidable models since they're not in the octree yet
|
||||
auto otherCollidables = m_World->GetComponents("Model");
|
||||
for (auto& cModel : *otherCollidables) {
|
||||
if (cModel.EntityID == entity.ID) {
|
||||
continue;
|
||||
}
|
||||
if (!m_World->HasComponent(cModel.EntityID, "Collidable")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RawModel* model;
|
||||
try {
|
||||
model = ResourceManager::Load<RawModel, true>(cModel["Resource"]);
|
||||
} catch (const std::exception&) {
|
||||
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);
|
||||
EntityAABB& boxA = *boundingBox;
|
||||
|
||||
// Collide against octree items
|
||||
m_OctreeResult.clear();
|
||||
m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult);
|
||||
for (auto& boxB : m_OctreeResult) {
|
||||
glm::vec3 resolutionVector;
|
||||
glm::vec3 newVelocity = (glm::vec3)cPhysics["Velocity"];
|
||||
if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, newVelocity, resolutionVector)) {
|
||||
if (boxA.Entity == boxB.Entity) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
|
||||
(glm::vec3&)cTransform["Position"] += resolutionVector;
|
||||
cPhysics["Velocity"] = newVelocity;
|
||||
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<Model>(cModel["Resource"]);
|
||||
// glm::vec3 resolutionVector;
|
||||
// if (Collision::AABBvsTriangles(boxA, model->m_Vertices, model->m_Indices, modelMatrix, resolutionVector)) {
|
||||
// (glm::vec3&)cTransform["Position"] += resolutionVector;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -3,79 +3,72 @@
|
||||
#include "Core/AABB.h"
|
||||
#include "Rendering/Model.h"
|
||||
|
||||
void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
|
||||
void TriggerSystem::UpdateComponent(EntityWrapper& triggerEntity, ComponentWrapper& cTrigger, double dt)
|
||||
{
|
||||
//Currently only players can trigger things.
|
||||
auto players = m_World->GetComponents("Player");
|
||||
if (players == nullptr) {
|
||||
return;
|
||||
}
|
||||
EntityID tId = component.EntityID;
|
||||
boost::optional<AABB> triggerBox = Collision::EntityAbsoluteAABB(entity);
|
||||
//The trigger *should* have a bounding box, or something, to test against so it can be triggered.
|
||||
// The trigger *should* have a bounding box, or something, to test against so it can be triggered.
|
||||
boost::optional<EntityAABB> triggerBox = Collision::EntityAbsoluteAABB(triggerEntity);
|
||||
if (!triggerBox) {
|
||||
return;
|
||||
}
|
||||
for (auto& pc : *players) {
|
||||
EntityID pId = pc.EntityID;
|
||||
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId));
|
||||
//The player can't trigger anything without an AABB.
|
||||
if (!playerBox) {
|
||||
continue;
|
||||
}
|
||||
if (!Collision::AABBVsAABB(*triggerBox, *playerBox)) {
|
||||
//Entity is not touching the trigger,
|
||||
//Throw event if it was previously.
|
||||
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) {
|
||||
continue;
|
||||
}
|
||||
//This only occurs if the entity was completely inside the trigger one frame,
|
||||
//then completely outside the trigger, e.g. when dying and respawning.
|
||||
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId);
|
||||
} else {
|
||||
//Entity is at least touching the trigger.
|
||||
|
||||
m_OctreeOut.clear();
|
||||
m_Octree->ObjectsInSameRegion(*triggerBox, m_OctreeOut);
|
||||
|
||||
for (EntityAABB& colliderBox : m_OctreeOut) {
|
||||
EntityWrapper colliderEntity = colliderBox.Entity;
|
||||
|
||||
if (Collision::AABBVsAABB(*triggerBox, colliderBox)) {
|
||||
AABB completelyInsideBox;
|
||||
bool playerFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), (*playerBox).Size()));
|
||||
if (playerFitsInTrigger) {
|
||||
completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * (*playerBox).Size());
|
||||
bool colliderFitsInTrigger = glm::all(glm::greaterThan((*triggerBox).Size(), colliderBox.Size()));
|
||||
if (colliderFitsInTrigger) {
|
||||
completelyInsideBox = AABB::FromOriginSize((*triggerBox).Origin(), (*triggerBox).Size() - 2.0f * colliderBox.Size());
|
||||
}
|
||||
if (playerFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, *playerBox)) {
|
||||
//Entity is completely inside the trigger.
|
||||
//If it was only touching before, it is erased.
|
||||
m_EntitiesTouchingTrigger[tId].erase(pId);
|
||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
||||
if (completeSet.count(pId) == 0) {
|
||||
//If it wasn't completely in the trigger, throw Enter and add to the set.
|
||||
completeSet.insert(pId);
|
||||
publish<Events::TriggerEnter>(pId, tId);
|
||||
if (colliderFitsInTrigger && Collision::AABBVsAABB(completelyInsideBox, colliderBox)) {
|
||||
// Entity is completely inside the trigger.
|
||||
// If it was only touching before, it is erased.
|
||||
m_EntitiesTouchingTrigger[triggerEntity].erase(colliderEntity);
|
||||
auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity];
|
||||
if (completeSet.count(colliderEntity) == 0) {
|
||||
// If it wasn't completely in the trigger, throw Enter and add to the set.
|
||||
completeSet.insert(colliderEntity);
|
||||
publish<Events::TriggerEnter>(colliderEntity, triggerEntity);
|
||||
}
|
||||
} else {
|
||||
//Entity is only touching the trigger.
|
||||
std::unordered_set<EntityID>& touchSet = m_EntitiesTouchingTrigger[tId];
|
||||
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
|
||||
const auto& it = completeSet.find(pId);
|
||||
// Entity is only touching the trigger.
|
||||
auto& touchSet = m_EntitiesTouchingTrigger[triggerEntity];
|
||||
auto& completeSet = m_EntitiesCompletelyInTrigger[triggerEntity];
|
||||
const auto& it = completeSet.find(colliderEntity);
|
||||
//If it was completely inside before.
|
||||
if (it != completeSet.end()) {
|
||||
completeSet.erase(it);
|
||||
touchSet.insert(pId);
|
||||
touchSet.insert(colliderEntity);
|
||||
//If it was completely outside before.
|
||||
} else if (touchSet.count(pId) == 0) {
|
||||
publish<Events::TriggerTouch>(pId, tId);
|
||||
touchSet.insert(pId);
|
||||
} else if (touchSet.count(colliderEntity) == 0) {
|
||||
publish<Events::TriggerTouch>(colliderEntity, triggerEntity);
|
||||
touchSet.insert(colliderEntity);
|
||||
}
|
||||
//Else, it was touching the trigger last frame too and nothing is done.
|
||||
// Else, it was touching the trigger last frame too and nothing is done.
|
||||
}
|
||||
} else {
|
||||
// Entity is not touching the trigger,
|
||||
// Throw event if it was previously.
|
||||
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[triggerEntity], colliderEntity, triggerEntity)) {
|
||||
continue;
|
||||
}
|
||||
// This only occurs if the entity was completely inside the trigger one frame,
|
||||
// then completely outside the trigger, e.g. when dying and respawning.
|
||||
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[triggerEntity], colliderEntity, triggerEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId)
|
||||
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityWrapper>& triggerSet, EntityWrapper colliderEntity, EntityWrapper triggerEntity)
|
||||
{
|
||||
const auto& it = triggerSet.find(pId);
|
||||
const auto& it = triggerSet.find(colliderEntity);
|
||||
if (it != triggerSet.end()) {
|
||||
//If it was in the trigger, but not anymore, throw leaveEvent and erase from the set.
|
||||
triggerSet.erase(it);
|
||||
publish<Events::TriggerLeave>(pId, tId);
|
||||
publish<Events::TriggerLeave>(colliderEntity, triggerEntity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -20,10 +20,6 @@ AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos)
|
||||
}
|
||||
}
|
||||
|
||||
AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos)
|
||||
: AABB(glm::vec3(minPos), glm::vec3(maxPos))
|
||||
{ }
|
||||
|
||||
AABB AABB::FromOriginSize(const glm::vec3& origin, const glm::vec3& size)
|
||||
{
|
||||
return AABB(origin - (size/2.f), origin + (size/2.f));
|
||||
|
||||
@@ -20,7 +20,7 @@ void EntityFile::Parse(const EntityFileHandler* handler) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
EntityFileSAXHandler saxHandler(handler, nullptr);
|
||||
EntityFileSAXHandler saxHandler(handler, m_SAX2XMLReader);
|
||||
setReaderFeatures(m_SAX2XMLReader);
|
||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||
@@ -37,6 +37,7 @@ void EntityFile::setReaderFeatures(xercesc::SAX2XMLReader* reader)
|
||||
reader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchema, true);
|
||||
reader->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
reader->setFeature(XMLUni::fgXercesCalculateSrcOfs, true);
|
||||
}
|
||||
|
||||
std::size_t EntityFile::GetTypeStride(std::string typeName)
|
||||
@@ -111,8 +112,9 @@ void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& fie
|
||||
} catch (const boost::bad_lexical_cast&) { }
|
||||
}
|
||||
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
|
||||
: m_Handler(handler)
|
||||
, m_Reader(reader)
|
||||
{
|
||||
// 0 is imaginary base parent
|
||||
m_EntityStack.push(0);
|
||||
@@ -188,21 +190,29 @@ void EntityFileSAXHandler::characters(const XMLCh* const chars, const XMLSize_t
|
||||
|
||||
void EntityFileSAXHandler::fatalError(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
//throw e;
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tFatal Error: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::error(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tError: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::warning(const xercesc::SAXParseException& e)
|
||||
{
|
||||
XS::ToString s(e.getMessage());
|
||||
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
|
||||
std::string message = XS::ToString(e.getMessage());
|
||||
std::string systemId = XS::ToString(e.getSystemId());
|
||||
XMLFileLoc line = e.getLineNumber();
|
||||
XMLFileLoc column = e.getColumnNumber();
|
||||
LOG_ERROR("SAXParseException\n\tLocation: %s:%i:%i\n\tWarning: %s", systemId.c_str(), line, column, message.c_str());
|
||||
}
|
||||
|
||||
void EntityFileSAXHandler::onStartEntity(const xercesc::Attributes& attrs)
|
||||
|
||||
@@ -65,6 +65,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
|
||||
// Name
|
||||
compInfo.Name = XS::ToString(element->getName());
|
||||
bool brk = compInfo.Name == "HiddenForLocalPlayer";
|
||||
// Known allocation
|
||||
compInfo.Meta->Allocation = m_ComponentCounts[compInfo.Name];
|
||||
// Annotation
|
||||
@@ -90,7 +91,7 @@ void EntityFilePreprocessor::parseComponentInfo()
|
||||
// <xs:all>
|
||||
auto modelGroupParticle = complexTypeDefinition->getParticle();
|
||||
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
|
||||
//LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
|
||||
LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
|
||||
continue;
|
||||
}
|
||||
auto modelGroup = modelGroupParticle->getModelGroupTerm();
|
||||
|
||||
@@ -97,11 +97,6 @@ EntityWrapper::operator EntityID() const
|
||||
return this->ID;
|
||||
}
|
||||
|
||||
EntityWrapper::operator bool()
|
||||
{
|
||||
return this->Valid();
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name, EntityID parent)
|
||||
{
|
||||
if (!this->World->ValidEntity(parent)) {
|
||||
|
||||
@@ -105,8 +105,7 @@ bool Child::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const
|
||||
for (int i : m_DynamicObjIndices) {
|
||||
if (!m_DynamicObjectsRef[i].Checked) {
|
||||
const AABB& objBox = *m_DynamicObjectsRef[i].Box;
|
||||
if (!Collision::IsSameBoxProbably(boxToTest, objBox) &&
|
||||
Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
if (Collision::AABBVsAABB(boxToTest, objBox)) {
|
||||
outBoxIntersected = objBox;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,4 +4,40 @@
|
||||
_LOG_LEVEL LOG_LEVEL = LOG_LEVEL_DEBUG;
|
||||
#else
|
||||
_LOG_LEVEL LOG_LEVEL = LOG_LEVEL_INFO;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char* _LOG_LEVEL_PREFIX[] =
|
||||
{
|
||||
"EE: ",
|
||||
"",
|
||||
"WW: ",
|
||||
"DD: "
|
||||
};
|
||||
|
||||
void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...)
|
||||
{
|
||||
if (logLevel > LOG_LEVEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* message = nullptr;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
size_t size = vsnprintf(message, 0, format, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
va_start(args, format);
|
||||
message = new char[size];
|
||||
vsnprintf(message, size, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (logLevel == LOG_LEVEL_ERROR) {
|
||||
std::cerr << file << ":" << line << " " << func << std::endl;
|
||||
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
} else {
|
||||
std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
|
||||
}
|
||||
|
||||
delete[] message;
|
||||
}
|
||||
@@ -54,8 +54,12 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp
|
||||
|
||||
bool World::HasComponent(EntityID entity, const std::string& componentType) const
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
return pool->KnowsEntity(entity);
|
||||
auto it = m_ComponentPools.find(componentType);
|
||||
if (it == m_ComponentPools.end()) {
|
||||
return false;
|
||||
} else {
|
||||
return it->second->KnowsEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
ComponentWrapper World::GetComponent(EntityID entity, const std::string& componentType)
|
||||
|
||||
@@ -12,7 +12,7 @@ EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker,
|
||||
|
||||
void EditorRenderSystem::Update(double dt)
|
||||
{
|
||||
if (m_CurrentCamera) {
|
||||
if (m_CurrentCamera.Valid()) {
|
||||
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
|
||||
m_EditorCamera->SetPosition(cameraTransform["Position"]);
|
||||
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
|
||||
@@ -49,7 +49,11 @@ void EditorRenderSystem::Update(double dt)
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World, glm::vec4(0), 0.f);
|
||||
scene.ForwardJobs.push_back(modelJob);
|
||||
if(cModel["Transparent"]) {
|
||||
scene.TransparentObjects.push_back(modelJob);
|
||||
} else {
|
||||
scene.OpaqueObjects.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper
|
||||
|
||||
auto camera = m_PickData.Camera;
|
||||
glm::vec3 axis = cEditorWidget["Axis"];
|
||||
glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution());
|
||||
glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->GetViewPortSize()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->GetViewPortSize());
|
||||
float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen);
|
||||
glm::vec3 worldMovement = dot * axis;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer)
|
||||
|
||||
void DrawBloomPass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
}
|
||||
|
||||
void DrawBloomPass::InitializeShaderPrograms()
|
||||
@@ -34,12 +34,12 @@ void DrawBloomPass::InitializeShaderPrograms()
|
||||
|
||||
void DrawBloomPass::InitializeBuffers()
|
||||
{
|
||||
GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0)));
|
||||
m_GaussianFrameBuffer_horiz.Generate();
|
||||
|
||||
GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
|
||||
m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0)));
|
||||
m_GaussianFrameBuffer_vert.Generate();
|
||||
|
||||
@@ -11,21 +11,23 @@ DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCulling
|
||||
|
||||
void DrawFinalPass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
m_BlackTexture = ResourceManager::Load<Texture>("Textures/Core/Black.png");
|
||||
m_NeutralNormalTexture = ResourceManager::Load<Texture>("Textures/Core/NeutralNormalMap.png");
|
||||
m_GreyTexture = ResourceManager::Load<Texture>("Textures/Core/Grey.png");
|
||||
}
|
||||
|
||||
void DrawFinalPass::InitializeFrameBuffers()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height);
|
||||
|
||||
GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RGB16F, GL_FLOAT, 4);
|
||||
|
||||
GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_RGB, GL_FLOAT);
|
||||
//GenerateMipMapTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RGB16F, GL_FLOAT, 4);
|
||||
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_SceneTexture, GL_COLOR_ATTACHMENT0)));
|
||||
m_FinalPassFrameBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_BloomTexture, GL_COLOR_ATTACHMENT1)));
|
||||
@@ -42,6 +44,15 @@ void DrawFinalPass::InitializeShaderPrograms()
|
||||
m_ForwardPlusProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ForwardPlusProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_ForwardPlusProgram->Link();
|
||||
|
||||
m_ExplosionEffectProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectProgram");
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new GeometryShader("Shaders/ExplosionEffect.geom.glsl")));
|
||||
m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlus.frag.glsl")));
|
||||
m_ExplosionEffectProgram->Compile();
|
||||
m_ExplosionEffectProgram->BindFragDataLocation(0, "sceneColor");
|
||||
m_ExplosionEffectProgram->BindFragDataLocation(1, "bloomColor");
|
||||
m_ExplosionEffectProgram->Link();
|
||||
}
|
||||
|
||||
void DrawFinalPass::Draw(RenderScene& scene)
|
||||
@@ -49,69 +60,15 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
GLERROR("DrawFinalPass::Draw: Pre");
|
||||
|
||||
DrawFinalPassState* state = new DrawFinalPassState(m_FinalPassFrameBuffer.GetHandle());
|
||||
|
||||
m_ForwardPlusProgram->Bind();
|
||||
GLuint shaderHandle = m_ForwardPlusProgram->GetHandle();
|
||||
|
||||
if (scene.ClearDepth) {
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
|
||||
DrawModelRenderQueues(scene.OpaqueObjects, scene);
|
||||
GLERROR("DrawFinalPass::Draw: OpaqueObjects");
|
||||
DrawModelRenderQueues(scene.TransparentObjects, scene);
|
||||
GLERROR("DrawFinalPass::Draw: TransparentObjects");
|
||||
|
||||
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);
|
||||
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
for (auto &job : scene.ForwardJobs) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if(modelJob) {
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "DiffuseColor"), 1, glm::value_ptr(modelJob->DiffuseColor));
|
||||
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "FillColor"), 1, glm::value_ptr(modelJob->FillColor));
|
||||
glUniform1f(glGetUniformLocation(shaderHandle, "FillPercentage"), modelJob->FillPercentage);
|
||||
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if(modelJob->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (modelJob->IncandescenceTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->IncandescenceTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
|
||||
/*if(modelJob->GlowMap != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->GlowMap->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}*/
|
||||
|
||||
//TODO: Fixa så att modelsJobs kan spela upp olika animationer och så att den kan få in en tid istället för 1.0f - Hälsningar Johan och Andreas :)
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones( *modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
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::Draw: END");
|
||||
delete state;
|
||||
}
|
||||
@@ -149,4 +106,152 @@ void DrawFinalPass::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm:
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
GLERROR("MipMap Texture initialization failed");
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFinalPass::DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>& job, RenderScene& scene)
|
||||
{
|
||||
GLuint forwardHandle = m_ForwardPlusProgram->GetHandle();
|
||||
GLuint explosionHandle = m_ExplosionEffectProgram->GetHandle();
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
|
||||
|
||||
for(auto &job : job)
|
||||
{
|
||||
auto explosionEffectJob = std::dynamic_pointer_cast<ExplosionEffectJob>(job);
|
||||
if(explosionEffectJob) {
|
||||
//Bind program
|
||||
m_ExplosionEffectProgram->Bind();
|
||||
|
||||
//Bind uniforms
|
||||
BindExplosionUniforms(explosionHandle, explosionEffectJob, scene);
|
||||
|
||||
if (explosionEffectJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (explosionEffectJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = explosionEffectJob->Skeleton->GetFrameBones(*explosionEffectJob->Animation, explosionEffectJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(explosionHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
//bind textures
|
||||
BindExplosionTextures(explosionEffectJob);
|
||||
//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)));
|
||||
|
||||
} else {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if (modelJob) {
|
||||
//bind forward program
|
||||
m_ForwardPlusProgram->Bind();
|
||||
|
||||
//bind uniforms
|
||||
BindModelUniforms(forwardHandle, modelJob, scene);
|
||||
|
||||
//bind textures
|
||||
BindModelTextures(modelJob);
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(forwardHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
//draw
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr<ExplosionEffectJob>& 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));
|
||||
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);
|
||||
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<ModelJob>& 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);
|
||||
}
|
||||
|
||||
|
||||
void DrawFinalPass::BindExplosionTextures(std::shared_ptr<ExplosionEffectJob>& job)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (job->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
if (job->IncandescenceTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->IncandescenceTexture->m_Texture);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFinalPass::BindModelTextures(std::shared_ptr<ModelJob>& job)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (job->DiffuseTexture != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, job->DiffuseTexture->m_Texture);
|
||||
} 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 {
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ void LightCullingPass::GenerateNewFrustum(RenderScene& scene)
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(scene.Camera->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glDispatchCompute((int)(m_Renderer->Resolution().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->Resolution().Height/(TILE_SIZE*TILE_SIZE) + 1), 1);
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height);
|
||||
glDispatchCompute((int)(m_Renderer->GetViewPortSize().Width/(TILE_SIZE*TILE_SIZE) + 1), (int)(m_Renderer->GetViewPortSize().Height/(TILE_SIZE*TILE_SIZE) + 1), 1);
|
||||
|
||||
GLERROR("CalculateFrustum Error: End");
|
||||
}
|
||||
@@ -40,7 +40,7 @@ void LightCullingPass::OnResolutionChange()
|
||||
|
||||
void LightCullingPass::SetSSBOSizes()
|
||||
{
|
||||
m_NumberOfTiles = (int)(m_Renderer->Resolution().Width/TILE_SIZE) * (int)(m_Renderer->Resolution().Height/TILE_SIZE);
|
||||
m_NumberOfTiles = (int)(m_Renderer->GetViewPortSize().Width/TILE_SIZE) * (int)(m_Renderer->GetViewPortSize().Height/TILE_SIZE);
|
||||
|
||||
m_Frustums = new Frustum[m_NumberOfTiles];
|
||||
m_LightGrid = new LightGrid[m_NumberOfTiles];
|
||||
@@ -67,14 +67,14 @@ void LightCullingPass::CullLights(RenderScene& scene)
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
m_LightCullProgram->Bind();
|
||||
glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glUniform2f(glGetUniformLocation(m_LightCullProgram->GetHandle(), "ScreenDimensions"), m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(scene.Camera->ViewMatrix()));
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glDispatchCompute(glm::ceil(m_Renderer->Resolution().Width / TILE_SIZE), glm::ceil(m_Renderer->Resolution().Height / TILE_SIZE), 1);
|
||||
glDispatchCompute(glm::ceil(m_Renderer->GetViewPortSize().Width/ TILE_SIZE), glm::ceil(m_Renderer->GetViewPortSize().Height / TILE_SIZE), 1);
|
||||
|
||||
GLERROR("CullLights Error: End");
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ PickingPass::~PickingPass()
|
||||
void PickingPass::InitializeTextures()
|
||||
{
|
||||
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
||||
glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
glm::vec2(m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
void PickingPass::InitializeFrameBuffers()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewPortSize().Width, m_Renderer->GetViewPortSize().Height);
|
||||
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
||||
@@ -56,7 +56,7 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
}
|
||||
m_Camera = scene.Camera;
|
||||
|
||||
for (auto &job : scene.ForwardJobs) {
|
||||
for (auto &job : scene.OpaqueObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
@@ -101,6 +101,52 @@ void PickingPass::Draw(RenderScene& scene)
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &job : scene.TransparentObjects) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] };
|
||||
|
||||
PickingInfo pickInfo;
|
||||
pickInfo.Entity = modelJob->Entity;
|
||||
pickInfo.World = modelJob->World;
|
||||
pickInfo.Camera = scene.Camera;
|
||||
|
||||
auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera));
|
||||
if (color != m_EntityColors.end()) {
|
||||
pickColor[0] = color->second[0];
|
||||
pickColor[1] = color->second[1];
|
||||
} else {
|
||||
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;
|
||||
} else {
|
||||
m_ColorCounter[0] += 50;
|
||||
}
|
||||
}
|
||||
|
||||
m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo;
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->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()));
|
||||
glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
|
||||
|
||||
if (modelJob->Model->m_RawModel->m_Skeleton != nullptr) {
|
||||
|
||||
if (modelJob->Animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Skeleton->GetFrameBones(*modelJob->Animation, modelJob->AnimationTime);
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "Bones"), frameBones.size(), GL_FALSE, glm::value_ptr(frameBones[0]));
|
||||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
m_PickingBuffer.Unbind();
|
||||
GLERROR("PickingPass Error");
|
||||
|
||||
@@ -31,33 +31,41 @@ bool RenderSystem::OnSetCamera(Events::SetCamera& e)
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
bool RenderSystem::isChildOfACamera(EntityWrapper entity)
|
||||
{
|
||||
return entity.FirstParentWithComponent("Camera").Valid();
|
||||
}
|
||||
bool RenderSystem::isChildOfCurrentCamera(EntityWrapper entity)
|
||||
{
|
||||
return entity == m_CurrentCamera || entity.IsChildOf(m_CurrentCamera);
|
||||
}
|
||||
|
||||
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& opaqueJobs, std::list<std::shared_ptr<RenderJob>>& transparentJobs)
|
||||
{
|
||||
auto models = m_World->GetComponents("Model");
|
||||
if (models == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& modelComponent : *models) {
|
||||
bool visible = modelComponent["Visible"];
|
||||
for (auto& cModel : *models) {
|
||||
bool visible = cModel["Visible"];
|
||||
if (!visible) {
|
||||
continue;
|
||||
}
|
||||
std::string resource = modelComponent["Resource"];
|
||||
std::string resource = cModel["Resource"];
|
||||
if (resource.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityWrapper entity(m_World, modelComponent.EntityID);
|
||||
EntityWrapper entity(m_World, cModel.EntityID);
|
||||
|
||||
// Don't render the local player
|
||||
if (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer)) {
|
||||
if (!entity.HasComponent("HealthHUD") && entity.Name() != "Crosshair" && entity.Name() != "Weapon") { //Should work but needs to be fixed. Should only render the things "childed" to the local player camera
|
||||
continue;
|
||||
}
|
||||
// Only render children of a camera if that camera is currently active
|
||||
if (isChildOfACamera(entity) && !isChildOfCurrentCamera(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entity.Name() == "Weapon" || entity.HasComponent("HealthHUD")) && !entity.IsChildOf(m_LocalPlayer)) {
|
||||
// Hide things parented to local player if they have the HiddenFromLocalPlayer component
|
||||
if (entity.HasComponent("HiddenForLocalPlayer") && (entity == m_LocalPlayer || entity.IsChildOf(m_LocalPlayer))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -75,22 +83,58 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float fillPercentage = 0.f;
|
||||
glm::vec4 fillColor = glm::vec4(0);
|
||||
|
||||
if(m_World->HasComponent(modelComponent.EntityID, "Fill")) {
|
||||
auto fillComponent = m_World->GetComponent(modelComponent.EntityID, "Fill");
|
||||
if(m_World->HasComponent(cModel.EntityID, "Fill")) {
|
||||
auto fillComponent = m_World->GetComponent(cModel.EntityID, "Fill");
|
||||
fillPercentage = (float)(double)fillComponent["Percentage"];
|
||||
fillColor = (glm::vec4)fillComponent["Color"];
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World);
|
||||
glm::mat4 modelMatrix = Transform::ModelMatrix(cModel.EntityID, m_World);
|
||||
for (auto matGroup : model->MaterialGroups()) {
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World, fillColor, fillPercentage));
|
||||
jobs.push_back(modelJob);
|
||||
if (m_World->HasComponent(cModel.EntityID, "ExplosionEffect")) {
|
||||
auto explosionEffectComponent = m_World->GetComponent(cModel.EntityID, "ExplosionEffect");
|
||||
std::shared_ptr<ExplosionEffectJob> explosionEffectJob = std::shared_ptr<ExplosionEffectJob>(new ExplosionEffectJob(
|
||||
explosionEffectComponent,
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
cModel,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
if(explosionEffectJob->Color.a != 1.f || explosionEffectJob->EndColor.a != 1.f || explosionEffectJob->DiffuseColor.a != 1.f) {
|
||||
cModel["Transparent"] = true;
|
||||
}
|
||||
|
||||
if (cModel["Transparent"]) {
|
||||
transparentJobs.push_back(explosionEffectJob);
|
||||
} else {
|
||||
opaqueJobs.push_back(explosionEffectJob);
|
||||
}
|
||||
} else {
|
||||
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(
|
||||
model,
|
||||
m_Camera,
|
||||
modelMatrix,
|
||||
matGroup,
|
||||
cModel,
|
||||
m_World,
|
||||
fillColor,
|
||||
fillPercentage
|
||||
));
|
||||
if (modelJob->Color.a != 1.f || modelJob->DiffuseColor.a != 1.f) {
|
||||
cModel["Transparent"] = true;
|
||||
}
|
||||
if (cModel["Transparent"]) {
|
||||
transparentJobs.push_back(modelJob);
|
||||
} else {
|
||||
opaqueJobs.push_back(modelJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,7 +244,7 @@ void RenderSystem::Update(double dt)
|
||||
RenderScene scene;
|
||||
scene.Camera = m_Camera;
|
||||
scene.Viewport = Rectangle(1280, 720);
|
||||
fillModels(scene.ForwardJobs);
|
||||
fillModels(scene.OpaqueObjects, scene.TransparentObjects);
|
||||
fillPointLights(scene.PointLightJobs, m_World);
|
||||
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
|
||||
fillText(scene.TextJobs, m_World);
|
||||
|
||||
@@ -58,11 +58,25 @@ void Renderer::InitializeWindow()
|
||||
LOG_ERROR("GLEW: Initialization failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int res[2];
|
||||
glfwGetWindowSize(m_Window, &res[0], &res[1]);
|
||||
SetViewPortSize(Rectangle::Rectangle(res[0], res[1]));
|
||||
|
||||
}
|
||||
|
||||
void Renderer::InitializeShaders()
|
||||
{
|
||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#m_BasicForwardProgram");
|
||||
m_ExplosionEffectProgram = ResourceManager::Load<ShaderProgram>("#ExplosionEffectProgram");
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ExplosionEffect.vert.glsl")));
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new GeometryShader("Shaders/ExplosionEffect.geom.glsl")));
|
||||
//m_ExplosionEffectProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ExplosionEffect.frag.glsl")));
|
||||
//m_ExplosionEffectProgram->Compile();
|
||||
//m_ExplosionEffectProgram->Link();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Renderer::InputUpdate(double dt)
|
||||
@@ -98,6 +112,7 @@ void Renderer::Draw(RenderFrame& frame)
|
||||
m_LightCullingPass->FillLightList(*scene);
|
||||
m_LightCullingPass->CullLights(*scene);
|
||||
m_DrawFinalPass->Draw(*scene);
|
||||
//m_DrawScenePass->Draw(*scene);
|
||||
|
||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||
|
||||
@@ -133,14 +148,14 @@ PickData Renderer::Pick(glm::vec2 screenCoord)
|
||||
void Renderer::InitializeTextures()
|
||||
{
|
||||
m_ErrorTexture = ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/White.png");
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SortRenderJobsByDepth(RenderScene &scene)
|
||||
{
|
||||
//Sort all forward jobs so transparency is good.
|
||||
scene.ForwardJobs.sort(Renderer::DepthSort);
|
||||
scene.TransparentObjects.sort(Renderer::DepthSort);
|
||||
}
|
||||
|
||||
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
||||
|
||||
Reference in New Issue
Block a user