Working build with CMake 3.3.1

This commit is contained in:
2015-09-04 13:51:41 +02:00
parent 98e363eda6
commit 7c92b6aef7
12 changed files with 995 additions and 62 deletions
-1
View File
@@ -36,6 +36,5 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
add_subdirectory(src/dd)
add_subdirectory(src/game)
add_subdirectory(src/tests)
+1 -1
View File
@@ -178,4 +178,4 @@ private:
double m_LastTime;
};
}
}
-24
View File
@@ -41,36 +41,12 @@ public:
{ }
//void Update(double dt) override;
void Initialize() override;
void UpdateEntity(double dt, EntityID entity, EntityID parent) override;
Components::Transform AbsoluteTransform(EntityID entity);
glm::vec3 AbsolutePosition(EntityID entity);
glm::quat AbsoluteOrientation(EntityID entity);
glm::vec3 AbsoluteScale(EntityID entity);
// Events
EventRelay<TransformSystem, Events::Move> m_EMove;
bool OnMove(const Events::Move &event);
EventRelay<TransformSystem, Events::Rotate> m_ERotate;
bool OnRotate(const Events::Rotate &event);
private:
struct MoveItems
{
EntityID Entity;
glm::vec3 GoalPosition;
float Speed;
};
std::unordered_map<EntityID, MoveItems> m_MoveItems;
std::multimap<EntityID, MoveItems> m_QueuedMoveItems;
struct RotationItems
{
EntityID Entity;
glm::quat GoalRotation;
double Time;
};
std::unordered_map<EntityID, RotationItems> m_RotationItems;
std::multimap<EntityID, RotationItems> m_QueuedRotationItems;
};
}
+22 -26
View File
@@ -9,7 +9,7 @@ find_package(ZLIB REQUIRED)
find_package(PNG REQUIRED)
# GLM
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include/dd)
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include)
include_directories(
${INCLUDE_PATH}
${OPENGL_INCLUDE_DIR}
@@ -31,59 +31,55 @@ file(GLOB SOURCE_FILES_Core_Util
source_group(Core FILES ${SOURCE_FILES_Core})
source_group(Core\\Util FILES ${SOURCE_FILES_Core_Util})
file(GLOB SOURCE_FILES_Input
"${INCLUDE_PATH}/Input/*.h"
"Input/*.cpp"
)
source_group(Input FILES ${SOURCE_FILES_Input})
file(GLOB SOURCE_FILES_Particles
"${INCLUDE_PATH}/Particles/*.h"
"Particles/*.cpp"
)
source_group(Particles FILES ${SOURCE_FILES_Particles})
file(GLOB SOURCE_FILES_Rendering
"${INCLUDE_PATH}/Rendering/*.h"
)
source_group(Rendering FILES ${SOURCE_FILES_Rendering})
file(GLOB SOURCE_FILES_Timer
"${INCLUDE_PATH}/Timer/*.h"
"Timer/*.cpp"
)
source_group(Timer FILES ${SOURCE_FILES_Timer})
file(GLOB SOURCE_FILES_Transform
"${INCLUDE_PATH}/Transform/*.h"
"Transform/*.cpp"
)
source_group(Transform FILES ${SOURCE_FILES_Transform})
file(GLOB SOURCE_FILES_Trigger
"${INCLUDE_PATH}/Trigger/*.h"
"Trigger/*.cpp"
)
source_group(Trigger FILES ${SOURCE_FILES_Trigger})
set(SOURCE_FILES
${SOURCE_FILES_Core}
${SOURCE_FILES_Core_Util}
${SOURCE_FILES_Input}
${SOURCE_FILES_Particles}
${SOURCE_FILES_Rendering}
${SOURCE_FILES_Timer}
${SOURCE_FILES_Transform}
${SOURCE_FILES_Trigger}
)
add_library(daydream ${SOURCE_FILES})
target_link_libraries(daydream
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
add_library(game ${SOURCE_FILES})
target_link_libraries(game
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
${GLFW_LIBRARIES}
${Boost_LIBRARIES}
${assimp_LIBRARIES}
${PNG_LIBRARIES}
)
)
add_executable(breakout
main.cpp
)
target_link_libraries(breakout
game
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
${GLFW_LIBRARIES}
${Boost_LIBRARIES}
${assimp_LIBRARIES}
${PNG_LIBRARIES}
)
+377
View File
@@ -0,0 +1,377 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Model.h"
dd::Model::Model(std::string fileName)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(fileName, aiProcess_CalcTangentSpace | aiProcess_Triangulate);
if (scene == nullptr) {
LOG_ERROR("Failed to load model \"%s\"", fileName.c_str());
LOG_ERROR("Assimp error: %s", importer.GetErrorString());
return;
}
auto meshes = scene->mMeshes;
// Pre-count vertices
int numVertices = 0;
int numIndices = 0;
for (int i = 0; i < scene->mNumMeshes; ++i) {
numVertices += meshes[i]->mNumVertices;
// Faces
for (int j = 0; j < meshes[i]->mNumFaces; ++j) {
auto face = meshes[i]->mFaces[j];
numIndices += face.mNumIndices;
}
}
LOG_DEBUG("Vertex count %i", numVertices);
LOG_DEBUG("Index count %i", numIndices);
LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
std::vector<std::tuple<std::string, glm::mat4>> boneInfo;
std::map<std::string, int> boneNameMapping;
for (int i = 0; i < scene->mNumMeshes; ++i) {
auto mesh = meshes[i];
auto material = scene->mMaterials[mesh->mMaterialIndex];
unsigned int indexOffset = m_Vertices.size();
// Vertices, normals and texture coordinates
for (int vertexIndex = 0; vertexIndex < mesh->mNumVertices; ++vertexIndex) {
Vertex desc;
// Position
auto position = mesh->mVertices[vertexIndex];
desc.Position = glm::vec3(position.x, position.y, position.z);
// Normal
auto normal = mesh->mNormals[vertexIndex];
desc.Normal = glm::vec3(normal.x, normal.y, normal.z);
//if (mesh->HasTangentsAndBitangents()) {
// // Tangent
// auto tangent = mesh->mTangents[vertexIndex];
// desc.Tangent = glm::vec3(tangent.x, tangent.y, tangent.z);
// // Bi-tangent
// auto bitangent = mesh->mBitangents[vertexIndex];
// desc.BiTangent = glm::vec3(bitangent.x, bitangent.y, bitangent.z);
//}
// UV
if (mesh->HasTextureCoords(0)) {
auto uv = mesh->mTextureCoords[0][vertexIndex];
desc.TextureCoords = glm::vec2(uv.x, uv.y);
}
// Material diffuse color
aiColor4D diffuse;
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a);
// Material specular color
aiColor4D specular;
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, specular.a);
m_Vertices.push_back(desc);
}
// Faces
for (int j = 0; j < mesh->mNumFaces; ++j) {
auto face = mesh->mFaces[j];
for (int k = 0; k < face.mNumIndices; ++k) {
unsigned int index = face.mIndices[k];
m_Indices.push_back(indexOffset + index);
}
}
// Calculate normal mapping tangents
for (int i = 0; i < m_Indices.size(); i += 3) {
Vertex& v0 = m_Vertices[m_Indices[i]];
Vertex& v1 = m_Vertices[m_Indices[i + 1]];
Vertex& v2 = m_Vertices[m_Indices[i + 2]];
glm::vec3 edge1 = v1.Position - v0.Position;
glm::vec3 edge2 = v2.Position - v0.Position;
float deltaU1 = v1.TextureCoords.x - v0.TextureCoords.x;
float deltaV1 = v1.TextureCoords.y - v0.TextureCoords.y;
float deltaU2 = v2.TextureCoords.x - v0.TextureCoords.x;
float deltaV2 = v2.TextureCoords.y - v0.TextureCoords.y;
float f = 1.0f / (deltaU1 * deltaV2 - deltaU2 * deltaV1);
glm::vec3 tangent;
tangent.x = f * (deltaV2 * edge1.x - deltaV1 * edge2.x);
tangent.y = f * (deltaV2 * edge1.y - deltaV1 * edge2.y);
tangent.z = f * (deltaV2 * edge1.z - deltaV1 * edge2.z);
v0.Tangent += tangent;
v1.Tangent += tangent;
v2.Tangent += tangent;
}
for (auto& vertex : m_Vertices) {
vertex.Tangent = glm::normalize(vertex.Tangent);
vertex.BiTangent = glm::normalize(glm::cross(vertex.Tangent, glm::normalize(vertex.Normal)));
}
// Material info
MaterialGroup matGroup;
matGroup.StartIndex = indexOffset;
matGroup.EndIndex = m_Indices.size() - 1;
// Material shininess
material->Get(AI_MATKEY_SHININESS, matGroup.Shininess);
LOG_DEBUG("Shininess: %f", matGroup.Shininess);
// Diffuse texture
LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
if (material->GetTextureCount(aiTextureType_DIFFUSE)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
matGroup.Texture = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
// Normal map
LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
if (material->GetTextureCount(aiTextureType_HEIGHT)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Normal map: %s", absolutePath.c_str());
matGroup.NormalMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
// Specular map
LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
if (material->GetTextureCount(aiTextureType_SPECULAR)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Specular map: %s", absolutePath.c_str());
matGroup.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
TextureGroups.push_back(matGroup);
// Bones
std::map<int, std::vector<std::tuple<int, float>>> vertexWeights;
for (int j = 0; j < mesh->mNumBones; ++j) {
auto bone = mesh->mBones[j];
std::string boneName = bone->mName.C_Str();
auto mat = bone->mOffsetMatrix;
glm::mat4 glmMat(mat.a1, mat.b1, mat.c1, mat.d1,
mat.a2, mat.b2, mat.c2, mat.d2,
mat.a3, mat.b3, mat.c3, mat.d3,
mat.a4, mat.b4, mat.c4, mat.d4);
int boneIndex;
if (boneNameMapping.find(boneName) != boneNameMapping.end()) {
boneIndex = boneNameMapping[boneName];
} else {
boneIndex = boneInfo.size();
boneInfo.push_back(std::make_tuple(boneName, glmMat));
boneNameMapping[boneName] = boneIndex;
}
for (int k = 0; k < bone->mNumWeights; ++k) {
auto weight = bone->mWeights[k];
unsigned int offsetVertexId = weight.mVertexId + indexOffset;
vertexWeights[offsetVertexId].push_back(std::make_tuple(boneIndex, weight.mWeight));
}
}
for (auto &pair : vertexWeights) {
auto weights = pair.second;
Vertex& desc = m_Vertices[pair.first];
const int maxWeights = 8;
if (weights.size() > maxWeights) {
LOG_WARNING("Vertex weights (%i) greater than max weights per vertex (%i)", weights.size(), maxWeights);
}
for (int weightIndex = 0; weightIndex < weights.size() && weightIndex < maxWeights && weightIndex < 4; ++weightIndex) {
std::tie(desc.BoneIndices1[weightIndex], desc.BoneWeights1[weightIndex]) = weights[weightIndex];
}
for (int weightIndex = 4; weightIndex < weights.size() && weightIndex < maxWeights && weightIndex < 8; ++weightIndex) {
std::tie(desc.BoneIndices2[weightIndex - 4], desc.BoneWeights2[weightIndex - 4]) = weights[weightIndex];
}
}
//break;
}
// Traverse the node tree and build a skeleton
if (!boneInfo.empty()) {
m_Skeleton = new Skeleton();
CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1);
int numBones = m_Skeleton->Bones.size();
LOG_DEBUG("Bone count: %i", numBones);
if (numBones > 0) {
m_Skeleton->PrintSkeleton();
}
}
// Animations
LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
for (int i = 0; i < scene->mNumAnimations; ++i) {
auto animation = scene->mAnimations[i];
std::string animationName = animation->mName.C_Str();
LOG_DEBUG("Animation: %s", animationName.c_str());
LOG_DEBUG("Duration: %f", animation->mDuration);
LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
Skeleton::Animation skelAnim;
skelAnim.Name = animationName;
skelAnim.Duration = animation->mDuration / animation->mTicksPerSecond;
std::map<int, double> frameTimes;
std::map<int, std::map<int, Skeleton::Animation::Keyframe::BoneProperty>> frameBoneProperties;
// For each animation channel (bone)
for (int channelIndex = 0; channelIndex < animation->mNumChannels; ++channelIndex) {
auto channel = animation->mChannels[channelIndex];
std::string boneName = channel->mNodeName.C_Str();
int boneID = m_Skeleton->GetBoneID(boneName);
if (boneID == -1) {
LOG_ERROR("Animation referenced a bone that doesn't exist: %s", boneName.c_str());
continue;
}
// If you don't have the same amount of keyframes for every transformation type you're dumb.
if (channel->mNumPositionKeys != channel->mNumRotationKeys || channel->mNumPositionKeys != channel->mNumScalingKeys) {
LOG_ERROR("Hey, animation! You're dumb!", animationName.c_str());
continue;
}
for (int keyframe = 0; keyframe < channel->mNumPositionKeys; ++keyframe) {
auto posKey = channel->mPositionKeys[keyframe];
auto rotKey = channel->mRotationKeys[keyframe];
auto scaleKey = channel->mScalingKeys[keyframe];
frameTimes[keyframe] = posKey.mTime;
auto &property = frameBoneProperties[keyframe][boneID];
property.ID = keyframe;
property.Position = glm::vec3(posKey.mValue.x, posKey.mValue.y, posKey.mValue.z);
property.Rotation = glm::quat(rotKey.mValue.w, rotKey.mValue.x, rotKey.mValue.y, rotKey.mValue.z);
property.Scale = glm::vec3(scaleKey.mValue.x, scaleKey.mValue.y, scaleKey.mValue.z);
}
}
// Create keyframes from bone properties
for (auto &kv : frameBoneProperties) {
int keyframe = kv.first;
Skeleton::Animation::Keyframe animationFrame;
animationFrame.Index = keyframe;
animationFrame.Time = frameTimes[keyframe] / animation->mTicksPerSecond;
for (auto &kv2 : kv.second) {
int boneID = kv2.first;
auto &property = kv2.second;
animationFrame.BoneProperties[boneID] = property;
}
skelAnim.Keyframes.push_back(animationFrame);
}
m_Skeleton->Animations[animationName] = skelAnim;
}
// Generate GL buffers
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(Vertex), &m_Vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &ElementBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_Indices.size() * sizeof(unsigned int), &m_Indices[0], GL_STATIC_DRAW);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLERROR("GLEW: BufferFail4");
glBindBuffer(GL_ARRAY_BUFFER, buffer);
std::vector<int> structSizes = { 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 4 };
int stride = 0;
for (int size : structSizes)
stride += size;
stride *= sizeof(GLfloat);
int offset = 0;
{
int element = 0;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * offset)); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
glVertexAttribPointer(element, structSizes[element], GL_FLOAT, GL_FALSE, stride, (GLvoid*)(sizeof(GLfloat) * (offset += structSizes[element - 1]))); element++;
}
GLERROR("GLEW: BufferFail5");
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glEnableVertexAttribArray(5);
glEnableVertexAttribArray(6);
glEnableVertexAttribArray(7);
glEnableVertexAttribArray(8);
glEnableVertexAttribArray(9);
glEnableVertexAttribArray(10);
GLERROR("GLEW: BufferFail5");
//CreateBuffers();
}
dd::Model::~Model()
{
if (m_Skeleton) {
delete m_Skeleton;
}
}
void dd::Model::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &boneInfo, std::map<std::string, int> &boneNameMapping, aiNode* node, int parentID)
{
std::string nodeName = node->mName.C_Str();
// Find the bone by name in the bone info list
if (boneNameMapping.find(nodeName) == boneNameMapping.end()) {
LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
} else {
glm::mat4 offsetMatrix;
int ID = boneNameMapping[nodeName];
std::tie(std::ignore, offsetMatrix) = boneInfo[ID];
m_Skeleton->CreateBone(ID, parentID, nodeName, offsetMatrix);
parentID = ID;
}
for (int childIndex = 0; childIndex < node->mNumChildren; ++childIndex) {
aiNode* child = node->mChildren[childIndex];
CreateSkeleton(boneInfo, boneNameMapping, child, parentID);
}
}
+427
View File
@@ -0,0 +1,427 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/OBJ.h"
bool dd::OBJ::LoadFromFile(std::string filename)
{
m_Path = boost::filesystem::path(filename);
// http://paulbourke.net/dataformats/obj/
std::ifstream file(m_Path.string());
if (!file.is_open())
{
LOG_ERROR("Failed to open .obj \"%s\": %s", m_Path.string().c_str(), strerror(errno));
return false;
}
//LOG_INFO("Parsing .obj \"%s\"", m_Path.string().c_str());
std::string line;
while (std::getline(file, line))
{
if (line.length() == 0)
continue;
std::stringstream ss(line);
std::string prefix;
ss >> prefix;
// Ignore comments
if (prefix == "#")
continue;
// Material files
if (prefix == "mtllib")
{
std::string materialFilename;
ss >> materialFilename;
m_MaterialPath = m_Path.branch_path() / materialFilename;
ParseMaterial();
continue;
}
// Material statement
if (prefix == "usemtl")
{
std::string material;
ss >> material;
m_CurrentMaterial = &Materials[material];
continue;
}
// Vertices
if (prefix == "v")
{
float x, y, z;
ss >> x >> y >> z;
Vertices.push_back(std::make_tuple(x, y, z));
continue;
}
// Normals
if (prefix == "vn")
{
float x, y, z;
ss >> x >> y >> z;
Normals.push_back(std::make_tuple(x, y, z));
}
// Texture coordinates
if (prefix == "vt")
{
float u, v, w;
ss >> u >> v >> w;
TextureCoords.push_back(std::make_tuple(u, v, w));
}
// Face definitions
if (prefix == "f")
{
Face face;
face.Material = m_CurrentMaterial;
std::string faceDefString;
while (ss >> faceDefString)
{
std::stringstream ss2(faceDefString);
FaceDefinition faceDef = { 0, 0, 0 };
ss2 >> faceDef.VertexIndex;
ss2.ignore(); // Ignore first delimiter
if (!ss2)
continue;
if (ss2.peek() == '/')
{
ss2.ignore();
ss2 >> faceDef.NormalIndex;
}
else
{
ss2 >> faceDef.TextureCoordIndex;
ss2.ignore();
ss2 >> faceDef.NormalIndex;
}
face.Definitions.push_back(faceDef);
}
Faces.push_back(face);
}
}
return true;
}
void dd::OBJ::ParseMaterial()
{
// http://paulbourke.net/dataformats/mtl/
std::ifstream file(m_MaterialPath.string());
if (!file.is_open())
{
LOG_ERROR("Failed to open .mtl \"%s\"", m_MaterialPath.string().c_str());
return;
}
//LOG_INFO("Parsing .mtl \"%s\"", m_MaterialPath.string().c_str());
std::string currentMaterialName;
MaterialInfo* currentMaterial = nullptr;
unsigned int currentLine = 0;
std::string line;
while (std::getline(file, line))
{
currentLine++;
if (line.length() == 0)
continue;
std::stringstream ss(line);
std::string prefix;
ss >> prefix;
// Create a new material definition
if (prefix == "newmtl")
{
MaterialInfo mat;
ss >> currentMaterialName;
//LOG_INFO("Parsing material %s", currentMaterialName.c_str());
Materials[currentMaterialName] = mat;
currentMaterial = &Materials[currentMaterialName];
continue;
}
if (!currentMaterial)
continue;
// Ambient color
if (prefix == "Ka")
{
float r, g, b;
ss >> r >> g >> b;
currentMaterial->AmbientColor = std::make_tuple(r, g, b);
continue;
}
// Diffuse color
if (prefix == "Kd")
{
float r, g, b;
ss >> r >> g >> b;
currentMaterial->DiffuseColor = std::make_tuple(r, g, b);
continue;
}
// Specular color
if (prefix == "Ks")
{
float r, g, b;
ss >> r >> g >> b;
currentMaterial->SpecularColor = std::make_tuple(r, g, b);
continue;
}
// Transmission filter
if (prefix == "Tf")
{
std::stringstream ss2;
ss2 << ss.str();
std::string command;
ss2 >> command;
if (command == "xyz")
{
// TODO: "The "Ks xyz" statement specifies the specular reflectivity using CIEXYZ values."
}
else if (command == "spectral")
{
// TODO: "The "Tf spectral" statement specifies the transmission filter using a spectral curve."
}
else
{
float r, g, b;
ss >> r;
// G and B are optional
if (!(ss >> g >> b))
{
g = r;
b = r;
}
currentMaterial->TransmissionFilter = std::make_tuple(r, g, b);
}
continue;
}
// Optical density
if (prefix == "Ni")
{
ss >> currentMaterial->OpticalDensity;
continue;
}
// Alpha
if (prefix == "d" || prefix == "Tr")
{
ss >> currentMaterial->Alpha;
continue;
}
// Shininess
if (prefix == "Ns")
{
ss >> currentMaterial->Shininess;
continue;
}
// Illumination model
if (prefix == "illum")
{
int illum = 0;
ss >> illum;
currentMaterial->IlluminationModel = illum;
continue;
}
// Diffuse texture
if (prefix == "map_Kd")
{
MaterialInfo::ColorMap colorMap;
std::string fileName;
std::string arg;
while (ss >> arg)
{
ParseColorMap(currentLine, ss, prefix, arg, colorMap);
}
// HACK: Should we really have to specify the full path here?
colorMap.FileName = (m_MaterialPath.branch_path() / colorMap.FileName).string();
currentMaterial->DiffuseTexture = colorMap;
continue;
}
// Specular map
if (prefix == "map_Ks")
{
MaterialInfo::ColorMap colorMap;
std::string fileName;
std::string arg;
while (ss >> arg)
{
ParseColorMap(currentLine, ss, prefix, arg, colorMap);
}
// HACK: Should we really have to specify the full path here?
colorMap.FileName = (m_MaterialPath.branch_path() / colorMap.FileName).string();
currentMaterial->SpecularMap = colorMap;
continue;
}
// Normal map (bump map)
if (prefix == "bump" || prefix == "map_Bump" )
{
MaterialInfo::BumpMap bumpMap;
std::string fileName;
std::string arg;
while (ss >> arg)
{
ParseBumpMap(currentLine, ss, prefix, arg, bumpMap);
}
// HACK: Should we really have to specify the full path here?
bumpMap.FileName = (m_MaterialPath.branch_path() / bumpMap.FileName).string();
currentMaterial->NormalMap = bumpMap;
continue;
}
}
}
void dd::OBJ::ParseTextureMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::TextureMap &textureMap)
{
if (arg == "-blendu")
{
std::string val;
ss >> val;
if (val == "off")
textureMap.blendu = false;
else if (val == "on")
textureMap.blendu = true;
else
LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line);
}
else if (arg == "-blendv")
{
std::string val;
ss >> val;
if (val == "off")
textureMap.blendv = false;
else if (val == "on")
textureMap.blendv = true;
else
LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line);
}
else if (arg == "-clamp")
{
std::string val;
ss >> val;
if (val == "off")
textureMap.clamp = false;
else if (val == "on")
textureMap.clamp = true;
else
LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line);
}
else if (arg == "-o")
{
float u, v, w;
if (ss >> u >> v >> w)
{
textureMap.o = std::make_tuple(u, v, w);
}
else
{
LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line);
}
}
else if (arg == "-s")
{
float u, v, w;
if (ss >> u >> v >> w)
{
textureMap.s = std::make_tuple(u, v, w);
}
else
{
LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line);
}
}
// Assume unrecognized options is part of the file name
else
{
if (!textureMap.FileName.empty())
textureMap.FileName += " ";
textureMap.FileName += arg;
}
}
void dd::OBJ::ParseColorMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::ColorMap &colorMap)
{
if (arg == "-cc")
{
if (prefix != "map_Kd" || prefix != "map_Ks")
{
LOG_ERROR("Invalid MTL argument \"%s\" to option \"%s\" on line %i", arg.c_str(), prefix.c_str(), line);
return;
}
std::string val;
if (ss >> val)
{
if (val == "off")
colorMap.cc = false;
else if (val == "on")
colorMap.cc = true;
else
LOG_ERROR("Unrecognized MTL value \"%s\" to argument \"%s %s\" on line %i", val.c_str(), prefix.c_str(), arg.c_str(), line);
}
else
{
LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line);
}
}
else
{
ParseTextureMap(line, ss, prefix, arg, colorMap);
}
}
void dd::OBJ::ParseBumpMap(unsigned int line, std::stringstream &ss, std::string prefix, std::string arg, MaterialInfo::BumpMap &bumpMap)
{
if (arg == "-bm")
{
if (prefix != "bump")
{
LOG_ERROR("Invalid MTL argument \"%s\" to option \"%s\" on line %i", arg.c_str(), prefix.c_str(), line);
return;
}
float val;
if (ss >> val)
bumpMap.bm = val;
else
LOG_ERROR("Unrecognized MTL value to argument \"%s %s\" on line %i", prefix.c_str(), arg.c_str(), line);
}
else
{
ParseTextureMap(line, ss, prefix, arg, bumpMap);
}
}
+150
View File
@@ -0,0 +1,150 @@
/*
This file is part of Daydream Engine.
Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung
Daydream Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Daydream Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Daydream Engine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "Core/Skeleton.h"
int dd::Skeleton::CreateBone(int ID, int parentID, std::string name, glm::mat4 offsetMatrix)
{
if (m_BonesByName.find(name) != m_BonesByName.end()) {
return m_BonesByName.at(name)->ID;
} else {
Bone* bone;
if (parentID == -1) {
bone = new Bone(ID, nullptr, name, offsetMatrix);
RootBone = bone;
} else {
Bone* parent = Bones[parentID];
bone = new Bone(ID, parent, name, offsetMatrix);
parent->Children.push_back(bone);
}
Bones[ID] = bone;
m_BonesByName[name] = bone;
return ID;
}
}
dd::Skeleton::~Skeleton()
{
for (auto &kv : Bones) {
delete kv.second;
}
}
std::vector<glm::mat4> dd::Skeleton::GetFrameBones(std::string animationName, double time, bool noRootMotion /*= false*/)
{
auto& animation = Animations.at(animationName);
// HACK: Animation wrap-around
while (time < 0)
time += animation.Duration;
while (time > animation.Duration)
time -= animation.Duration;
int currentKeyframeIndex = GetKeyframe(animation, time);
Animation::Keyframe& currentFrame = animation.Keyframes[currentKeyframeIndex];
Animation::Keyframe& nextFrame = animation.Keyframes[currentKeyframeIndex + 1];
float alpha = (time - currentFrame.Time) / (nextFrame.Time - currentFrame.Time);
//auto animationFrame = Animations[""].Keyframes[frame];
std::map<int, glm::mat4> frameBones;
AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, alpha, frameBones, RootBone, glm::mat4(1));
std::vector<glm::mat4> finalMatrices;
for (auto &kv : frameBones) {
finalMatrices.push_back(kv.second);
}
return finalMatrices;
}
void dd::Skeleton::AccumulateBoneTransforms(bool noRootMotion, Animation::Keyframe &currentFrame, Animation::Keyframe &nextFrame, float progress, std::map<int, glm::mat4> &boneMatrices, Bone* bone, glm::mat4 parentMatrix)
{
glm::mat4 boneMatrix;
if (currentFrame.BoneProperties.find(bone->ID) != currentFrame.BoneProperties.end() || nextFrame.BoneProperties.find(bone->ID) != nextFrame.BoneProperties.end()) {
Animation::Keyframe::BoneProperty currentBoneProperty = currentFrame.BoneProperties.at(bone->ID);
Animation::Keyframe::BoneProperty nextBoneProperty = nextFrame.BoneProperties.at(bone->ID);
glm::vec3 positionInterp = currentBoneProperty.Position * (1.f - progress) + nextBoneProperty.Position * progress;
glm::quat rotationInterp = glm::slerp(currentBoneProperty.Rotation, nextBoneProperty.Rotation, progress);
glm::vec3 scaleInterp = currentBoneProperty.Scale * (1.f - progress) + nextBoneProperty.Scale * progress;
// Flag for no root motion
if (bone == RootBone && noRootMotion) {
positionInterp.x = 0;
positionInterp.z = 0;
}
boneMatrix = parentMatrix * (glm::translate(positionInterp) * glm::toMat4(rotationInterp) * glm::scale(scaleInterp));
boneMatrices[bone->ID] = boneMatrix * bone->OffsetMatrix;
} else {
boneMatrix = parentMatrix * bone->Parent->OffsetMatrix; // * glm::inverse(bone->OffsetMatrix);
boneMatrices[bone->ID] = boneMatrix; // * bone->OffsetMatrix;
}
for (auto &child : bone->Children) {
std::string name = child->Name;
AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, progress, boneMatrices, child, boneMatrix);
}
}
int dd::Skeleton::GetBoneID(std::string name)
{
if (m_BonesByName.find(name) == m_BonesByName.end()) {
return -1;
} else {
return m_BonesByName.at(name)->ID;
}
}
void dd::Skeleton::PrintSkeleton()
{
PrintSkeleton(RootBone, 0);
}
void dd::Skeleton::PrintSkeleton(Bone* bone, int depthCount)
{
std::stringstream ss;
ss << std::string(depthCount, ' ');
ss << bone->ID << ": " << bone->Name;
std::cout << ss.str() << std::endl;
depthCount++;
for (auto &child : bone->Children) {
PrintSkeleton(child, depthCount);
}
}
int dd::Skeleton::GetKeyframe(Animation& animation, double time)
{
if (time < 0)
time = 0;
if (time > animation.Duration)
return animation.Keyframes.size() - 1;
for (int keyframe = 0; keyframe < animation.Keyframes.size(); ++keyframe) {
if (animation.Keyframes[keyframe].Time > time)
return keyframe - 1;
}
return 0;
}
-4
View File
@@ -20,10 +20,6 @@
#include "Transform/TransformSystem.h"
#include "Core/World.h"
void dd::Systems::TransformSystem::Initialize()
{
}
glm::vec3 dd::Systems::TransformSystem::AbsolutePosition(EntityID entity)
{
glm::vec3 absPosition;
+12
View File
@@ -0,0 +1,12 @@
#include "PrecompiledHeader.h"
#include "Core/Engine.h"
int main(int argc, char* argv[])
{
dd::Engine engine(argc, argv);
LOG_INFO("------------ Engine initialized ------------");
while (engine.Running())
engine.Tick();
return 0;
}
+2 -2
View File
@@ -3,7 +3,7 @@ project(tests)
find_package(Boost REQUIRED COMPONENTS chrono thread unit_test_framework)
include_directories(
${CMAKE_SOURCE_DIR}/include/dd
${CMAKE_SOURCE_DIR}/include
${Boost_INCLUDE_DIRS}
)
@@ -19,6 +19,6 @@ endif()
add_executable(tests ${SOURCE_FILES})
target_link_libraries(tests
daydream
game
${Boost_LIBRARIES}
)
+2 -2
View File
@@ -8,7 +8,7 @@ MKLINK "%DeployLocation%\Models\" "assets\Models" /J
MKLINK "%DeployLocation%\Textures\" "assets\Textures\" /J
MKLINK "%DeployLocation%\Sounds\" "assets\Sounds\" /J
:: Shaders
MKLINK "%DeployLocation%\Shaders\" "src\dd\Core\Shaders\" /J
MKLINK "%DeployLocation%\Shaders\" "src\game\Core\Shaders\" /J
:: Platform specific binaries
IF "%~1"=="" GOTO :EOF
ECHO Deploying %1 binaries to %DeployLocation%
@@ -17,4 +17,4 @@ COPY "deps\bin\%1\x64\*.dll" "%DeployLocation%"
::COPY "libs\assimp-3.1.1\LICENSE" "%ConfigPath%\Assimp License.txt"
::COPY "libs\glew-1.11.0\LICENSE.txt" "%ConfigPath%\GLEW License.txt"
::COPY "libs\glm-0.9.5.4\copying.txt" "%ConfigPath%\GLM License.txt"
::COPY "libs\assimp-3.1.1\LICENSE" "%ConfigPath%\Assimp License.txt"
::COPY "libs\assimp-3.1.1\LICENSE" "%ConfigPath%\Assimp License.txt"
Regular → Executable
+2 -2
View File
@@ -9,9 +9,9 @@ ln -srf assets/Models ${DeployLocation}
ln -srf assets/Textures ${DeployLocation}
ln -srf assets/Sounds ${DeployLocation}
# Shaders
ln -srf src/dd/Core/Shaders ${DeployLocation}
ln -srf src/game/Core/Shaders ${DeployLocation}
# Platform specific binaries
if [[ $# -eq 1 ]]; then
echo "Deploying {$1} binaries to ${DeployLocation}"
ln -srf deps/bin/$1/x64/*.dll ${DeployLocation}
fi
fi