Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac0c6ff952 | |||
| 06f64f8fbf | |||
| 0c56a05144 | |||
| 382eff169f | |||
| d4797b0808 | |||
| 25890c8d6c | |||
| 0fb1dbcae1 | |||
| 9f3d887ac4 | |||
| b4081b3e45 | |||
| 8d61632c26 | |||
| 2eaad2aa00 | |||
| 235b26ad61 | |||
| f80fb5eda8 | |||
| aa115befa9 | |||
| aa20b48188 | |||
| 96a735c542 | |||
| 666f1fd878 | |||
| 4c5d17b203 | |||
| 8286d052b3 | |||
| 67477ff3ae | |||
| b5b1140f5c | |||
| 7567f47a68 | |||
| 97d70f8e32 | |||
| 3baa988ad4 | |||
| a28748b35d | |||
| f1835fd89c | |||
| ecdb5ed07d | |||
| 6d2c656a04 | |||
| 2bf0434bcb | |||
| c984f76b2f | |||
| 84b7cf165c | |||
| 386e76f642 | |||
| a47317bb32 | |||
| e643581971 | |||
| 3826142e94 | |||
| 2a3009212a | |||
| 16c39df439 | |||
| 8437b9c734 | |||
| 6317a6092d | |||
| 4e70439653 | |||
| 24486c314d | |||
| 7b62dc19bf | |||
| 0e90382fd1 | |||
| 1667358e0c | |||
| eb5fca898f | |||
| c9db46564f | |||
| 509a989d3b | |||
| bc4cc5db54 | |||
| 73708ec706 | |||
| 67017fcaf4 | |||
| 498afb3a5e | |||
| 4e535c1102 | |||
| 1689370356 | |||
| 60b3ce89b2 | |||
| a22d086e60 | |||
| 74c1beed20 | |||
| c8cb0ee939 |
@@ -4,3 +4,11 @@ bin/
|
||||
lib/
|
||||
# Because apparently nobody has any self control
|
||||
*.orig
|
||||
|
||||
*.suo
|
||||
*.sdf
|
||||
tools/MayaExporter/MayaExporter/x64/Debug/
|
||||
tools/MayaExporter/x64/Debug/
|
||||
|
||||
tools/MayaExporter/MayaExporter/Debug/
|
||||
tools/MayaExporter/MayaExporter/GeneratedFiles/
|
||||
|
||||
+1
-1
Submodule assets updated: e8174f630f...068fbb2d20
@@ -10,7 +10,8 @@
|
||||
|
||||
#include "../Core/Ray.h"
|
||||
#include "../Core/AABB.h"
|
||||
#include "../Rendering/RawModel.h"
|
||||
#include "Rendering/RawModelCustom.h"
|
||||
//#include "Rendering/RawModelAssimp.h"
|
||||
#include "../Core/Transform.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef EComponentDeleted_h__
|
||||
#define EComponentDeleted_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "Event.h"
|
||||
#include "Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct ComponentDeleted : Event
|
||||
{
|
||||
EntityID Entity;
|
||||
std::string ComponentType;
|
||||
// True if the component was deleted as a result of the entity it was attached to being deleted
|
||||
bool Cascaded;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef EEntityDeleted_h__
|
||||
#define EEntityDeleted_h__
|
||||
|
||||
#include "Event.h"
|
||||
#include "Entity.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct EntityDeleted : Event
|
||||
{
|
||||
EntityID DeletedEntity;
|
||||
// True if the entity deletion was triggered because the entity's parent was deleted before it
|
||||
bool Cascaded;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,15 +2,15 @@
|
||||
#define EPlayerDamage_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct PlayerDamage : Event
|
||||
{
|
||||
double DamageAmount;
|
||||
EntityID PlayerDamagedID;
|
||||
EntityWrapper Player;
|
||||
double Damage;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ struct PlayerSpawned : Event
|
||||
int PlayerID;
|
||||
EntityWrapper Player;
|
||||
EntityWrapper Spawner;
|
||||
std::string PlayerName;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,16 +2,14 @@
|
||||
#define EShoot_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
#include "../Core/Entity.h"
|
||||
#include "Engine/GLM.h"
|
||||
#include "../Core/EntityWrapper.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct Shoot : Event
|
||||
{
|
||||
//ID for who made the shot
|
||||
EntityID shooter;
|
||||
EntityWrapper Player;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@ struct EntityWrapper
|
||||
|
||||
static const EntityWrapper Invalid;
|
||||
|
||||
bool HasComponent(const std::string& componentName);
|
||||
bool HasComponent(const std::string& componentType);
|
||||
EntityWrapper Parent();
|
||||
EntityWrapper FirstChildByName(const std::string& name);
|
||||
EntityWrapper FirstParentWithComponent(const std::string& componentType);
|
||||
bool IsChildOf(EntityWrapper potentialParent);
|
||||
bool Valid();
|
||||
|
||||
|
||||
@@ -32,10 +32,10 @@ public:
|
||||
};
|
||||
struct FailedLoadingException : public std::exception
|
||||
{
|
||||
virtual const char* what() const throw()
|
||||
{
|
||||
return "Resource is failed to load.";
|
||||
}
|
||||
FailedLoadingException(char const* const _Message)
|
||||
: std::exception(_Message)
|
||||
{ }
|
||||
FailedLoadingException() :std::exception("Resource failed to load.") { };
|
||||
};
|
||||
|
||||
// Pretend that this is a pure virtual function that you have to implement
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
#include "Entity.h"
|
||||
#include "ObjectPool.h"
|
||||
#include "ComponentPool.h"
|
||||
#include "EventBroker.h"
|
||||
|
||||
class World
|
||||
{
|
||||
public:
|
||||
World() = default;
|
||||
World(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ }
|
||||
~World();
|
||||
|
||||
// Create empty entity
|
||||
@@ -46,6 +50,7 @@ public:
|
||||
std::string GetName(EntityID entity) const;
|
||||
|
||||
private:
|
||||
EventBroker* m_EventBroker = nullptr;
|
||||
EntityID m_CurrentEntityID = 0;
|
||||
|
||||
std::unordered_map<EntityID, EntityID> m_EntityParents;
|
||||
@@ -55,6 +60,7 @@ private:
|
||||
std::unordered_map<EntityID, std::string> m_EntityNames;
|
||||
|
||||
EntityID generateEntityID();
|
||||
void deleteEntityRecursive(EntityID entity, bool cascaded = false);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -43,6 +43,7 @@ private:
|
||||
PacketID m_PacketID = 0;
|
||||
PacketID m_PreviousPacketID = 0;
|
||||
PacketID m_SendPacketID = 0;
|
||||
AckBitPattern ackBitField = 0;
|
||||
|
||||
// Game logic
|
||||
World* m_World;
|
||||
@@ -50,6 +51,7 @@ private:
|
||||
PlayerID m_PlayerID = -1;
|
||||
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
|
||||
bool m_IsConnected = false;
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
// Server Client Lookup map
|
||||
// Assumes that root node for client and server is EntityID 0.
|
||||
|
||||
@@ -79,12 +81,15 @@ private:
|
||||
void parsePing();
|
||||
void parseKick();
|
||||
void parsePlayersSpawned(Packet& packet);
|
||||
void parseEntityDeletion(Packet& packet);
|
||||
void parseComponentDeletion(Packet& packet);
|
||||
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
|
||||
void parseSnapshot(Packet& packet);
|
||||
void identifyPacketLoss();
|
||||
bool hasServerTimedOut();
|
||||
EntityID createPlayer();
|
||||
void sendInputCommands();
|
||||
void sendLocalPlayerTransform();
|
||||
void becomePlayer();
|
||||
// Mapping Logic
|
||||
// Returns if local EntityID exist in map
|
||||
@@ -92,13 +97,16 @@ private:
|
||||
// Returns if server EntityID exist in map
|
||||
bool serverClientMapsHasEntity(EntityID serverEntityID);
|
||||
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
||||
void deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
|
||||
|
||||
// Events
|
||||
EventBroker* m_EventBroker;
|
||||
EventRelay<Client, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
EventRelay<Client, Events::PlayerDamage> m_EPlayeDamage;
|
||||
EventRelay<Client, Events::PlayerDamage> m_EPlayerDamage;
|
||||
bool OnPlayerDamage(const Events::PlayerDamage& e);
|
||||
EventRelay<Client, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,10 @@ enum class MessageType
|
||||
PlayerConnected,
|
||||
BecomePlayer,
|
||||
Kick,
|
||||
OnPlayerSpawned
|
||||
OnPlayerSpawned,
|
||||
EntityDeleted,
|
||||
ComponentDeleted,
|
||||
PlayerTransform
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
#include "Core/ConfigFile.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
#define INPUTSIZE 4097
|
||||
typedef unsigned int PlayerID;
|
||||
typedef unsigned int PacketID;
|
||||
typedef unsigned int UserID;
|
||||
typedef unsigned int AckBitPattern;
|
||||
|
||||
class Network
|
||||
{
|
||||
|
||||
@@ -11,12 +11,12 @@ class Packet
|
||||
public:
|
||||
// arg1: Type of message (Connect, Disconnect...)
|
||||
// arg2: PacketID for identifying packet loss.
|
||||
Packet(MessageType type, unsigned int& packetID);
|
||||
Packet(MessageType type, unsigned int& packetID, unsigned int lastReceivedPacket, unsigned int ackBitField);
|
||||
// Used to create packet from already existing data buffer.
|
||||
Packet(char* data, const int sizeOfPacket);
|
||||
Packet(MessageType type);
|
||||
~Packet();
|
||||
void Init(MessageType type, unsigned int& packetID);
|
||||
void Init(MessageType type, unsigned int& packetID, unsigned int lastReceivedPacket, unsigned int ackBitField);
|
||||
|
||||
// Add primitive types like int, float, char...
|
||||
template<typename T>
|
||||
@@ -50,7 +50,9 @@ public:
|
||||
// Pops the first element as if it was a string.
|
||||
std::string ReadString();
|
||||
char* ReadData(int SizeOfData);
|
||||
void ChangePacketID(unsigned int& packetID);
|
||||
// No purpose any more
|
||||
//void ChangePacketID(unsigned int& packetID);
|
||||
void ChangeHeaderInfo(unsigned int& packetID, unsigned int lastReceivedPacket, unsigned int ackBitField);
|
||||
int Size() { return m_Offset; };
|
||||
char* Data() { return m_Data; };
|
||||
unsigned int DataReadSize() { return m_ReturnDataOffset; }
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
#ifndef PlayerDefinition_h__
|
||||
#define PlayerDefinition_h__
|
||||
#include <string>
|
||||
#include "../Core/Entity.h"
|
||||
|
||||
struct PlayerDefinition {
|
||||
int EntityID = -1;
|
||||
::EntityID EntityID = EntityID_Invalid;
|
||||
std::string Name = "";
|
||||
boost::asio::ip::udp::endpoint Endpoint;
|
||||
// The ID of the last sent packet. (Local sequence number)
|
||||
unsigned int PacketID;
|
||||
// The ID of the last received packet. (Remote sequence number)
|
||||
// This is sent as the ackNumber.
|
||||
unsigned int LastPacketReceivedID;
|
||||
// The bit pattern of the last 32 received packets.
|
||||
unsigned int AckBitField;
|
||||
std::clock_t StopTime;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "Core/EPlayerDamage.h"
|
||||
#include "Network/EPlayerDisconnected.h"
|
||||
#include "Core/EPlayerSpawned.h"
|
||||
#include "Core/EEntityDeleted.h"
|
||||
#include "Core/EComponentDeleted.h"
|
||||
|
||||
class Server : public Network
|
||||
{
|
||||
@@ -31,18 +33,18 @@ private:
|
||||
boost::asio::ip::udp::socket m_Socket;
|
||||
|
||||
// Sending messages to client logic
|
||||
PlayerDefinition m_PlayerDefinitions[8]; //
|
||||
std::vector<PlayerDefinition> m_ConnectedUsers;
|
||||
std::map<PlayerID, PlayerDefinition> m_ConnectedPlayers;
|
||||
char readBuffer[INPUTSIZE] = { 0 };
|
||||
int bytesRead = 0;
|
||||
// time for previouse message
|
||||
std::clock_t previousePingMessage = std::clock();
|
||||
std::clock_t previousPingMessage = std::clock();
|
||||
std::clock_t previousSnapshotMessage = std::clock();
|
||||
std::clock_t timOutTimer = std::clock();
|
||||
// How often we send messages (milliseconds)
|
||||
int pingIntervalMs;
|
||||
int snapshotInterval;
|
||||
int checkTimeOutInterval = 100;
|
||||
int m_NextPlayerID = 0;
|
||||
|
||||
//Timers
|
||||
std::clock_t m_StartPingTime;
|
||||
@@ -56,32 +58,37 @@ private:
|
||||
PacketID m_PreviousPacketID = 0;
|
||||
|
||||
// Private member functions
|
||||
void addChildrenToPacket(Packet& packet, EntityID entityID);
|
||||
void broadcast(Packet& packet);
|
||||
void checkForTimeOuts();
|
||||
void disconnect(PlayerID playerID);
|
||||
void identifyPacketLoss();
|
||||
void kick(PlayerID player);
|
||||
int receive(char* data);
|
||||
void readFromClients();
|
||||
void send(Packet& packet, UserID user);
|
||||
void send(PlayerID player, Packet& packet);
|
||||
void send(PlayerID playerID, Packet& packet);
|
||||
void send(Packet& packet);
|
||||
void broadcast(Packet& packet);
|
||||
void sendSnapshot();
|
||||
void sendPing();
|
||||
void checkForTimeOuts();
|
||||
void disconnect(UserID user);
|
||||
void parseClientPing(PlayerID playerID);
|
||||
void parseConnect(Packet& packet, PlayerID playerID);
|
||||
void parseDisconnect();
|
||||
void parseMessageType(Packet& packet);
|
||||
void parseOnInputCommand(Packet& packet);
|
||||
void parseOnPlayerDamage(Packet& packet);
|
||||
void parseConnect(Packet& packet);
|
||||
void parseDisconnect();
|
||||
void parseClientPing();
|
||||
void parsePing();
|
||||
void identifyPacketLoss();
|
||||
void createPlayer();
|
||||
void kick(PlayerID player);
|
||||
|
||||
PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
|
||||
// Debug event
|
||||
EventRelay<Server, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
EventRelay<Server, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||
EventRelay<Server, Events::EntityDeleted> m_EEntityDeleted;
|
||||
bool OnEntityDeleted(const Events::EntityDeleted& e);
|
||||
EventRelay<Server, Events::ComponentDeleted> m_EComponentDeleted;
|
||||
bool OnComponentDeleted(const Events::ComponentDeleted& e);
|
||||
void parsePlayerTransform(Packet& packet);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef Model_h__
|
||||
#define Model_h__
|
||||
|
||||
#include "RawModel.h"
|
||||
#include "Rendering/RawModelCustom.h"
|
||||
//#include "Rendering/RawModelAssimp.h"
|
||||
#include "../OpenGL.h"
|
||||
|
||||
class Model : public ThreadUnsafeResource
|
||||
@@ -19,12 +20,11 @@ public:
|
||||
|
||||
GLuint VAO;
|
||||
GLuint ElementBuffer;
|
||||
RawModel* m_RawModel;
|
||||
|
||||
private:
|
||||
RawModel* m_RawModel;
|
||||
|
||||
GLuint VertexBuffer;
|
||||
GLuint DiffuseVertexColorBuffer;
|
||||
GLuint SpecularVertexColorBuffer;
|
||||
GLuint NormalBuffer;
|
||||
GLuint TangentNormalsBuffer;
|
||||
GLuint BiTangentNormalsBuffer;
|
||||
|
||||
@@ -24,6 +24,10 @@ struct ModelJob : RenderJob
|
||||
DiffuseTexture = matGroup.Texture.get();
|
||||
NormalTexture = matGroup.NormalMap.get();
|
||||
SpecularTexture = matGroup.SpecularMap.get();
|
||||
IncandescenceTexture = matGroup.IncandescenceMap.get();
|
||||
DiffuseColor = matGroup.DiffuseColor;
|
||||
SpecularColor = matGroup.SpecularColor;
|
||||
IncandescenceColor = matGroup.IncandescenceColor;
|
||||
StartIndex = matGroup.StartIndex;
|
||||
EndIndex = matGroup.EndIndex;
|
||||
Matrix = matrix;
|
||||
@@ -43,9 +47,13 @@ struct ModelJob : RenderJob
|
||||
const Texture* DiffuseTexture;
|
||||
const Texture* NormalTexture;
|
||||
const Texture* SpecularTexture;
|
||||
const Texture* IncandescenceTexture;
|
||||
float Shininess = 0.f;
|
||||
glm::vec4 Color;
|
||||
const ::Model* Model = nullptr;
|
||||
glm::vec4 DiffuseColor;
|
||||
glm::vec4 SpecularColor;
|
||||
glm::vec4 IncandescenceColor;
|
||||
unsigned int StartIndex = 0;
|
||||
unsigned int EndIndex = 0;
|
||||
World* World;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef RawModel_h__
|
||||
#define RawModel_h__
|
||||
#ifndef RawModelAssimp_h__
|
||||
#define RawModelAssimp_h__
|
||||
|
||||
#ifdef USING_ASSIMP_AS_IMPORTER
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -18,29 +20,27 @@
|
||||
#include "Texture.h"
|
||||
#include "Skeleton.h"
|
||||
|
||||
class RawModel : public Resource
|
||||
#define RawModel RawModelAssimp
|
||||
|
||||
class RawModelAssimp : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
protected:
|
||||
RawModel(std::string fileName);
|
||||
RawModelAssimp(std::string fileName);
|
||||
|
||||
public:
|
||||
~RawModel();
|
||||
~RawModelAssimp();
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec3 Position;
|
||||
glm::vec3 Normal;
|
||||
glm::vec3 Tangent;
|
||||
glm::vec3 BiTangent;
|
||||
glm::vec3 BiNormal;
|
||||
glm::vec2 TextureCoords;
|
||||
glm::vec4 DiffuseVertexColor;
|
||||
glm::vec4 SpecularVertexColor;
|
||||
glm::vec4 BoneIndices1;
|
||||
glm::vec4 BoneIndices2;
|
||||
glm::vec4 BoneWeights1;
|
||||
glm::vec4 BoneWeights2;
|
||||
glm::vec4 BoneIndices;
|
||||
glm::vec4 BoneWeights;
|
||||
};
|
||||
|
||||
struct MaterialGroup
|
||||
@@ -68,8 +68,6 @@ private:
|
||||
std::vector<glm::ivec2> BoneIndices;
|
||||
std::vector<glm::vec2> BoneWeights;
|
||||
std::vector<glm::vec3> Normals;
|
||||
std::vector<glm::vec4> DiffuseVertexColor;
|
||||
std::vector<glm::vec4> SpecularVertexColor;
|
||||
std::vector<glm::vec3> TangentNormals;
|
||||
std::vector<glm::vec3> BiTangentNormals;
|
||||
std::vector<glm::vec2> TextureCoords;
|
||||
@@ -78,3 +76,4 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef RawModelCustom_h__
|
||||
#define RawModelCustom_h__
|
||||
|
||||
#ifndef USING_ASSIMP_AS_IMPORTER
|
||||
|
||||
#define RawModel RawModelCustom
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <stack>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../GLM.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "Texture.h"
|
||||
#include "Skeleton.h"
|
||||
|
||||
#include "boost\endian\buffers.hpp"
|
||||
|
||||
|
||||
|
||||
class RawModelCustom : public Resource
|
||||
{
|
||||
friend class ResourceManager;
|
||||
|
||||
protected:
|
||||
RawModelCustom(std::string fileName);
|
||||
|
||||
public:
|
||||
~RawModelCustom();
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec3 Position;
|
||||
glm::vec3 Normal;
|
||||
glm::vec3 Tangent;
|
||||
glm::vec3 BiNormal;
|
||||
glm::vec2 TextureCoords;
|
||||
glm::vec4 BoneIndices;
|
||||
glm::vec4 BoneWeights;
|
||||
};
|
||||
|
||||
struct MaterialGroup
|
||||
{
|
||||
float SpecularExponent;
|
||||
float ReflectionFactor;
|
||||
glm::vec4 DiffuseColor{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glm::vec4 SpecularColor{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glm::vec4 IncandescenceColor{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
unsigned int StartIndex;
|
||||
unsigned int EndIndex;
|
||||
//float Transparency;
|
||||
std::string TexturePath;
|
||||
std::shared_ptr<::Texture> Texture;
|
||||
std::string NormalMapPath;
|
||||
std::shared_ptr<::Texture> NormalMap;
|
||||
std::string SpecularMapPath;
|
||||
std::shared_ptr<::Texture> SpecularMap;
|
||||
std::string IncandescenceMapPath;
|
||||
std::shared_ptr<::Texture> IncandescenceMap;
|
||||
};
|
||||
|
||||
std::vector<MaterialGroup> MaterialGroups;
|
||||
|
||||
std::vector<Vertex> m_Vertices;
|
||||
std::vector<unsigned int> m_Indices;
|
||||
Skeleton* m_Skeleton = nullptr;
|
||||
glm::mat4 m_Matrix;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void ReadMeshFile(std::string filePath);
|
||||
void ReadMeshFileHeader(unsigned int& offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadMesh(unsigned int& offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadVertices(unsigned int& offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadIndices(unsigned int& offset, char* fileData, unsigned int& fileByteSize);
|
||||
|
||||
void ReadMaterialFile(std::string filePath);
|
||||
void ReadMaterials(unsigned int &offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadMaterialSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize);
|
||||
|
||||
void ReadAnimationFile(std::string filePath);
|
||||
void ReadAnimationBindPoses(unsigned int &offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadAnimationJoint(unsigned int &offset, char* fileData, unsigned int& fileByteSize);
|
||||
void ReadAnimationClips(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfClips);
|
||||
void ReadAnimationClipSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int clipIndex);
|
||||
void ReadAnimationKeyFrame(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfJoints, Skeleton::Animation& animation);
|
||||
|
||||
//void CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &boneInfo, std::map<std::string, int> &boneNameMapping, aiNode* node, int parentID);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include "RawModelAssimp.h"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <sstream>
|
||||
#include "Common.h"
|
||||
#include "../GLM.h"
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
|
||||
//struct Bone
|
||||
//{
|
||||
@@ -38,9 +39,9 @@ public:
|
||||
, OffsetMatrix(offsetMatrix)
|
||||
{ }
|
||||
|
||||
int ID;
|
||||
std::string Name;
|
||||
glm::mat4 OffsetMatrix;
|
||||
int ID;
|
||||
|
||||
Bone* Parent;
|
||||
std::vector<Bone*> Children;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Core/System.h"
|
||||
#include "Core/EPlayerDamage.h"
|
||||
#include "Core/EShoot.h"
|
||||
#include "Core/EPlayerSpawned.h"
|
||||
#include "Input/EInputCommand.h"
|
||||
|
||||
#include <tuple>
|
||||
@@ -23,16 +24,18 @@ public:
|
||||
virtual void Update(double dt) override;
|
||||
|
||||
private:
|
||||
//methods which will take care of specific events
|
||||
EventRelay<WeaponSystem, Events::Shoot> m_EShoot;
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& e);
|
||||
|
||||
EventRelay<WeaponSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e);
|
||||
|
||||
IRenderer* m_Renderer;
|
||||
|
||||
std::vector<std::tuple<EntityID, glm::vec2>> m_EShootVector;
|
||||
// State
|
||||
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
|
||||
|
||||
// Events
|
||||
EventRelay<WeaponSystem, Events::PlayerSpawned> m_EPlayerSpawned;
|
||||
bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e);
|
||||
EventRelay<WeaponSystem, Events::Shoot> m_EShoot;
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& e);
|
||||
EventRelay<WeaponSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -21,4 +21,5 @@ F1=ToggleEditor
|
||||
X=EditorToggleTransformSpace
|
||||
C=ConnectToServer
|
||||
N=SwitchToServer
|
||||
M=SwitchToClient
|
||||
M=SwitchToClient
|
||||
P=SwitchToPlayer
|
||||
@@ -0,0 +1,273 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Camera/>
|
||||
<c:Listener/>
|
||||
<c:Transform>
|
||||
<Position X="4.52910185" Y="5.50171423" Z="7.69566345"/>
|
||||
<Orientation X="-0.453785568" Y="0.436270237" Z="-1.03594937e-06"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/dummyscene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="-0" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/animtest.</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-0.0966923237" Y="1.2939688" Z="0.399702221"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/animTest.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="1.31816244" Z="1.1888907"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/animTest.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0.708824873" Y="1.30000007" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/animTest.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="1.36948848" Y="1.20000005" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:DirectionalLight>
|
||||
<Intensity>0.13000047206878662</Intensity>
|
||||
</c:DirectionalLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="2.77622533" Z="0"/>
|
||||
<Orientation X="0" Y="1.30900002" Z="1.73600006"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:RaptorCopter>
|
||||
<Speed>0.30000001192092896</Speed>
|
||||
<Axis X="0" Y="5" Z="0"/>
|
||||
</c:RaptorCopter>
|
||||
<c:Transform>
|
||||
<Orientation X="117.03714" Y="3023.50244" Z="3.03297734"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="1" Z="1.29999995"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0" G="1" R="0"/>
|
||||
<Radius>5</Radius>
|
||||
<Intensity>0.80000001192092896</Intensity>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="1" Z="-1.29999995"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="1" G="0" R="0.478431374"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="-1.30000007" Y="1" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="1.29999995" Y="1" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:RaptorCopter>
|
||||
<Speed>0.50999981164932251</Speed>
|
||||
<Axis X="0" Y="1" Z="0"/>
|
||||
</c:RaptorCopter>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="-0.100000001" Z="0"/>
|
||||
<Orientation X="0" Y="191.457993" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0.301960796" G="0.0901960805" R="0.247058824"/>
|
||||
<Radius>5</Radius>
|
||||
<Intensity>5</Intensity>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="3" Z="5"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0.960784316" G="1" R="0"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="3" Z="-7.66608238"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0.00784313772" G="1" R="1"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="-3.47176075" Y="3" Z="-8.09415054"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0" G="0" R="1"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="-9.50536728" Y="2" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="1" G="0" R="1"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="3" Z="4.40877533"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0.431372553" G="0.0745098069" R="1"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="5.83008432" Y="3" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0" G="0.623529434" R="0.929411769"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="3.72500014" Y="3" Z="-4.26100016"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="3" Z="-7.50000048"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Color A="1" B="0.192156866" G="1" R="0"/>
|
||||
<Radius>5</Radius>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="-5.90153885" Y="3" Z="-5.40681458"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -41,7 +41,7 @@
|
||||
<HomePointForTeam>3</HomePointForTeam>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.200000003" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -61,7 +61,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -81,7 +81,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -102,7 +102,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -120,7 +120,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -138,7 +138,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -42,7 +42,7 @@
|
||||
<CaptureTimer>6.9158446328696002</CaptureTimer>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -63,7 +63,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -83,7 +83,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -104,7 +104,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -122,7 +122,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -140,7 +140,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -41,7 +41,7 @@
|
||||
<HomePointForTeam>3</HomePointForTeam>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.200000003" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -61,7 +61,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -79,7 +79,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -98,7 +98,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -116,7 +116,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -134,7 +134,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -41,7 +41,7 @@
|
||||
<HomePointForTeam>3</HomePointForTeam>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.200000003" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -61,7 +61,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -81,7 +81,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -101,7 +101,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -122,7 +122,7 @@
|
||||
<CapturePointNumber>4</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -140,7 +140,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -158,7 +158,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -176,7 +176,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -194,7 +194,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -41,7 +41,7 @@
|
||||
<HomePointForTeam>3</HomePointForTeam>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.200000003" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -61,7 +61,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -79,7 +79,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
<c:Transform>
|
||||
@@ -96,7 +96,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -115,7 +115,7 @@
|
||||
<CapturePointNumber>4</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -133,7 +133,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -151,7 +151,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -169,7 +169,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -187,7 +187,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<Static>false</Static>
|
||||
</c:Collidable>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/DummyScene.obj</Resource>
|
||||
<Resource>Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
@@ -17,7 +17,7 @@
|
||||
<Scale X="1" Y="1" Z="1"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
@@ -28,7 +28,7 @@
|
||||
<Scale X="2" Y="2" Z="2"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidgetX.obj</Resource>
|
||||
<Resource>Models/RotationWidgetX.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Trigger>
|
||||
</c:Trigger>
|
||||
@@ -43,7 +43,7 @@
|
||||
<Position X="2.5"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:AABB>
|
||||
</c:AABB>
|
||||
@@ -69,7 +69,7 @@
|
||||
<Orientation X="0.0" Y="0" Z="1.0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitRaptor.obj</Resource>
|
||||
<Resource>Models/Core/UnitRaptor.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
@@ -94,7 +94,7 @@
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
@@ -107,7 +107,7 @@
|
||||
<Orientation X="0" Y="1.57" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Scale X="100" Y="1" Z="100"/>
|
||||
@@ -58,7 +58,7 @@
|
||||
<Components>
|
||||
<c:DirectionalLight/>
|
||||
<c:Model>
|
||||
<Resource>Models/DirectionalLightWidget.obj</Resource>
|
||||
<Resource>Models/DirectionalLightWidget.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="2.1529963" Y="6.59221172" Z="0.169116676"/>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-2.00568962" Y="0.527161121" Z="0"/>
|
||||
@@ -94,7 +94,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="3.70000029" Z="0"/>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<Axis X="1" Y="0" Z="0"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidgetX.obj</Resource>
|
||||
<Resource>Models/RotationWidgetX.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -33,7 +33,7 @@
|
||||
<Axis X="0" Y="1" Z="0"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidgetY.obj</Resource>
|
||||
<Resource>Models/RotationWidgetY.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -48,7 +48,7 @@
|
||||
<Axis X="0" Y="0" Z="1"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/RotationWidgetZ.obj</Resource>
|
||||
<Resource>Models/RotationWidgetZ.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/ScaleWidgetOrigin.obj</Resource>
|
||||
<Resource>Models/ScaleWidgetOrigin.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
<c:UniformScale>
|
||||
@@ -20,7 +20,7 @@
|
||||
</Type>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/ScaleWidgetX.obj</Resource>
|
||||
<Resource>Models/ScaleWidgetX.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -34,7 +34,7 @@
|
||||
</Type>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/ScaleWidgetY.obj</Resource>
|
||||
<Resource>Models/ScaleWidgetY.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -48,7 +48,7 @@
|
||||
</Type>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/ScaleWidgetZ.obj</Resource>
|
||||
<Resource>Models/ScaleWidgetZ.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/TranslationWidgetOrigin.obj</Resource>
|
||||
<Resource>Models/TranslationWidgetOrigin.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
<c:UniformScale>
|
||||
@@ -18,7 +18,7 @@
|
||||
<Axis X="1" Y="0" Z="0"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/TranslationWidgetX.obj</Resource>
|
||||
<Resource>Models/TranslationWidgetX.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -30,7 +30,7 @@
|
||||
<Axis X="0" Y="1" Z="0"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/TranslationWidgetY.obj</Resource>
|
||||
<Resource>Models/TranslationWidgetY.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -42,7 +42,7 @@
|
||||
<Axis X="0" Y="0" Z="1"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/TranslationWidgetZ.obj</Resource>
|
||||
<Resource>Models/TranslationWidgetZ.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -54,7 +54,7 @@
|
||||
<Axis X="0" Y="1" Z="1"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/WidgetPlaneX.obj</Resource>
|
||||
<Resource>Models/WidgetPlaneX.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -66,7 +66,7 @@
|
||||
<Axis X="1" Y="0" Z="1"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/WidgetPlaneY.obj</Resource>
|
||||
<Resource>Models/WidgetPlaneY.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -78,7 +78,7 @@
|
||||
<Axis X="1" Y="1" Z="0"/>
|
||||
</c:EditorWidget>
|
||||
<c:Model>
|
||||
<Resource>Models/WidgetPlaneZ.obj</Resource>
|
||||
<Resource>Models/WidgetPlaneZ.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children/>
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource></Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children>
|
||||
<Entity name="Scenemesh">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models\MapVersion1.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="DirectionalLight">
|
||||
<Components>
|
||||
<c:DirectionalLight>
|
||||
<Intensity>2</Intensity>
|
||||
</c:DirectionalLight>
|
||||
<c:Model>
|
||||
<Resource>Models/DirectionalLightWidget.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="61.9050903" Z="0"/>
|
||||
<Scale X="50" Y="50" Z="50"/>
|
||||
<Orientation X="4.42700005" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="PointLight">
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Radius>8</Radius>
|
||||
<Intensity>2.7999999523162842</Intensity>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0.370978802" Y="1.88588905" Z="-0.55370003"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity name="PointLight">
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Radius>8</Radius>
|
||||
<Intensity>2.7999999523162842</Intensity>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="38.0347443" Y="1.88588905" Z="62.7340622"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-0.904668212" Y="0" Z="8.48177528"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-4.61666441" Y="0" Z="-8.51156044"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-7.56803513" Y="-0.0658408776" Z="0.59418112"/>
|
||||
<Scale X="1.20000005" Y="0.900000036" Z="1.30000007"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="10.460474" Y="0" Z="-3.92580295"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="1.09146011" Y="-0.315138876" Z="-0.333906144"/>
|
||||
<Scale X="150" Y="1" Z="180"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
|
||||
<Children>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Camera/>
|
||||
<c:Listener/>
|
||||
<c:Transform>
|
||||
<Orientation X="0" Y="-0" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>models/animTest.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
<Children/>
|
||||
</Entity>
|
||||
</Children>
|
||||
|
||||
</Entity>
|
||||
@@ -11,7 +11,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.513725519" G="0" R="1"/>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
@@ -42,7 +42,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="1"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -55,7 +55,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
<Color A="1" B="0.0117647061" G="0" R="1"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -70,7 +70,7 @@
|
||||
<Components>
|
||||
<c:DirectionalLight/>
|
||||
<c:Model>
|
||||
<Resource>Models/DirectionalLightWidget.obj</Resource>
|
||||
<Resource>Models/DirectionalLightWidget.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-6.00145912" Y="1.42697716" Z="3.04144025"/>
|
||||
@@ -82,7 +82,7 @@
|
||||
<Entity name="ObstacleCourse">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Test/ObstacleCourse.obj</Resource>
|
||||
<Resource>Models/Test/ObstacleCourse.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -93,7 +93,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -108,7 +108,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -123,7 +123,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -154,7 +154,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.254901975" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -167,7 +167,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.254901975" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<c:AABB/>
|
||||
<c:Collidable/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -27,7 +27,7 @@
|
||||
<Static>false</Static>
|
||||
</c:Collidable>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="1"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -42,7 +42,7 @@
|
||||
<Static>false</Static>
|
||||
</c:Collidable>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
</c:AABB>
|
||||
<c:Collidable/>
|
||||
<c:Model/>
|
||||
<c:Physics>
|
||||
<Velocity X="8.33307467e-09" Y="0" Z="9.82836834e-09"/>
|
||||
</c:Physics>
|
||||
<c:Physics/>
|
||||
<c:Player>
|
||||
<MovementSpeed>5</MovementSpeed>
|
||||
</c:Player>
|
||||
@@ -20,7 +18,7 @@
|
||||
</Team>
|
||||
</c:Team>
|
||||
<c:Transform>
|
||||
<Position X="2.84928203" Y="0.0264999866" Z="7.31610918"/>
|
||||
<Position X="-0.246963501" Y="0.0265000071" Z="3.01600003"/>
|
||||
<Orientation X="0" Y="2.14675093" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
@@ -31,7 +29,6 @@
|
||||
<c:Camera/>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="1.37700009" Z="0"/>
|
||||
<Orientation X="0.921535373" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
<Children>
|
||||
@@ -53,7 +50,7 @@
|
||||
<Entity name="CameraModel">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Camera.obj</Resource>
|
||||
<Resource>Models/Camera.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.0331346765" Z="-0.0792061687"/>
|
||||
@@ -68,7 +65,7 @@
|
||||
<Components>
|
||||
<c:Camera/>
|
||||
<c:Model>
|
||||
<Resource>Models/Camera.obj</Resource>
|
||||
<Resource>Models/Camera.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -81,7 +78,8 @@
|
||||
<Entity name="PlayerModel">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/AssaultHeadless.obj</Resource>
|
||||
<Resource>Models/AssaultHeadless.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="1"/>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Orientation X="0" Y="3.14159274" Z="0"/>
|
||||
@@ -92,7 +90,7 @@
|
||||
<Entity name="AABBStanding">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="0.427450985" B="1" G="1" R="1"/>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
@@ -106,7 +104,7 @@
|
||||
<Entity name="AABBCrouching">
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="0.745098054" B="1" G="0" R="1"/>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<Entity name="PointLight" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
|
||||
|
||||
<Components>
|
||||
<c:PointLight>
|
||||
<Radius>8</Radius>
|
||||
<Intensity>2.7999999523162842</Intensity>
|
||||
</c:PointLight>
|
||||
<c:Transform>
|
||||
<Position X="0.370978802" Y="1.88588905" Z="-0.55370003"/>
|
||||
</c:Transform>
|
||||
</Components>
|
||||
|
||||
<Children/>
|
||||
|
||||
</Entity>
|
||||
@@ -7,7 +7,7 @@
|
||||
<Orientation X="0.0" Y="0" Z="0.0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitRaptor.obj</Resource>
|
||||
<Resource>Models/Core/UnitRaptor.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
@@ -31,7 +31,7 @@
|
||||
<Scale X="0.1" Y="0.4" Z="0.1"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCylinder.obj</Resource>
|
||||
<Resource>Models/Core/UnitCylinder.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
@@ -44,7 +44,7 @@
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
@@ -57,7 +57,7 @@
|
||||
<Orientation X="0" Y="1.57" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color R="1" G="0.4" B="0.8"/>
|
||||
</c:Model>
|
||||
</Components>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Name>ActionCamera</Name>
|
||||
</c:Camera>
|
||||
<c:Model>
|
||||
<Resource>Models/Camera.obj</Resource>
|
||||
<Resource>Models/Camera.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-0.504807115" Y="6.00582743" Z="9.68687439"/>
|
||||
@@ -39,7 +39,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitPlane.obj</Resource>
|
||||
<Resource>Models/Core/UnitPlane.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="-1" Z="0.600000024"/>
|
||||
@@ -51,7 +51,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-2.5" Y="0" Z="1"/>
|
||||
@@ -190,7 +190,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Assault.obj</Resource>
|
||||
<Resource>Models/Assault.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="2.5" Y="0" Z="1"/>
|
||||
@@ -205,7 +205,7 @@
|
||||
</c:Camera>
|
||||
<c:Listener/>
|
||||
<c:Model>
|
||||
<Resource>Models/Camera.obj</Resource>
|
||||
<Resource>Models/Camera.mesh</Resource>
|
||||
<Visible>false</Visible>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
@@ -237,7 +237,7 @@
|
||||
<Intensity>0.80000001192092896</Intensity>
|
||||
</c:DirectionalLight>
|
||||
<c:Model>
|
||||
<Resource>Models/DirectionalLightWidget.obj</Resource>
|
||||
<Resource>Models/DirectionalLightWidget.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-0.0013256073" Y="1.89540339" Z="6.53467274"/>
|
||||
@@ -249,7 +249,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="-5.4082036" Y="0" Z="-1.84950542"/>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/DummyScene.obj</Resource>
|
||||
<Resource>../assets/Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
</Components>
|
||||
@@ -41,7 +41,7 @@
|
||||
<HomePointForTeam>3</HomePointForTeam>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.200000003" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -61,7 +61,7 @@
|
||||
<CapturePointNumber>1</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="1" G="1" R="0"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -79,7 +79,7 @@
|
||||
<CapturePointNumber>2</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
<c:Transform>
|
||||
@@ -96,7 +96,7 @@
|
||||
<CapturePointNumber>3</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="1" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team/>
|
||||
@@ -115,7 +115,7 @@
|
||||
<CapturePointNumber>4</CapturePointNumber>
|
||||
</c:CapturePoint>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitSphere.mesh</Resource>
|
||||
<Color A="1" B="0" G="0.200000003" R="1"/>
|
||||
</c:Model>
|
||||
<c:Team>
|
||||
@@ -133,7 +133,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -151,7 +151,7 @@
|
||||
<c:Health/>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -171,7 +171,7 @@
|
||||
</c:Health>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="2.25"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
@@ -191,7 +191,7 @@
|
||||
</c:Health>
|
||||
<c:AABB/>
|
||||
<c:Model>
|
||||
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>../assets/Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="0" G="0" R="4.5"/>
|
||||
</c:Model>
|
||||
<c:Player/>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<FilePath></FilePath>
|
||||
</c:SoundEmitter>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
<Resource>Models/Core/UnitCube.mesh</Resource>
|
||||
<Color A="1" B="1" G="0.58431375" R="0.43921569"/>
|
||||
</c:Model>
|
||||
<c:Transform/>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0" Z="1.26689196"/>
|
||||
@@ -37,7 +37,7 @@
|
||||
<Components>
|
||||
<c:SpawnPoint/>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitSphere.obj</Resource>
|
||||
<Resource>Models/Core/UnitSphere.mesh</Resource>
|
||||
</c:Model>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0" Z="-1.14786315"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/DummyScene.obj</Resource>
|
||||
<Resource>Models/DummyScene.mesh</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
@@ -19,7 +19,7 @@
|
||||
<c:Camera>
|
||||
</c:Camera>
|
||||
<c:Model>
|
||||
<Resource>Models/Camera.obj</Resource>
|
||||
<Resource>Models/Camera.mesh</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
|
||||
@@ -9,18 +9,14 @@ layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec3 Tangent;
|
||||
layout(location = 3) in vec3 BiTangent;
|
||||
layout(location = 4) in vec2 TextureCoords;
|
||||
layout(location = 5) in vec4 DiffuseVertexColor;
|
||||
layout(location = 6) in vec4 SpecularVertexColor;
|
||||
layout(location = 7) in vec4 BoneIndices1;
|
||||
layout(location = 8) in vec4 BoneIndices2;
|
||||
layout(location = 9) in vec4 BoneWeights1;
|
||||
layout(location = 10) in vec4 BoneWeights2;
|
||||
layout(location = 5) in vec4 BoneIndices;
|
||||
layout(location = 6) in vec4 BoneWeights;
|
||||
|
||||
|
||||
out VertexData{
|
||||
vec3 Position;
|
||||
vec3 Normal;
|
||||
vec2 TextureCoordinate;
|
||||
vec4 DiffuseColor;
|
||||
}Output;
|
||||
|
||||
void main()
|
||||
@@ -30,5 +26,4 @@ void main()
|
||||
Output.Position = Position;
|
||||
Output.TextureCoordinate = TextureCoords;
|
||||
Output.Normal = Normal;
|
||||
Output.DiffuseColor = DiffuseVertexColor;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ uniform mat4 M;
|
||||
uniform mat4 V;
|
||||
uniform mat4 P;
|
||||
uniform vec4 Color;
|
||||
uniform vec4 DiffuseColor;
|
||||
uniform vec2 ScreenDimensions;
|
||||
layout (binding = 0) uniform sampler2D DiffuseTexture;
|
||||
layout (binding = 1) uniform sampler2D GlowMap;
|
||||
@@ -46,7 +47,6 @@ in VertexData{
|
||||
vec3 Position;
|
||||
vec3 Normal;
|
||||
vec2 TextureCoordinate;
|
||||
vec4 DiffuseColor;
|
||||
}Input;
|
||||
|
||||
out vec4 sceneColor;
|
||||
@@ -135,7 +135,7 @@ void main()
|
||||
}
|
||||
|
||||
//sceneColor += Input.DiffuseColor;
|
||||
vec4 color_result = Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * diffuseTexel * Color;
|
||||
vec4 color_result = DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * diffuseTexel * Color;
|
||||
//bloomColor = vec4(0.3, 0.8, 0.6, 1.0);
|
||||
sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1));
|
||||
//These if statements should be removed if they are slow.
|
||||
|
||||
@@ -3,32 +3,37 @@
|
||||
uniform mat4 M;
|
||||
uniform mat4 V;
|
||||
uniform mat4 P;
|
||||
uniform mat4 Bones[100];
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec3 Normal;
|
||||
layout(location = 2) in vec3 Tangent;
|
||||
layout(location = 3) in vec3 BiTangent;
|
||||
layout(location = 4) in vec2 TextureCoords;
|
||||
layout(location = 5) in vec4 DiffuseVertexColor;
|
||||
layout(location = 6) in vec4 SpecularVertexColor;
|
||||
layout(location = 7) in vec4 BoneIndices1;
|
||||
layout(location = 8) in vec4 BoneIndices2;
|
||||
layout(location = 9) in vec4 BoneWeights1;
|
||||
layout(location = 10) in vec4 BoneWeights2;
|
||||
layout(location = 5) in vec4 BoneIndices;
|
||||
layout(location = 6) in vec4 BoneWeights;
|
||||
|
||||
out VertexData{
|
||||
vec3 Position;
|
||||
vec3 Normal;
|
||||
vec2 TextureCoordinate;
|
||||
vec4 DiffuseColor;
|
||||
}Output;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = P*V*M * vec4(Position, 1.0);
|
||||
|
||||
Output.Position = Position;
|
||||
|
||||
mat4 boneTransform = mat4(1);
|
||||
if(BoneWeights[0] > 0.0f){
|
||||
boneTransform = BoneWeights[0] * Bones[int(BoneIndices[0])]
|
||||
+ BoneWeights[1] * Bones[int(BoneIndices[1])]
|
||||
+ BoneWeights[2] * Bones[int(BoneIndices[2])]
|
||||
+ BoneWeights[3] * Bones[int(BoneIndices[3])];
|
||||
}
|
||||
|
||||
gl_Position = P*V*M*boneTransform * vec4(Position, 1.0);
|
||||
|
||||
Output.Position = (boneTransform * vec4(Position, 1.0)).xyz;
|
||||
Output.TextureCoordinate = TextureCoords;
|
||||
Output.Normal = vec3(M * vec4(Normal, 0.0));
|
||||
Output.DiffuseColor = DiffuseVertexColor;
|
||||
}
|
||||
@@ -36,6 +36,18 @@ EntityWrapper EntityWrapper::FirstChildByName(const std::string& name)
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& componentType)
|
||||
{
|
||||
EntityWrapper entity = *this;
|
||||
while (entity.Parent().Valid()) {
|
||||
entity = entity.Parent();
|
||||
if (entity.HasComponent(componentType)) {
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return EntityWrapper::Invalid;
|
||||
}
|
||||
|
||||
bool EntityWrapper::IsChildOf(EntityWrapper potentialParent)
|
||||
{
|
||||
EntityWrapper entity = *this;
|
||||
|
||||
+66
-32
@@ -1,4 +1,6 @@
|
||||
#include "Core/World.h"
|
||||
#include "Core/EEntityDeleted.h"
|
||||
#include "Core/EComponentDeleted.h"
|
||||
|
||||
World::~World()
|
||||
{
|
||||
@@ -21,37 +23,7 @@ EntityID World::CreateEntity(EntityID parent /*= 0*/)
|
||||
|
||||
void World::DeleteEntity(EntityID entity)
|
||||
{
|
||||
// Delete components
|
||||
for (auto& pair : m_ComponentPools) {
|
||||
auto& pool = pair.second;
|
||||
if (pool->KnowsEntity(entity)) {
|
||||
auto& c = pool->GetByEntity(entity);
|
||||
pool->Delete(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through children
|
||||
std::vector<EntityID> childrenToDelete;
|
||||
auto children = m_EntityChildren.equal_range(entity);
|
||||
for (auto it = children.first; it != children.second; ++it) {
|
||||
childrenToDelete.push_back(it->second);
|
||||
}
|
||||
for (auto& child : childrenToDelete) {
|
||||
DeleteEntity(child);
|
||||
}
|
||||
|
||||
EntityID parent = m_EntityParents.at(entity);
|
||||
m_EntityParents.erase(entity);
|
||||
auto parentChildren = m_EntityChildren.equal_range(parent);
|
||||
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
||||
if (it->second == entity) {
|
||||
m_EntityChildren.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase potential name
|
||||
m_EntityNames.erase(entity);
|
||||
deleteEntityRecursive(entity, false);
|
||||
}
|
||||
|
||||
bool World::ValidEntity(EntityID entity) const
|
||||
@@ -96,7 +68,15 @@ void World::DeleteComponent(EntityID entity, const std::string& componentType)
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
ComponentWrapper c = pool->GetByEntity(entity);
|
||||
return pool->Delete(c);
|
||||
pool->Delete(c);
|
||||
|
||||
if (m_EventBroker != nullptr) {
|
||||
Events::ComponentDeleted e;
|
||||
e.Entity = entity;
|
||||
e.ComponentType = componentType;
|
||||
e.Cascaded = false;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
|
||||
const ComponentPool* World::GetComponents(const std::string& componentType)
|
||||
@@ -155,3 +135,57 @@ EntityID World::generateEntityID()
|
||||
return m_CurrentEntityID++;
|
||||
}
|
||||
|
||||
void World::deleteEntityRecursive(EntityID entity, bool cascaded /*= false*/)
|
||||
{
|
||||
// Don't attempt to delete entities that don't exist anyway
|
||||
if (!ValidEntity(entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_EventBroker != nullptr) {
|
||||
Events::EntityDeleted e;
|
||||
e.DeletedEntity = entity;
|
||||
e.Cascaded = cascaded;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
// Delete components
|
||||
for (auto& pair : m_ComponentPools) {
|
||||
auto& pool = pair.second;
|
||||
if (pool->KnowsEntity(entity)) {
|
||||
auto& c = pool->GetByEntity(entity);
|
||||
pool->Delete(c);
|
||||
if (m_EventBroker != nullptr) {
|
||||
Events::ComponentDeleted e;
|
||||
e.Entity = entity;
|
||||
e.ComponentType = pair.first;
|
||||
e.Cascaded = true;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through children
|
||||
std::vector<EntityID> childrenToDelete;
|
||||
auto children = m_EntityChildren.equal_range(entity);
|
||||
for (auto it = children.first; it != children.second; ++it) {
|
||||
childrenToDelete.push_back(it->second);
|
||||
}
|
||||
for (auto& child : childrenToDelete) {
|
||||
deleteEntityRecursive(child, true);
|
||||
}
|
||||
|
||||
EntityID parent = m_EntityParents.at(entity);
|
||||
m_EntityParents.erase(entity);
|
||||
auto parentChildren = m_EntityChildren.equal_range(parent);
|
||||
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
||||
if (it->second == entity) {
|
||||
m_EntityChildren.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Erase potential name
|
||||
m_EntityNames.erase(entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ void EditorRenderSystem::Update(double dt)
|
||||
continue;
|
||||
} catch (const std::exception&) {
|
||||
try {
|
||||
model = ResourceManager::Load<::Model>("Models/Core/Error.obj");
|
||||
model = ResourceManager::Load<::Model>("Models/Core/Error.mesh");
|
||||
} catch (const std::exception&) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+136
-71
@@ -7,13 +7,13 @@ Client::Client(ConfigFile* config) : m_Socket(m_IOService)
|
||||
{
|
||||
Network::initialize();
|
||||
|
||||
// Asumes root node is EntityID 0
|
||||
insertIntoServerClientMaps(0, 0);
|
||||
// Asumes root node is EntityID_Invalid
|
||||
insertIntoServerClientMaps(EntityID_Invalid, EntityID_Invalid);
|
||||
// Init timer
|
||||
m_TimeSinceSentInputs = std::clock();
|
||||
// Default is local host
|
||||
std::string address = config->Get<std::string>("Networking.Address", "127.0.0.1");
|
||||
int port = config->Get<int>("Networking.Port", 13);
|
||||
int port = config->Get<int>("Networking.Port", 27666);
|
||||
m_ReceiverEndpoint = udp::endpoint(boost::asio::ip::address::from_string(address), port);
|
||||
// Set up network stream
|
||||
m_PlayerName = config->Get<std::string>("Networking.Name", "Raptorcopter");
|
||||
@@ -31,7 +31,8 @@ void Client::Start(World* world, EventBroker* eventBroker)
|
||||
|
||||
// Subscribe to events
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Client::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayeDamage, &Client::OnPlayerDamage);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerDamage, &Client::OnPlayerDamage);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Client::OnPlayerSpawned);
|
||||
|
||||
m_Socket.connect(m_ReceiverEndpoint);
|
||||
LOG_INFO("I am client. BIP BOP");
|
||||
@@ -48,6 +49,7 @@ void Client::Update()
|
||||
sendInputCommands();
|
||||
m_TimeSinceSentInputs = std::clock();
|
||||
}
|
||||
sendLocalPlayerTransform();
|
||||
}
|
||||
Network::Update();
|
||||
}
|
||||
@@ -96,6 +98,12 @@ void Client::parseMessageType(Packet& packet)
|
||||
case MessageType::OnPlayerSpawned:
|
||||
parsePlayersSpawned(packet);
|
||||
break;
|
||||
case MessageType::EntityDeleted:
|
||||
parseEntityDeletion(packet);
|
||||
break;
|
||||
case MessageType::ComponentDeleted:
|
||||
parseComponentDeletion(packet);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -122,26 +130,49 @@ void Client::parsePing()
|
||||
LOG_INFO("%i: response time with ctime(ms): %f", m_PacketID, m_DurationOfPingTime);
|
||||
m_StartPingTime = std::clock();
|
||||
|
||||
Packet packet(MessageType::Ping, m_SendPacketID);
|
||||
Packet packet(MessageType::Ping, m_SendPacketID, m_PacketID, ackBitField);
|
||||
packet.WriteString("Ping recieved");
|
||||
send(packet);
|
||||
}
|
||||
|
||||
void Client::parseKick()
|
||||
{
|
||||
{
|
||||
LOG_WARNING("You have been kicked from the server.");
|
||||
m_IsConnected = false;
|
||||
}
|
||||
|
||||
void Client::parsePlayersSpawned(Packet& packet)
|
||||
{
|
||||
{
|
||||
Events::PlayerSpawned e;
|
||||
e.Player = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||
e.Spawner = EntityWrapper(m_World, m_ServerIDToClientID[packet.ReadPrimitive<EntityID>()]);
|
||||
e.PlayerID = -1;
|
||||
e.PlayerName = packet.ReadString();
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
void Client::parseEntityDeletion(Packet & packet)
|
||||
{
|
||||
EntityID entityToDelete = packet.ReadPrimitive<EntityID>();
|
||||
// TODO: What if an entity that didn't previously exist comes as a delete request and later comes in a delayed snapshot?
|
||||
if (m_ServerIDToClientID.find(entityToDelete) != m_ServerIDToClientID.end()) {
|
||||
EntityID localEntity = m_ServerIDToClientID.at(entityToDelete);
|
||||
if (m_World->ValidEntity(localEntity)) {
|
||||
m_World->DeleteEntity(localEntity);
|
||||
deleteFromServerClientMaps(entityToDelete, localEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::parseComponentDeletion(Packet & packet)
|
||||
{
|
||||
EntityID entity = packet.ReadPrimitive<EntityID>();
|
||||
std::string componentType = packet.ReadString();
|
||||
if (m_World->HasComponent(entity, componentType)) {
|
||||
m_World->DeleteComponent(m_ServerIDToClientID.at(entity), componentType);
|
||||
}
|
||||
}
|
||||
|
||||
// Fields with strings will not work right now
|
||||
void Client::InterpolateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType)
|
||||
{
|
||||
@@ -176,66 +207,53 @@ void Client::updateFields(Packet& packet, const ComponentInfo& componentInfo, co
|
||||
|
||||
void Client::parseSnapshot(Packet& packet)
|
||||
{
|
||||
std::string componentType = packet.ReadString();
|
||||
while (packet.DataReadSize() < packet.Size()) {
|
||||
// HACK
|
||||
std::string entityName = packet.ReadString();
|
||||
// Components EntityID
|
||||
EntityID receivedEntityID = packet.ReadPrimitive<EntityID>();
|
||||
// HACK
|
||||
m_World->SetName(receivedEntityID, entityName);
|
||||
// Parents EntityID
|
||||
EntityID receivedParentEntityID = packet.ReadPrimitive<EntityID>();
|
||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||
// Check if the received EntityID is mapped to one of our local EntityIDs
|
||||
if (serverClientMapsHasEntity(receivedEntityID)) {
|
||||
// Get the local EntityID
|
||||
EntityID entityID = m_ServerIDToClientID.at(receivedEntityID);
|
||||
// Check if the component exists
|
||||
if (m_World->HasComponent(entityID, componentType)) {
|
||||
// If the entity and the component exists update it
|
||||
if (componentType == "Transform") {
|
||||
InterpolateFields(packet, componentInfo, entityID, componentType);
|
||||
EntityID serverEntityID = packet.ReadPrimitive<EntityID>();
|
||||
EntityID serverParentID = packet.ReadPrimitive<EntityID>();
|
||||
std::string serverEntityName = packet.ReadString();
|
||||
int ammountOfComponents = packet.ReadPrimitive<int>();
|
||||
for (int i = 0; i < ammountOfComponents; i++) {
|
||||
std::string componentType = packet.ReadString();
|
||||
ComponentInfo componentInfo = m_World->GetComponents(componentType)->ComponentInfo();
|
||||
if (serverClientMapsHasEntity(serverEntityID)) {
|
||||
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||
// Update entity
|
||||
if (m_World->HasComponent(localEntityID, componentType)) {
|
||||
// Update component
|
||||
if (componentType == "Transform") {
|
||||
// Interpolate only transform components
|
||||
InterpolateFields(packet, componentInfo, localEntityID, componentType);
|
||||
} else if (componentType == "Physics" && m_World->HasComponent(localEntityID, "Player")) {
|
||||
// HACK: Ignore velocity of physics
|
||||
packet.ReadData(componentInfo.Stride);
|
||||
} else {
|
||||
// Set component values
|
||||
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||
}
|
||||
} else {
|
||||
updateFields(packet, componentInfo, entityID, componentType);
|
||||
// Has entity but no component
|
||||
m_World->AttachComponent(localEntityID, componentType);
|
||||
updateFields(packet, componentInfo, localEntityID, componentType);
|
||||
}
|
||||
// if entity exists but not the component
|
||||
} else {
|
||||
// Create component
|
||||
m_World->AttachComponent(entityID, componentType);
|
||||
// Copy data to newly created component
|
||||
updateFields(packet, componentInfo, entityID, componentType);
|
||||
// Create Entity and component
|
||||
EntityID newLocalEntityID;
|
||||
if (serverParentID == EntityID_Invalid) {
|
||||
newLocalEntityID = m_World->CreateEntity(EntityID_Invalid);
|
||||
} else {
|
||||
newLocalEntityID = m_World->CreateEntity(m_ServerIDToClientID.at(serverParentID));
|
||||
}
|
||||
m_World->SetName(newLocalEntityID, serverEntityName);
|
||||
insertIntoServerClientMaps(serverEntityID, newLocalEntityID);
|
||||
m_World->AttachComponent(newLocalEntityID, componentType);
|
||||
updateFields(packet, componentInfo, newLocalEntityID, componentType);
|
||||
}
|
||||
// If the entity dosent exist nor the component
|
||||
} else {
|
||||
// Create Entity
|
||||
// If entity dosen't exist
|
||||
EntityID newEntityID = m_World->CreateEntity();
|
||||
insertIntoServerClientMaps(receivedEntityID, newEntityID);
|
||||
// Check if EntityIDs are out of sync
|
||||
if (newEntityID != receivedEntityID) {
|
||||
LOG_INFO("Client::parseSnapshot(Packet& packet): Newly created EntityID is not the \
|
||||
same as the one sent by server (EntityIDs are out of sync)");
|
||||
}
|
||||
// Create component
|
||||
m_World->AttachComponent(newEntityID, componentType);
|
||||
// Copy data to newly created component
|
||||
updateFields(packet, componentInfo, newEntityID, componentType);
|
||||
}
|
||||
|
||||
// Parent Logic
|
||||
// Don't need to check if receivedEntityID is mapped. (It should have been set)
|
||||
if (receivedParentEntityID != std::numeric_limits<EntityID>::max()) {
|
||||
if (serverClientMapsHasEntity(receivedParentEntityID)) {
|
||||
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), m_ServerIDToClientID.at(receivedParentEntityID));
|
||||
// If Parent dosen't exist create one and map receivedParentEntityID to it.
|
||||
} else {
|
||||
// Create the new parent and add it to map
|
||||
EntityID newParentEntityID = m_World->CreateEntity();
|
||||
insertIntoServerClientMaps(receivedParentEntityID, newParentEntityID);
|
||||
// Set the newly created Entity as parent.
|
||||
m_World->SetParent(m_ServerIDToClientID.at(receivedEntityID), newParentEntityID);
|
||||
}
|
||||
// Parent logic
|
||||
// This should be enough beacause we know that the entities arives in pre-order (there will always be a parent)
|
||||
if (serverParentID != EntityID_Invalid) {
|
||||
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||
m_World->SetParent(localEntityID, m_ServerIDToClientID.at(serverParentID));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,7 +294,7 @@ void Client::send(Packet& packet)
|
||||
|
||||
void Client::connect()
|
||||
{
|
||||
Packet packet(MessageType::Connect, m_SendPacketID);
|
||||
Packet packet(MessageType::Connect, m_SendPacketID, m_PacketID, ackBitField);
|
||||
packet.WriteString(m_PlayerName);
|
||||
m_StartPingTime = std::clock();
|
||||
send(packet);
|
||||
@@ -286,7 +304,7 @@ void Client::disconnect()
|
||||
{
|
||||
m_PreviousPacketID = 0;
|
||||
m_PacketID = 0;
|
||||
Packet packet(MessageType::Disconnect, m_SendPacketID);
|
||||
Packet packet(MessageType::Disconnect, m_SendPacketID, m_PacketID, ackBitField);
|
||||
send(packet);
|
||||
}
|
||||
|
||||
@@ -326,13 +344,40 @@ bool Client::OnInputCommand(const Events::InputCommand & e)
|
||||
|
||||
bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
|
||||
{
|
||||
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
|
||||
packet.WritePrimitive(e.DamageAmount);
|
||||
packet.WritePrimitive(e.PlayerDamagedID);
|
||||
Packet packet(MessageType::OnPlayerDamage, m_SendPacketID, m_PacketID, ackBitField);
|
||||
packet.WritePrimitive(e.Damage);
|
||||
packet.WritePrimitive(e.Player.ID);
|
||||
send(packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Client::OnPlayerSpawned(const Events::PlayerSpawned& e)
|
||||
{
|
||||
if (e.PlayerID == -1) {
|
||||
m_LocalPlayer = e.Player;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::sendLocalPlayerTransform()
|
||||
{
|
||||
if (!m_LocalPlayer.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentWrapper cTransform = m_LocalPlayer["Transform"];
|
||||
glm::vec3& position = cTransform["Position"];
|
||||
glm::vec3& orientation = cTransform["Orientation"];
|
||||
Packet packet(MessageType::PlayerTransform, m_SendPacketID, m_PacketID, ackBitField);
|
||||
packet.WritePrimitive(position.x);
|
||||
packet.WritePrimitive(position.y);
|
||||
packet.WritePrimitive(position.z);
|
||||
packet.WritePrimitive(orientation.x);
|
||||
packet.WritePrimitive(orientation.y);
|
||||
packet.WritePrimitive(orientation.z);
|
||||
send(packet);
|
||||
}
|
||||
|
||||
void Client::identifyPacketLoss()
|
||||
{
|
||||
// if no packets lost, difference should be equal to 1
|
||||
@@ -360,7 +405,7 @@ EntityID Client::createPlayer()
|
||||
EntityID entityID = m_World->CreateEntity();
|
||||
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform");
|
||||
ComponentWrapper model = m_World->AttachComponent(entityID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
model["Resource"] = "Models/Core/UnitSphere.mesh";
|
||||
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
||||
return entityID;
|
||||
}
|
||||
@@ -368,7 +413,7 @@ EntityID Client::createPlayer()
|
||||
void Client::sendInputCommands()
|
||||
{
|
||||
if (m_InputCommandBuffer.size() > 0) {
|
||||
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
|
||||
Packet packet(MessageType::OnInputCommand, m_SendPacketID, m_PacketID, ackBitField);
|
||||
for (int i = 0; i < m_InputCommandBuffer.size(); i++) {
|
||||
packet.WriteString(m_InputCommandBuffer[i].Command);
|
||||
packet.WritePrimitive(m_InputCommandBuffer[i].Value);
|
||||
@@ -380,18 +425,32 @@ void Client::sendInputCommands()
|
||||
|
||||
void Client::becomePlayer()
|
||||
{
|
||||
Packet packet = Packet(MessageType::BecomePlayer, m_SendPacketID);
|
||||
Packet packet(MessageType::BecomePlayer, m_SendPacketID, m_PacketID, ackBitField);
|
||||
send(packet);
|
||||
}
|
||||
|
||||
bool Client::clientServerMapsHasEntity(EntityID clientEntityID)
|
||||
{
|
||||
return m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end();
|
||||
if (m_ClientIDToServerID.find(clientEntityID) != m_ClientIDToServerID.end()) {
|
||||
if (m_World->ValidEntity(clientEntityID)) {
|
||||
return true;
|
||||
}
|
||||
EntityID serverEntityID = m_ClientIDToServerID.at(clientEntityID);
|
||||
deleteFromServerClientMaps(serverEntityID, clientEntityID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Client::serverClientMapsHasEntity(EntityID serverEntityID)
|
||||
{
|
||||
return m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end();
|
||||
if (m_ServerIDToClientID.find(serverEntityID) != m_ServerIDToClientID.end()) {
|
||||
EntityID localEntityID = m_ServerIDToClientID.at(serverEntityID);
|
||||
if (m_World->ValidEntity(localEntityID)) {
|
||||
return true;
|
||||
}
|
||||
deleteFromServerClientMaps(serverEntityID, localEntityID);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
|
||||
@@ -400,3 +459,9 @@ void Client::insertIntoServerClientMaps(EntityID serverEntityID, EntityID client
|
||||
m_ClientIDToServerID.insert(std::make_pair(clientEntityID, serverEntityID));
|
||||
|
||||
}
|
||||
|
||||
void Client::deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID)
|
||||
{
|
||||
m_ServerIDToClientID.erase(serverEntityID);
|
||||
m_ClientIDToServerID.erase(clientEntityID);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "Network/Packet.h"
|
||||
|
||||
Packet::Packet(MessageType type, unsigned int& packetID)
|
||||
Packet::Packet(MessageType type, unsigned int& packetID, unsigned int lastReceivedPacket, unsigned int ackBitField)
|
||||
{
|
||||
m_Data = new char[m_MaxPacketSize];
|
||||
Init(type, packetID);
|
||||
Init(type, packetID, lastReceivedPacket, ackBitField);
|
||||
}
|
||||
|
||||
// Create message
|
||||
@@ -21,7 +21,9 @@ Packet::Packet(MessageType type)
|
||||
{
|
||||
m_Data = new char[m_MaxPacketSize];
|
||||
unsigned int dummy = 0;
|
||||
Init(type, dummy);
|
||||
// Dummy allocates memory for later insertion of
|
||||
// correct values
|
||||
Init(type, dummy, dummy, dummy);
|
||||
}
|
||||
|
||||
Packet::~Packet()
|
||||
@@ -29,15 +31,17 @@ Packet::~Packet()
|
||||
delete[] m_Data;
|
||||
}
|
||||
|
||||
void Packet::Init(MessageType type, unsigned int & packetID)
|
||||
void Packet::Init(MessageType type, unsigned int & packetID, unsigned int lastReceivedPacket, unsigned int ackBitField)
|
||||
{
|
||||
m_ReturnDataOffset = 0;
|
||||
m_Offset = 0;
|
||||
// Create message header
|
||||
// Add message type
|
||||
int messageType = static_cast<int>(type);
|
||||
Packet::WritePrimitive<int>(messageType);
|
||||
Packet::WritePrimitive<int>(packetID);
|
||||
WritePrimitive<int>(messageType);
|
||||
WritePrimitive<unsigned int>(packetID);
|
||||
WritePrimitive<unsigned int>(lastReceivedPacket);
|
||||
WritePrimitive<unsigned int>(ackBitField);
|
||||
packetID++;
|
||||
m_HeaderSize = m_Offset;
|
||||
}
|
||||
@@ -87,16 +91,31 @@ char * Packet::ReadData(int SizeOfData)
|
||||
return (m_Data + oldReturnDataOffset);
|
||||
}
|
||||
|
||||
void Packet::ChangePacketID(unsigned int & packetID)
|
||||
//void Packet::ChangePacketID(unsigned int & packetID)
|
||||
//{
|
||||
// packetID = packetID + 1;
|
||||
// // Overwrite old PacketID
|
||||
// memcpy(m_Data + sizeof(int), &packetID, sizeof(int));
|
||||
//}
|
||||
|
||||
void Packet::ChangeHeaderInfo(unsigned int& packetID, unsigned int lastReceivedPacket, unsigned int ackBitField)
|
||||
{
|
||||
packetID = packetID + 1;
|
||||
// Start at sizeOf(int) cause of MessageType
|
||||
int offset = sizeof(int);
|
||||
// Overwrite old PacketID
|
||||
memcpy(m_Data + sizeof(int), &packetID, sizeof(int));
|
||||
memcpy(m_Data + sizeof(unsigned int), &packetID, offset);
|
||||
offset += sizeof(unsigned int);
|
||||
// Overwrite old LastReceivedPacket
|
||||
memcpy(m_Data + sizeof(unsigned int), &lastReceivedPacket, offset);
|
||||
offset += sizeof(unsigned int);
|
||||
// Overwrite old ackBitField
|
||||
memcpy(m_Data + sizeof(unsigned int), &ackBitField, offset);
|
||||
offset += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
void Packet::resizeData()
|
||||
{
|
||||
|
||||
// Allocate memory to store our data in
|
||||
char* holdData = new char[m_MaxPacketSize];
|
||||
// Copy our data to the newly allocated memory
|
||||
|
||||
+171
-155
@@ -21,9 +21,8 @@ void Server::Start(World* world, EventBroker* eventBroker)
|
||||
// Subscribe to events
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Server::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &Server::OnPlayerSpawned);
|
||||
for (size_t i = 0; i < m_MaxConnections; i++) {
|
||||
m_PlayerDefinitions[i].StopTime = std::clock();
|
||||
}
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EEntityDeleted, &Server::OnEntityDeleted);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EComponentDeleted, &Server::OnComponentDeleted);
|
||||
LOG_INFO("I am Server. BIP BOP\n");
|
||||
}
|
||||
|
||||
@@ -33,6 +32,16 @@ void Server::Update()
|
||||
m_EventBroker->Process<Server>();
|
||||
if (isReadingData) {
|
||||
Network::Update();
|
||||
// Test bit patterns
|
||||
//std::bitset<32> bitPattern;
|
||||
//bitPattern[0].flip();
|
||||
//bitPattern[15].flip();
|
||||
//bitPattern[31].flip();
|
||||
//std::cout << "bitPattern: " << bitPattern << '\n';
|
||||
//unsigned int bitPatternInt = static_cast<unsigned int>(bitPattern.to_ulong());
|
||||
//std::cout << "Int pattern: " << bitPatternInt << '\n';
|
||||
//std::bitset<32> bitPatternRev(bitPatternInt);
|
||||
//std::cout << "bitPatternReverted: " << bitPatternRev << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,9 +65,9 @@ void Server::readFromClients()
|
||||
}
|
||||
|
||||
// Send pings each
|
||||
if (pingIntervalMs < (1000 * (currentTime - previousePingMessage) / (double)CLOCKS_PER_SEC)) {
|
||||
if (pingIntervalMs < (1000 * (currentTime - previousPingMessage) / (double)CLOCKS_PER_SEC)) {
|
||||
sendPing();
|
||||
previousePingMessage = currentTime;
|
||||
previousPingMessage = currentTime;
|
||||
}
|
||||
|
||||
// Time out logic
|
||||
@@ -70,15 +79,19 @@ void Server::readFromClients()
|
||||
|
||||
void Server::parseMessageType(Packet& packet)
|
||||
{
|
||||
int messageType = packet.ReadPrimitive<int>(); // Read what type off message was sent from server
|
||||
PlayerID playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
||||
|
||||
int messageType = packet.ReadPrimitive<int>(); // Read what type off message was sent from server
|
||||
// Read packet ID
|
||||
m_PreviousPacketID = m_PacketID; // Set previous packet id
|
||||
m_PacketID = packet.ReadPrimitive<int>(); //Read new packet id
|
||||
if (playerID != -1) {
|
||||
// TODO: Bit pattern stuff!"#!"#
|
||||
m_ConnectedPlayers[playerID].LastPacketReceivedID = packet.ReadPrimitive<PacketID>();
|
||||
}
|
||||
|
||||
//identifyPacketLoss();
|
||||
switch (static_cast<MessageType>(messageType)) {
|
||||
case MessageType::Connect:
|
||||
parseConnect(packet);
|
||||
parseConnect(packet, playerID);
|
||||
break;
|
||||
case MessageType::Ping:
|
||||
parsePing();
|
||||
@@ -96,8 +109,8 @@ void Server::parseMessageType(Packet& packet)
|
||||
case MessageType::OnPlayerDamage:
|
||||
parseOnPlayerDamage(packet);
|
||||
break;
|
||||
case MessageType::BecomePlayer:
|
||||
createPlayer();
|
||||
case MessageType::PlayerTransform:
|
||||
parsePlayerTransform(packet);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -119,31 +132,22 @@ int Server::receive(char * data)
|
||||
return length;
|
||||
}
|
||||
|
||||
void Server::send(Packet& packet, UserID user)
|
||||
void Server::send(PlayerID playerID, Packet& packet)
|
||||
{
|
||||
int bytesSent = m_Socket.send_to(
|
||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||
m_ConnectedUsers[user].Endpoint,
|
||||
0);
|
||||
// Network Debug data
|
||||
if (isReadingData) {
|
||||
m_NetworkData.TotalDataSent += packet.Size();
|
||||
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||
m_NetworkData.AmountOfMessagesSent++;
|
||||
}
|
||||
}
|
||||
|
||||
void Server::send(PlayerID player, Packet& packet)
|
||||
{
|
||||
int bytesSent = m_Socket.send_to(
|
||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||
m_PlayerDefinitions[player].Endpoint,
|
||||
0);
|
||||
// Network Debug data
|
||||
if (isReadingData) {
|
||||
m_NetworkData.TotalDataSent += packet.Size();
|
||||
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||
m_NetworkData.AmountOfMessagesSent++;
|
||||
try {
|
||||
int bytesSent = m_Socket.send_to(
|
||||
boost::asio::buffer(packet.Data(), packet.Size()),
|
||||
m_ConnectedPlayers[playerID].Endpoint,
|
||||
0);
|
||||
// Network Debug data
|
||||
if (isReadingData) {
|
||||
m_NetworkData.TotalDataSent += packet.Size();
|
||||
m_NetworkData.DataSentThisInterval += packet.Size();
|
||||
m_NetworkData.AmountOfMessagesSent++;
|
||||
}
|
||||
} catch (const boost::system::system_error& e) {
|
||||
// TODO: Clean up invalid endpoints out of m_ConnectedPlayers later
|
||||
m_ConnectedPlayers[playerID].Endpoint = boost::asio::ip::udp::endpoint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,58 +168,76 @@ void Server::send(Packet & packet)
|
||||
|
||||
void Server::broadcast(Packet& packet)
|
||||
{
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
|
||||
packet.ChangePacketID(m_ConnectedUsers[i].PacketID);
|
||||
send(packet, i);
|
||||
}
|
||||
for (auto& kv : m_ConnectedPlayers) {
|
||||
packet.ChangeHeaderInfo(
|
||||
kv.second.PacketID,
|
||||
kv.second.LastPacketReceivedID,
|
||||
kv.second.AckBitField
|
||||
);
|
||||
send(kv.first, packet);
|
||||
}
|
||||
}
|
||||
|
||||
// Send snapshot fields
|
||||
void Server::sendSnapshot()
|
||||
{
|
||||
// Should time this
|
||||
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
||||
for (auto& it : worldComponentPools) {
|
||||
Packet packet(MessageType::Snapshot);
|
||||
ComponentPool* componentPool = it.second;
|
||||
ComponentInfo componentInfo = componentPool->ComponentInfo();
|
||||
Packet packet(MessageType::Snapshot);
|
||||
addChildrenToPacket(packet, EntityID_Invalid);
|
||||
broadcast(packet);
|
||||
}
|
||||
|
||||
// Component Type
|
||||
packet.WriteString(componentInfo.Name);
|
||||
for (auto& componentWrapper : *componentPool) {
|
||||
// HACK: Send entity name
|
||||
packet.WriteString(m_World->GetName(componentWrapper.EntityID));
|
||||
// Components EntityID
|
||||
packet.WritePrimitive(componentWrapper.EntityID);
|
||||
// Parents EntityID
|
||||
packet.WritePrimitive(m_World->GetParent(componentWrapper.EntityID));
|
||||
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentInfo.Fields.at(componentField);
|
||||
if (fieldInfo.Type == "string") {
|
||||
std::string& value = componentWrapper[componentField];
|
||||
packet.WriteString(value);
|
||||
} else {
|
||||
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
|
||||
void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
|
||||
{
|
||||
auto itPair = m_World->GetChildren(entityID);
|
||||
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
|
||||
// Loop through every child
|
||||
for (auto it = itPair.first; it != itPair.second; it++) {
|
||||
EntityID childEntityID = it->second;
|
||||
// Write EntityID and parentsID and Entity name
|
||||
packet.WritePrimitive(childEntityID);
|
||||
packet.WritePrimitive(entityID);
|
||||
packet.WriteString(m_World->GetName(childEntityID));
|
||||
// Write components to child
|
||||
int numberOfComponents = 0;
|
||||
for (auto& i : worldComponentPools) {
|
||||
if (i.second->KnowsEntity(childEntityID)) {
|
||||
numberOfComponents++;
|
||||
}
|
||||
}
|
||||
// Write how many components should be read
|
||||
packet.WritePrimitive(numberOfComponents);
|
||||
for (auto& i : worldComponentPools) {
|
||||
// If the entity exist in the pool
|
||||
if (i.second->KnowsEntity(childEntityID)) {
|
||||
ComponentWrapper componentWrapper = i.second->GetByEntity(childEntityID);
|
||||
// ComponentType
|
||||
packet.WriteString(componentWrapper.Info.Name);
|
||||
// Loop through fields
|
||||
for (auto& componentField : componentWrapper.Info.FieldsInOrder) {
|
||||
ComponentInfo::Field_t fieldInfo = componentWrapper.Info.Fields.at(componentField);
|
||||
if (fieldInfo.Type == "string") {
|
||||
std::string& value = componentWrapper[componentField];
|
||||
packet.WriteString(value);
|
||||
} else {
|
||||
packet.WriteData(componentWrapper.Data + fieldInfo.Offset, fieldInfo.Stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (packet.Size() > packet.HeaderSize() + componentInfo.Name.size()) {
|
||||
broadcast(packet);
|
||||
}
|
||||
// Go to to your children
|
||||
addChildrenToPacket(packet, childEntityID);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::sendPing()
|
||||
{
|
||||
// Prints connected players ping
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
|
||||
int ping = 1000 * (m_ConnectedUsers[i].StopTime - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
||||
LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedUsers[i].PacketID, i, std::abs(ping));
|
||||
}
|
||||
}
|
||||
//for (int i = 0; i < m_ConnectedPlayers.size(); i++) {
|
||||
// if (m_ConnectedPlayers[i].Endpoint.address() != boost::asio::ip::address()) {
|
||||
// int ping = 1000 * (m_ConnectedPlayers[i].StopTime - m_StartPingTime) / static_cast<double>(CLOCKS_PER_SEC);
|
||||
// LOG_INFO("Last packetID received %i: User %i's ping: %i", m_ConnectedPlayers[i].PacketID, i, std::abs(ping));
|
||||
// }
|
||||
//}
|
||||
// Create ping message
|
||||
Packet packet(MessageType::Ping);
|
||||
packet.WriteString("Ping from server");
|
||||
@@ -230,9 +252,9 @@ void Server::checkForTimeOuts()
|
||||
int startPing = 1000 * m_StartPingTime
|
||||
/ static_cast<double>(CLOCKS_PER_SEC);
|
||||
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() != boost::asio::ip::address()) {
|
||||
int stopPing = 1000 * m_ConnectedUsers[i].StopTime /
|
||||
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 /
|
||||
static_cast<double>(CLOCKS_PER_SEC);
|
||||
if (startPing > stopPing + m_TimeoutMs) {
|
||||
LOG_INFO("User %i timed out!", i);
|
||||
@@ -242,35 +264,24 @@ void Server::checkForTimeOuts()
|
||||
}
|
||||
}
|
||||
|
||||
void Server::disconnect(UserID user)
|
||||
void Server::disconnect(PlayerID playerID)
|
||||
{
|
||||
//broadcast("A player disconnected");
|
||||
LOG_INFO("User %s disconnected/timed out", m_PlayerDefinitions[user].Name.c_str());
|
||||
LOG_INFO("User %s disconnected/timed out", m_ConnectedPlayers[playerID].Name.c_str());
|
||||
// Remove enteties and stuff (When we can remove entity, remove it and tell clients to remove the copy they have)
|
||||
Events::PlayerDisconnected e;
|
||||
e.Entity = m_PlayerDefinitions[user].EntityID;
|
||||
e.PlayerID = user;
|
||||
e.Entity = m_ConnectedPlayers[playerID].EntityID;
|
||||
e.PlayerID = playerID;
|
||||
m_EventBroker->Publish(e);
|
||||
|
||||
m_PlayerDefinitions[user].Endpoint = boost::asio::ip::udp::endpoint();
|
||||
m_PlayerDefinitions[user].EntityID = -1;
|
||||
m_PlayerDefinitions[user].Name = "";
|
||||
m_PlayerDefinitions[user].PacketID = 0;
|
||||
m_ConnectedUsers.erase(m_ConnectedUsers.begin() + user);
|
||||
m_ConnectedPlayers.erase(playerID);
|
||||
}
|
||||
|
||||
void Server::parseOnInputCommand(Packet& packet)
|
||||
{
|
||||
PlayerID player = -1;
|
||||
// Check which player it was who sent the message
|
||||
for (int i = 0; i < m_MaxConnections; i++) {
|
||||
// if the player is connected set playerID to the correct PlayerID
|
||||
if (m_PlayerDefinitions[i].Endpoint.address() == m_ReceiverEndpoint.address()
|
||||
&& m_PlayerDefinitions[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||
player = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
||||
if (player != -1) {
|
||||
while (packet.DataReadSize() < packet.Size()) {
|
||||
Events::InputCommand e;
|
||||
@@ -286,26 +297,19 @@ void Server::parseOnInputCommand(Packet& packet)
|
||||
void Server::parseOnPlayerDamage(Packet & packet)
|
||||
{
|
||||
Events::PlayerDamage e;
|
||||
e.DamageAmount = packet.ReadPrimitive<double>();
|
||||
e.PlayerDamagedID = packet.ReadPrimitive<EntityID>();
|
||||
e.Damage = packet.ReadPrimitive<double>();
|
||||
e.Player = EntityWrapper(m_World, packet.ReadPrimitive<EntityID>());
|
||||
m_EventBroker->Publish(e);
|
||||
//LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str());
|
||||
}
|
||||
|
||||
void Server::parseConnect(Packet& packet)
|
||||
void Server::parseConnect(Packet& packet, PlayerID playerID)
|
||||
{
|
||||
LOG_INFO("Parsing connections");
|
||||
// Check if player is already connected
|
||||
if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) {
|
||||
if (playerID != -1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address() &&
|
||||
m_ConnectedUsers[i].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||
// Already connected
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Create a new player
|
||||
PlayerDefinition pd;
|
||||
pd.EntityID = 0; // Overlook this
|
||||
@@ -313,11 +317,11 @@ void Server::parseConnect(Packet& packet)
|
||||
pd.Name = packet.ReadString();
|
||||
pd.PacketID = 0;
|
||||
pd.StopTime = std::clock();
|
||||
m_ConnectedUsers.push_back(pd);
|
||||
Packet connnectPacket(MessageType::Connect, pd.PacketID, pd.LastPacketReceivedID, pd.AckBitField);
|
||||
m_ConnectedPlayers[m_NextPlayerID++] = pd;
|
||||
LOG_INFO("Spectator \"%s\" connected on IP: %s", pd.Name.c_str(), pd.Endpoint.address().to_string().c_str());
|
||||
|
||||
// Send a message to the player that connected
|
||||
Packet connnectPacket(MessageType::Connect, m_ConnectedUsers[m_ConnectedUsers.size() - 1].PacketID);
|
||||
send(connnectPacket);
|
||||
|
||||
// Send notification that a player has connected
|
||||
@@ -329,32 +333,36 @@ void Server::parseDisconnect()
|
||||
{
|
||||
LOG_INFO("%i: Parsing disconnect", m_PacketID);
|
||||
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
||||
disconnect(i);
|
||||
for (auto& kv : m_ConnectedPlayers) {
|
||||
if (kv.second.Endpoint.address() == m_ReceiverEndpoint.address() &&
|
||||
kv.second.Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||
disconnect(kv.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::parseClientPing()
|
||||
void Server::parseClientPing(PlayerID player)
|
||||
{
|
||||
LOG_INFO("%i: Parsing ping", m_PacketID);
|
||||
PlayerID player = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
||||
if (player == -1) {
|
||||
return;
|
||||
}
|
||||
// Return ping
|
||||
Packet packet(MessageType::Ping, m_PlayerDefinitions[player].PacketID);
|
||||
Packet packet(
|
||||
MessageType::Ping,
|
||||
m_ConnectedPlayers[player].PacketID,
|
||||
m_ConnectedPlayers[player].LastPacketReceivedID,
|
||||
m_ConnectedPlayers[player].AckBitField
|
||||
);
|
||||
packet.WriteString("Ping received");
|
||||
send(packet);
|
||||
}
|
||||
|
||||
void Server::parsePing()
|
||||
{
|
||||
for (int i = 0; i < m_ConnectedUsers.size(); i++) {
|
||||
if (m_ConnectedUsers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
||||
m_ConnectedUsers[i].StopTime = std::clock();
|
||||
for (int i = 0; i < m_ConnectedPlayers.size(); i++) {
|
||||
if (m_ConnectedPlayers[i].Endpoint.address() == m_ReceiverEndpoint.address()) {
|
||||
m_ConnectedPlayers[i].StopTime = std::clock();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -369,43 +377,6 @@ void Server::identifyPacketLoss()
|
||||
}
|
||||
}
|
||||
|
||||
void Server::createPlayer()
|
||||
{
|
||||
if (GetPlayerIDFromEndpoint(m_ReceiverEndpoint) != -1) {
|
||||
// Already connected as player
|
||||
LOG_WARNING("Already connected!");
|
||||
return;
|
||||
}
|
||||
UserID userIndex;
|
||||
for (userIndex = 0; userIndex < m_ConnectedUsers.size(); userIndex++) {
|
||||
if (m_ConnectedUsers[userIndex].Endpoint.address() == m_ReceiverEndpoint.address() &&
|
||||
m_ConnectedUsers[userIndex].Endpoint.port() == m_ReceiverEndpoint.port()) {
|
||||
// Found user
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (userIndex == m_ConnectedUsers.size()) {
|
||||
LOG_WARNING("Not a recognized user!");
|
||||
return;
|
||||
}
|
||||
for (PlayerID playerIndex = 0; playerIndex < m_MaxConnections; playerIndex++) {
|
||||
if (m_PlayerDefinitions[playerIndex].Endpoint.address() == boost::asio::ip::address()) {
|
||||
m_PlayerDefinitions[playerIndex] = m_ConnectedUsers[userIndex];
|
||||
EntityID entityID = m_World->CreateEntity();
|
||||
ComponentWrapper transform = m_World->AttachComponent(entityID, "Transform");
|
||||
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
|
||||
ComponentWrapper model = m_World->AttachComponent(entityID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
model["Color"] = glm::vec4(rand()%255 / 255.f, rand()%255 / 255.f, rand() %255 / 255.f, 1.f);
|
||||
ComponentWrapper player = m_World->AttachComponent(entityID, "Player");
|
||||
m_PlayerDefinitions[playerIndex].EntityID = entityID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_WARNING("Server is full!");
|
||||
|
||||
}
|
||||
|
||||
void Server::kick(PlayerID player)
|
||||
{
|
||||
disconnect(player);
|
||||
@@ -415,10 +386,10 @@ void Server::kick(PlayerID player)
|
||||
|
||||
PlayerID Server::GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint)
|
||||
{
|
||||
for (int i = 0; i < m_MaxConnections; i++) {
|
||||
if (m_PlayerDefinitions[i].Endpoint.address() == endpoint.address() &&
|
||||
m_PlayerDefinitions[i].Endpoint.port() == endpoint.port()) {
|
||||
return i;
|
||||
for (auto& kv : m_ConnectedPlayers) {
|
||||
if (kv.second.Endpoint.address() == endpoint.address() &&
|
||||
kv.second.Endpoint.port() == endpoint.port()) {
|
||||
return kv.first;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -443,9 +414,54 @@ bool Server::OnInputCommand(const Events::InputCommand & e)
|
||||
|
||||
bool Server::OnPlayerSpawned(const Events::PlayerSpawned & e)
|
||||
{
|
||||
m_ConnectedPlayers[e.PlayerID].EntityID = e.Player.ID;
|
||||
|
||||
Packet packet = Packet(MessageType::OnPlayerSpawned);
|
||||
packet.WritePrimitive<EntityID>(e.Player.ID);
|
||||
packet.WritePrimitive<EntityID>(e.Spawner.ID);
|
||||
// We don't send PlayerID here because it will always be set to -1
|
||||
packet.WriteString(m_ConnectedPlayers[e.PlayerID].Name);
|
||||
send(e.PlayerID, packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Server::OnEntityDeleted(const Events::EntityDeleted & e)
|
||||
{
|
||||
if (!e.Cascaded) {
|
||||
Packet packet = Packet(MessageType::EntityDeleted);
|
||||
packet.WritePrimitive<EntityID>(e.DeletedEntity);
|
||||
broadcast(packet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Server::OnComponentDeleted(const Events::ComponentDeleted & e)
|
||||
{
|
||||
if (!e.Cascaded) {
|
||||
Packet packet = Packet(MessageType::ComponentDeleted);
|
||||
packet.WritePrimitive<EntityID>(e.Entity);
|
||||
packet.WriteString(e.ComponentType);
|
||||
broadcast(packet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Server::parsePlayerTransform(Packet& packet)
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec3 orientation;
|
||||
position.x = packet.ReadPrimitive<float>();
|
||||
position.y = packet.ReadPrimitive<float>();
|
||||
position.z = packet.ReadPrimitive<float>();
|
||||
orientation.x = packet.ReadPrimitive<float>();
|
||||
orientation.y = packet.ReadPrimitive<float>();
|
||||
orientation.z = packet.ReadPrimitive<float>();
|
||||
|
||||
PlayerID playerID = GetPlayerIDFromEndpoint(m_ReceiverEndpoint);
|
||||
EntityWrapper player(m_World, m_ConnectedPlayers.at(playerID).EntityID);
|
||||
|
||||
if (player.Valid()) {
|
||||
player["Transform"]["Position"] = position;
|
||||
player["Transform"]["Orientation"] = orientation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ DrawBloomPass::DrawBloomPass(IRenderer* renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.mesh");
|
||||
|
||||
InitializeTextures();
|
||||
InitializeBuffers();
|
||||
|
||||
@@ -4,8 +4,8 @@ DrawColorCorrectionPass::DrawColorCorrectionPass(IRenderer* renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_Exposure = 1; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting.
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.mesh");
|
||||
m_Exposure = 0.4; //TODO: Renderer: Fixa så att denna går att ändra på genom komponent eller setting.
|
||||
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
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);
|
||||
@@ -72,6 +73,7 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
//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));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if(modelJob->DiffuseTexture != nullptr) {
|
||||
@@ -80,22 +82,35 @@ void DrawFinalPass::Draw(RenderScene& scene)
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||
|
||||
/*if(modelJob->GlowMap != nullptr) {
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->GlowMap->m_Texture);
|
||||
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) {
|
||||
auto animation = modelJob->Model->m_RawModel->m_Skeleton->GetAnimation("running");
|
||||
if (animation != nullptr) {
|
||||
std::vector<glm::mat4> frameBones = modelJob->Model->m_RawModel->m_Skeleton->GetFrameBones(
|
||||
*animation,
|
||||
0.0f
|
||||
);
|
||||
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);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
|
||||
|
||||
continue;
|
||||
glDrawElements(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(modelJob->StartIndex * sizeof(unsigned int)));
|
||||
}
|
||||
}
|
||||
m_FinalPassFrameBuffer.Unbind();
|
||||
GLERROR("DrawFinalPass::Draw: END");
|
||||
delete state;
|
||||
}
|
||||
@@ -133,4 +148,4 @@ 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");
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ DrawScreenQuadPass::DrawScreenQuadPass(IRenderer* renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.mesh");
|
||||
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ Model::Model(std::string fileName)
|
||||
if (!group.SpecularMapPath.empty()) {
|
||||
group.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(group.SpecularMapPath));
|
||||
}
|
||||
if (!group.IncandescenceMapPath.empty()) {
|
||||
group.IncandescenceMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(group.IncandescenceMapPath));
|
||||
}
|
||||
}
|
||||
|
||||
// Generate GL buffers
|
||||
@@ -32,7 +35,7 @@ Model::Model(std::string fileName)
|
||||
GLERROR("GLEW: BufferFail4");
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
std::vector<int> structSizes = { 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 4 };
|
||||
std::vector<int> structSizes = { 3, 3, 3, 3, 2, 4, 4 };
|
||||
int stride = 0;
|
||||
for (int size : structSizes) {
|
||||
stride += size;
|
||||
@@ -48,10 +51,6 @@ Model::Model(std::string fileName)
|
||||
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");
|
||||
|
||||
@@ -62,10 +61,6 @@ Model::Model(std::string fileName)
|
||||
glEnableVertexAttribArray(4);
|
||||
glEnableVertexAttribArray(5);
|
||||
glEnableVertexAttribArray(6);
|
||||
glEnableVertexAttribArray(7);
|
||||
glEnableVertexAttribArray(8);
|
||||
glEnableVertexAttribArray(9);
|
||||
glEnableVertexAttribArray(10);
|
||||
GLERROR("GLEW: BufferFail5");
|
||||
|
||||
//CreateBuffers();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "Rendering/RawModel.h"
|
||||
#include "Rendering/RawModelAssimp.h"
|
||||
|
||||
RawModel::RawModel(std::string fileName)
|
||||
#ifdef USING_ASSIMP_AS_IMPORTER
|
||||
|
||||
RawModelAssimp::RawModelAssimp(std::string fileName)
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(fileName, aiProcess_CalcTangentSpace | aiProcess_Triangulate);
|
||||
@@ -38,7 +40,7 @@ RawModel::RawModel(std::string fileName)
|
||||
//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;
|
||||
|
||||
@@ -74,21 +76,7 @@ RawModel::RawModel(std::string fileName)
|
||||
auto uv = mesh->mTextureCoords[0][vertexIndex];
|
||||
desc.TextureCoords = glm::vec2(uv.x, uv.y);
|
||||
}
|
||||
|
||||
// Material diffuse color
|
||||
aiColor3D diffuse;
|
||||
material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse);
|
||||
float opacity;
|
||||
material->Get(AI_MATKEY_OPACITY, opacity);
|
||||
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity);
|
||||
|
||||
desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity);
|
||||
|
||||
// Material specular color
|
||||
aiColor3D specular;
|
||||
material->Get(AI_MATKEY_COLOR_SPECULAR, specular);
|
||||
desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, 1.f);
|
||||
|
||||
m_Vertices.push_back(desc);
|
||||
}
|
||||
|
||||
@@ -128,7 +116,7 @@ RawModel::RawModel(std::string fileName)
|
||||
}
|
||||
for (auto& vertex : m_Vertices) {
|
||||
vertex.Tangent = glm::normalize(vertex.Tangent);
|
||||
vertex.BiTangent = glm::normalize(glm::cross(vertex.Tangent, glm::normalize(vertex.Normal)));
|
||||
vertex.BiNormal = glm::normalize(glm::cross(vertex.Tangent, glm::normalize(vertex.Normal)));
|
||||
}
|
||||
|
||||
// Material info
|
||||
@@ -201,10 +189,7 @@ RawModel::RawModel(std::string fileName)
|
||||
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];
|
||||
std::tie(desc.BoneIndices[weightIndex], desc.BoneWeights[weightIndex]) = weights[weightIndex];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,14 +275,14 @@ RawModel::RawModel(std::string fileName)
|
||||
}
|
||||
}
|
||||
|
||||
RawModel::~RawModel()
|
||||
RawModelAssimp::~RawModelAssimp()
|
||||
{
|
||||
if (m_Skeleton) {
|
||||
delete m_Skeleton;
|
||||
}
|
||||
}
|
||||
|
||||
void RawModel::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &boneInfo, std::map<std::string, int> &boneNameMapping, aiNode* node, int parentID)
|
||||
void RawModelAssimp::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();
|
||||
|
||||
@@ -317,3 +302,5 @@ void RawModel::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &b
|
||||
CreateSkeleton(boneInfo, boneNameMapping, child, parentID);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,381 @@
|
||||
#include "Rendering/RawModelCustom.h"
|
||||
|
||||
#ifndef USING_ASSIMP_AS_IMPORTER
|
||||
|
||||
RawModelCustom::RawModelCustom(std::string fileName)
|
||||
{
|
||||
if(fileName.substr(fileName.find_last_of(".")).compare(".mesh") != 0) {
|
||||
throw Resource::FailedLoadingException("Unknown model file format. Please use \".mesh\" files.");
|
||||
}
|
||||
fileName = fileName.erase(fileName.find_last_of("."), fileName.find_last_of(".") - fileName.size());
|
||||
ReadMeshFile(fileName);
|
||||
ReadMaterialFile(fileName);
|
||||
ReadAnimationFile(fileName);
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMeshFile(std::string filePath)
|
||||
{
|
||||
char* fileData;
|
||||
filePath += ".mesh";
|
||||
std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate);
|
||||
|
||||
if (!in.is_open()) {
|
||||
throw Resource::FailedLoadingException("Open mesh file failed");
|
||||
}
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
ReadMeshFileHeader(offset, fileData, fileByteSize);
|
||||
ReadMesh(offset, fileData, fileByteSize);
|
||||
}
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMeshFileHeader(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
m_Vertices.resize(*(unsigned int*)(fileData + offset));
|
||||
offset += sizeof(unsigned int);
|
||||
m_Indices.resize(*(unsigned int*)(fileData + offset));
|
||||
offset += sizeof(unsigned int);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMesh(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
ReadVertices(offset, fileData, fileByteSize);
|
||||
ReadIndices(offset, fileData, fileByteSize);
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadVertices(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + m_Vertices.size() * sizeof(Vertex) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading vertices failed");
|
||||
}
|
||||
|
||||
memcpy(&m_Vertices[0], fileData + offset, m_Vertices.size() * sizeof(Vertex));
|
||||
offset += m_Vertices.size() * sizeof(Vertex);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadIndices(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + m_Indices.size() * sizeof(unsigned int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading indices failed");
|
||||
}
|
||||
|
||||
memcpy(&m_Indices[0], fileData + offset, m_Indices.size() * sizeof(unsigned int));
|
||||
offset += m_Indices.size() * sizeof(unsigned int);
|
||||
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMaterialFile(std::string filePath)
|
||||
{
|
||||
char* fileData;
|
||||
filePath += ".mtrl";
|
||||
std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate);
|
||||
|
||||
if (!in.is_open()) {
|
||||
throw Resource::FailedLoadingException("Open material file failed");
|
||||
}
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
ReadMaterials(offset, fileData, fileByteSize);
|
||||
}
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMaterials(unsigned int& offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
unsigned int* numMaterials = (unsigned int*)(fileData);
|
||||
MaterialGroups.reserve(*numMaterials);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
for (int i = 0; i < *numMaterials; i++) {
|
||||
ReadMaterialSingle(offset, fileData, fileByteSize);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadMaterialSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
MaterialGroup newMaterial;
|
||||
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
|
||||
if (offset + sizeof(unsigned int) * 4 > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material texture names length failed");
|
||||
}
|
||||
|
||||
unsigned int* nameLengths = (unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int) * 4;
|
||||
|
||||
if (offset + sizeof(float) * 11 + sizeof(unsigned int) * 2 > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material specular, reflection, color and start and end index values failed");
|
||||
}
|
||||
|
||||
newMaterial.SpecularExponent = *(float*)(fileData + offset);
|
||||
offset += sizeof(float);
|
||||
newMaterial.ReflectionFactor = *(float*)(fileData + offset);
|
||||
offset += sizeof(float);
|
||||
|
||||
memcpy(&newMaterial.DiffuseColor[0], fileData + offset, sizeof(float) * 3);
|
||||
offset += sizeof(float) * 3;
|
||||
memcpy(&newMaterial.SpecularColor[0], fileData + offset, sizeof(float) * 3);
|
||||
offset += sizeof(float) * 3;
|
||||
memcpy(&newMaterial.IncandescenceColor[0], fileData + offset, sizeof(float) * 3);
|
||||
offset += sizeof(float) * 3;
|
||||
|
||||
newMaterial.StartIndex = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
newMaterial.EndIndex = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
if (nameLengths[0] > 0) {
|
||||
if (offset + nameLengths[0] > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material texture path failed");
|
||||
}
|
||||
|
||||
newMaterial.TexturePath = "Textures/";
|
||||
newMaterial.TexturePath += (fileData + offset);
|
||||
newMaterial.TexturePath += ".png";
|
||||
offset += nameLengths[0];
|
||||
}
|
||||
|
||||
if (nameLengths[1] > 0) {
|
||||
if (offset + nameLengths[1] > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material NormalMap path failed");
|
||||
}
|
||||
newMaterial.NormalMapPath = "Textures/";
|
||||
newMaterial.NormalMapPath += (fileData + offset);
|
||||
newMaterial.NormalMapPath += ".png";
|
||||
offset += nameLengths[1];
|
||||
}
|
||||
|
||||
if (nameLengths[2] > 0) {
|
||||
if (offset + nameLengths[2] > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material SpecularMap path failed");
|
||||
}
|
||||
newMaterial.SpecularMapPath = "Textures/";
|
||||
newMaterial.SpecularMapPath += (fileData + offset);
|
||||
newMaterial.SpecularMapPath += ".png";
|
||||
offset += nameLengths[2];
|
||||
}
|
||||
|
||||
if (nameLengths[3] > 0) {
|
||||
if (offset + nameLengths[3] > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Material IncandescenceMap path failed");
|
||||
}
|
||||
newMaterial.IncandescenceMapPath = "Textures/";
|
||||
newMaterial.IncandescenceMapPath += (fileData + offset);
|
||||
newMaterial.IncandescenceMapPath += ".png";
|
||||
offset += nameLengths[3];
|
||||
}
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
MaterialGroups.push_back(newMaterial);
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationFile(std::string filePath)
|
||||
{
|
||||
char* fileData;
|
||||
filePath += ".anim";
|
||||
std::ifstream in(filePath.c_str(), std::ios_base::binary | std::ios_base::ate);
|
||||
|
||||
if (!in.is_open()) {
|
||||
//throw Resource::FailedLoadingException("Open animation file failed");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int fileByteSize = in.tellg();
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
|
||||
fileData = new char[fileByteSize];
|
||||
in.read(fileData, fileByteSize);
|
||||
in.close();
|
||||
|
||||
unsigned int offset = 0;
|
||||
if (fileByteSize > 0) {
|
||||
m_Skeleton = new Skeleton();
|
||||
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
unsigned int numBindPoses = *(unsigned int*)(fileData);
|
||||
offset += sizeof(unsigned int);
|
||||
unsigned int numAnimations = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
#else
|
||||
#endif
|
||||
|
||||
ReadAnimationBindPoses(offset, fileData, fileByteSize);
|
||||
ReadAnimationClips(offset, fileData, fileByteSize, numAnimations);
|
||||
}
|
||||
delete fileData;
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationBindPoses(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
unsigned int* numBones = (unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
for (unsigned int i = 0; i < *numBones; i++) {
|
||||
ReadAnimationJoint(offset, fileData, fileByteSize);
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationJoint(unsigned int &offset, char* fileData, unsigned int& fileByteSize)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
if (offset + sizeof(unsigned int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Joint name length failed");
|
||||
}
|
||||
unsigned int jointNameLength = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
if (offset + jointNameLength > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Joint name failed");
|
||||
}
|
||||
std::string jointName = (fileData + offset);
|
||||
offset += jointNameLength;
|
||||
|
||||
if (offset + sizeof(float) * 4 * 4 > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Joint offset matrix failed");
|
||||
}
|
||||
glm::mat4 offsetMatrix;
|
||||
memcpy(&offsetMatrix, fileData + offset, sizeof(float) * 4 * 4);
|
||||
offset += sizeof(float) * 4 * 4;
|
||||
|
||||
if (offset + sizeof(int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Joint ID failed");
|
||||
}
|
||||
int jointID = *(int*)(fileData + offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (offset + sizeof(int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading Joint Parent ID failed");
|
||||
}
|
||||
int jointParentID = *(int*)(fileData + offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
// Adding joint to the Skeleton
|
||||
m_Skeleton->CreateBone(jointID, jointParentID, jointName, offsetMatrix);
|
||||
|
||||
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationClips(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int numberOfClips)
|
||||
{
|
||||
for (unsigned int i = 0; i < numberOfClips; i++) {
|
||||
ReadAnimationClipSingle(offset, fileData, fileByteSize, i);
|
||||
}
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationClipSingle(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int clipIndex)
|
||||
{
|
||||
#ifdef BOOST_LITTLE_ENDIAN
|
||||
Skeleton::Animation newAnimation;
|
||||
|
||||
if (offset + sizeof(unsigned int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationClip name length failed");
|
||||
}
|
||||
unsigned int clipNameLength = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
if (offset + clipNameLength > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationClip name failed");
|
||||
}
|
||||
newAnimation.Name = (fileData + offset);
|
||||
offset += clipNameLength;
|
||||
|
||||
if (offset + sizeof(float) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationClip duration failed");
|
||||
}
|
||||
|
||||
newAnimation.Duration = *(float*)(fileData + offset);
|
||||
offset += sizeof(float);
|
||||
|
||||
if (offset + sizeof(unsigned int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationClip NrOfKeyframes failed");
|
||||
}
|
||||
unsigned int nrOfKeyframes = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
if (offset + sizeof(unsigned int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationClip NrOfJoints failed");
|
||||
}
|
||||
unsigned int nrOfJoints = *(unsigned int*)(fileData + offset);
|
||||
offset += sizeof(unsigned int);
|
||||
|
||||
newAnimation.Keyframes.reserve(nrOfKeyframes);
|
||||
for (unsigned int i = 0; i < nrOfKeyframes; i++) {
|
||||
ReadAnimationKeyFrame(offset, fileData, fileByteSize, nrOfJoints, newAnimation);
|
||||
}
|
||||
m_Skeleton->Animations[newAnimation.Name] = newAnimation;
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void RawModelCustom::ReadAnimationKeyFrame(unsigned int &offset, char* fileData, unsigned int& fileByteSize, unsigned int nrOfJoints, Skeleton::Animation& animation)
|
||||
{
|
||||
Skeleton::Animation::Keyframe newKeyFrame;
|
||||
|
||||
if (offset + sizeof(int) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationKeyFrame index failed");
|
||||
}
|
||||
newKeyFrame.Index = *(int*)(fileData + offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (offset + sizeof(float) > fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationKeyFrame time failed");
|
||||
}
|
||||
newKeyFrame.Time = *(float*)(fileData + offset);
|
||||
offset += sizeof(float);
|
||||
|
||||
if (offset + sizeof(Skeleton::Animation::Keyframe::BoneProperty) * nrOfJoints> fileByteSize) {
|
||||
throw Resource::FailedLoadingException("Reading AnimationKeyFrame joints failed");
|
||||
}
|
||||
|
||||
Skeleton::Animation::Keyframe::BoneProperty newBone;
|
||||
for (unsigned int i = 0; i < nrOfJoints; i++) {
|
||||
memcpy(&newBone, (fileData + offset), sizeof(Skeleton::Animation::Keyframe::BoneProperty));
|
||||
offset += sizeof(Skeleton::Animation::Keyframe::BoneProperty);
|
||||
newKeyFrame.BoneProperties[newBone.ID] = newBone;
|
||||
}
|
||||
animation.Keyframes.push_back(newKeyFrame);
|
||||
}
|
||||
|
||||
RawModelCustom::~RawModelCustom()
|
||||
{
|
||||
if (m_Skeleton != nullptr) {
|
||||
delete m_Skeleton;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -59,10 +59,10 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
|
||||
model = ResourceManager::Load<::Model, true>(resource);
|
||||
} catch (const Resource::StillLoadingException&) {
|
||||
//continue;
|
||||
model = ResourceManager::Load<::Model>("Models/Core/UnitRaptor.obj");
|
||||
model = ResourceManager::Load<::Model>("Models/Core/UnitRaptor.mesh");
|
||||
} catch (const std::exception&) {
|
||||
try {
|
||||
model = ResourceManager::Load<::Model>("Models/Core/Error.obj");
|
||||
model = ResourceManager::Load<::Model>("Models/Core/Error.mesh");
|
||||
} catch (const std::exception&) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ void Renderer::Initialize()
|
||||
m_TextPass->Initialize();
|
||||
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
/* m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
|
||||
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");*/
|
||||
|
||||
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ std::vector<glm::mat4> Skeleton::GetFrameBones(const Animation& animation, doubl
|
||||
|
||||
void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyframe ¤tFrame, const Animation::Keyframe &nextFrame, float progress, std::map<int, glm::mat4> &boneMatrices, const Bone* bone, glm::mat4 parentMatrix)
|
||||
{
|
||||
glm::mat4 boneMatrix;
|
||||
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);
|
||||
@@ -84,10 +84,13 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyf
|
||||
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);
|
||||
if (bone->Parent) {
|
||||
boneMatrix = parentMatrix; // * glm::inverse(bone->OffsetMatrix);
|
||||
}
|
||||
boneMatrices[bone->ID] = boneMatrix; // * bone->OffsetMatrix;
|
||||
}
|
||||
|
||||
@@ -95,6 +98,7 @@ void Skeleton::AccumulateBoneTransforms(bool noRootMotion, const Animation::Keyf
|
||||
std::string name = child->Name;
|
||||
AccumulateBoneTransforms(noRootMotion, currentFrame, nextFrame, progress, boneMatrices, child, boneMatrix);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int Skeleton::GetBoneID(std::string name)
|
||||
|
||||
@@ -198,7 +198,7 @@ bool SoundSystem::OnPlaySoundOnPosition(const Events::PlaySoundOnPosition & e)
|
||||
(float&)(double)emitter["RollOffFactor"] = e.RollOffFactor;
|
||||
(float&)(double)emitter["ReferenceDistance"] = e.ReferenceDistance;
|
||||
auto model = m_World->AttachComponent(emitterID, "Model");
|
||||
(std::string&)model["Resource"] = "Models/Core/UnitCube.obj";
|
||||
(std::string&)model["Resource"] = "Models/Core/UnitCube.mesh"; // 360NoScope UnitCube
|
||||
source->Type = SoundType::SFX;
|
||||
m_Sources[emitterID] = source;
|
||||
playSound(source);
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ Game::Game(int argc, char* argv[])
|
||||
m_FrameStack->Height = m_Renderer->Resolution().Height;
|
||||
|
||||
// Create a world
|
||||
m_World = new World();
|
||||
m_World = new World(m_EventBroker);
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
auto file = ResourceManager::Load<EntityFile>(mapToLoad);
|
||||
@@ -77,7 +77,7 @@ Game::Game(int argc, char* argv[])
|
||||
// All systems with orderlevel 0 will be updated first.
|
||||
unsigned int updateOrderLevel = 0;
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
//m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
|
||||
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
|
||||
|
||||
@@ -12,7 +12,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)
|
||||
ComponentWrapper player = m_World->GetComponent(component.EntityID, "Player");
|
||||
double maxHealth = (double)component["MaxHealth"];
|
||||
|
||||
//process the DeltaHealthVector and change the entitys health accordingly
|
||||
@@ -49,7 +48,7 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& comp
|
||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e)
|
||||
{
|
||||
//save the changed HP to a vector. it will be taken care of in UpdateComponent
|
||||
m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount));
|
||||
//m_DeltaHealthVector.push_back(std::make_tuple(e.PlayerDamagedID, -e.DamageAmount));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@ InterpolationSystem::InterpolationSystem(World* world, EventBroker* eventBroker)
|
||||
|
||||
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
|
||||
{
|
||||
// Don't interpolate entities that might already have been removed
|
||||
if (!entity.Valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
|
||||
m_NextTransform[transform.EntityID].interpolationTime += dt;
|
||||
Transform sTransform = m_NextTransform[transform.EntityID];
|
||||
@@ -31,11 +36,10 @@ void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrappe
|
||||
// Position
|
||||
glm::vec3 nextPosition = sTransform.Position;
|
||||
glm::vec3 currentPosition = static_cast<glm::vec3>(transform["Position"]);
|
||||
// HACK: Hardcoded tolerance value for player position desync = 1
|
||||
if (isLocalPlayer && glm::length(nextPosition - currentPosition) < 1.f) {
|
||||
return;
|
||||
// HACK: Don't force position for players
|
||||
if (!isLocalPlayer) {
|
||||
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
|
||||
}
|
||||
(glm::vec3&)transform["Position"] += vectorInterpolation<glm::vec3>(currentPosition, nextPosition, sTransform.interpolationTime);
|
||||
// Orientation
|
||||
// Don't force orientation for players
|
||||
if (!isLocalPlayer) {
|
||||
|
||||
@@ -5,49 +5,80 @@ WeaponSystem::WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* re
|
||||
, ImpureSystem()
|
||||
, m_Renderer(renderer)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot);
|
||||
}
|
||||
|
||||
void WeaponSystem::Update(double dt)
|
||||
{
|
||||
for (int i = m_EShootVector.size(); i > 0; i--)
|
||||
{
|
||||
//TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
|
||||
//pick the object
|
||||
PickData pickDataFromShot = m_Renderer->Pick(std::get<1>(m_EShootVector[i - 1]));
|
||||
if (pickDataFromShot.Entity == EntityID_Invalid) {
|
||||
m_EShootVector.erase(m_EShootVector.begin() + i - 1);
|
||||
continue;
|
||||
}
|
||||
//if its a player, do PlayerDamage event
|
||||
const bool hasPlayerComponent = m_World->HasComponent(pickDataFromShot.Entity, "Player");
|
||||
if (hasPlayerComponent) {
|
||||
Events::PlayerDamage ePlayerDamage;
|
||||
//TODO: damage based on weapontype/class?
|
||||
//TODO: multiple shots at the same time? (shotgunner)
|
||||
ePlayerDamage.DamageAmount = 25;
|
||||
ePlayerDamage.PlayerDamagedID = pickDataFromShot.Entity;
|
||||
m_EventBroker->Publish(ePlayerDamage);
|
||||
}
|
||||
m_EShootVector.erase(m_EShootVector.begin() + i - 1);
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e)
|
||||
{
|
||||
if (e.PlayerID == -1) {
|
||||
m_LocalPlayer = e.Player;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
// Only shoot client-side!
|
||||
if (e.PlayerID != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only shoot if the player is alive
|
||||
if (!m_LocalPlayer.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.Command == "PrimaryFire" && e.Value > 0) {
|
||||
Events::Shoot eShoot;
|
||||
eShoot.shooter = e.PlayerID;
|
||||
eShoot.Player = m_LocalPlayer;
|
||||
m_EventBroker->Publish(eShoot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& e) {
|
||||
//screen center, based on current resolution!
|
||||
|
||||
bool WeaponSystem::OnShoot(const Events::Shoot& eShoot) {
|
||||
// Screen center, based on current resolution!
|
||||
//TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
Rectangle screenResolution = m_Renderer->Resolution();
|
||||
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
|
||||
m_EShootVector.push_back(std::make_pair(e.shooter, centerScreen));
|
||||
|
||||
// TODO: check if player has enough ammo and if weapon has a cooldown or not
|
||||
|
||||
// Pick middle of screen
|
||||
PickData pickData = m_Renderer->Pick(centerScreen);
|
||||
if (pickData.Entity == EntityID_Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityWrapper player(m_World, pickData.Entity);
|
||||
|
||||
// Only care about players being hit
|
||||
if (!player.HasComponent("Player")) {
|
||||
player = player.FirstParentWithComponent("Player");
|
||||
}
|
||||
if (!player.Valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for friendly fire
|
||||
EntityWrapper shooter = eShoot.Player;
|
||||
if ((ComponentInfo::EnumType)player["Team"]["Team"] == (ComponentInfo::EnumType)shooter["Team"]["Team"]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Weapon damage calculations etc
|
||||
Events::PlayerDamage ePlayerDamage;
|
||||
ePlayerDamage.Player = player;
|
||||
ePlayerDamage.Damage = 100;
|
||||
m_EventBroker->Publish(ePlayerDamage);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ using boost::unit_test_framework::test_case;
|
||||
void RayTest(std::string fileName) {
|
||||
//simple box test
|
||||
Ray ray(glm::vec3(-50, 0, 0), glm::vec3(1, 0, 0));
|
||||
//using a rawmodel here, else we have to init the renderingsystem
|
||||
//using a
|
||||
|
||||
//here, else we have to init the renderingsystem
|
||||
ResourceManager::RegisterType<RawModel>("RawModel");
|
||||
auto unitBox = ResourceManager::Load<RawModel>(fileName);
|
||||
BOOST_REQUIRE(unitBox != nullptr);
|
||||
@@ -106,7 +108,7 @@ BOOST_AUTO_TEST_CASE(collisionTest2)
|
||||
BOOST_AUTO_TEST_CASE(rayVsModelTest)
|
||||
{
|
||||
//simple box test
|
||||
RayTest("Models/Core/UnitCube.obj");
|
||||
RayTest("Models/Core/UnitCube.mesh"); // 360NoScope Unitcube
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
||||
@@ -128,7 +130,7 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
||||
someAABB = AABB(minPos, maxPos);
|
||||
//using a rawmodel here, else we have to init the renderingsystem
|
||||
ResourceManager::RegisterType<RawModel>("RawModel");
|
||||
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitCube.obj");
|
||||
auto unitBox = ResourceManager::Load<RawModel>("Models/Core/UnitCube.mesh"); // 360NoScope unitcube
|
||||
BOOST_CHECK(unitBox != nullptr);
|
||||
|
||||
for (size_t i = 0; i < 1000000; i++)
|
||||
@@ -187,19 +189,19 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2)
|
||||
BOOST_AUTO_TEST_CASE(rayVsModelTest3)
|
||||
{
|
||||
//simple test
|
||||
RayTest("Models/Core/UnitSphere.obj");
|
||||
RayTest("Models/Core/UnitSphere.mesh"); // 360NoScope unitSphere
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rayVsModelTest4)
|
||||
{
|
||||
//simple test
|
||||
RayTest("Models/Core/UnitCylinder.obj");
|
||||
RayTest("Models/Core/UnitCylinder.mesh"); // 360NoScope unitCylinder
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rayVsModelTest5)
|
||||
{
|
||||
//simple test
|
||||
RayTest("Models/Core/UnitRaptor.obj");
|
||||
RayTest("Models/Core/UnitRaptor.mesh"); // 360NoScope unitRaptor
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(octTest)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ GameHealthSystemTest::GameHealthSystemTest()
|
||||
EntityID playerID = m_World->CreateEntity();
|
||||
ComponentWrapper transform = m_World->AttachComponent(playerID, "Transform");
|
||||
ComponentWrapper model = m_World->AttachComponent(playerID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
model["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere
|
||||
ComponentWrapper player = m_World->AttachComponent(playerID, "Player");
|
||||
ComponentWrapper health = m_World->AttachComponent(playerID, "Health");
|
||||
healthsID = playerID;
|
||||
@@ -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.Player = healthsID;
|
||||
m_EventBroker->Publish(e);
|
||||
//heal some other player with 40
|
||||
Events::PlayerHealthPickup e2;
|
||||
@@ -81,7 +81,7 @@ GameHealthSystemTest::GameHealthSystemTest()
|
||||
EntityID playerID2 = m_World->CreateEntity();
|
||||
ComponentWrapper transform2 = m_World->AttachComponent(playerID2, "Transform");
|
||||
ComponentWrapper model2 = m_World->AttachComponent(playerID2, "Model");
|
||||
model2["Resource"] = "Models/Core/UnitSphere.obj";
|
||||
model2["Resource"] = "Models/Core/UnitSphere.mesh"; // 360NoScope UnitSphere
|
||||
ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player");
|
||||
ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health");
|
||||
//END TEST
|
||||
|
||||
@@ -112,7 +112,7 @@ void OctTree::Update(float dt, World* world, Camera* cam)
|
||||
ComponentWrapper transform = world->AttachComponent(m_BoxID, "Transform");
|
||||
transform["Scale"] = boxSize;
|
||||
ComponentWrapper model = world->AttachComponent(m_BoxID, "Model");
|
||||
model["Resource"] = "Models/Core/UnitBox.obj";
|
||||
model["Resource"] = "Models/Core/UnitBox.mesh"; // 360NoScope UnitBox
|
||||
m_UpdatedOnce = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ BOOST_AUTO_TEST_CASE(resourceManagerTest)
|
||||
BOOST_CHECK(!ResourceManager::IsResourceLoaded("ConfigFile", "Config.ini"));
|
||||
|
||||
//configfile without register
|
||||
BOOST_CHECK_THROW(ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj"),Resource::FailedLoadingException);
|
||||
BOOST_CHECK_THROW(ResourceManager::Load<Model>("Models/Core/ScreenQuad.mesh"),Resource::FailedLoadingException);
|
||||
//there is no error feedback to check if you try to release the wrong resources - hence that cant be tested either
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
#include "Export.h"
|
||||
|
||||
Export::Export()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Export::Meshes(std::string pathName, bool selectedOnly)
|
||||
{
|
||||
MStatus status;
|
||||
if (pathName.empty()) {
|
||||
MGlobal::displayError(MString() + "Export::Meshes() got no pathName. Do not know where to write file");
|
||||
return false;
|
||||
}
|
||||
|
||||
MSelectionList selectedOnStart;
|
||||
MGlobal::getActiveSelectionList(selectedOnStart);
|
||||
if (selectedOnStart.length() > 0) {
|
||||
for (int i = 0; i < selectedOnStart.length(); i++) {
|
||||
MObject item;
|
||||
selectedOnStart.getDependNode(i, item);
|
||||
MGlobal::unselect(item);
|
||||
}
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "Disabel IKSolvers");
|
||||
status = MGlobal::executeCommand("doEnableNodeItems false all;");
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "EnableNodeItems false all failed: " + status.errorString());
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "Has disabel IKSolvers");
|
||||
MObjectArray Objects;
|
||||
if (selectedOnly) {
|
||||
// Retrieving the objects we currently have selected
|
||||
|
||||
// Loop through or list of selection(s)
|
||||
for (unsigned int i = 0; i < selectedOnStart.length(); i++) {
|
||||
MObject object;
|
||||
selectedOnStart.getDependNode(i, object);
|
||||
|
||||
if (object.hasFn(MFn::kMesh)) {
|
||||
MFnMesh shape(object);
|
||||
|
||||
for (unsigned int k = 0; k < shape.parentCount(); k++) {
|
||||
MFnDependencyNode thisNode(object);
|
||||
MPlugArray connections;
|
||||
thisNode.findPlug("inMesh").connectedTo(connections, true, true);
|
||||
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
MGlobal::select(shape.parent(i), MGlobal::kReplaceList);
|
||||
MGlobal::displayInfo(MString() + "Moving " + thisNode.name() + " to bindPose.");
|
||||
status = MGlobal::executeCommand("GoToBindPose;");
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "GoToBindPose: " + status.errorString());
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "Has moved " + thisNode.name() + " to bindPose.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Objects.append(object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Loop through all nodes in the scene
|
||||
MItDependencyNodes it(MFn::kMesh);
|
||||
for (; !it.isDone(); it.next()) {
|
||||
MObject node = it.thisNode();
|
||||
MFnDependencyNode thisNode(node);
|
||||
MPlugArray connections;
|
||||
thisNode.findPlug("inMesh").connectedTo(connections, true, true);
|
||||
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
MGlobal::select(node);
|
||||
MGlobal::displayInfo(MString() + "Moving " + thisNode.name() + " to bindPose.");
|
||||
MGlobal::executeCommand("GoToBindPose");
|
||||
MGlobal::displayInfo(MString() + "Has moved " + thisNode.name() + " to bindPose.");
|
||||
}
|
||||
}
|
||||
|
||||
Objects.append(node);
|
||||
}
|
||||
}
|
||||
GetMeshData(Objects);
|
||||
WriteMeshData(pathName);
|
||||
MGlobal::displayInfo(MString() + "Enabling IKSolvers");
|
||||
status = MGlobal::executeCommand("doEnableNodeItems true all;");
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "doEnableNodeItems true all: " + status.errorString());
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "Has enabling IKSolvers");
|
||||
if (selectedOnStart.length() > 0) {
|
||||
for (int i = 0; i < selectedOnStart.length(); i++) {
|
||||
MObject item;
|
||||
selectedOnStart.getDependNode(i, item);
|
||||
MGlobal::select(item);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::Materials(std::string pathName)
|
||||
{
|
||||
if (!GetMaterialData())
|
||||
return false;
|
||||
WriteMaterialData(pathName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::Animations(std::string pathName, std::vector<AnimationInfo> animInfo)
|
||||
{
|
||||
if (MAnimControl::currentTime().unit() != MTime::kNTSCField) {
|
||||
|
||||
MGlobal::displayError(MString() + "Please change to 60 FPS under Preferences/Settings!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pathName.empty()) {
|
||||
MGlobal::displayError(MString() + "Export::Animations() got no pathName. Do not know where to write file");
|
||||
return false;
|
||||
}
|
||||
allBindPoses = m_SkeletonHandler.GetBindPoses();
|
||||
|
||||
for (auto clip : animInfo) {
|
||||
if (!GetAnimationData(clip)) {
|
||||
MGlobal::displayError(MString() + "Export::Animations() failed to export " + clip.Name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
WriteAnimData(pathName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetMeshData(MObjectArray object)
|
||||
{
|
||||
meshes = m_MeshHandler.GetMeshData(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetMaterialData()
|
||||
{
|
||||
// Traverse scene and return vector with all materials
|
||||
AllMaterials = m_MaterialHandler.DoIt(meshes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetAnimationData(AnimationInfo animInfo)
|
||||
{
|
||||
if (animInfo.Name.empty()) {
|
||||
MGlobal::displayError(MString() + "A clip does not have a name");
|
||||
return false;
|
||||
}
|
||||
if (animInfo.End - animInfo.Start <= 0) {
|
||||
MGlobal::displayError(MString() + "A clip ends before it starts or contains 0 frames");
|
||||
return false;
|
||||
}
|
||||
|
||||
allAnimations.push_back(m_SkeletonHandler.GetAnimData(animInfo.Name, animInfo.Start, animInfo.End));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Export::WriteMeshData(std::string pathName)
|
||||
{
|
||||
m_MeshFile.ASCIIFilePath(pathName +"_mesh.txt");
|
||||
m_MeshFile.binaryFilePath(pathName + ".mesh");
|
||||
|
||||
m_MeshFile.OpenFiles();
|
||||
|
||||
m_MeshFile.writeToFiles((OutputData*)&meshes);
|
||||
|
||||
m_MeshFile.CloseFiles();
|
||||
}
|
||||
|
||||
void Export::WriteAnimData(std::string pathName)
|
||||
{
|
||||
if (allBindPoses.size() > 0) {
|
||||
m_AnimFile.ASCIIFilePath(pathName + "_anim.txt");
|
||||
m_AnimFile.binaryFilePath(pathName + ".anim");
|
||||
|
||||
m_AnimFile.OpenFiles();
|
||||
int size = allBindPoses.size();
|
||||
m_AnimFile.writeToFiles(&size);
|
||||
|
||||
|
||||
size = allAnimations.size();
|
||||
m_AnimFile.writeToFiles(&size);
|
||||
|
||||
//print out all bind poses
|
||||
for (auto aBindPose : allBindPoses) {
|
||||
m_AnimFile.writeToFiles((OutputData*)&aBindPose);
|
||||
}
|
||||
for (auto aAnimation : allAnimations) {
|
||||
m_AnimFile.writeToFiles((OutputData*)&aAnimation);
|
||||
}
|
||||
|
||||
m_AnimFile.CloseFiles();
|
||||
} else
|
||||
MGlobal::displayInfo("Export::WriteAnimData() got called when allBindPoses contained no data, did not write nor created them");
|
||||
}
|
||||
|
||||
void Export::WriteMaterialData(std::string pathName)
|
||||
{
|
||||
m_MtrlFile.ASCIIFilePath(pathName +"_mtrl.txt");
|
||||
m_MtrlFile.binaryFilePath(pathName + ".mtrl");
|
||||
|
||||
m_MtrlFile.OpenFiles();
|
||||
|
||||
int size = (*AllMaterials).size();
|
||||
m_MtrlFile.writeToFiles(&size);
|
||||
|
||||
for (auto aMaterial : *AllMaterials) {
|
||||
m_MtrlFile.writeToFiles((OutputData*)&aMaterial);
|
||||
}
|
||||
m_MtrlFile.CloseFiles();
|
||||
}
|
||||
|
||||
Export::~Export()
|
||||
{
|
||||
/* delete m_MaterialHandler;
|
||||
delete m_SkeletonHandler;
|
||||
delete m_MeshHandler;*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef Export_Export_h__
|
||||
#define Export_Export_h__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
#include "Material.h"
|
||||
#include "Mesh.h"
|
||||
#include "Skeleton.h"
|
||||
#include "WriteToFile.h"
|
||||
|
||||
class Export {
|
||||
public:
|
||||
Export();
|
||||
|
||||
~Export();
|
||||
|
||||
struct AnimationInfo {
|
||||
std::string Name;
|
||||
int Start;
|
||||
int End;
|
||||
};
|
||||
|
||||
bool Meshes(std::string pathName, bool selectedOnly = false);
|
||||
bool Materials(std::string pathName);
|
||||
bool Animations(std::string pathName, std::vector<AnimationInfo> animInfo);
|
||||
|
||||
private:
|
||||
bool GetMeshData(MObjectArray object);
|
||||
bool GetMaterialData();
|
||||
bool GetAnimationData(AnimationInfo info);
|
||||
|
||||
void WriteMeshData(std::string pathName);
|
||||
void WriteAnimData(std::string pathName);
|
||||
void WriteMaterialData(std::string pathName);
|
||||
|
||||
Material m_MaterialHandler;
|
||||
Skeleton m_SkeletonHandler;
|
||||
MeshClass m_MeshHandler;
|
||||
|
||||
|
||||
//File export
|
||||
WriteToFile m_MeshFile;
|
||||
WriteToFile m_AnimFile;
|
||||
WriteToFile m_MtrlFile;
|
||||
|
||||
//Mesh Data
|
||||
Mesh meshes;
|
||||
|
||||
//Animation Data
|
||||
std::vector<BindPoseSkeletonNode> allBindPoses;
|
||||
std::vector<Animation> allAnimations;
|
||||
|
||||
//Material Data
|
||||
std::vector<MaterialNode>* AllMaterials;
|
||||
};
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@ static const uint qt_meta_data_Menu[] = {
|
||||
6, // revision
|
||||
0, // classname
|
||||
0, 0, // classinfo
|
||||
7, 14, // methods
|
||||
5, 14, // methods
|
||||
0, 0, // properties
|
||||
0, 0, // enums/sets
|
||||
0, 0, // constructors
|
||||
@@ -30,22 +30,19 @@ static const uint qt_meta_data_Menu[] = {
|
||||
0, // signalCount
|
||||
|
||||
// slots: signature, parameters, type, tag, flags
|
||||
14, 6, 5, 5, 0x08,
|
||||
35, 5, 5, 5, 0x08,
|
||||
59, 5, 5, 5, 0x08,
|
||||
6, 5, 5, 5, 0x08,
|
||||
30, 5, 5, 5, 0x08,
|
||||
51, 5, 5, 5, 0x08,
|
||||
75, 5, 5, 5, 0x08,
|
||||
95, 5, 5, 5, 0x08,
|
||||
116, 5, 5, 5, 0x08,
|
||||
137, 5, 5, 5, 0x08,
|
||||
91, 5, 5, 5, 0x08,
|
||||
|
||||
0 // eod
|
||||
};
|
||||
|
||||
static const char qt_meta_stringdata_Menu[] = {
|
||||
"Menu\0\0checked\0ExportSelected(bool)\0"
|
||||
"ExportPathClicked(bool)\0ExportAll(bool)\0"
|
||||
"CancelClicked(bool)\0Button1Clicked(bool)\0"
|
||||
"Button2Clicked(bool)\0Button3Clicked(bool)\0"
|
||||
"Menu\0\0ExportPathClicked(bool)\0"
|
||||
"AddClipClicked(bool)\0RemoveClipClicked(bool)\0"
|
||||
"ExportAll(bool)\0CancelClicked(bool)\0"
|
||||
};
|
||||
|
||||
void Menu::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
|
||||
@@ -54,13 +51,11 @@ void Menu::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void *
|
||||
Q_ASSERT(staticMetaObject.cast(_o));
|
||||
Menu *_t = static_cast<Menu *>(_o);
|
||||
switch (_id) {
|
||||
case 0: _t->ExportSelected((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 1: _t->ExportPathClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 2: _t->ExportAll((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 3: _t->CancelClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 4: _t->Button1Clicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 5: _t->Button2Clicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 6: _t->Button3Clicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 0: _t->ExportPathClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 1: _t->AddClipClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 2: _t->RemoveClipClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 3: _t->ExportAll((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
case 4: _t->CancelClicked((*reinterpret_cast< bool(*)>(_a[1]))); break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
@@ -98,9 +93,9 @@ int Menu::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
|
||||
if (_id < 0)
|
||||
return _id;
|
||||
if (_c == QMetaObject::InvokeMetaMethod) {
|
||||
if (_id < 7)
|
||||
if (_id < 5)
|
||||
qt_static_metacall(this, _c, _id, _a);
|
||||
_id -= 7;
|
||||
_id -= 5;
|
||||
}
|
||||
return _id;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
#include "Material.h"
|
||||
|
||||
void Material::grabLambertProperties(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
material_node.Name = node.name().asChar();
|
||||
|
||||
if (!findColorTexture(material_node, node)) {
|
||||
node.findPlug("colorR").getValue(material_node.DiffuseColor[0]);
|
||||
node.findPlug("colorG").getValue(material_node.DiffuseColor[1]);
|
||||
node.findPlug("colorB").getValue(material_node.DiffuseColor[2]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!findIncandescenceTexture(material_node, node)) {
|
||||
node.findPlug("incandescenceR").getValue(material_node.IncandescenceColor[0]);
|
||||
node.findPlug("incandescenceG").getValue(material_node.IncandescenceColor[1]);
|
||||
node.findPlug("incandescenceB").getValue(material_node.IncandescenceColor[2]);
|
||||
}
|
||||
|
||||
if (findNormalTexture(material_node, node)) {
|
||||
MGlobal::displayWarning(MString() + "Material " + node.name() + " has no normal texture.");
|
||||
}
|
||||
}
|
||||
|
||||
void Material::grabBlinnProperties(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
if (!findSpecularTexture(material_node, node)) {
|
||||
node.findPlug("specularColorR").getValue(material_node.SpecularColor[0]);
|
||||
node.findPlug("specularColorG").getValue(material_node.SpecularColor[1]);
|
||||
node.findPlug("specularColorB").getValue(material_node.SpecularColor[2]);
|
||||
}
|
||||
|
||||
m_Plug = node.findPlug("reflectivity");
|
||||
m_Plug.getValue(material_node.ReflectionFactor);
|
||||
|
||||
m_Plug = node.findPlug("eccentricity");
|
||||
float TempEccent;
|
||||
m_Plug.getValue(TempEccent);
|
||||
|
||||
// Blinn works differently from Phong which is used in-game.
|
||||
// This is some magic numbers and math to make a conversion estimate between the two.
|
||||
// There is no exact conversion between the two, so there are errors.
|
||||
|
||||
// Phong min/max is around Blinn 0.7/0.1
|
||||
TempEccent = std::max(std::min(TempEccent, 0.7f), 0.1f);
|
||||
|
||||
material_node.SpecularExponent = std::max(std::min(((2.66f) + (427.0f) * exp((-14.8f) * TempEccent)), 100.0f), 2.0f);
|
||||
}
|
||||
|
||||
void Material::grabPhongProperties(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
if (!findSpecularTexture(material_node, node)) {
|
||||
node.findPlug("specularColorR").getValue(material_node.SpecularColor[0]);
|
||||
node.findPlug("specularColorG").getValue(material_node.SpecularColor[1]);
|
||||
node.findPlug("specularColorB").getValue(material_node.SpecularColor[2]);
|
||||
}
|
||||
|
||||
m_Plug = node.findPlug("reflectivity");
|
||||
m_Plug.getValue(material_node.ReflectionFactor);
|
||||
|
||||
m_Plug = node.findPlug("cosinePower ");
|
||||
m_Plug.getValue(material_node.SpecularExponent);
|
||||
}
|
||||
|
||||
bool Material::findColorTexture(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
MPlugArray AllConnections;
|
||||
|
||||
m_Plug = node.findPlug("color", true);
|
||||
m_Plug.connectedTo(AllConnections, true, false);
|
||||
|
||||
for (int i = 0; i < AllConnections.length(); i++) {
|
||||
if (AllConnections[i].node().hasFn(MFn::kFileTexture)) {
|
||||
MFnDependencyNode TextureNode(AllConnections[i].node());
|
||||
|
||||
std::string FullPath = TextureNode.findPlug("fileTextureName").asString().asChar();
|
||||
m_TexturePaths.push_back(FullPath);
|
||||
|
||||
MString workspace;
|
||||
MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"),
|
||||
workspace);
|
||||
FullPath = FullPath.substr(workspace.length());
|
||||
FullPath = FullPath.substr(FullPath.find_first_of("/") + 1);
|
||||
material_node.ColorMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size());
|
||||
|
||||
material_node.ColorMapFileLength = material_node.ColorMapFile.length() + 1;
|
||||
// Test
|
||||
MGlobal::displayInfo(MString() + "getAbsolutePathToResources: " + workspace);
|
||||
MGlobal::displayInfo(MString() + "Texture file: " + FullPath.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::findNormalTexture(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
MPlugArray AllConnections;
|
||||
MPlugArray AllBumpConnections;
|
||||
|
||||
m_Plug = node.findPlug("normalCamera", true);
|
||||
m_Plug.connectedTo(AllConnections, true, false);
|
||||
|
||||
for (int i = 0; i < AllConnections.length(); i++) {
|
||||
if (AllConnections[i].node().apiType() == MFn::kBump) {
|
||||
MFnDependencyNode BumpNode(AllConnections[i].node());
|
||||
|
||||
BumpNode.findPlug("bumpValue").connectedTo(AllBumpConnections, true, false);
|
||||
for (int j = 0; j < AllBumpConnections.length(); j++) {
|
||||
if (AllBumpConnections[j].node().hasFn(MFn::kFileTexture)) {
|
||||
MFnDependencyNode TextureNode(AllBumpConnections[j].node());
|
||||
|
||||
std::string FullPath = TextureNode.findPlug("ftn").asString().asChar();
|
||||
m_TexturePaths.push_back(FullPath);
|
||||
|
||||
MString workspace;
|
||||
MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"),
|
||||
workspace);
|
||||
FullPath = FullPath.substr(workspace.length());
|
||||
FullPath = FullPath.substr(FullPath.find_first_of("/") + 1);
|
||||
material_node.NormalMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size());
|
||||
material_node.NormalMapFileLength = material_node.NormalMapFile.length() + 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::findSpecularTexture(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
MPlugArray AllConnections;
|
||||
|
||||
m_Plug = node.findPlug("specularColor", true);
|
||||
m_Plug.connectedTo(AllConnections, true, false);
|
||||
|
||||
for (int i = 0; i < AllConnections.length(); i++) {
|
||||
if (AllConnections[i].node().hasFn(MFn::kFileTexture)) {
|
||||
MFnDependencyNode TextureNode(AllConnections[i].node());
|
||||
|
||||
std::string FullPath = TextureNode.findPlug("ftn").asString().asChar();
|
||||
m_TexturePaths.push_back(FullPath);
|
||||
|
||||
MString workspace;
|
||||
MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"),
|
||||
workspace);
|
||||
FullPath = FullPath.substr(workspace.length());
|
||||
FullPath = FullPath.substr(FullPath.find_first_of("/") + 1);
|
||||
material_node.SpecularMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size());
|
||||
material_node.SpecularMapFileLength = material_node.SpecularMapFile.length() + 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::findIncandescenceTexture(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
MPlugArray AllConnections;
|
||||
|
||||
m_Plug = node.findPlug("incandescence", true);
|
||||
m_Plug.connectedTo(AllConnections, true, false);
|
||||
|
||||
for (int i = 0; i < AllConnections.length(); i++) {
|
||||
if (AllConnections[i].node().hasFn(MFn::kFileTexture)) {
|
||||
MFnDependencyNode TextureNode(AllConnections[i].node());
|
||||
|
||||
std::string FullPath = TextureNode.findPlug("ftn").asString().asChar();
|
||||
m_TexturePaths.push_back(FullPath);
|
||||
|
||||
MString workspace;
|
||||
MStatus status = MGlobal::executeCommand(MString("workspace -q -rd;"),
|
||||
workspace);
|
||||
FullPath = FullPath.substr(workspace.length());
|
||||
FullPath = FullPath.substr(FullPath.find_first_of("/") + 1);
|
||||
material_node.IncandescenceMapFile = FullPath.erase(FullPath.find_last_of("."), FullPath.find_last_of(".") - FullPath.size());
|
||||
material_node.IncandescenceMapFileLength = material_node.IncandescenceMapFile.length() + 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the absolute path for all textures. Use for copying texture files.
|
||||
std::vector<std::string>* Material::TexturePaths()
|
||||
{
|
||||
return &m_TexturePaths;
|
||||
}
|
||||
|
||||
// Traverse the DAG and grab all the materials
|
||||
std::vector<MaterialNode>* Material::DoIt(Mesh mesh)
|
||||
{
|
||||
// All materials we care about inherit from Lambert
|
||||
MItDependencyNodes matIt(MFn::kLambert);
|
||||
m_AllMaterials.clear();
|
||||
while (!matIt.isDone()) {
|
||||
MFnDependencyNode MaterialFnDN(matIt.thisNode());
|
||||
MaterialNode MaterialStorage;
|
||||
bool meshHasMaterial = false;
|
||||
//Mesh Indices is a map with <string : MaterialName, vector<int> : indices>
|
||||
int totalIndices = 0;
|
||||
for (auto aMeshMaterial : mesh.Indices) {
|
||||
MGlobal::displayInfo(MString() + "Material: " + aMeshMaterial.first.c_str() + " " + MaterialFnDN.name().asChar());
|
||||
if (aMeshMaterial.first.compare(MaterialFnDN.name().asChar()) == 0) {
|
||||
meshHasMaterial = true;
|
||||
MaterialStorage.IndexStart = totalIndices;
|
||||
MaterialStorage.IndexEnd = totalIndices + aMeshMaterial.second.size() - 1;
|
||||
break;
|
||||
}
|
||||
totalIndices += aMeshMaterial.second.size();
|
||||
}
|
||||
if (meshHasMaterial) {
|
||||
grabLambertProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
if (matIt.thisNode().hasFn(MFn::kPhong)) {
|
||||
grabPhongProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
} else if (matIt.thisNode().hasFn(MFn::kBlinn)) {
|
||||
grabBlinnProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
} else if (matIt.thisNode().hasFn(MFn::kLambert)) {
|
||||
MaterialStorage.ReflectionFactor = 0.0f;
|
||||
MaterialStorage.SpecularExponent = 0.0f;
|
||||
}
|
||||
|
||||
m_AllMaterials.push_back(MaterialStorage);
|
||||
}
|
||||
matIt.next();
|
||||
}
|
||||
|
||||
return &m_AllMaterials;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef Material_Material_h__
|
||||
#define Material_Material_h__
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
#include "OutputData.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
class MaterialNode : public OutputData
|
||||
{
|
||||
public:
|
||||
std::string Name;
|
||||
|
||||
float ReflectionFactor;
|
||||
float SpecularExponent;
|
||||
|
||||
float DiffuseColor[3]{ 1.0f, 1.0f, 1.0f };
|
||||
unsigned int ColorMapFileLength = 0;
|
||||
std::string ColorMapFile;
|
||||
|
||||
float SpecularColor[3]{ 1.0f, 1.0f, 1.0f };
|
||||
unsigned int SpecularMapFileLength = 0;
|
||||
std::string SpecularMapFile;
|
||||
|
||||
unsigned int NormalMapFileLength = 0;
|
||||
std::string NormalMapFile;
|
||||
|
||||
float IncandescenceColor[3]{ 1.0f, 1.0f, 1.0f };
|
||||
unsigned int IncandescenceMapFileLength = 0;
|
||||
std::string IncandescenceMapFile;
|
||||
|
||||
unsigned int IndexStart;
|
||||
unsigned int IndexEnd;
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&ColorMapFileLength, sizeof(unsigned int));
|
||||
out.write((char*)&NormalMapFileLength, sizeof(unsigned int));
|
||||
out.write((char*)&SpecularMapFileLength, sizeof(unsigned int));
|
||||
out.write((char*)&IncandescenceMapFileLength, sizeof(unsigned int));
|
||||
|
||||
out.write((char*)&SpecularExponent, sizeof(float));
|
||||
out.write((char*)&ReflectionFactor, sizeof(float));
|
||||
out.write((char*)&DiffuseColor, sizeof(float) * 3);
|
||||
out.write((char*)&SpecularColor, sizeof(float) * 3);
|
||||
out.write((char*)&IncandescenceColor, sizeof(float) * 3);
|
||||
out.write((char*)&IndexStart, sizeof(unsigned int));
|
||||
out.write((char*)&IndexEnd, sizeof(unsigned int));
|
||||
|
||||
out.write(ColorMapFile.c_str(), ColorMapFileLength);
|
||||
out.write(NormalMapFile.c_str(), NormalMapFileLength);
|
||||
out.write(SpecularMapFile.c_str(), SpecularMapFileLength);
|
||||
out.write(IncandescenceMapFile.c_str(), IncandescenceMapFileLength);
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "New Material _ not in binary" << endl;
|
||||
out << "number of indices: " << Name << " _ not in binary" << endl;
|
||||
|
||||
out << "ColorMapFile length: " << ColorMapFileLength << endl;
|
||||
out << "NormalMapFile length: " << NormalMapFileLength << endl;
|
||||
out << "SpecularMapFile length: " << SpecularMapFileLength << endl;
|
||||
out << "IncandescenceMapFile length: " << IncandescenceMapFileLength << endl;
|
||||
|
||||
out << "SpecularExponent: " << SpecularExponent << endl;
|
||||
out << "ReflectionFactor: " << ReflectionFactor << endl;
|
||||
out << "DiffuseColor: " << DiffuseColor[0] << " " << DiffuseColor[1] << " " << DiffuseColor[2] << endl;
|
||||
out << "SpecularColor: " << SpecularColor[0] << " " << SpecularColor[1] << " " << SpecularColor[2] << endl;
|
||||
out << "IncandescenceColor: " << IncandescenceColor[0] << " " << IncandescenceColor[1] << " " << IncandescenceColor[2] << endl;
|
||||
out << "IndexStart: " << IndexStart << endl;
|
||||
out << "IndexEnd: " << IndexEnd << endl;
|
||||
|
||||
if (ColorMapFileLength > 0)
|
||||
out << "ColorMapFile: " << ColorMapFile << endl;
|
||||
|
||||
if (NormalMapFileLength > 0)
|
||||
out << "NormalMapFile: " << NormalMapFile << endl;
|
||||
|
||||
if (SpecularMapFileLength > 0)
|
||||
out << "SpecularMapFile: " << SpecularMapFile << endl;
|
||||
|
||||
if (IncandescenceMapFileLength > 0)
|
||||
out << "IncandescenceMapFile: " << IncandescenceMapFile << endl;
|
||||
}
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material() {};
|
||||
~Material() {};
|
||||
std::vector<MaterialNode>* DoIt(Mesh mesh);
|
||||
std::vector<std::string>* TexturePaths();
|
||||
private:
|
||||
MPlug m_Plug;
|
||||
|
||||
std::vector<MaterialNode> m_AllMaterials;
|
||||
std::vector<std::string> m_TexturePaths;
|
||||
|
||||
bool findColorTexture(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
bool findNormalTexture(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
bool findSpecularTexture(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
bool findIncandescenceTexture(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
void grabLambertProperties(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
void grabBlinnProperties(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
void grabPhongProperties(MaterialNode& material_node, MFnDependencyNode& node);
|
||||
};
|
||||
|
||||
#endif // Material_Material_h__
|
||||
@@ -140,6 +140,7 @@
|
||||
</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -152,6 +153,8 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Export.cpp" />
|
||||
<ClCompile Include="Material.cpp" />
|
||||
<ClCompile Include="Menu.cpp" />
|
||||
<ClCompile Include="GeneratedFiles\Debug\moc_Menu.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@@ -172,6 +175,9 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="Mesh.cpp" />
|
||||
<ClCompile Include="Skeleton.cpp" />
|
||||
<ClCompile Include="WriteToFile.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="MayaExporter.ui">
|
||||
@@ -194,6 +200,11 @@
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Export.h" />
|
||||
<ClInclude Include="Mesh.h" />
|
||||
<ClInclude Include="OutputData.h" />
|
||||
<ClInclude Include="Skeleton.h" />
|
||||
<ClInclude Include="WriteToFile.h" />
|
||||
<CustomBuild Include="Menu.h">
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing Menu.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
@@ -213,6 +224,7 @@
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="GeneratedFiles\ui_MayaExporter.h" />
|
||||
<ClInclude Include="Material.h" />
|
||||
<ClInclude Include="MayaIncludes.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -50,6 +50,21 @@
|
||||
<ClCompile Include="Main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Material.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mesh.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Skeleton.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WriteToFile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Export.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="leeeeel.qrc">
|
||||
@@ -69,5 +84,23 @@
|
||||
<ClInclude Include="GeneratedFiles\ui_MayaExporter.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Material.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mesh.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Skeleton.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WriteToFile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="OutputData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Export.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -30,6 +30,21 @@
|
||||
#include <maya/MItDependencyNodes.h>
|
||||
#include <maya/MFnNurbsCurve.h>
|
||||
#include <maya/MCommandMessage.h>
|
||||
#include <maya/MPlug.h>
|
||||
#include <maya/MAnimControl.h>
|
||||
#include <maya/MTime.h>
|
||||
#include <maya/MDataHandle.h>
|
||||
#include <maya/MTransformationMatrix.h>
|
||||
#include <maya/MFnMatrixData.h>
|
||||
#include <maya/MItMeshFaceVertex.h>
|
||||
#include <maya/MFnSkinCluster.h>
|
||||
#include <maya/MDagPathArray.h>
|
||||
#include <maya/MItGeometry.h>
|
||||
#include <maya/MItMeshVertex.h>
|
||||
#include <maya/MFnWeightGeometryFilter.h>
|
||||
#include <maya/MItDependencyGraph.h>
|
||||
#include <maya/MQuaternion.h>
|
||||
#include <maya/MFnNumericAttribute.h>
|
||||
|
||||
|
||||
// Wrappers
|
||||
@@ -58,5 +73,6 @@
|
||||
#pragma comment(lib,"Foundation.lib")
|
||||
#pragma comment(lib,"OpenMaya.lib")
|
||||
#pragma comment(lib,"OpenMayaUI.lib")
|
||||
#pragma comment (lib, "OpenMayaAnim.lib")
|
||||
|
||||
#endif
|
||||
@@ -10,223 +10,200 @@ Menu::Menu()
|
||||
Menu::Menu(QDialog* dialog)
|
||||
{
|
||||
// Save the dialog pointer. Needed when the application gets destroyed
|
||||
dialogPointer = dialog;
|
||||
m_DialogPointer = dialog;
|
||||
|
||||
// Create QpushButtons & give them names
|
||||
exportSelectedButton = new QPushButton("&Export Selected", this);
|
||||
browseButton = new QPushButton("&...", this);
|
||||
exportAllButton = new QPushButton("&Export All", this);
|
||||
cancelButton = new QPushButton("&Cancel", this);
|
||||
m_BrowseButton = new QPushButton("&...", this);
|
||||
m_ExportAllButton = new QPushButton("&Export", this);
|
||||
m_CancelButton = new QPushButton("&Cancel", this);
|
||||
m_AddClipsButton = new QPushButton("&Add Clips", this);
|
||||
m_RemoveClipsButton = new QPushButton("&Remove Latest Clip", this);
|
||||
|
||||
// Option box and checkboxes
|
||||
QGroupBox *optionsBox = new QGroupBox(tr("Options"));
|
||||
|
||||
exportAnimationsButton = new QCheckBox(tr("&Export Animations"));
|
||||
copyTexturesButton = new QCheckBox(tr("&Copy Textures"));
|
||||
button3 = new QCheckBox(tr("option3"));
|
||||
m_ExportSelectedButton = new QCheckBox(tr("&Export Selected"));
|
||||
m_ExportAnimationsButton = new QCheckBox(tr("&Export Animations"));
|
||||
m_ExportMaterialButton = new QCheckBox(tr("&Export Material"));;
|
||||
|
||||
exportAnimationsButton->setChecked(true);
|
||||
copyTexturesButton->setChecked(true);
|
||||
m_ExportAnimationsButton->setChecked(true);
|
||||
m_ExportMaterialButton->setChecked(true);
|
||||
QVBoxLayout *vbox = new QVBoxLayout;
|
||||
vbox->addWidget(exportAnimationsButton);
|
||||
vbox->addWidget(copyTexturesButton);
|
||||
vbox->addWidget(button3);
|
||||
vbox->addWidget(m_ExportSelectedButton);
|
||||
vbox->addWidget(m_ExportAnimationsButton);
|
||||
vbox->addWidget(m_ExportMaterialButton);
|
||||
|
||||
vbox->addStretch(1);
|
||||
optionsBox->setLayout(vbox);
|
||||
|
||||
// Connect the buttons with signals & functions
|
||||
connect(exportSelectedButton, SIGNAL(clicked(bool)), this, SLOT(ExportSelected(bool)));
|
||||
connect(browseButton, SIGNAL(clicked(bool)), this, SLOT(ExportPathClicked(bool)));
|
||||
connect(exportAllButton, SIGNAL(clicked(bool)), this, SLOT(ExportAll(bool)));
|
||||
connect(cancelButton, SIGNAL(clicked(bool)), this, SLOT(CancelClicked(bool)));
|
||||
connect(m_BrowseButton, SIGNAL(clicked(bool)), this, SLOT(ExportPathClicked(bool)));
|
||||
connect(m_ExportAllButton, SIGNAL(clicked(bool)), this, SLOT(ExportAll(bool)));
|
||||
connect(m_CancelButton, SIGNAL(clicked(bool)), this, SLOT(CancelClicked(bool)));
|
||||
connect(m_AddClipsButton, SIGNAL(clicked(bool)), this, SLOT(AddClipClicked(bool)));
|
||||
connect(m_RemoveClipsButton, SIGNAL(clicked(bool)), this, SLOT(RemoveClipClicked(bool)));
|
||||
|
||||
connect(exportAnimationsButton, SIGNAL(clicked(bool)), this, SLOT(Button1Clicked(bool)));
|
||||
connect(copyTexturesButton, SIGNAL(clicked(bool)), this, SLOT(Button2Clicked(bool)));
|
||||
connect(button3, SIGNAL(clicked(bool)), this, SLOT(Button3Clicked(bool)));
|
||||
connect(m_ExportSelectedButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_ExportAnimationsButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_ExportMaterialButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
|
||||
// Creating several layouts, adding widgets & adding them to one layout in the end
|
||||
QHBoxLayout* topLayout = new QHBoxLayout;
|
||||
QVBoxLayout* midLayout = new QVBoxLayout;
|
||||
QHBoxLayout* botLayout = new QHBoxLayout;
|
||||
QVBoxLayout* baseLayout = new QVBoxLayout;
|
||||
QHBoxLayout* clipButtonLayout = new QHBoxLayout;
|
||||
QHBoxLayout* startEndLabelLayout = new QHBoxLayout;
|
||||
m_ClipLayout = new QVBoxLayout;
|
||||
|
||||
exportPath = new QLineEdit;
|
||||
fileDialog = new QFileDialog;
|
||||
|
||||
|
||||
m_ExportPath = new QLineEdit;
|
||||
m_FileDialog = new QFileDialog;
|
||||
QString tmpPath("C:/Users/Nickelodion/Desktop/workspace/tacticalZ/assets/models/");
|
||||
m_ExportPath->setText(tmpPath);
|
||||
QLabel* exportLabel = new QLabel;
|
||||
exportLabel->setText("Export Path:");
|
||||
|
||||
QLabel* nameLabel = new QLabel;
|
||||
nameLabel->setText("Name:");
|
||||
QLabel* startLabel = new QLabel;
|
||||
startLabel->setText("Start:");
|
||||
QLabel* endLabel = new QLabel;
|
||||
endLabel->setText("End:");
|
||||
|
||||
//exportLabel->setText("Export Path:");
|
||||
|
||||
midLayout->addWidget(optionsBox);
|
||||
|
||||
topLayout->addWidget(exportLabel);
|
||||
topLayout->addWidget(exportPath);
|
||||
topLayout->addWidget(browseButton);
|
||||
topLayout->addWidget(m_ExportPath);
|
||||
topLayout->addWidget(m_BrowseButton);
|
||||
|
||||
botLayout->addWidget(exportSelectedButton);
|
||||
botLayout->addWidget(exportAllButton);
|
||||
botLayout->addWidget(cancelButton);
|
||||
botLayout->addWidget(m_ExportAllButton);
|
||||
botLayout->addWidget(m_CancelButton);
|
||||
|
||||
startEndLabelLayout->addWidget(nameLabel);
|
||||
startEndLabelLayout->addWidget(startLabel);
|
||||
startEndLabelLayout->addWidget(endLabel);
|
||||
|
||||
clipButtonLayout->addWidget(m_AddClipsButton);
|
||||
clipButtonLayout->addWidget(m_RemoveClipsButton);
|
||||
|
||||
baseLayout->addLayout(topLayout);
|
||||
baseLayout->addLayout(midLayout);
|
||||
|
||||
baseLayout->addSpacing(10);
|
||||
|
||||
baseLayout->addLayout(botLayout);
|
||||
|
||||
baseLayout->addSpacing(10);
|
||||
baseLayout->addLayout(clipButtonLayout);
|
||||
baseLayout->addLayout(startEndLabelLayout);
|
||||
baseLayout->addLayout(m_ClipLayout);
|
||||
baseLayout->addStretch();
|
||||
|
||||
// Set the layout for our window
|
||||
dialog->setLayout(baseLayout);
|
||||
|
||||
}
|
||||
this->AddClipClicked(true);
|
||||
//for (unsigned int i = 0; i < 3; i++) {
|
||||
// this->AddClipClicked(true);
|
||||
//}
|
||||
|
||||
void Menu::ExportSelected(bool checked)
|
||||
{
|
||||
// Retrieving the objects we currently have selected
|
||||
MSelectionList selected;
|
||||
MGlobal::getActiveSelectionList(selected);
|
||||
|
||||
// Loop through or list of selection(s)
|
||||
for (unsigned int i = 0; i < selected.length();i++)
|
||||
{
|
||||
MObject object;
|
||||
selected.getDependNode(i, object);
|
||||
MFnDependencyNode thisNode(object);
|
||||
|
||||
cout << thisNode.name().asChar() << endl;
|
||||
GetMeshData(object);
|
||||
}
|
||||
if (exportPath->text().isEmpty())
|
||||
cout << "Please select a folder." << endl;
|
||||
else
|
||||
cout << exportPath->text().toLocal8Bit().constData() << endl;
|
||||
}
|
||||
|
||||
void Menu::ExportPathClicked(bool)
|
||||
{
|
||||
// Opens up a file dialog. Save/Changes the name in the exportPath
|
||||
fileDialog->setFileMode(QFileDialog::Directory);
|
||||
fileDialog->setOption(QFileDialog::ShowDirsOnly);
|
||||
QString fileName = fileDialog->getExistingDirectory(this, "Select", "/home", QFileDialog::ShowDirsOnly);
|
||||
exportPath->setText(fileName);
|
||||
m_FileDialog->setFileMode(QFileDialog::Directory);
|
||||
m_FileDialog->setOption(QFileDialog::ShowDirsOnly);
|
||||
QString fileName = m_FileDialog->getExistingDirectory(this, "Select", "/home", QFileDialog::ShowDirsOnly);
|
||||
m_ExportPath->setText(fileName);
|
||||
}
|
||||
|
||||
void Menu::AddClipClicked(bool)
|
||||
{
|
||||
QHBoxLayout* tempLayout = new QHBoxLayout;
|
||||
|
||||
QLineEdit* nameLineEdit = new QLineEdit;
|
||||
QLineEdit* startLineEdit = new QLineEdit;
|
||||
QLineEdit* endLineEdit = new QLineEdit;
|
||||
|
||||
m_AnimationClipName.push_back(nameLineEdit);
|
||||
m_StartFrameLines.push_back(startLineEdit);
|
||||
m_EndFrameLines.push_back(endLineEdit);
|
||||
|
||||
tempLayout->addWidget(nameLineEdit);
|
||||
tempLayout->addWidget(startLineEdit);
|
||||
tempLayout->addWidget(endLineEdit);
|
||||
|
||||
m_ClipLayout->addLayout(tempLayout);
|
||||
//m_ClipLayout->update();
|
||||
layouts.push_back(tempLayout);
|
||||
}
|
||||
|
||||
void Menu::RemoveClipClicked(bool)
|
||||
{
|
||||
if (m_StartFrameLines.size() > 0) {
|
||||
QLayoutItem* tempWidget;// = m_ClipLayout->itemAt(0);
|
||||
|
||||
for (unsigned int i = 0; i < layouts.size(); i++) {
|
||||
while ((tempWidget = layouts[layouts.size() - 1]->takeAt(0)) != 0) {
|
||||
delete tempWidget->widget();
|
||||
delete tempWidget;
|
||||
}
|
||||
}
|
||||
|
||||
m_ClipLayout->removeItem(tempWidget);
|
||||
m_ClipLayout->update();
|
||||
|
||||
layouts.pop_back();
|
||||
m_StartFrameLines.pop_back();
|
||||
m_EndFrameLines.pop_back();
|
||||
m_AnimationClipName.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::ExportAll(bool)
|
||||
{
|
||||
MDagPath path;
|
||||
|
||||
// Loop through all nodes in the scene
|
||||
MItDependencyNodes it(MFn::kInvalid);
|
||||
for (;!it.isDone();it.next())
|
||||
{
|
||||
MObject node = it.thisNode();
|
||||
if (node.hasFn(MFn::kMesh))
|
||||
{
|
||||
MFnDependencyNode thisNode(node);
|
||||
if (m_ExportPath->text().isEmpty()) {
|
||||
MGlobal::displayError(MString() + "Please select a folder.");
|
||||
return;
|
||||
}
|
||||
|
||||
cout << thisNode.name().asChar() << endl;
|
||||
GetMeshData(node);
|
||||
}
|
||||
}
|
||||
if (exportPath->text().isEmpty())
|
||||
cout << "Please select a folder." << endl;
|
||||
else
|
||||
cout << exportPath->text().toLocal8Bit().constData() << endl;
|
||||
//Export meshes
|
||||
if (!m_Export.Meshes(m_ExportPath->text().toLocal8Bit().constData(), m_ExportSelectedButton->isChecked())) {
|
||||
MGlobal::displayError(MString() + "Could not export mesh");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ExportMaterialButton->isChecked()) {
|
||||
if (!m_Export.Materials(m_ExportPath->text().toLocal8Bit().constData())) {
|
||||
MGlobal::displayError(MString() + "Could not export materials");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Export::AnimationInfo> animations;
|
||||
for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) {
|
||||
Export::AnimationInfo thisClip;
|
||||
thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData());
|
||||
thisClip.Start = m_StartFrameLines[i]->text().toInt();
|
||||
thisClip.End = m_EndFrameLines[i]->text().toInt();
|
||||
|
||||
animations.push_back(thisClip);
|
||||
}
|
||||
if (m_ExportAnimationsButton->isChecked()) {
|
||||
//Export Animations
|
||||
if (!m_Export.Animations(m_ExportPath->text().toLocal8Bit().constData(), animations)) {
|
||||
MGlobal::displayError(MString() + "Could not export animations");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::CancelClicked(bool)
|
||||
{
|
||||
dialogPointer->close();
|
||||
}
|
||||
|
||||
void Menu::Button1Clicked(bool)
|
||||
{
|
||||
if(exportAnimationsButton->isChecked())
|
||||
cout << "1 checked!" << endl;
|
||||
else
|
||||
cout << "1 unchecked!" << endl;
|
||||
}
|
||||
|
||||
void Menu::Button2Clicked(bool)
|
||||
{
|
||||
if (copyTexturesButton->isChecked())
|
||||
cout << "2 checked!" << endl;
|
||||
else
|
||||
cout << "2 unchecked!" << endl;
|
||||
}
|
||||
|
||||
void Menu::Button3Clicked(bool)
|
||||
{
|
||||
if (button3->isChecked())
|
||||
cout << "3 checked!" << endl;
|
||||
else
|
||||
cout << "3 unchecked!" << endl;
|
||||
}
|
||||
|
||||
void Menu::GetMeshData(MObject object)
|
||||
{
|
||||
// In here, we retrieve triangulated polygons from the mesh
|
||||
MFnMesh mesh(object);
|
||||
|
||||
map<UINT, vector<UINT>> vertexToIndex;
|
||||
|
||||
vector<VertexLayout> verticesData;
|
||||
vector<UINT>indexArray;
|
||||
|
||||
MIntArray intdexOffsetVertexCount, vertices, triangleList;
|
||||
MPointArray dummy;
|
||||
|
||||
UINT vertexIndex;
|
||||
MVector normal;
|
||||
MPoint pos;
|
||||
float2 UV;
|
||||
VertexLayout thisVertex;
|
||||
|
||||
for (MItMeshPolygon meshPolyIter(object); !meshPolyIter.isDone(); meshPolyIter.next())
|
||||
{
|
||||
vector<UINT> localVertexToGlobalIndex;
|
||||
meshPolyIter.getVertices(vertices);
|
||||
|
||||
meshPolyIter.getTriangles(dummy, triangleList);
|
||||
UINT indexOffset = verticesData.size();
|
||||
|
||||
for (UINT i = 0; i < vertices.length(); i++)
|
||||
{
|
||||
vertexIndex = meshPolyIter.vertexIndex(i);
|
||||
pos = meshPolyIter.point(i);
|
||||
pos.get(thisVertex.pos);
|
||||
|
||||
meshPolyIter.getNormal(i, normal);
|
||||
thisVertex.normal[0] = normal[0];
|
||||
thisVertex.normal[1] = normal[1];
|
||||
thisVertex.normal[2] = normal[2];
|
||||
|
||||
meshPolyIter.getUV(i, UV);
|
||||
thisVertex.uv[0] = UV[0];
|
||||
thisVertex.uv[1] = UV[1];
|
||||
|
||||
verticesData.push_back(thisVertex);
|
||||
localVertexToGlobalIndex.push_back(vertexIndex);
|
||||
|
||||
cout << "Pos: " << thisVertex.pos[0] << "/" << thisVertex.pos[1] << "/" << thisVertex.pos[2] << endl;
|
||||
cout << "Normals: " << thisVertex.normal[0] << "/" << thisVertex.normal[1] << "/" << thisVertex.normal[2] << endl;
|
||||
cout << "UV: " << thisVertex.uv[0] << "/" << thisVertex.uv[1] << endl;
|
||||
}
|
||||
for (UINT i = 0; i < triangleList.length(); i++)
|
||||
{
|
||||
UINT k = 0;
|
||||
while (localVertexToGlobalIndex[k] != triangleList[i])
|
||||
k++;
|
||||
indexArray.push_back(indexOffset + k);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Menu::exportMaterial(MObject object)
|
||||
{
|
||||
MItDependencyNodes matIt(MFn::kLambert);
|
||||
|
||||
|
||||
m_DialogPointer->close();
|
||||
}
|
||||
|
||||
Menu::~Menu()
|
||||
@@ -235,5 +212,8 @@ Menu::~Menu()
|
||||
//delete browseButton;
|
||||
//delete exportPath;
|
||||
//delete fileDialog;
|
||||
fileDialog->~QFileDialog();
|
||||
m_FileDialog->~QFileDialog();
|
||||
|
||||
//delete m_Export;
|
||||
//delete MaterialHandler;
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
#ifndef BUTTONS_H
|
||||
#define BUTTONS_H
|
||||
#ifndef Menu_Menu_h__
|
||||
#define Menu_Menu_h__
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
// Qt
|
||||
#pragma comment(lib, "QtCore4")
|
||||
#pragma comment(lib, "QtGui4")
|
||||
@@ -30,13 +29,11 @@
|
||||
#include <QtGui/qfiledialog.h>
|
||||
#include <QtGui/qlineedit.h>
|
||||
#include <QtGui/qgroupbox.h>
|
||||
#include <QtGui/qlayoutitem.h>
|
||||
#include <QtGui/qtabwidget.h>
|
||||
|
||||
struct VertexLayout
|
||||
{
|
||||
float pos[3];
|
||||
float normal[3];
|
||||
float uv[2];
|
||||
};
|
||||
#include "MayaIncludes.h"
|
||||
#include "Export.h"
|
||||
|
||||
class Menu : public QWidget
|
||||
{
|
||||
@@ -45,35 +42,36 @@ public:
|
||||
Menu(QDialog* dialog);
|
||||
~Menu();
|
||||
|
||||
void GetMeshData(MObject object);
|
||||
void exportMaterial(MObject object);
|
||||
|
||||
private slots:
|
||||
void ExportSelected(bool checked);
|
||||
void ExportPathClicked(bool);
|
||||
void AddClipClicked(bool);
|
||||
void RemoveClipClicked(bool);
|
||||
void ExportAll(bool);
|
||||
void CancelClicked(bool);
|
||||
|
||||
void Button1Clicked(bool);
|
||||
void Button2Clicked(bool);
|
||||
void Button3Clicked(bool);
|
||||
|
||||
|
||||
private:
|
||||
Menu();
|
||||
QPushButton* exportSelectedButton;
|
||||
QPushButton* browseButton;
|
||||
QPushButton* exportAllButton;
|
||||
QPushButton* cancelButton;
|
||||
std::vector<QLineEdit*> m_AnimationClipName;
|
||||
std:: vector<QLineEdit*> m_StartFrameLines;
|
||||
std::vector<QLineEdit*> m_EndFrameLines;
|
||||
std::vector<QHBoxLayout*> layouts;
|
||||
QVBoxLayout* m_ClipLayout;
|
||||
|
||||
QCheckBox* exportAnimationsButton;
|
||||
QCheckBox* copyTexturesButton;
|
||||
QCheckBox* button3;
|
||||
QPushButton* m_BrowseButton = nullptr;
|
||||
QPushButton* m_ExportAllButton = nullptr;
|
||||
QPushButton* m_CancelButton = nullptr;
|
||||
QPushButton* m_AddClipsButton = nullptr;
|
||||
QPushButton* m_RemoveClipsButton = nullptr;
|
||||
|
||||
QLineEdit* exportPath;
|
||||
QFileDialog* fileDialog;
|
||||
QDialog* dialogPointer;
|
||||
QCheckBox* m_ExportSelectedButton = nullptr;
|
||||
QCheckBox* m_ExportAnimationsButton = nullptr;
|
||||
QCheckBox* m_ExportMaterialButton = nullptr;
|
||||
|
||||
QLineEdit* m_ExportPath = nullptr;
|
||||
QFileDialog* m_FileDialog = nullptr;
|
||||
QDialog* m_DialogPointer = nullptr;
|
||||
|
||||
Export m_Export;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,402 @@
|
||||
#pragma once
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
MeshClass::MeshClass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::map<int, MeshClass::WeightInfo> MeshClass::GetWeightData()
|
||||
{
|
||||
MS status;
|
||||
map<int, WeightInfo> weightMap;
|
||||
|
||||
MItDependencyNodes it(MFn::kSkinClusterFilter);
|
||||
|
||||
while (!it.isDone()) {
|
||||
|
||||
MObject object = it.thisNode(&status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " it.thisNode() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
MFnSkinCluster skinCluster(object, &status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "skinCluster() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
MDagPathArray influences;
|
||||
|
||||
unsigned int nrOfInfluences = skinCluster.influenceObjects(influences,&status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "skinCluster.influenceObjects() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int index;
|
||||
index = skinCluster.indexForOutputConnection(0,&status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "skinCluster.indexForOutputConnection() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
MDagPath skinPath;
|
||||
status = skinCluster.getPathAtIndex(index, skinPath);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "skinCluster.getPathAtIndex() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
|
||||
MItGeometry geomIter(skinPath);
|
||||
//for (unsigned int i = 0; i < nrOfInfluences; i++) {
|
||||
// MGlobal::displayInfo(MString() + " Influence object name: " + influences[i].partialPathName().asChar());
|
||||
//}
|
||||
WeightInfo weightInfo;
|
||||
|
||||
while (!geomIter.isDone()) {
|
||||
MObject comp = geomIter.component(&status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "geomIter.component() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
MFloatArray weights;
|
||||
unsigned int influenceCount;
|
||||
status = skinCluster.getWeights(skinPath, comp, weights, influenceCount);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "skinCluster.getWeights() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
MFnDependencyNode test(comp);
|
||||
unsigned int nrOfWeights = 0;
|
||||
|
||||
for (unsigned int j = 0; j < weights.length() && nrOfWeights != 4; j++) {
|
||||
if (weights[j] > 0.00001) {
|
||||
weightInfo.BoneWeights[nrOfWeights] = weights[j];
|
||||
weightInfo.BoneIndices[nrOfWeights] = j;
|
||||
nrOfWeights++;
|
||||
}
|
||||
}
|
||||
|
||||
float totalWeight = 0.0f;
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
totalWeight += weightInfo.BoneWeights[i];
|
||||
}
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
weightInfo.BoneWeights[i] /= totalWeight;
|
||||
}
|
||||
weightMap[geomIter.index()] = weightInfo;
|
||||
|
||||
|
||||
for (unsigned int k = 0; k!=nrOfWeights; k++) {
|
||||
MGlobal::displayInfo(MString() + "influence: " + weightInfo.BoneIndices[k] + " weight: " + weightInfo.BoneWeights[k]);
|
||||
}
|
||||
geomIter.next();
|
||||
}
|
||||
it.next();
|
||||
}
|
||||
return weightMap;
|
||||
}
|
||||
|
||||
Mesh MeshClass::GetMeshData(MObjectArray object)
|
||||
{
|
||||
MS status;
|
||||
Mesh newMesh;
|
||||
vector<VertexLayout>& vertexList = newMesh.Vertices;
|
||||
map<string, vector<int>>& indexLists = newMesh.Indices;
|
||||
for (int ObjectID = 0; ObjectID < object.length(); ObjectID++) {
|
||||
if (!object[ObjectID].hasFn(MFn::kMesh))
|
||||
continue;
|
||||
|
||||
MObject node = object[ObjectID];
|
||||
MFnDependencyNode thisNode(node);
|
||||
MPlugArray connections;
|
||||
thisNode.findPlug("inMesh").connectedTo(connections, true, true);
|
||||
MGlobal::displayInfo(MString() + "inMesh");
|
||||
bool hasSkin = false;
|
||||
MPlug weightList, weights;
|
||||
MObject weightListObject;
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
MFnSkinCluster skinCluster(connections[i].node());
|
||||
weightList = skinCluster.findPlug("weightList", &status);
|
||||
weightListObject = weightList.attribute();
|
||||
weights = skinCluster.findPlug("weights");
|
||||
hasSkin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// In here, we retrieve triangulated polygons from the mesh
|
||||
MFnMesh mesh(object[ObjectID]);
|
||||
MDagPathArray dagPaths;
|
||||
status = MDagPath::getAllPathsTo(object[ObjectID], dagPaths);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "MDagPath::getAllPathsTo() ERROR: " + status.errorString());
|
||||
break;
|
||||
}
|
||||
|
||||
for (int pathID = 0; pathID < dagPaths.length(); pathID++) {
|
||||
MGlobal::displayInfo(dagPaths[pathID].fullPathName());
|
||||
MDagPath thisMeshPath(dagPaths[pathID]);
|
||||
|
||||
MMatrix transformMatrix = thisMeshPath.inclusiveMatrix(&status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "thisMeshPath.inclusiveMatrix() ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
map<unsigned int, vector<unsigned int>> vertexToIndex;;
|
||||
|
||||
MIntArray intdexOffsetVertexCount, vertices, triangleList;
|
||||
MPointArray dummy;
|
||||
unsigned int vertexIndex;
|
||||
MVector normal;
|
||||
MPoint pos;
|
||||
float2 UV;
|
||||
double biTangent[3];
|
||||
double biNormal[3];
|
||||
MFloatVectorArray Tangents;
|
||||
MFloatVectorArray biNormals;
|
||||
|
||||
MObjectArray shaderList;
|
||||
MIntArray shaderIndexList;
|
||||
status = mesh.getConnectedShaders(0, shaderList, shaderIndexList);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "mesh.getConnectedShaders() ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
if (shaderList.length() == 0) {
|
||||
MGlobal::displayError(MString() + "Object: \"" + thisMeshPath.fullPathName() + "\" have no material and will not be exported");
|
||||
break;
|
||||
}
|
||||
map<string, vector<int>> materialFaceIDs;
|
||||
MGlobal::displayInfo(MString() + "shaderIndexList: " + shaderIndexList.length());
|
||||
MGlobal::displayInfo(MString() + "shaderList: " + shaderList.length());
|
||||
MPlugArray plugArray;
|
||||
for (int i = 0; i < shaderIndexList.length(); i++) {
|
||||
MFnDependencyNode shader(shaderList[shaderIndexList[i]]);
|
||||
MPlug p_Plug = shader.findPlug("surfaceShader", status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "shader.findPlug(\"surfaceShader\") ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
if (p_Plug.connectedTo(plugArray, true, false, &status)) {
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "p_Plug.connectedTo() ERROR in if: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
MFnDependencyNode node = plugArray[0].node();
|
||||
materialFaceIDs[node.name().asChar()].push_back(i);
|
||||
}
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "p_Plug.connectedTo() ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// map<int, WeightInfo> vertexWeights = GetWeightData();
|
||||
status = mesh.getTangents(Tangents, MSpace::kObject);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "mesh.getTangents ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
status = mesh.getBinormals(biNormals, MSpace::kObject);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "mesh.getBinormals ERROR: " + status.errorString() + " for " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
if(Tangents.length() == 0 || biNormals.length() == 0){
|
||||
MGlobal::displayError(MString() + "Unknown ERROR with " + thisMeshPath.fullPathName());
|
||||
continue;
|
||||
}
|
||||
MItMeshFaceVertex faceVert(object[ObjectID]);
|
||||
int intDummy = 0;
|
||||
|
||||
MItMeshPolygon meshPolyIter(object[ObjectID]);
|
||||
MFloatPointArray positions;
|
||||
|
||||
mesh.getPoints(positions);
|
||||
|
||||
for (auto aMaterial : materialFaceIDs) {
|
||||
for (auto faceID : aMaterial.second) {
|
||||
vector<array<unsigned int, 2>> localVertexToGlobalIndex;
|
||||
|
||||
status = meshPolyIter.setIndex(faceID, intDummy);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " meshPolyIter.setIndex() ERROR: " + status.errorString() + " for faceID " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
status = meshPolyIter.getVertices(vertices);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " meshPolyIter.getVertices() ERROR: " + status.errorString() + " for faceID " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
status = meshPolyIter.getTriangles(dummy, triangleList);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " meshPolyIter.getTriangles() ERROR: " + status.errorString() + " for faceID " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
//MGlobal::displayInfo("Befor Second Loop");
|
||||
for (unsigned int i = 0; i < vertices.length(); i++) {
|
||||
VertexLayout thisVertex;
|
||||
|
||||
vertexIndex = meshPolyIter.vertexIndex(i, &status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " meshPolyIter.vertexIndex() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
|
||||
status = faceVert.setIndex(meshPolyIter.index(), i, intDummy, intDummy);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "faceVert.setIndex() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
//MGlobal::displayInfo("In Second Loop");
|
||||
//pos = faceVert.position(MSpace::kTransform);
|
||||
//mesh.getPoint(vertexIndex, pos, MSpace::kPostTransform);
|
||||
pos = positions[vertexIndex];
|
||||
pos = pos * transformMatrix;
|
||||
if (abs(pos.x) > 0.0001)
|
||||
thisVertex.Pos[0] = pos.x;
|
||||
if (abs(pos.y) > 0.0001)
|
||||
thisVertex.Pos[1] = pos.y;
|
||||
if (abs(pos.z) > 0.0001)
|
||||
thisVertex.Pos[2] = pos.z;
|
||||
|
||||
status = faceVert.getNormal(normal, MSpace::kObject);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "faceVert.getNormal() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
if (abs(normal[0]) > 0.0001)
|
||||
thisVertex.Normal[0] = normal[0];
|
||||
if (abs(normal[1]) > 0.0001)
|
||||
thisVertex.Normal[1] = normal[1];
|
||||
if (abs(normal[2]) > 0.0001)
|
||||
thisVertex.Normal[2] = normal[2];
|
||||
|
||||
MFloatVector Tangent = Tangents[faceVert.tangentId()];
|
||||
//MVector tmp = faceVert.getTangent(MSpace::kObject, NULL);
|
||||
//tmp.get(biTangent);
|
||||
if (abs(Tangent[0]) > 0.0001)
|
||||
thisVertex.Tangent[0] = Tangent[0];
|
||||
if (abs(Tangent[1]) > 0.0001)
|
||||
thisVertex.Tangent[1] = Tangent[1];
|
||||
if (abs(Tangent[2]) > 0.0001)
|
||||
thisVertex.Tangent[2] = Tangent[2];
|
||||
|
||||
MFloatVector biNormal = biNormals[faceVert.tangentId()];
|
||||
//faceVert.getBinormal().get(biNormal);
|
||||
if (abs(biNormal[0]) > 0.0001)
|
||||
thisVertex.BiNormal[0] = biNormal[0];
|
||||
if (abs(biNormal[1]) > 0.0001)
|
||||
thisVertex.BiNormal[1] = biNormal[1];
|
||||
if (abs(biNormal[2]) > 0.0001)
|
||||
thisVertex.BiNormal[2] = biNormal[2];
|
||||
|
||||
status = faceVert.getUV(UV);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + " faceVert.getUV() ERROR: " + status.errorString() + "for local vertex " + i + " in " + faceID + " in mesh " + thisMeshPath.fullPathName());
|
||||
break;
|
||||
}
|
||||
thisVertex.Uv[0] = UV[0];
|
||||
thisVertex.Uv[1] = UV[1];
|
||||
|
||||
|
||||
if (hasSkin) {
|
||||
float totalWeight = 0.0f;
|
||||
unsigned int totalBones = 0;
|
||||
MIntArray jointIDs /* ??? */;
|
||||
weights.selectAncestorLogicalIndex(vertexIndex, weightListObject);
|
||||
weights.getExistingArrayAttributeIndices(jointIDs);
|
||||
for (unsigned int i = 0; i < jointIDs.length() && i < 4; i++) {
|
||||
if (weights[i].asFloat() > 0.001f) {
|
||||
thisVertex.BoneIndices[totalBones] = jointIDs[i];
|
||||
thisVertex.BoneWeights[totalBones] = weights[i].asFloat();
|
||||
totalWeight = totalWeight + weights[i].asFloat();
|
||||
totalBones++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
thisVertex.BoneWeights[i] = thisVertex.BoneWeights[i] / totalWeight;
|
||||
}
|
||||
}
|
||||
|
||||
//float totalWeight = thisVertex.BoneWeights[0] + thisVertex.BoneWeights[1] + thisVertex.BoneWeights[2] + thisVertex.BoneWeights[3];
|
||||
//if (totalWeight > 0.0001f) {
|
||||
// thisVertex.BoneWeights[0] /= totalWeight;
|
||||
// thisVertex.BoneWeights[1] /= totalWeight;
|
||||
// thisVertex.BoneWeights[2] /= totalWeight;
|
||||
// thisVertex.BoneWeights[3] /= totalWeight;
|
||||
//}
|
||||
|
||||
std::vector<VertexLayout>::iterator it = std::find(vertexList.begin(), vertexList.end(), thisVertex);
|
||||
array<unsigned int, 2> tmp;
|
||||
if (it != vertexList.end()) {
|
||||
tmp[0] = vertexIndex;
|
||||
tmp[1] = it - vertexList.begin();
|
||||
localVertexToGlobalIndex.push_back(tmp);
|
||||
} else {
|
||||
tmp[0] = vertexIndex;
|
||||
tmp[1] = vertexList.size();
|
||||
localVertexToGlobalIndex.push_back(tmp);
|
||||
vertexList.push_back(thisVertex);
|
||||
}
|
||||
//MGlobal::displayInfo(MString() + "localVertexToGlobalIndex[localVertexToGlobalIndex.size()-1]: " + localVertexToGlobalIndex[localVertexToGlobalIndex.size()-1][0] + " " + localVertexToGlobalIndex[localVertexToGlobalIndex.size()-1][1]);
|
||||
//cout << "Pos: " << thisVertex.Pos[0] << "/" << thisVertex.Pos[1] << "/" << thisVertex.Pos[2] << endl;
|
||||
//cout << "Normals: " << thisVertex.Normal[0] << "/" << thisVertex.Normal[1] << "/" << thisVertex.Normal[2] << endl;
|
||||
//cout << "Bi-Normals: " << thisVertex.BiNormal[0] << "/" << thisVertex.BiNormal[1] << "/" << thisVertex.BiNormal[2] << endl;
|
||||
//cout << "Bi-Tangents: " << thisVertex.BiTangent[0] << "/" << thisVertex.BiTangent[1] << "/" << thisVertex.BiTangent[2] << endl;
|
||||
//cout << "UV: " << thisVertex.Uv[0] << "/" << thisVertex.Uv[1] << endl;
|
||||
}
|
||||
for (unsigned int i = 0; i < triangleList.length(); i++) {
|
||||
unsigned int k = 0;
|
||||
if (localVertexToGlobalIndex.size() > 0) {
|
||||
//MGlobal::displayInfo(MString() + "triangleList[i] : " + triangleList[i]);
|
||||
while (localVertexToGlobalIndex[k][0] != triangleList[i] && k < localVertexToGlobalIndex.size()) {
|
||||
k++;
|
||||
}
|
||||
//MGlobal::displayInfo(MString() + "localVertexToGlobalIndex[k] : " + localVertexToGlobalIndex[k][0] + " " + localVertexToGlobalIndex[k][1]);
|
||||
indexLists[aMaterial.first.c_str()].push_back(localVertexToGlobalIndex[k][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// MGlobal::displayInfo( MString() + "localVertexToGlobalIndex.size(): " + localVertexToGlobalIndex.size());
|
||||
// if (localVertexToGlobalIndex.size() > 0) {
|
||||
// MGlobal::displayInfo(MString() + "triangleList.length(): " + triangleList.length());
|
||||
// for (unsigned int i = triangleList.length() - 1; i >= 0; i--) {
|
||||
// MGlobal::displayInfo(MString() + "i: " + i);
|
||||
// unsigned int k = localVertexToGlobalIndex.size() - 1;
|
||||
// MGlobal::displayInfo(MString() + "triangleList[i] : " + triangleList[i]);
|
||||
// while (localVertexToGlobalIndex[k] != triangleList[i] && k >= 0) {
|
||||
// MGlobal::displayInfo(MString() + "k: " + k);
|
||||
// k--;
|
||||
// }
|
||||
// MGlobal::displayInfo(MString() + "localVertexToGlobalIndex[k] : " + localVertexToGlobalIndex[k]);
|
||||
// indexList.push_back(indexOffset + k);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int totalIndices = 0;
|
||||
for (auto aList : newMesh.Indices) {
|
||||
totalIndices += aList.second.size();
|
||||
}
|
||||
newMesh.NumIndices = totalIndices;
|
||||
newMesh.NumVertices = newMesh.Vertices.size();
|
||||
|
||||
return newMesh;
|
||||
}
|
||||
|
||||
MeshClass::~MeshClass()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
#ifndef Mesh_Mesh_h__
|
||||
#define Mesh_Mesh_h__
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "OutputData.h"
|
||||
#include "MayaIncludes.h"
|
||||
|
||||
class VertexLayout : public OutputData
|
||||
{
|
||||
public:
|
||||
float Pos[3]{ 0 };
|
||||
float Normal[3]{ 0 };
|
||||
float Tangent[3]{ 0 };
|
||||
float BiNormal[3]{ 0 };
|
||||
float Uv[2]{ 0 };
|
||||
float BoneIndices[4]{ 0 };
|
||||
float BoneWeights[4]{ 0 };
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&Pos, sizeof(float) * 3);
|
||||
out.write((char*)&Normal, sizeof(float) * 3);
|
||||
out.write((char*)&Tangent, sizeof(float) * 3);
|
||||
out.write((char*)&BiNormal, sizeof(float) * 3);
|
||||
out.write((char*)&Uv, sizeof(float) * 2);
|
||||
out.write((char*)&BoneIndices, sizeof(float) * 4);
|
||||
out.write((char*)&BoneWeights, sizeof(float) * 4);
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << Pos[0] << " " << Pos[1] << " " << Pos[2] << endl;
|
||||
out << Normal[0] << " " << Normal[1] << " " << Normal[2] << endl;
|
||||
out << Tangent[0] << " " << Tangent[1] << " " << Tangent[2] << endl;
|
||||
out << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl;
|
||||
out << Uv[0] << " " << Uv[1] << endl;
|
||||
out << BoneIndices[0] << " " << BoneIndices[1] << " " << BoneIndices[2] << " " << BoneIndices[3] << endl;
|
||||
out << BoneWeights[0] << " " << BoneWeights[1] << " " << BoneWeights[2] << " " << BoneWeights[3] << endl;
|
||||
|
||||
}
|
||||
bool operator==(const VertexLayout& right)
|
||||
{
|
||||
return
|
||||
this->Pos[0] == right.Pos[0] && this->Pos[1] == right.Pos[1] && this->Pos[2] == right.Pos[2] &&
|
||||
this->Normal[0] == right.Normal[0] && this->Normal[1] == right.Normal[1] && this->Normal[2] == right.Normal[2] &&
|
||||
this->Tangent[0] == right.Tangent[0] && this->Tangent[1] == right.Tangent[1] && this->Tangent[2] == right.Tangent[2] &&
|
||||
this->BiNormal[0] == right.BiNormal[0] && this->BiNormal[1] == right.BiNormal[1] && this->BiNormal[2] == right.BiNormal[2] &&
|
||||
this->Uv[0] == right.Uv[0] && this->Uv[1] == right.Uv[1] &&
|
||||
this->BoneIndices[0] == right.BoneIndices[0] && this->BoneIndices[1] == right.BoneIndices[1] && this->BoneIndices[2] == right.BoneIndices[2] && this->BoneIndices[3] == right.BoneIndices[3] &&
|
||||
this->BoneWeights[0] == right.BoneWeights[0] && this->BoneWeights[1] == right.BoneWeights[1] && this->BoneWeights[2] == right.BoneWeights[2] && this->BoneWeights[3] == right.BoneWeights[3]
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
class Mesh : public OutputData {
|
||||
public:
|
||||
unsigned int NumVertices;
|
||||
unsigned int NumIndices;
|
||||
std::vector<VertexLayout> Vertices;
|
||||
std::map<std::string, std::vector<int>> Indices;
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&NumVertices, sizeof(int));
|
||||
out.write((char*)&NumIndices, sizeof(int));
|
||||
for (auto aVertex : Vertices) {
|
||||
aVertex.WriteBinary(out);
|
||||
}
|
||||
for (auto aIndex : Indices) {
|
||||
//for (std::map<std::string, std::vector<int>>::reverse_iterator aIndex = Indices.rbegin(); aIndex != Indices.rend(); aIndex++){
|
||||
//out.write((char*)(*aIndex).second.data(), sizeof(int) * (*aIndex).second.size());
|
||||
out.write((char*)aIndex.second.data(), sizeof(int) * aIndex.second.size());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "New Mesh _ not in binary" << endl;
|
||||
out << "Number of vertices: " << NumVertices << endl;
|
||||
out << "number of indices: " << NumIndices << endl;
|
||||
int vertexNumber = 0;
|
||||
for (auto aVertex : Vertices) {
|
||||
out << "New vertex number: " << vertexNumber << " _ not in binary" << endl;
|
||||
aVertex.WriteASCII(out);
|
||||
vertexNumber++;
|
||||
}
|
||||
out << "New vertex Triangels: " << NumIndices/3 << " _ not in binary" << endl;
|
||||
for (auto aIndexList : Indices) {
|
||||
out << "Using Material: " << aIndexList.first << " _ not in binary" << endl;
|
||||
for (int i = 0; i < aIndexList.second.size(); i += 3) {
|
||||
out << aIndexList.second[i] << " " << aIndexList.second[i+1] << " " << aIndexList.second[i + 2] << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MeshClass
|
||||
{
|
||||
public:
|
||||
MeshClass();
|
||||
Mesh GetMeshData(MObjectArray Object);
|
||||
~MeshClass();
|
||||
private:
|
||||
struct WeightInfo {
|
||||
float BoneIndices[4] = { 0 };
|
||||
float BoneWeights[4] = { 0 };
|
||||
};
|
||||
std::map<int, WeightInfo> GetWeightData();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef OutputData_OutputData_h__
|
||||
#define OutputData_OutputData_h__
|
||||
#include <fstream>
|
||||
//template <typename T>
|
||||
class OutputData
|
||||
{
|
||||
public://std::ostream& out, const OutputData& obj
|
||||
//OutputData(T& object)
|
||||
// : m_Object(object)
|
||||
//{};
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const OutputData& obj)
|
||||
{
|
||||
obj.WriteASCII(out);
|
||||
return out;
|
||||
};
|
||||
virtual void WriteBinary(std::ostream& out) = 0;
|
||||
virtual void WriteASCII(std::ostream& out) const = 0;
|
||||
|
||||
//T& m_Object = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,342 @@
|
||||
#include "Skeleton.h"
|
||||
|
||||
|
||||
|
||||
|
||||
//std::vector<SkeletonNode> Skeleton::DoIt()
|
||||
//{
|
||||
// std::vector<SkeletonNode> m_AllSkeletons;
|
||||
//
|
||||
// MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint);
|
||||
// SkeletonNode SkeletonStorage;
|
||||
//
|
||||
// while (!jointIt.isDone()) {
|
||||
// MFnTransform TransformNode(jointIt.currentItem());
|
||||
// Joint NewJoint;
|
||||
//
|
||||
// if (MFnDependencyNode(TransformNode.parent(0)).name() == "world") {
|
||||
// if (SkeletonStorage.Joints.size() != 0) {
|
||||
// m_AllSkeletons.push_back(SkeletonStorage);
|
||||
//
|
||||
// SkeletonStorage.Joints.clear();
|
||||
// SkeletonStorage.Name.clear();
|
||||
// }
|
||||
//
|
||||
// SkeletonStorage.Name = TransformNode.name().asChar();
|
||||
//
|
||||
// //NewJoint.ParentIndex = -1; // This joint is root
|
||||
// }
|
||||
//
|
||||
// //NewJoint.Name = TransformNode.name().asChar();
|
||||
//
|
||||
// MMatrix Matrix = TransformNode.transformationMatrix();
|
||||
//
|
||||
// //double tmp[3];
|
||||
// //((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp);
|
||||
// //NewJoint.Rotation[0] = tmp[0];
|
||||
// //NewJoint.Rotation[1] = tmp[1];
|
||||
// //NewJoint.Rotation[2] = tmp[2];
|
||||
// //((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform);
|
||||
// //NewJoint.Scale[0] = tmp[0];
|
||||
// //NewJoint.Scale[1] = tmp[1];
|
||||
// //NewJoint.Scale[2] = tmp[2];
|
||||
// //((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp);
|
||||
// //NewJoint.Translation[0] = tmp[0];
|
||||
// //NewJoint.Translation[1] = tmp[1];
|
||||
// //NewJoint.Translation[2] = tmp[2];
|
||||
//
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// for (int j = 0; j < 4; j++) {
|
||||
// NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j];
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// SkeletonStorage.Joints.push_back(NewJoint);
|
||||
//
|
||||
// jointIt.next();
|
||||
// }
|
||||
//
|
||||
// m_AllSkeletons.push_back(SkeletonStorage);
|
||||
//
|
||||
// return m_AllSkeletons;
|
||||
//}
|
||||
std::string attr[9] = { "scaleX", "scaleY", "scaleZ", "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" };
|
||||
|
||||
Animation Skeleton::GetAnimData(std::string animationName, int startFrame, int endFrame)
|
||||
{
|
||||
MStatus status;
|
||||
std::vector<MObject> animatedJoints;
|
||||
std::vector<MObject> m_Hierarchy;
|
||||
|
||||
Animation returnData;
|
||||
double oneDivSixty = 1 / 60.0;
|
||||
returnData.Name = animationName;
|
||||
returnData.nameLength = animationName.size() + 1;
|
||||
returnData.Duration = (endFrame - startFrame) * oneDivSixty;
|
||||
|
||||
MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint);
|
||||
while (!jointIt.isDone())
|
||||
{
|
||||
m_Hierarchy.push_back(jointIt.item());
|
||||
|
||||
MFnDependencyNode depNode(jointIt.item());
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
MStatus tmp;
|
||||
MPlug plug = depNode.findPlug(attr[i].c_str(), &tmp);
|
||||
|
||||
MPlugArray connections;
|
||||
plug.connectedTo(connections, true, false, 0);
|
||||
for (int j = 0; j != connections.length(); j++) {
|
||||
MObject connected = connections[j].node();
|
||||
|
||||
if (connected.hasFn(MFn::kAnimCurve)) {
|
||||
|
||||
MFnAnimCurve jointAnim(connected);
|
||||
|
||||
unsigned int startKeyFrameIndex = jointAnim.findClosest(MTime(startFrame, MTime::kNTSCField), &tmp);
|
||||
|
||||
if (tmp == MStatus::kFailure)
|
||||
MGlobal::displayInfo(MString() + "Fail :c");
|
||||
|
||||
if (startFrame * oneDivSixty <= jointAnim.time(startKeyFrameIndex).value() && jointAnim.time(startKeyFrameIndex).value() <= endFrame * oneDivSixty) {
|
||||
animatedJoints.push_back(jointIt.item());
|
||||
i = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int endKeyFrameIndex = jointAnim.findClosest(MTime(endFrame, MTime::kNTSCField));
|
||||
MGlobal::displayInfo(MString() + startKeyFrameIndex + " " + endKeyFrameIndex);
|
||||
|
||||
if (startFrame * oneDivSixty <= jointAnim.time(endKeyFrameIndex).value() && jointAnim.time(endKeyFrameIndex).value() <= endFrame * oneDivSixty || endKeyFrameIndex - startKeyFrameIndex > 0) {
|
||||
animatedJoints.push_back(jointIt.item());
|
||||
i = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
MFnTransform MayaJoint(jointIt.item());
|
||||
|
||||
MPlug BindPose = MayaJoint.findPlug("bindPose");
|
||||
MDataHandle DataHandle;
|
||||
BindPose.getValue(DataHandle);
|
||||
MFnMatrixData MartixFn(DataHandle.data());
|
||||
MMatrix BindPoseMatrix = MartixFn.matrix();
|
||||
|
||||
if (!BindPoseMatrix.isEquivalent(MayaJoint.transformationMatrix()))
|
||||
{
|
||||
MGlobal::displayError(MString() + animationName.c_str() + " is using " + MayaJoint.name() + " that is not in bind pose nor is it key framed in the animation, the exported animation will NOT correspond to the animation in Maya");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jointIt.next();
|
||||
}
|
||||
|
||||
int currentFrame = startFrame;
|
||||
while (currentFrame != endFrame + 1) { // ANDREAS
|
||||
Animation::Keyframe thisKeyFrame;
|
||||
thisKeyFrame.Index = currentFrame - startFrame;
|
||||
thisKeyFrame.Time = thisKeyFrame.Index * oneDivSixty;
|
||||
|
||||
MAnimControl::setCurrentTime(MTime(currentFrame, MTime::kNTSCField));
|
||||
MTime time = MAnimControl::currentTime();
|
||||
|
||||
for (auto aJoint : animatedJoints){
|
||||
MFnTransform thisJoint(aJoint);
|
||||
Animation::Keyframe::JointProperty joint;
|
||||
|
||||
auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), thisJoint.object());
|
||||
if (it != m_Hierarchy.end()) {
|
||||
joint.ID = it - m_Hierarchy.begin();
|
||||
}
|
||||
else {
|
||||
MGlobal::displayError(MString() + "Could not find joint ID for: " + thisJoint.name());
|
||||
}
|
||||
|
||||
MTransformationMatrix Matrix = thisJoint.transformation();
|
||||
MPlug BindPose = thisJoint.findPlug("bindPose");
|
||||
MDataHandle DataHandle;
|
||||
BindPose.getValue(DataHandle);
|
||||
MFnMatrixData MartixFn(DataHandle.data());
|
||||
MMatrix BindPoseMatrix = MartixFn.matrix();
|
||||
Matrix = Matrix.asMatrix();
|
||||
|
||||
MObject jointOrientObj = thisJoint.attribute("jointOrient");
|
||||
MFnNumericAttribute jointOrient(jointOrientObj);
|
||||
double jointOrientDouble[3];
|
||||
jointOrient.getDefault(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]);
|
||||
//MGlobal::displayError(MString() + "Joint Matrix: ");
|
||||
//MGlobal::displayError(MString() + Matrix.asMatrix()[0][0] + " " + Matrix.asMatrix()[0][1] + " " + Matrix.asMatrix()[0][2] + " " + Matrix.asMatrix()[0][3]);
|
||||
//MGlobal::displayError(MString() + Matrix.asMatrix()[1][0] + " " + Matrix.asMatrix()[1][1] + " " + Matrix.asMatrix()[1][2] + " " + Matrix.asMatrix()[1][3]);
|
||||
//MGlobal::displayError(MString() + Matrix.asMatrix()[2][0] + " " + Matrix.asMatrix()[2][1] + " " + Matrix.asMatrix()[2][2] + " " + Matrix.asMatrix()[2][3]);
|
||||
//MGlobal::displayError(MString() + Matrix.asMatrix()[3][0] + " " + Matrix.asMatrix()[3][1] + " " + Matrix.asMatrix()[3][2] + " " + Matrix.asMatrix()[3][3]);
|
||||
|
||||
MEulerRotation joEuler(jointOrientDouble[0], jointOrientDouble[1], jointOrientDouble[2]);
|
||||
MQuaternion jo = joEuler.asQuaternion();
|
||||
|
||||
double tmp[4];
|
||||
Matrix.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]);
|
||||
MQuaternion rotation(tmp);
|
||||
|
||||
rotation = rotation * jo;
|
||||
rotation.get(tmp);
|
||||
|
||||
joint.Rotation[0] = tmp[0];
|
||||
joint.Rotation[1] = tmp[1];
|
||||
joint.Rotation[2] = tmp[2];
|
||||
joint.Rotation[3] = tmp[3];
|
||||
Matrix.getTranslation(MSpace::kTransform).get(tmp);
|
||||
joint.Position[0] = tmp[0];
|
||||
joint.Position[1] = tmp[1];
|
||||
joint.Position[2] = tmp[2];
|
||||
Matrix.getScale(tmp, MSpace::kTransform);
|
||||
joint.Scale[0] = tmp[0];
|
||||
joint.Scale[1] = tmp[1];
|
||||
joint.Scale[2] = tmp[2];
|
||||
|
||||
thisKeyFrame.JointProperties.push_back(joint);
|
||||
}
|
||||
returnData.Keyframes.push_back(thisKeyFrame);
|
||||
currentFrame++;
|
||||
}
|
||||
|
||||
returnData.NumKeyFrames = returnData.Keyframes.size();
|
||||
returnData.NumberOfJoints = animatedJoints.size();
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
std::vector<BindPoseSkeletonNode> Skeleton::GetBindPoses()
|
||||
{
|
||||
MStatus status;
|
||||
std::vector<BindPoseSkeletonNode> m_AllSkeletons;
|
||||
std::vector<MObject> m_Hierarchy;
|
||||
|
||||
MItDag jointIt(MItDag::TraversalType::kDepthFirst, MFn::kJoint);
|
||||
BindPoseSkeletonNode SkeletonStorage;
|
||||
while (!jointIt.isDone()) {
|
||||
MFnTransform MayaJoint(jointIt.currentItem());
|
||||
BindPoseSkeletonNode::BindPoseJoint NewJoint;
|
||||
|
||||
if (MFnDependencyNode(MayaJoint.parent(0)).name() == "world") {
|
||||
if (SkeletonStorage.Joints.size() != 0) {
|
||||
m_AllSkeletons.push_back(SkeletonStorage);
|
||||
|
||||
SkeletonStorage.Joints.clear();
|
||||
SkeletonStorage.Name.clear();
|
||||
}
|
||||
SkeletonStorage.Name = std::string(MayaJoint.name().asChar());
|
||||
NewJoint.ParentID = -1; // This joint is root
|
||||
}
|
||||
else {
|
||||
auto it = std::find(m_Hierarchy.begin(), m_Hierarchy.end(), MayaJoint.parent(0));
|
||||
if (it != m_Hierarchy.end()) {
|
||||
NewJoint.ParentID = it - m_Hierarchy.begin();
|
||||
}
|
||||
else {
|
||||
MGlobal::displayError(MString() + "Could not find joint parent for: " + MayaJoint.name());
|
||||
}
|
||||
}
|
||||
m_Hierarchy.push_back(MayaJoint.object());
|
||||
|
||||
MPlug BindPose = MayaJoint.findPlug("bindPose", &status);
|
||||
if (status != MS::kSuccess) {
|
||||
MGlobal::displayError(MString() + "Could not find bindPose plug: " + status.errorString());
|
||||
}
|
||||
MDataHandle DataHandle;
|
||||
BindPose.getValue(DataHandle);
|
||||
MFnMatrixData MartixFn(DataHandle.data());
|
||||
MMatrix Matrix = MartixFn.matrix();
|
||||
|
||||
|
||||
MVector tmp = MayaJoint.transformation().getTranslation(MSpace::kObject);
|
||||
MGlobal::displayError(MString() + "translation befor: " + tmp[0] + " " + tmp[1] + " " + tmp[2]);
|
||||
//Matrix[3][0] *= -1;
|
||||
//Matrix[3][2] *= -1;
|
||||
//Matrix[3][1] *= -1;
|
||||
|
||||
double test[3];
|
||||
MayaJoint.transformation().getScale(test, MSpace::kObject);
|
||||
MGlobal::displayError(MString() + "scale: " + test[0] + " " + test[1] + " " + test[2]);
|
||||
|
||||
MTransformationMatrix::RotationOrder order = MTransformationMatrix::RotationOrder::kXYZ;
|
||||
MayaJoint.transformation().getRotation(test, order);
|
||||
MGlobal::displayError(MString() + "rotation: " + test[0] + " " + test[1] + " " + test[2]);
|
||||
|
||||
//----- test
|
||||
|
||||
|
||||
//MDataHandle DataHandle;
|
||||
//MObject jointObject(jointIt.currentItem());
|
||||
//MFnDependencyNode jointDependNode(jointObject);
|
||||
//MPlug worldMatrixArray(jointObject, jointDependNode.attribute("worldMatrix"));
|
||||
|
||||
//MMatrix Matrix;
|
||||
//for (int i = 0; i < worldMatrixArray.numElements(); i++) {
|
||||
// MPlugArray connections;
|
||||
|
||||
// MPlug element = worldMatrixArray[i];
|
||||
// unsigned int logicalIndex = element.logicalIndex();
|
||||
|
||||
// MItDependencyGraph it(element, MFn::kSkinClusterFilter);
|
||||
|
||||
// for (; !it.isDone(); it.next()) {
|
||||
// MFnSkinCluster skinCluster(it.thisNode());
|
||||
|
||||
// MPlug bindPreMatrixArrayPlug =
|
||||
// skinCluster.findPlug("bindPreMatrix", &status);
|
||||
|
||||
// if (status != MS::kSuccess) {
|
||||
// MGlobal::displayError(MString() + "Could not find bindPreMatrix plug: " + status.errorString());
|
||||
// break;
|
||||
// }
|
||||
|
||||
// MPlug bindPreMatrixPlug =
|
||||
// bindPreMatrixArrayPlug.elementByLogicalIndex(logicalIndex);
|
||||
// MObject dataObject;
|
||||
// bindPreMatrixPlug.getValue(dataObject);
|
||||
|
||||
// MFnMatrixData matDataFn(dataObject);
|
||||
|
||||
// MMatrix invMat = matDataFn.matrix();
|
||||
// Matrix = invMat.inverse();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//----- end test
|
||||
|
||||
|
||||
Matrix = Matrix.inverse();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
NewJoint.OffsetMatrix[i][j] = Matrix.matrix[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
NewJoint.Name = MayaJoint.name().asChar();
|
||||
NewJoint.NameLength = MayaJoint.name().length() + 1;
|
||||
NewJoint.ID = SkeletonStorage.Joints.size();
|
||||
//double tmp[3];
|
||||
//((MTransformationMatrix)Matrix).eulerRotation().asVector().get(tmp);
|
||||
//NewJoint.Rotation[0] = tmp[0];
|
||||
//NewJoint.Rotation[1] = tmp[1];
|
||||
//NewJoint.Rotation[2] = tmp[2];
|
||||
//((MTransformationMatrix)Matrix).getScale(tmp, MSpace::Space::kTransform);
|
||||
//NewJoint.Scale[0] = tmp[0];
|
||||
//NewJoint.Scale[1] = tmp[1];
|
||||
//NewJoint.Scale[2] = tmp[2];
|
||||
//((MTransformationMatrix)Matrix).getTranslation(MSpace::Space::kTransform).get(tmp);
|
||||
//NewJoint.Translation[0] = tmp[0];
|
||||
//NewJoint.Translation[1] = tmp[1];
|
||||
//NewJoint.Translation[2] = tmp[2];
|
||||
SkeletonStorage.Joints.push_back(NewJoint);
|
||||
SkeletonStorage.numBones++;
|
||||
jointIt.next();
|
||||
}
|
||||
m_AllSkeletons.push_back(SkeletonStorage);
|
||||
|
||||
return m_AllSkeletons;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
#ifndef Skeleton_Skeleton_h__
|
||||
#define Skeleton_Skeleton_h__
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include "MayaIncludes.h"
|
||||
#include "OutputData.h"
|
||||
|
||||
class Animation : public OutputData {
|
||||
public:
|
||||
struct Keyframe
|
||||
{
|
||||
struct JointProperty
|
||||
{
|
||||
int ID = 0;
|
||||
float Position[3]{ 0 };
|
||||
float Rotation[4]{ 0 };
|
||||
float Scale[3]{ 0 };
|
||||
};
|
||||
|
||||
int Index = 0;
|
||||
float Time = 0;
|
||||
std::vector<JointProperty> JointProperties;
|
||||
};
|
||||
|
||||
std::string Name;
|
||||
int nameLength = 0;
|
||||
float Duration = 0;
|
||||
int NumKeyFrames = 0;
|
||||
int NumberOfJoints = 0;
|
||||
std::vector<Keyframe> Keyframes;
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&nameLength, sizeof(int));
|
||||
out.write(Name.c_str(), Name.size() + 1);
|
||||
out.write((char*)&Duration, sizeof(float));
|
||||
out.write((char*)&NumKeyFrames, sizeof(int));
|
||||
out.write((char*)&NumberOfJoints, sizeof(int));
|
||||
//Här under loopas alla key frames igenom
|
||||
for (auto aKeyframe : Keyframes) {
|
||||
out.write((char*)&aKeyframe.Index, sizeof(int));
|
||||
out.write((char*)&aKeyframe.Time, sizeof(float));
|
||||
for (auto aJoint : aKeyframe.JointProperties) {
|
||||
out.write((char*)&aJoint.ID, sizeof(int));
|
||||
out.write((char*)aJoint.Position, sizeof(float) * 3);
|
||||
out.write((char*)aJoint.Rotation, sizeof(float) * 4);
|
||||
out.write((char*)aJoint.Scale, sizeof(float) * 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "Animation Name: " << Name << endl;
|
||||
out << "Duration: " << Duration << endl;
|
||||
out << "Number of KeyFrames: " << NumKeyFrames << endl;
|
||||
out << "Number of Joints: " << NumberOfJoints << endl;
|
||||
for (auto aKeyframe : Keyframes) {
|
||||
out << "Frame: " << aKeyframe.Index << endl;
|
||||
out << "Time: " << aKeyframe.Time << endl;
|
||||
for (auto aJoint : aKeyframe.JointProperties) {
|
||||
out << "Joint ID: " << aJoint.ID << endl;
|
||||
out << aJoint.Position[0] << " " << aJoint.Position[1] << " " << aJoint.Position[2] << endl;
|
||||
out << aJoint.Rotation[0] << " " << aJoint.Rotation[1] << " " << aJoint.Rotation[2] << " " << aJoint.Rotation[3] << endl;
|
||||
out << aJoint.Scale[0] << " " << aJoint.Scale[1] << " " << aJoint.Scale[2] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class BindPoseSkeletonNode : public OutputData {
|
||||
public:
|
||||
struct BindPoseJoint
|
||||
{
|
||||
int NameLength;
|
||||
std::string Name;
|
||||
float OffsetMatrix[4][4]{ 0 };
|
||||
int ID = 0;
|
||||
int ParentID = 0;
|
||||
};
|
||||
int numBones = 0;
|
||||
std::string Name;
|
||||
std::vector<BindPoseJoint> Joints;
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&numBones, sizeof(int));
|
||||
for (auto Joint:Joints)
|
||||
{
|
||||
out.write((char*)&Joint.NameLength, sizeof(int));
|
||||
out.write(Joint.Name.c_str(), Joint.Name.size() + 1);
|
||||
out.write((char*)&Joint.OffsetMatrix, sizeof(float) * 4 * 4);
|
||||
out.write((char*)&Joint.ID, sizeof(int));
|
||||
out.write((char*)&Joint.ParentID, sizeof(int));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "Bind Pose: " << Name << " _ not in binary" << endl;
|
||||
out << "numberOfBones: " << numBones << endl;
|
||||
for (auto Joint : Joints)
|
||||
{
|
||||
out << "Joint NameLength " << Joint.NameLength << endl;
|
||||
out << "Joint name " << Joint.Name << endl;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++){
|
||||
out << Joint.OffsetMatrix[i][j] << " ";
|
||||
}
|
||||
out << endl;
|
||||
}
|
||||
out << Joint.ID << endl;
|
||||
out << Joint.ParentID << endl;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class Skeleton {
|
||||
public:
|
||||
//std::vector<SkeletonNode> DoIt();
|
||||
Animation GetAnimData(std::string animationName, int startFrame, int endFrame);
|
||||
std::vector<BindPoseSkeletonNode> GetBindPoses();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //Skeleton_Skeleton_h__
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "WriteToFile.h"
|
||||
|
||||
WriteToFile::~WriteToFile()
|
||||
{
|
||||
CloseFiles();
|
||||
}
|
||||
|
||||
bool WriteToFile::binaryFilePath(string filePathAndFileName)
|
||||
{
|
||||
binFileName = filePathAndFileName;
|
||||
ofstream binFile(filePathAndFileName, ofstream::binary);
|
||||
if (!binFile)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteToFile::ASCIIFilePath(string filePathAndFileName)
|
||||
{
|
||||
ASCIIFileName = filePathAndFileName;
|
||||
ofstream ASCIIFile(filePathAndFileName);
|
||||
if (!ASCIIFile)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteToFile::OpenFiles()
|
||||
{
|
||||
if (binFile) {
|
||||
binFile.open(binFileName, ofstream::binary);
|
||||
}
|
||||
if (ASCIIFile){
|
||||
ASCIIFile.open(ASCIIFileName);
|
||||
ASCIIFile << std::fixed << std::setprecision(3);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteToFile::CloseFiles()
|
||||
{
|
||||
binFile.close();
|
||||
ASCIIFile.close();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef WriteToFile_WriteToFile_h__
|
||||
#define WriteToFile_WriteToFile_h__
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
#include "OutputData.h"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class WriteToFile
|
||||
{
|
||||
public:
|
||||
~WriteToFile();
|
||||
bool binaryFilePath(string filePathAndFileName);
|
||||
bool ASCIIFilePath(string filePathAndFileName);
|
||||
|
||||
void writeToFiles(OutputData* toWrite, unsigned int numOfElementToWrite = 1, unsigned int startIndex = 0)
|
||||
{
|
||||
MGlobal::displayInfo("WriteToFile::writeToFiles(OutputData*)");
|
||||
if (ASCIIFile.is_open())
|
||||
{
|
||||
for (unsigned int i = startIndex; i < numOfElementToWrite + startIndex; i++)
|
||||
ASCIIFile << toWrite[i] << endl;
|
||||
}
|
||||
|
||||
if (binFile.is_open())
|
||||
{
|
||||
for (unsigned int i = startIndex; i < numOfElementToWrite + startIndex; i++)
|
||||
toWrite[i].WriteBinary(binFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void writeToFiles(T* toWrite, unsigned int numOfElementToWrite = 1, unsigned int startIndex = 0)
|
||||
{
|
||||
MGlobal::displayInfo("WriteToFile::writeToFiles(T*) - Template T");
|
||||
if (ASCIIFile.is_open()) {
|
||||
for (unsigned int i = startIndex; i < numOfElementToWrite + startIndex; i++)
|
||||
ASCIIFile << toWrite[i] << endl;
|
||||
}
|
||||
|
||||
if (binFile.is_open()) {
|
||||
for (unsigned int i = startIndex; i < numOfElementToWrite + startIndex; i++)
|
||||
binFile.write((char*)toWrite, sizeof(T));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void OpenFiles();
|
||||
void CloseFiles();
|
||||
|
||||
private:
|
||||
string binFileName;
|
||||
string ASCIIFileName;
|
||||
ofstream binFile;
|
||||
ofstream ASCIIFile;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user