Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 24486c314d | |||
| 7b62dc19bf | |||
| 0e90382fd1 | |||
| dc7ed2e0ba | |||
| f71bfca142 | |||
| dbb44fb4e4 | |||
| 1667358e0c | |||
| 6e6460a000 | |||
| 9f871bbe7c | |||
| 2bd60be741 | |||
| dab4ba2164 | |||
| 25a99a04c5 | |||
| 13ade6d7f2 | |||
| 592776e783 | |||
| ff44dccb33 | |||
| e7bb8954bf | |||
| e510f2b88c | |||
| eb5fca898f | |||
| c9db46564f | |||
| eb69e03e82 | |||
| d38f58165f | |||
| 069a6756b9 | |||
| ef4cbfece8 | |||
| ab6af30a28 | |||
| 3636ad45af | |||
| 6cf7c12d34 | |||
| 509a989d3b | |||
| bc4cc5db54 | |||
| 4a817613e3 | |||
| 73708ec706 | |||
| 6a3c14540d | |||
| 5602b32507 | |||
| 67017fcaf4 | |||
| 498afb3a5e | |||
| 1431bd1a11 | |||
| 1e370bac13 | |||
| 4e535c1102 | |||
| 1689370356 | |||
| 7c714d1f98 | |||
| 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: 673d4a4e4c...c8e631f449
@@ -0,0 +1,38 @@
|
||||
#ifndef DrawFinalPass_h__
|
||||
#define DrawFinalPass_h__
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "DrawFinalPassState.h"
|
||||
#include "LightCullingPass.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class DrawFinalPass
|
||||
{
|
||||
public:
|
||||
DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass);
|
||||
~DrawFinalPass() { }
|
||||
void InitializeTextures();
|
||||
void InitializeFrameBuffers();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
void Draw(RenderQueueCollection& rq);
|
||||
|
||||
//Getters
|
||||
|
||||
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
|
||||
Texture* m_WhiteTexture;
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
const LightCullingPass* m_LightCullingPass;
|
||||
|
||||
ShaderProgram* m_ForwardPlusProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef DrawFinalPassState_h__
|
||||
#define DrawFinalPassState_h__
|
||||
|
||||
#include "Rendering/RenderState.h"
|
||||
|
||||
class DrawFinalPassState : public RenderState
|
||||
{
|
||||
public:
|
||||
DrawFinalPassState();
|
||||
~DrawFinalPassState();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef LightCullingPass_h__
|
||||
#define LightCullingPass_h__
|
||||
|
||||
#define TILE_SIZE 16
|
||||
#define NUM_LIGHTS 1000
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "LightCullingPassState.h"
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
|
||||
class LightCullingPass
|
||||
{
|
||||
public:
|
||||
LightCullingPass(IRenderer* renderer);
|
||||
~LightCullingPass();
|
||||
|
||||
void GenerateNewFrustum();
|
||||
void CullLights();
|
||||
void FillLightList(RenderQueueCollection& rq);
|
||||
|
||||
GLuint FrustumSSBO() const { return m_FrustumSSBO; }
|
||||
GLuint LightSSBO() const { return m_LightSSBO; }
|
||||
GLuint LightGridSSBO() const { return m_LightGridSSBO; }
|
||||
GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; }
|
||||
GLuint LightIndexSSBO() const { return m_LightIndexSSBO; }
|
||||
private:
|
||||
|
||||
void InitializeSSBOs();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
GLuint m_FrustumSSBO = 0;
|
||||
GLuint m_LightSSBO = 0;
|
||||
GLuint m_LightGridSSBO = 0;
|
||||
GLuint m_LightOffsetSSBO = 0;
|
||||
GLuint m_LightIndexSSBO = 0;
|
||||
|
||||
ShaderProgram* m_CalculateFrustumProgram;
|
||||
ShaderProgram* m_LightCullProgram;
|
||||
|
||||
struct Plane {
|
||||
glm::vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
|
||||
|
||||
//This should be a component
|
||||
struct PointLight {
|
||||
glm::vec4 Position = glm::vec4(0.f);
|
||||
glm::vec4 Color = glm::vec4(1.f);
|
||||
float Radius = 5.f;
|
||||
float Intensity = 0.8f;
|
||||
float Falloff = 0.3f;
|
||||
float Padding = 1337;
|
||||
};
|
||||
std::vector<PointLight> m_PointLights;
|
||||
|
||||
struct LightGrid {
|
||||
float Start;
|
||||
float Amount;
|
||||
glm::vec2 Padding;
|
||||
};
|
||||
|
||||
LightGrid m_LightGrid[80*45]; //TODO: Renderer: Make this change with resolution
|
||||
|
||||
int m_LightOffset = 0;
|
||||
|
||||
float m_LightIndex[80*45*200]; //TODO: Renderer: Make this change with resolution
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef PickingPass_h__
|
||||
#define PickingPass_h__
|
||||
|
||||
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "PickingPassState.h"
|
||||
#include "FrameBuffer.h"
|
||||
@@ -9,6 +11,8 @@
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "EPicking.h"
|
||||
|
||||
|
||||
|
||||
class PickingPass
|
||||
{
|
||||
public:
|
||||
@@ -20,7 +24,6 @@ public:
|
||||
|
||||
void Draw(RenderQueueCollection& rq);
|
||||
|
||||
|
||||
//Getters
|
||||
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
|
||||
const std::unordered_map<glm::vec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
|
||||
@@ -28,7 +31,6 @@ public:
|
||||
GLuint DepthBuffer() const { return m_DepthBuffer; }
|
||||
const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; }
|
||||
|
||||
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
|
||||
|
||||
@@ -82,11 +82,12 @@ struct SpriteJob : RenderJob
|
||||
|
||||
struct PointLightJob : RenderJob
|
||||
{
|
||||
glm::vec3 Position;
|
||||
glm::vec3 SpecularColor = glm::vec3(1, 1, 1);
|
||||
glm::vec3 DiffuseColor = glm::vec3(1, 1, 1);
|
||||
float Radius = 1.f;
|
||||
float Intensity = 0.8f;
|
||||
glm::vec4 Position;
|
||||
glm::vec4 Color;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float Falloff;
|
||||
float padding = 123;
|
||||
|
||||
void CalculateHash() override
|
||||
{
|
||||
|
||||
@@ -13,19 +13,8 @@
|
||||
#include "PickingPass.h"
|
||||
#include "DrawScenePass.h"
|
||||
#include "DebugCameraInputController.h"
|
||||
|
||||
|
||||
#define TILE_SIZE 16
|
||||
#define NUM_LIGHTS 3
|
||||
|
||||
|
||||
enum lightType
|
||||
{
|
||||
Point,
|
||||
Spot,
|
||||
Directional,
|
||||
Area
|
||||
};
|
||||
#include "LightCullingPass.h"
|
||||
#include "DrawFinalPass.h"
|
||||
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "EPicking.h"
|
||||
@@ -58,70 +47,24 @@ private:
|
||||
|
||||
DrawScenePass* m_DrawScenePass;
|
||||
PickingPass* m_PickingPass;
|
||||
LightCullingPass* m_LightCullingPass;
|
||||
ImGuiRenderPass* m_ImGuiRenderPass;
|
||||
DrawFinalPass* m_DrawFinalPass;
|
||||
|
||||
//----------------------Functions----------------------//
|
||||
void InitializeWindow();
|
||||
void InitializeShaders();
|
||||
void InitializeTextures();
|
||||
void InitializeSSBOs();
|
||||
void InitializeRenderPasses();
|
||||
//TODO: Renderer: Get InputUpdate out of renderer
|
||||
void InputUpdate(double dt);
|
||||
//void PickingPass(RenderQueueCollection& rq);
|
||||
void DrawScreenQuad(GLuint textureToDraw);
|
||||
|
||||
//----------------------Forward+-----------------------//
|
||||
void CalculateFrustum();
|
||||
void CullLights();
|
||||
//Frustum
|
||||
struct Plane {
|
||||
glm::vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
|
||||
|
||||
//Lights
|
||||
void TEMPCreateLights();
|
||||
//TODO: Renderer: Add Directionllights, spotlights and area lights to this as type.
|
||||
struct PointLight {
|
||||
glm::vec4 Position = glm::vec4(0.f);
|
||||
glm::vec4 Color = glm::vec4(1.f);
|
||||
float Radius = 5.f;
|
||||
float Intensity = 0.8f;
|
||||
float Falloff = 0.3f;
|
||||
float Padding = 1337;
|
||||
};
|
||||
PointLight m_PointLights[NUM_LIGHTS];
|
||||
|
||||
struct LightGrid {
|
||||
int Amount;
|
||||
int Start;
|
||||
glm::vec2 Padding;
|
||||
};
|
||||
LightGrid m_LightGrid[80*45];
|
||||
|
||||
int m_LightOffset = 0;
|
||||
|
||||
int m_LightIndex[80*45*200];
|
||||
|
||||
//-------------------------SSBO------------------------//
|
||||
GLuint m_FrustumSSBO = 0;
|
||||
GLuint m_LightSSBO = 1;
|
||||
GLuint m_LightGridSSBO = 2;
|
||||
GLuint m_LightOffsetSSBO = 3;
|
||||
GLuint m_LightIndexSSBO = 4;
|
||||
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
|
||||
//--------------------ShaderPrograms-------------------//
|
||||
ShaderProgram* m_BasicForwardProgram;
|
||||
ShaderProgram* m_DrawScreenQuadProgram;
|
||||
ShaderProgram* m_CalculateFrustumProgram;
|
||||
ShaderProgram* m_LightCullProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@
|
||||
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
||||
<xs:include schemaLocation="Components/Player.xsd"/>
|
||||
<xs:include schemaLocation="Components/AABB.xsd"/>
|
||||
<xs:include schemaLocation="Components/PointLight.xsd"/>
|
||||
<xs:include schemaLocation="Components/Trigger.xsd"/>
|
||||
<xs:include schemaLocation="Components/Health.xsd"/>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,7 @@
|
||||
<c:PointLight>
|
||||
<Color R="1" G="1" B="1" A="1"/>
|
||||
<Radius>1.0</Radius>
|
||||
<Intensity>0.8</Intensity>
|
||||
<Falloff>0.3</Falloff>
|
||||
<Visible>true</Visible>
|
||||
</c:PointLight>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="PointLight">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A pointlight that lights up geometry in a radius.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Color" type="t:Color" minOccurs="0"/>
|
||||
<xs:element name="Radius" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Falloff" type="t:double" minOccurs="0"/>
|
||||
<xs:element name="Visible" type="t:bool" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -10,7 +10,7 @@
|
||||
</c:Model>
|
||||
</Components>
|
||||
<Children>
|
||||
<Entity>
|
||||
<!--<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="-1.5"/>
|
||||
@@ -20,8 +20,8 @@
|
||||
<Resource>Models/ScaleWidget.obj</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
</Entity>-->
|
||||
<!--<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="1.5"/>
|
||||
@@ -33,7 +33,7 @@
|
||||
<c:Trigger>
|
||||
</c:Trigger>
|
||||
</Components>
|
||||
</Entity>
|
||||
</Entity>-->
|
||||
<!--<Entity>
|
||||
<Components>
|
||||
<c:Player>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||
<xs:element ref="c:Player" minOccurs="0"/>
|
||||
<xs:element ref="c:Health" minOccurs="0"/>
|
||||
<xs:element ref="c:PointLight" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
#version 430
|
||||
|
||||
//in uvec3 gl_NumWorkGroups; //contains the number of workgroups that have been dispatched to a compute shader
|
||||
//in uvec3 gl_WorkGroupID; //contains the index of the workgroup currently being operated on by a compute shader
|
||||
//in uvec3 gl_LocalInvocationID; //contains the index of work item currently being operated on by a compute shader
|
||||
//in uvec3 gl_GlobalInvocationID; //contains the global index of work item currently being operated on by a compute shader
|
||||
//in uint gl_LocalInvocationIndex; //contains the local linear index of work item currently being operated on by a compute shader
|
||||
|
||||
|
||||
|
||||
#define MAX_LIGHTS_PER_TILE 200
|
||||
#define NUM_TILES 3600
|
||||
#define TILE_SIZE 16
|
||||
|
||||
uniform mat4 V;
|
||||
|
||||
struct Plane {
|
||||
vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
|
||||
layout (std430, binding = 0) buffer FrustumBuffer
|
||||
{
|
||||
Frustum Data[];
|
||||
} Frustums;
|
||||
|
||||
struct PointLight {
|
||||
vec4 Position;
|
||||
vec4 Color;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float Falloff;
|
||||
float Padding;
|
||||
};
|
||||
|
||||
layout (std430, binding = 1) buffer LightBuffer
|
||||
{
|
||||
PointLight List[];
|
||||
} PointLights;
|
||||
|
||||
struct LightGrid {
|
||||
float Start;
|
||||
float Amount;
|
||||
vec2 Padding;
|
||||
};
|
||||
|
||||
layout (std430, binding = 2) buffer LightGridBuffer
|
||||
{
|
||||
LightGrid Data[];
|
||||
} LightGrids;
|
||||
|
||||
layout (std430, binding = 3) buffer LightOffsetBuffer
|
||||
{
|
||||
int LightOffset[];
|
||||
};
|
||||
|
||||
layout (std430, binding = 4) buffer LightIndexBuffer
|
||||
{
|
||||
float LightIndex[];
|
||||
};
|
||||
|
||||
shared int GroupLightCount;
|
||||
shared int GroupLightIndexStartOffset;
|
||||
shared int GroupLightIndex[MAX_LIGHTS_PER_TILE];
|
||||
shared Frustum GroupFrustum;
|
||||
int GroupIndex;
|
||||
|
||||
bool SphereInsidePlane(vec3 center, float radius, Plane plane)
|
||||
{
|
||||
return dot(plane.Normal, center) - plane.d > -radius;
|
||||
}
|
||||
|
||||
bool SphereInsideFrustrum(vec3 center, float radius, Frustum frustum/*, float zNear, float zFar*/)
|
||||
{
|
||||
|
||||
//Check depth here
|
||||
//if ( sphere.c.z - sphere.r > zNear || sphere.c.z + sphere.r < zFar )
|
||||
//{
|
||||
// result = false;
|
||||
//}
|
||||
|
||||
for (int i =0; i < 4; i++)
|
||||
{
|
||||
if(! SphereInsidePlane(center, radius, frustum.Planes[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AppendLight(int li)
|
||||
{
|
||||
int index;
|
||||
index = atomicAdd(GroupLightCount, 1);
|
||||
if( index < MAX_LIGHTS_PER_TILE )
|
||||
{
|
||||
GroupLightIndex[index] = int(li);
|
||||
}
|
||||
}
|
||||
|
||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
void main ()
|
||||
{
|
||||
GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * 80));
|
||||
if(gl_LocalInvocationIndex == 0)
|
||||
{
|
||||
GroupLightCount = 0;
|
||||
GroupFrustum = Frustums.Data[GroupIndex];
|
||||
}
|
||||
|
||||
barrier();
|
||||
memoryBarrierShared();
|
||||
|
||||
for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE)
|
||||
{
|
||||
PointLight light = PointLights.List[i];
|
||||
|
||||
//if pointlight
|
||||
//Pos i view antagligen
|
||||
if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum))
|
||||
{
|
||||
//TODO: Fix transparent and opaque list, and depth test.
|
||||
AppendLight( i );
|
||||
}
|
||||
|
||||
|
||||
//if conelight
|
||||
|
||||
//if directional
|
||||
|
||||
}
|
||||
|
||||
barrier();
|
||||
memoryBarrierShared();
|
||||
|
||||
if(gl_LocalInvocationIndex == 0)
|
||||
{
|
||||
GroupLightIndexStartOffset = atomicAdd(LightOffset[0], GroupLightCount);
|
||||
LightGrids.Data[GroupIndex].Start = GroupLightIndexStartOffset;
|
||||
LightGrids.Data[GroupIndex].Amount = GroupLightCount;
|
||||
}
|
||||
|
||||
barrier();
|
||||
|
||||
|
||||
for (uint i = gl_LocalInvocationIndex; i < GroupLightCount; i += TILE_SIZE * TILE_SIZE )
|
||||
{
|
||||
LightIndex[GroupLightIndexStartOffset + i] = GroupLightIndex[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#version 430
|
||||
|
||||
uniform mat4 M;
|
||||
uniform mat4 V;
|
||||
uniform mat4 P;
|
||||
uniform vec4 Color;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
|
||||
#define TILE_SIZE 16
|
||||
|
||||
struct PointLight {
|
||||
vec4 Position;
|
||||
vec4 Color;
|
||||
float Radius;
|
||||
float Intensity;
|
||||
float Falloff;
|
||||
float Padding;
|
||||
};
|
||||
|
||||
layout (std430, binding = 1) buffer LightBuffer
|
||||
{
|
||||
PointLight List[];
|
||||
} PointLights;
|
||||
|
||||
struct LightGrid {
|
||||
float Start;
|
||||
float Amount;
|
||||
vec2 Padding;
|
||||
};
|
||||
|
||||
layout (std430, binding = 2) buffer LightGridBuffer
|
||||
{
|
||||
LightGrid Data[];
|
||||
} LightGrids;
|
||||
|
||||
layout (std430, binding = 4) buffer LightIndexBuffer
|
||||
{
|
||||
float LightIndex[];
|
||||
};
|
||||
|
||||
|
||||
in VertexData{
|
||||
vec3 Position;
|
||||
vec3 Normal;
|
||||
vec2 TextureCoordinate;
|
||||
vec4 DiffuseColor;
|
||||
}Input;
|
||||
|
||||
out vec4 fragmentColor;
|
||||
|
||||
vec4 scene_ambient = vec4(0.3,0.3,0.3,1);
|
||||
|
||||
struct LightResult {
|
||||
vec4 Diffuse;
|
||||
vec4 Specular;
|
||||
};
|
||||
|
||||
float CalcAttenuation(float radius, float dist) {
|
||||
return 1.0 - smoothstep(radius * 0.3, radius, dist);
|
||||
}
|
||||
|
||||
vec4 CalcSpecular(vec4 lightColor, vec4 viewVec, vec4 lightVec, vec4 normal) {
|
||||
vec4 R = normalize( reflect(-lightVec, normal));
|
||||
float RdotV = max( dot(R, viewVec), 0.0);
|
||||
return lightColor * pow(RdotV, 90.0);
|
||||
}
|
||||
|
||||
vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) {
|
||||
float power = max( dot(normal, lightVec), 0.0);
|
||||
return lightColor * power;
|
||||
}
|
||||
|
||||
LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal)
|
||||
{
|
||||
vec4 L = lightPos - position;
|
||||
float dist = length(L);
|
||||
L = normalize(L);
|
||||
|
||||
float attenuation = CalcAttenuation(lightRadius, dist);
|
||||
|
||||
LightResult result;
|
||||
result.Diffuse = CalcDiffuse(lightColor, L, normal) * attenuation * intensity;
|
||||
result.Specular = CalcSpecular(lightColor, viewVec, L, normal) * attenuation * intensity;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texel = texture2D(texture0, Input.TextureCoordinate);
|
||||
vec4 position = V * M * vec4(Input.Position, 1.0);
|
||||
vec4 normal = V * vec4(Input.Normal, 0.0);
|
||||
vec4 viewVec = normalize(-position);
|
||||
|
||||
vec2 tilePos;
|
||||
tilePos.x = int(gl_FragCoord.x/16);
|
||||
tilePos.y = int(gl_FragCoord.y/16);
|
||||
|
||||
LightResult totalLighting;
|
||||
totalLighting.Diffuse = scene_ambient;
|
||||
int currentTile = int(floor(gl_FragCoord.x/TILE_SIZE) + (floor(gl_FragCoord.y/TILE_SIZE) * 80));
|
||||
|
||||
int start = int(LightGrids.Data[currentTile].Start);
|
||||
int amount = int(LightGrids.Data[currentTile].Amount);
|
||||
//for(int i = 0; i < 3; i++)
|
||||
for(int i = start; i < start + amount; i++)
|
||||
{
|
||||
int l = int(LightIndex[i]);
|
||||
|
||||
LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal);
|
||||
|
||||
totalLighting.Diffuse += result.Diffuse;
|
||||
totalLighting.Specular += result.Specular;
|
||||
}
|
||||
|
||||
fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color;
|
||||
//fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color;
|
||||
//fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1);
|
||||
//fragmentColor = texel * Input.DiffuseColor * Color;
|
||||
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 )
|
||||
{
|
||||
//fragmentColor += vec4(0.5, 0, 0, 0);
|
||||
} else {
|
||||
//fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#version 430
|
||||
|
||||
uniform mat4 M;
|
||||
uniform mat4 V;
|
||||
uniform mat4 P;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
Output.TextureCoordinate = TextureCoords;
|
||||
Output.Normal = Normal;
|
||||
Output.DiffuseColor = DiffuseVertexColor;
|
||||
}
|
||||
@@ -16,7 +16,7 @@ struct Frustum {
|
||||
|
||||
layout (std430, binding = 0) buffer FrustumBuffer
|
||||
{
|
||||
Frustum Data[3600];
|
||||
Frustum Data[];
|
||||
} Frustums;
|
||||
|
||||
vec4 ConvertToView(vec4 ScreenCoords)
|
||||
@@ -43,31 +43,34 @@ Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 )
|
||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
void main ()
|
||||
{
|
||||
if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) {
|
||||
//Top-Left = 0 | Top-Right = 1
|
||||
//Bottom-Left = 2 | Bottom-Right = 3
|
||||
vec4 ScreenCoords[4];
|
||||
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1
|
||||
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
|
||||
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
||||
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
||||
|
||||
vec3 ViewVectors[4];
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
|
||||
}
|
||||
|
||||
vec3 EyePos = vec3(0,0,0);
|
||||
|
||||
Frustum f;
|
||||
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]);
|
||||
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]);
|
||||
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]);
|
||||
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]);
|
||||
//Top-Left = 0 | Top-Right = 1
|
||||
//Bottom-Left = 2 | Bottom-Right = 3
|
||||
vec4 ScreenCoords[4];
|
||||
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
|
||||
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
|
||||
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
||||
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
|
||||
|
||||
|
||||
|
||||
|
||||
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f;
|
||||
vec3 ViewVectors[4];
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
|
||||
}
|
||||
|
||||
vec3 EyePos = vec3(0.0, 0.0 ,0.0);
|
||||
|
||||
Frustum f;
|
||||
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]); // left plane
|
||||
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]); // right plane
|
||||
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]); // top plane
|
||||
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]); // bottom plane
|
||||
|
||||
|
||||
|
||||
|
||||
if ( gl_GlobalInvocationID.x < ScreenDimensions.x / TILE_SIZE && gl_GlobalInvocationID.y < ScreenDimensions.y / TILE_SIZE ) { // inside the screen
|
||||
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#version 430
|
||||
|
||||
//in uvec3 gl_NumWorkGroups;
|
||||
//in uvec3 gl_WorkGroupID;
|
||||
//in uvec3 gl_LocalInvocationID;
|
||||
//in uvec3 gl_GlobalInvocationID;
|
||||
//in uint gl_LocalInvocationIndex;
|
||||
|
||||
|
||||
|
||||
#define NUM_LIGHTS 3
|
||||
#define MAX_LIGHTS_PER_TILE 200
|
||||
#define NUM_TILES 3600
|
||||
|
||||
struct Plane {
|
||||
vec3 Normal;
|
||||
float d;
|
||||
};
|
||||
struct Frustum {
|
||||
Plane Planes[4];
|
||||
};
|
||||
|
||||
layout (std430, binding = 0) buffer FrustumBuffer
|
||||
{
|
||||
Frustum Data[3600];
|
||||
} Frustums;
|
||||
|
||||
|
||||
|
||||
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
|
||||
void main ()
|
||||
{
|
||||
if(1 == 1) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "Rendering/DrawFinalPass.h"
|
||||
|
||||
DrawFinalPass::DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
m_LightCullingPass = lightCullingPass;
|
||||
InitializeTextures();
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
void DrawFinalPass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
}
|
||||
|
||||
void DrawFinalPass::InitializeShaderPrograms()
|
||||
{
|
||||
m_ForwardPlusProgram = ResourceManager::Load<ShaderProgram>("#ForwardPlusProgram");
|
||||
m_ForwardPlusProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/ForwardPlus.vert.glsl")));
|
||||
m_ForwardPlusProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/ForwardPlus.frag.glsl")));
|
||||
m_ForwardPlusProgram->Compile();
|
||||
m_ForwardPlusProgram->Link();
|
||||
}
|
||||
|
||||
void DrawFinalPass::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
GLERROR("DrawFinalPass::Draw: Pre");
|
||||
|
||||
DrawFinalPassState state;
|
||||
m_ForwardPlusProgram->Bind();
|
||||
GLuint shaderHandle = m_ForwardPlusProgram->GetHandle();
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
|
||||
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
for (auto &job : rq.Forward) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if(modelJob) {
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
||||
glUniform4fv(glGetUniformLocation(shaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
|
||||
if(modelJob->DiffuseTexture != nullptr) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
GLERROR("DrawFinalPass::Draw: END");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "Rendering/DrawFinalPassState.h"
|
||||
|
||||
|
||||
DrawFinalPassState::DrawFinalPassState()
|
||||
{
|
||||
BindFramebuffer(0);
|
||||
|
||||
Enable(GL_DEPTH_TEST);
|
||||
Enable(GL_CULL_FACE);
|
||||
ClearColor(glm::vec4(200.f / 255, 0.f / 255, 200.f / 255, 0.f));
|
||||
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
DrawFinalPassState::~DrawFinalPassState()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -14,23 +14,21 @@ void DrawScenePass::InitializeTextures()
|
||||
|
||||
void DrawScenePass::InitializeShaderPrograms()
|
||||
{
|
||||
//Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat.
|
||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#BasicForwardProgram");
|
||||
|
||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
|
||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
|
||||
m_BasicForwardProgram->Compile();
|
||||
m_BasicForwardProgram->Link();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DrawScenePass::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
GLERROR("Renderer::Draw PickingPass");
|
||||
GLERROR("DrawScenePass::Draw: Pre");
|
||||
|
||||
DrawScenePassState state;
|
||||
m_BasicForwardProgram->Bind();
|
||||
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
@@ -39,7 +37,6 @@ void DrawScenePass::Draw(RenderQueueCollection& rq)
|
||||
if (modelJob) {
|
||||
GLuint ShaderHandle = m_BasicForwardProgram->GetHandle();
|
||||
|
||||
m_BasicForwardProgram->Bind();
|
||||
//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->ModelMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
||||
@@ -61,6 +58,12 @@ void DrawScenePass::Draw(RenderQueueCollection& rq)
|
||||
|
||||
continue;
|
||||
}
|
||||
auto spriteJob = std::dynamic_pointer_cast<SpriteJob>(job);
|
||||
if(spriteJob)
|
||||
{
|
||||
//Hello im a sprite, please draw me.
|
||||
}
|
||||
|
||||
}
|
||||
GLERROR("DrawScene Error");
|
||||
GLERROR("DrawScenePass::Draw: End");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "Rendering/LightCullingPass.h"
|
||||
|
||||
LightCullingPass::LightCullingPass(IRenderer* renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
InitializeSSBOs();
|
||||
InitializeShaderPrograms();
|
||||
GenerateNewFrustum();
|
||||
}
|
||||
|
||||
LightCullingPass::~LightCullingPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LightCullingPass::GenerateNewFrustum()
|
||||
{
|
||||
GLERROR("CalculateFrustum Error: Pre");
|
||||
|
||||
m_CalculateFrustumProgram->Bind();
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
glDispatchCompute(5, 3, 1); //TODO: Renderer: This needs change so resolution will be right.
|
||||
|
||||
GLERROR("CalculateFrustum Error: End");
|
||||
}
|
||||
|
||||
void LightCullingPass::CullLights()
|
||||
{
|
||||
GLERROR("CullLights Error: Pre");
|
||||
m_LightOffset = 0;
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
|
||||
if (m_PointLights.size() > 0) {
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY);
|
||||
} else {
|
||||
GLfloat zero = 0.f;
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), &zero , GL_DYNAMIC_COPY);
|
||||
|
||||
}
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
m_LightCullProgram->Bind();
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_LightCullProgram->GetHandle(), "V"), 1, false, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glDispatchCompute(m_Renderer->Resolution().Width / TILE_SIZE, m_Renderer->Resolution().Height / TILE_SIZE, 1);
|
||||
|
||||
GLERROR("CullLights Error: End");
|
||||
}
|
||||
|
||||
void LightCullingPass::FillLightList(RenderQueueCollection& rq)
|
||||
{
|
||||
m_PointLights.clear();
|
||||
for(auto &job : rq.Lights) {
|
||||
auto pointLightjob = std::dynamic_pointer_cast<PointLightJob>(job);
|
||||
if (pointLightjob) {
|
||||
PointLight p;
|
||||
p.Color = pointLightjob->Color;
|
||||
p.Falloff = pointLightjob->Falloff;
|
||||
p.Intensity = pointLightjob->Intensity;
|
||||
p.Position = glm::vec4(glm::vec3(pointLightjob->Position), 1.f);
|
||||
p.Radius = pointLightjob->Radius;
|
||||
p.Padding = 123.f;
|
||||
m_PointLights.push_back(p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LightCullingPass::InitializeSSBOs()
|
||||
{
|
||||
glGenBuffers(1, &m_FrustumSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
GLERROR("m_FrustumSSBO");
|
||||
|
||||
glGenBuffers(1, &m_LightSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
|
||||
if(m_PointLights.size() > 0) {
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(PointLight) * m_PointLights.size(), &(m_PointLights[0]), GL_DYNAMIC_COPY);
|
||||
}
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
GLERROR("m_LightSSBO");
|
||||
|
||||
glGenBuffers(1, &m_LightGridSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
GLERROR("m_LightGridSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightOffsetSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
GLERROR("m_LightOffsetSSBO");
|
||||
|
||||
glGenBuffers(1, &m_LightIndexSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
GLERROR("m_LightIndexSSBO");
|
||||
}
|
||||
|
||||
void LightCullingPass::InitializeShaderPrograms()
|
||||
{
|
||||
m_CalculateFrustumProgram = ResourceManager::Load<ShaderProgram>("#CalculateFrustumProgram");
|
||||
m_CalculateFrustumProgram->AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/GridFrustum.comp.glsl")));
|
||||
m_CalculateFrustumProgram->Compile();
|
||||
m_CalculateFrustumProgram->Link();
|
||||
|
||||
m_LightCullProgram = ResourceManager::Load<ShaderProgram>("#LightCullProgram");
|
||||
m_LightCullProgram->AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/CullLights.comp.glsl")));
|
||||
m_LightCullProgram->Compile();
|
||||
m_LightCullProgram->Link();
|
||||
}
|
||||
|
||||
@@ -111,6 +111,34 @@ void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
||||
|
||||
void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue)
|
||||
{
|
||||
auto pointLights = world->GetComponents("PointLight");
|
||||
if(pointLights == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto& pointlightC : *pointLights) {
|
||||
bool visible = pointlightC["Visible"];
|
||||
if(!visible) {
|
||||
continue;
|
||||
}
|
||||
auto transformC = world->GetComponent(pointlightC.EntityID, "Transform");
|
||||
if(&transformC == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec4 color = pointlightC["Color"];
|
||||
float radius = (double)pointlightC["Radius"];
|
||||
float intensity = (double)pointlightC["Intensity"];
|
||||
float falloff = (double)pointlightC["Falloff"];
|
||||
|
||||
PointLightJob job;
|
||||
job.Position = glm::vec4(AbsolutePosition(world, transformC.EntityID), 1.f);
|
||||
job.Color = color;
|
||||
job.Radius = radius;
|
||||
job.Intensity = intensity;
|
||||
job.Falloff = falloff;
|
||||
|
||||
renderQueue->Add(job);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
bool RenderState::Enable(GLenum cap)
|
||||
{
|
||||
if (glIsEnabled(cap)) {
|
||||
//LOG_WARNING("Trying to enable somthing that is already enabled.");
|
||||
return false;
|
||||
}
|
||||
m_ResetFunctions.push_back(std::bind(glDisable, cap));
|
||||
|
||||
@@ -4,20 +4,17 @@ void Renderer::Initialize()
|
||||
{
|
||||
InitializeWindow();
|
||||
// Create default camera
|
||||
m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f);
|
||||
m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10));
|
||||
m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(90.0f), 0.01f, 5000.f);
|
||||
m_DefaultCamera->SetPosition(glm::vec3(0, 1, 10));
|
||||
if (m_Camera == nullptr) {
|
||||
m_Camera = m_DefaultCamera;
|
||||
}
|
||||
m_DebugCameraInputController = std::make_shared<DebugCameraInputController<Renderer>>(m_EventBroker, -1);
|
||||
TEMPCreateLights();
|
||||
InitializeRenderPasses();
|
||||
|
||||
glfwSwapInterval(m_VSYNC);
|
||||
InitializeShaders();
|
||||
InitializeTextures();
|
||||
InitializeSSBOs();
|
||||
//CalculateFrustum();
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||
@@ -75,49 +72,10 @@ void Renderer::InitializeShaders()
|
||||
m_DrawScreenQuadProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl")));
|
||||
m_DrawScreenQuadProgram->Compile();
|
||||
m_DrawScreenQuadProgram->Link();
|
||||
|
||||
//m_CalculateFrustumProgram = ResourceManager::Load<ShaderProgram>("#CalculateFrustumProgram");
|
||||
//m_CalculateFrustumProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/GridFrustum.comp.glsl")));
|
||||
//m_CalculateFrustumProgram.Compile();
|
||||
//m_CalculateFrustumProgram.Link();
|
||||
|
||||
//m_LightCullProgram = ResourceManager::Load<ShaderProgram>("#LightCullProgram");
|
||||
//m_LightCullProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/cullLights.comp.glsl")));
|
||||
//m_LightCullProgram.Compile();
|
||||
//m_LightCullProgram.Link();
|
||||
}
|
||||
|
||||
void Renderer::InputUpdate(double dt)
|
||||
{
|
||||
glm::vec3 m_Position = m_Camera->Position();
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS)
|
||||
{
|
||||
m_Position = glm::vec3(0.f, 0.f, 5.f);
|
||||
}
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_W) == GLFW_PRESS)
|
||||
{
|
||||
m_Position += m_Camera->Forward() * m_CameraMoveSpeed * (float)dt;
|
||||
}
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_S) == GLFW_PRESS)
|
||||
{
|
||||
m_Position -= m_Camera->Forward() * m_CameraMoveSpeed * (float)dt;
|
||||
}
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_D) == GLFW_PRESS)
|
||||
{
|
||||
m_Position += m_Camera->Right() * m_CameraMoveSpeed * (float)dt;
|
||||
}
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_A) == GLFW_PRESS)
|
||||
{
|
||||
m_Position -= m_Camera->Right() * m_CameraMoveSpeed * (float)dt;
|
||||
}
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
|
||||
{
|
||||
m_CameraMoveSpeed = 5.f;
|
||||
}
|
||||
else {
|
||||
m_CameraMoveSpeed = 0.5f;
|
||||
}
|
||||
|
||||
m_DebugCameraInputController->Update(dt);
|
||||
m_Camera->SetOrientation(m_DebugCameraInputController->Orientation());
|
||||
m_Camera->SetPosition(m_DebugCameraInputController->Position());
|
||||
@@ -134,11 +92,12 @@ void Renderer::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
m_PickingPass->Draw(rq);
|
||||
//DrawScreenQuad(m_PickingPass->PickingTexture());
|
||||
//CullLights();
|
||||
m_LightCullingPass->FillLightList(rq);
|
||||
m_LightCullingPass->CullLights();
|
||||
|
||||
//m_DrawScenePass->Draw(rq);
|
||||
m_DrawFinalPass->Draw(rq);
|
||||
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f);
|
||||
|
||||
m_DrawScenePass->Draw(rq);
|
||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||
m_ImGuiRenderPass->Draw();
|
||||
glfwSwapBuffers(m_Window);
|
||||
@@ -183,95 +142,10 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin
|
||||
GLERROR("Texture initialization failed");
|
||||
}
|
||||
|
||||
void Renderer::InitializeSSBOs()
|
||||
{
|
||||
printf("Size: %i\n", sizeof(m_Frustums));
|
||||
glGenBuffers(1, &m_FrustumSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_FrustumSSBO");
|
||||
|
||||
glGenBuffers(1, &m_LightSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightGridSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightGridSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightOffsetSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightOffsetSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightIndexSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightIndexSSBO");
|
||||
|
||||
}
|
||||
|
||||
void Renderer::InitializeRenderPasses()
|
||||
{
|
||||
m_DrawScenePass = new DrawScenePass(this);
|
||||
m_PickingPass = new PickingPass(this, m_EventBroker);
|
||||
}
|
||||
|
||||
void Renderer::CalculateFrustum()
|
||||
{
|
||||
GLERROR("CalculateFrustum Error-1");
|
||||
m_CalculateFrustumProgram->Bind();
|
||||
|
||||
GLERROR("CalculateFrustum Error1");
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
GLERROR("CalculateFrustum Error2");
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix()));
|
||||
GLERROR("CalculateFrustum Error3");
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height);
|
||||
GLERROR("CalculateFrustum Error4");
|
||||
glDispatchCompute(5, 3, 1);
|
||||
GLERROR("CalculateFrustum Error5");
|
||||
|
||||
}
|
||||
|
||||
void Renderer::TEMPCreateLights()
|
||||
{
|
||||
for (int i = 0; i < NUM_LIGHTS; i++) {
|
||||
m_PointLights[i].Position = glm::vec4(i, 0.f, 0.f, 0.f);
|
||||
m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CullLights()
|
||||
{
|
||||
m_LightCullProgram->Bind();
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1);
|
||||
GLERROR("CullLights Error");
|
||||
|
||||
}
|
||||
|
||||
m_LightCullingPass = new LightCullingPass(this);
|
||||
m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass);
|
||||
}
|
||||
+17
-10
@@ -19,22 +19,29 @@ void HealthSystem::UpdateComponent(World *world, ComponentWrapper &health, doubl
|
||||
for (size_t i = m_DeltaHealthVector.size(); i > 0; i--)
|
||||
{
|
||||
auto deltaHP = m_DeltaHealthVector[i - 1];
|
||||
//if we have a healthchange for the current player, then apply it
|
||||
if (std::get<0>(deltaHP) == player.EntityID) {
|
||||
//if we have a healthchange for the current player and health is greater than 0, then apply it
|
||||
if (std::get<0>(deltaHP) == player.EntityID && (double)health["Health"] > 0.0f) {
|
||||
//get the deltaHP value from the tuple and make sure you dont get more than maxHealth
|
||||
double newHealth = std::min((double)health["Health"] + (double)std::get<1>(deltaHP), maxHealth);
|
||||
health["Health"] = newHealth;
|
||||
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + i - 1);
|
||||
//check if health is <= 0
|
||||
if ((double)health["Health"] <= 0.0f) {
|
||||
//publish death event
|
||||
Events::PlayerDeath e;
|
||||
e.PlayerID = player.EntityID;
|
||||
m_EventBroker->Publish(e);
|
||||
//clear the remaining hpDeltas for the dead player
|
||||
for (size_t j = m_DeltaHealthVector.size(); j > 0; j--)
|
||||
{
|
||||
if (std::get<0>(m_DeltaHealthVector[j - 1]) == player.EntityID)
|
||||
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1);
|
||||
}
|
||||
//break the loop if the player is dead
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check if health is <= 0
|
||||
if ((double)health["Health"] <= 0.0f) {
|
||||
//publish death event
|
||||
Events::PlayerDeath e;
|
||||
e.PlayerID = player.EntityID;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
|
||||
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e)
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
#include "Export.h"
|
||||
|
||||
Export::Export()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Export::Meshes(std::string pathName, bool selectedOnly)
|
||||
{
|
||||
if (pathName.empty()) {
|
||||
MGlobal::displayError(MString() + "Export::Meshes() got no pathName. Do not know where to write file");
|
||||
return false;
|
||||
}
|
||||
meshes.clear();
|
||||
|
||||
if (selectedOnly) {
|
||||
// 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);
|
||||
|
||||
if (object.hasFn(MFn::kMesh)) {
|
||||
MFnDependencyNode thisNode(object);
|
||||
GetMeshData(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);
|
||||
bool next = false;
|
||||
|
||||
for (unsigned int i = 0; i < connections.length(); i++) {
|
||||
if (connections[i].node().apiType() == MFn::kSkinClusterFilter) {
|
||||
next = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next)
|
||||
continue;
|
||||
|
||||
GetMeshData(node);
|
||||
}
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "nrofmeshes: " + meshes.size());
|
||||
WriteMeshData(pathName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::Materials()
|
||||
{
|
||||
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;
|
||||
}
|
||||
MGlobal::displayInfo("HALLOOOO");
|
||||
allBindPoses = m_SkeletonHandler.GetBindPoses();
|
||||
|
||||
for (auto clip : animInfo) {
|
||||
MGlobal::displayInfo("preben");
|
||||
if (!GetAnimationData(clip)) {
|
||||
MGlobal::displayError(MString() + "Export::Animations() failed to export " + clip.Name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
MGlobal::displayInfo("ghihgihi");
|
||||
WriteAnimData(pathName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetMeshData(MObject object)
|
||||
{
|
||||
if (!object.hasFn(MFn::kMesh))
|
||||
return false;
|
||||
|
||||
meshes.push_back(m_MeshHandler.GetMeshData(object));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Export::GetMaterialData()
|
||||
{
|
||||
// Traverse scene and return vector with all materials
|
||||
std::vector<MaterialNode>* AllMaterials = m_MaterialHandler.DoIt();
|
||||
|
||||
// Access the colorR component of one material (example)
|
||||
cout << AllMaterials->at(0).Color[0] << endl;
|
||||
MGlobal::displayInfo(MString() + AllMaterials->at(0).Color[0]);
|
||||
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();
|
||||
|
||||
for (auto aMesh : meshes) {
|
||||
m_MeshFile.writeToFiles((OutputData*)&aMesh);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
Export::~Export()
|
||||
{
|
||||
/* delete m_MaterialHandler;
|
||||
delete m_SkeletonHandler;
|
||||
delete m_MeshHandler;*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#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();
|
||||
bool Animations(std::string pathName, std::vector<AnimationInfo> animInfo);
|
||||
|
||||
private:
|
||||
bool GetMeshData(MObject object);
|
||||
bool GetMaterialData();
|
||||
bool GetAnimationData(AnimationInfo info);
|
||||
|
||||
void WriteMeshData(std::string pathName);
|
||||
void WriteAnimData(std::string pathName);
|
||||
|
||||
Material m_MaterialHandler;
|
||||
Skeleton m_SkeletonHandler;
|
||||
MeshClass m_MeshHandler;
|
||||
|
||||
|
||||
//File export
|
||||
WriteToFile m_MeshFile;
|
||||
WriteToFile m_AnimFile;
|
||||
|
||||
//Mesh Data
|
||||
std::vector<Mesh> meshes;
|
||||
|
||||
//Animation Data
|
||||
std::vector<BindPoseSkeletonNode> allBindPoses;
|
||||
std::vector<Animation> allAnimations;
|
||||
|
||||
};
|
||||
#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,241 @@
|
||||
#include "Material.h"
|
||||
|
||||
void Material::grabLambertProperties(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
material_node.Name = node.name().asChar();
|
||||
|
||||
if (findColorTexture(material_node, node)) {
|
||||
material_node.Color.fill(1.0f);
|
||||
}
|
||||
else {
|
||||
m_Plug = node.findPlug("colorR");
|
||||
m_Plug.getValue(material_node.Color[0]);
|
||||
m_Plug = node.findPlug("colorG");
|
||||
m_Plug.getValue(material_node.Color[1]);
|
||||
m_Plug = node.findPlug("colorB");
|
||||
m_Plug.getValue(material_node.Color[2]);
|
||||
|
||||
float TempTransp[3];
|
||||
m_Plug = node.findPlug("transparencyR");
|
||||
m_Plug.getValue(TempTransp[0]);
|
||||
m_Plug = node.findPlug("transparencyG");
|
||||
m_Plug.getValue(TempTransp[1]);
|
||||
m_Plug = node.findPlug("transparencyB");
|
||||
m_Plug.getValue(TempTransp[2]);
|
||||
|
||||
MColor TranspNode(TempTransp[0], TempTransp[1], TempTransp[2]);
|
||||
float DummyH, DummyS;
|
||||
TranspNode.get(MColor::kHSV, DummyH, DummyS, material_node.Color[3]);
|
||||
}
|
||||
|
||||
if (findIncandescenceTexture(material_node, node)) {
|
||||
material_node.Incandescence.fill(1.0f);
|
||||
}
|
||||
else {
|
||||
m_Plug = node.findPlug("incandescenceR");
|
||||
m_Plug.getValue(material_node.Incandescence[0]);
|
||||
m_Plug = node.findPlug("incandescenceG");
|
||||
m_Plug.getValue(material_node.Incandescence[1]);
|
||||
m_Plug = node.findPlug("incandescenceB");
|
||||
m_Plug.getValue(material_node.Incandescence[2]);
|
||||
}
|
||||
|
||||
findNormalTexture(material_node, node);
|
||||
}
|
||||
|
||||
void Material::grabBlinnProperties(MaterialNode& material_node, MFnDependencyNode& node)
|
||||
{
|
||||
if (findSpecularTexture(material_node, node)) {
|
||||
material_node.Specular.fill(1.0f);
|
||||
}
|
||||
else {
|
||||
m_Plug = node.findPlug("specularColorR");
|
||||
m_Plug.getValue(material_node.Specular[0]);
|
||||
m_Plug = node.findPlug("specularColorG");
|
||||
m_Plug.getValue(material_node.Specular[1]);
|
||||
m_Plug = node.findPlug("specularColorB");
|
||||
m_Plug.getValue(material_node.Specular[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)) {
|
||||
material_node.Specular.fill(1.0f);
|
||||
}
|
||||
else {
|
||||
m_Plug = node.findPlug("specularColorR");
|
||||
m_Plug.getValue(material_node.Specular[0]);
|
||||
m_Plug = node.findPlug("specularColorG");
|
||||
m_Plug.getValue(material_node.Specular[1]);
|
||||
m_Plug = node.findPlug("specularColorB");
|
||||
m_Plug.getValue(material_node.Specular[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("ftn").asString().asChar();
|
||||
m_TexturePaths.push_back(FullPath);
|
||||
|
||||
material_node.ColorMapFile = FullPath.substr(FullPath.find_last_of("/"));
|
||||
|
||||
// Test
|
||||
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);
|
||||
|
||||
material_node.NormalMapFile = FullPath.substr(FullPath.find_last_of("/"));
|
||||
|
||||
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);
|
||||
|
||||
material_node.SpecularMapFile = FullPath.substr(FullPath.find_last_of("/"));
|
||||
|
||||
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);
|
||||
|
||||
material_node.SpecularMapFile = FullPath.substr(FullPath.find_last_of("/"));
|
||||
|
||||
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()
|
||||
{
|
||||
// All materials we care about inherit from Lambert
|
||||
MItDependencyNodes matIt(MFn::kLambert);
|
||||
|
||||
while (!matIt.isDone()) {
|
||||
MFnDependencyNode MaterialFnDN(matIt.thisNode());
|
||||
MaterialNode MaterialStorage;
|
||||
|
||||
if (matIt.thisNode().hasFn(MFn::kPhong)) {
|
||||
grabLambertProperties(MaterialStorage, MaterialFnDN);
|
||||
grabPhongProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
m_AllMaterials.push_back(MaterialStorage);
|
||||
}
|
||||
else if (matIt.thisNode().hasFn(MFn::kBlinn)) {
|
||||
grabLambertProperties(MaterialStorage, MaterialFnDN);
|
||||
grabBlinnProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
m_AllMaterials.push_back(MaterialStorage);
|
||||
}
|
||||
else if (matIt.thisNode().hasFn(MFn::kLambert)) {
|
||||
grabLambertProperties(MaterialStorage, MaterialFnDN);
|
||||
|
||||
MaterialStorage.Specular.fill(0.0f);
|
||||
MaterialStorage.ReflectionFactor = 0.0f;
|
||||
MaterialStorage.SpecularExponent = 0.0f;
|
||||
|
||||
m_AllMaterials.push_back(MaterialStorage);
|
||||
}
|
||||
|
||||
matIt.next();
|
||||
}
|
||||
|
||||
return &m_AllMaterials;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef Material_Material_h__
|
||||
#define Material_Material_h__
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
|
||||
struct MaterialNode
|
||||
{
|
||||
std::string Name;
|
||||
std::array<float, 4> Color;
|
||||
std::array<float, 3> Incandescence;
|
||||
std::array<float, 3> Specular;
|
||||
float ReflectionFactor;
|
||||
float SpecularExponent;
|
||||
std::string ColorMapFile;
|
||||
std::string SpecularMapFile;
|
||||
std::string NormalMapFile;
|
||||
std::string IncandescenceMapFile;
|
||||
};
|
||||
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
Material() {};
|
||||
~Material() {};
|
||||
std::vector<MaterialNode>* DoIt();
|
||||
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,18 @@
|
||||
#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>
|
||||
|
||||
|
||||
// Wrappers
|
||||
@@ -58,5 +70,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_CopyTexturesButton = new QCheckBox(tr("&Copy Textures"));
|
||||
m_Button3 = new QCheckBox(tr("Test Materials"));
|
||||
|
||||
exportAnimationsButton->setChecked(true);
|
||||
copyTexturesButton->setChecked(true);
|
||||
m_ExportAnimationsButton->setChecked(true);
|
||||
m_CopyTexturesButton->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_CopyTexturesButton);
|
||||
vbox->addWidget(m_Button3);
|
||||
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_CopyTexturesButton, SIGNAL(clicked(bool)), this, SLOT(NULL));
|
||||
connect(m_Button3, 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/Baljj");
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
for (unsigned int i = 0; i < 3; i++) {
|
||||
this->AddClipClicked(true);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<Export::AnimationInfo> animations;
|
||||
MGlobal::displayInfo(MString() + "yeeehaa");
|
||||
for (unsigned int i = 0; i < m_AnimationClipName.size(); i++) {
|
||||
Export::AnimationInfo thisClip;
|
||||
MGlobal::displayInfo(MString() + "qwqw");
|
||||
thisClip.Name = std::string(m_AnimationClipName[i]->text().toLocal8Bit().constData());
|
||||
MGlobal::displayInfo(MString() + "shizzzz");
|
||||
thisClip.Start = m_StartFrameLines[i]->text().toInt();
|
||||
MGlobal::displayInfo(MString() + "dsdsfg");
|
||||
thisClip.End = m_EndFrameLines[i]->text().toInt();
|
||||
MGlobal::displayInfo(MString() + "aaaaaaaaaaaaaaaaaaaa");
|
||||
|
||||
animations.push_back(thisClip);
|
||||
}
|
||||
MGlobal::displayInfo(MString() + "asdf");
|
||||
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,37 @@ 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_CopyTexturesButton = nullptr;
|
||||
QCheckBox* m_Button3 = nullptr;
|
||||
|
||||
QLineEdit* m_ExportPath = nullptr;
|
||||
QFileDialog* m_FileDialog = nullptr;
|
||||
QDialog* m_DialogPointer = nullptr;
|
||||
|
||||
Export m_Export;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,190 @@
|
||||
#pragma once
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
MeshClass::MeshClass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::map<int, MeshClass::WeightInfo> MeshClass::GetWeightData()
|
||||
{
|
||||
map<int, WeightInfo> weightMap;
|
||||
|
||||
MItDependencyNodes it(MFn::kSkinClusterFilter);
|
||||
|
||||
while (!it.isDone()) {
|
||||
|
||||
MObject object = it.item();
|
||||
MFnSkinCluster skinCluster(object);
|
||||
MDagPathArray influences;
|
||||
|
||||
unsigned int nrOfInfluences = skinCluster.influenceObjects(influences);
|
||||
|
||||
unsigned int index;
|
||||
index = skinCluster.indexForOutputConnection(0);
|
||||
MDagPath skinPath;
|
||||
skinCluster.getPathAtIndex(index, skinPath);
|
||||
|
||||
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();
|
||||
MFloatArray weights;
|
||||
unsigned int influenceCount;
|
||||
skinCluster.getWeights(skinPath, comp, weights, influenceCount);
|
||||
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(MObject object)
|
||||
{
|
||||
Mesh newMesh;
|
||||
std::vector<VertexLayout>& vertexList = newMesh.Vertices;
|
||||
std::vector<int>& indexList = newMesh.Indices;
|
||||
// In here, we retrieve triangulated polygons from the mesh
|
||||
MFnMesh mesh(object);
|
||||
|
||||
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];
|
||||
VertexLayout thisVertex;
|
||||
MFloatVectorArray biTangents;
|
||||
MFloatVectorArray biNormals;
|
||||
|
||||
std::map<int, WeightInfo> vertexWeights = GetWeightData();
|
||||
|
||||
mesh.getTangents(biTangents, MSpace::kObject, NULL);
|
||||
mesh.getBinormals(biNormals, MSpace::kObject, NULL);
|
||||
|
||||
MItMeshFaceVertex faceVert(object);
|
||||
|
||||
int intDummy = 0;
|
||||
|
||||
for (MItMeshPolygon meshPolyIter(object); !meshPolyIter.isDone(); meshPolyIter.next()) {
|
||||
|
||||
vector<unsigned int> localVertexToGlobalIndex;
|
||||
unsigned int indexOffset = vertexList.size();
|
||||
|
||||
meshPolyIter.getVertices(vertices);
|
||||
meshPolyIter.getTriangles(dummy, triangleList);
|
||||
|
||||
//MGlobal::displayInfo("Befor Second Loop");
|
||||
for (unsigned int i = 0; i < vertices.length(); i++) {
|
||||
vertexIndex = meshPolyIter.vertexIndex(i);
|
||||
faceVert.setIndex(meshPolyIter.index(), i, intDummy, intDummy);
|
||||
//MGlobal::displayInfo("In Second Loop");
|
||||
faceVert.position().get(thisVertex.Pos);
|
||||
faceVert.getNormal(normal);
|
||||
thisVertex.Normal[0] = normal[0];
|
||||
thisVertex.Normal[1] = normal[1];
|
||||
thisVertex.Normal[2] = normal[2];
|
||||
|
||||
MFloatVector biTangent = biTangents[faceVert.tangentId()];
|
||||
//MVector tmp = faceVert.getTangent(MSpace::kObject, NULL);
|
||||
//tmp.get(biTangent);
|
||||
thisVertex.BiTangent[0] = biTangent[0];
|
||||
thisVertex.BiTangent[1] = biTangent[1];
|
||||
thisVertex.BiTangent[2] = biTangent[2];
|
||||
|
||||
MFloatVector biNormal = biNormals[faceVert.tangentId()];
|
||||
//faceVert.getBinormal().get(biNormal);
|
||||
thisVertex.BiNormal[0] = biNormal[0];
|
||||
thisVertex.BiNormal[1] = biNormal[1];
|
||||
thisVertex.BiNormal[2] = biNormal[2];
|
||||
|
||||
faceVert.getUV(UV);
|
||||
thisVertex.Uv[0] = UV[0];
|
||||
thisVertex.Uv[1] = UV[1];
|
||||
|
||||
thisVertex.BoneIndices[0] = vertexWeights[faceVert.vertId()].BoneIndices[0];
|
||||
thisVertex.BoneIndices[1] = vertexWeights[faceVert.vertId()].BoneIndices[1];
|
||||
thisVertex.BoneIndices[2] = vertexWeights[faceVert.vertId()].BoneIndices[2];
|
||||
thisVertex.BoneIndices[3] = vertexWeights[faceVert.vertId()].BoneIndices[3];
|
||||
|
||||
thisVertex.BoneWeights[0] = vertexWeights[faceVert.vertId()].BoneWeights[0];
|
||||
thisVertex.BoneWeights[1] = vertexWeights[faceVert.vertId()].BoneWeights[1];
|
||||
thisVertex.BoneWeights[2] = vertexWeights[faceVert.vertId()].BoneWeights[2];
|
||||
thisVertex.BoneWeights[3] = vertexWeights[faceVert.vertId()].BoneWeights[3];
|
||||
|
||||
std::vector<VertexLayout>::iterator it = std::find(vertexList.begin(), vertexList.end(), thisVertex);
|
||||
|
||||
if (it != vertexList.end()) {
|
||||
localVertexToGlobalIndex.push_back(vertexIndex);
|
||||
} else {
|
||||
localVertexToGlobalIndex.push_back(vertexIndex);
|
||||
vertexList.push_back(thisVertex);
|
||||
}
|
||||
|
||||
//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) {
|
||||
while (localVertexToGlobalIndex[k] != triangleList[i] && k < localVertexToGlobalIndex.size()) {
|
||||
k++;
|
||||
}
|
||||
indexList.push_back(indexOffset + k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newMesh.NumIndices = newMesh.Indices.size();
|
||||
newMesh.NumVertices = newMesh.Vertices.size();
|
||||
|
||||
return newMesh;
|
||||
}
|
||||
|
||||
MeshClass::~MeshClass()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef Mesh_Mesh_h__
|
||||
#define Mesh_Mesh_h__
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "OutputData.h"
|
||||
#include "MayaIncludes.h"
|
||||
|
||||
class VertexLayout : public OutputData
|
||||
{
|
||||
public:
|
||||
float Pos[3];
|
||||
float Normal[3];
|
||||
float BiNormal[3];
|
||||
float BiTangent[3];
|
||||
float Uv[2];
|
||||
float BoneIndices[4];
|
||||
float BoneWeights[4];
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write((char*)&Pos, sizeof(float) * 3);
|
||||
out.write((char*)&Normal, sizeof(float) * 3);
|
||||
out.write((char*)&BiNormal, sizeof(float) * 3);
|
||||
out.write((char*)&BiTangent, 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 << BiNormal[0] << " " << BiNormal[1] << " " << BiNormal[2] << endl;
|
||||
out << BiTangent[0] << " " << BiTangent[1] << " " << BiTangent[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->BiNormal[0] == right.BiNormal[0] && this->BiNormal[1] == right.BiNormal[1] && this->BiNormal[2] == right.BiNormal[2] &&
|
||||
this->BiTangent[0] == right.BiTangent[0] && this->BiTangent[1] == right.BiTangent[1] && this->BiTangent[2] == right.BiTangent[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:
|
||||
int NumVertices;
|
||||
int NumIndices;
|
||||
std::vector<VertexLayout> Vertices;
|
||||
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) {
|
||||
out.write((char*)&aIndex, sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
for (int i = 0; i < NumIndices; i += 3) {
|
||||
out << Indices[i] << " " << Indices[i+1] << " " << Indices[i + 2] << endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MeshClass
|
||||
{
|
||||
public:
|
||||
MeshClass();
|
||||
Mesh GetMeshData(MObject 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,251 @@
|
||||
#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)
|
||||
{
|
||||
std::vector<MObject> animatedJoints;
|
||||
std::vector<MObject> m_Hierarchy;
|
||||
|
||||
Animation returnData;
|
||||
double oneDivSixty = 1 / 60.0;
|
||||
returnData.Name = animationName;
|
||||
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 != 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) {
|
||||
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());
|
||||
}
|
||||
|
||||
MMatrix Matrix = thisJoint.transformationMatrix();
|
||||
|
||||
double tmp[4];
|
||||
thisJoint.getRotationQuaternion(tmp[0], tmp[1], tmp[2], tmp[3]);
|
||||
joint.Rotation[0] = tmp[0];
|
||||
joint.Rotation[1] = tmp[1];
|
||||
joint.Rotation[2] = tmp[2];
|
||||
joint.Rotation[3] = tmp[3];
|
||||
thisJoint.getTranslation(MSpace::kPreTransform).get(tmp);
|
||||
joint.Position[0] = tmp[0];
|
||||
joint.Position[1] = tmp[1];
|
||||
joint.Position[2] = tmp[2];
|
||||
thisJoint.getScale(tmp);
|
||||
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()
|
||||
{
|
||||
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");
|
||||
MDataHandle DataHandle;
|
||||
BindPose.getValue(DataHandle);
|
||||
MFnMatrixData MartixFn(DataHandle.data());
|
||||
MMatrix Matrix = MartixFn.matrix();
|
||||
|
||||
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();
|
||||
|
||||
//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);
|
||||
jointIt.next();
|
||||
}
|
||||
|
||||
m_AllSkeletons.push_back(SkeletonStorage);
|
||||
|
||||
return m_AllSkeletons;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#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;
|
||||
float Position[3];
|
||||
float Rotation[4];
|
||||
float Scale[3];
|
||||
};
|
||||
|
||||
int Index;
|
||||
double Time;
|
||||
std::vector<JointProperty> JointProperties;
|
||||
};
|
||||
|
||||
std::string Name;
|
||||
double Duration;
|
||||
int NumKeyFrames;
|
||||
int NumberOfJoints;
|
||||
std::vector<Keyframe> Keyframes;
|
||||
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write(Name.c_str(), Name.size() + 1);
|
||||
out.write((char*)&Duration, sizeof(double));
|
||||
out.write((char*)&NumKeyFrames, sizeof(int));
|
||||
out.write((char*)&NumberOfJoints, sizeof(int));
|
||||
for (auto aKeyframe : Keyframes) {
|
||||
out.write((char*)&aKeyframe.Index, sizeof(int));
|
||||
out.write((char*)&aKeyframe.Time, sizeof(double));
|
||||
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 ParentID;
|
||||
std::string Name;
|
||||
float OffsetMatrix[4][4];
|
||||
};
|
||||
|
||||
std::string Name;
|
||||
std::vector<BindPoseJoint> Joints;
|
||||
virtual void WriteBinary(std::ostream& out)
|
||||
{
|
||||
out.write(Name.c_str(), Name.size() + 1);
|
||||
for (auto Joint:Joints)
|
||||
{
|
||||
out.write(Joint.Name.c_str(), Joint.Name.size() + 1);
|
||||
out.write((char*)&Joint.OffsetMatrix, sizeof(float) * 4 * 4);
|
||||
out.write((char*)&Joint.ParentID, sizeof(int));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void WriteASCII(std::ostream& out) const
|
||||
{
|
||||
out << "Bind Pose: " << Name << endl;
|
||||
for (auto Joint : Joints)
|
||||
{
|
||||
out << 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.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,38 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
void WriteToFile::CloseFiles()
|
||||
{
|
||||
binFile.close();
|
||||
ASCIIFile.close();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef WriteToFile_WriteToFile_h__
|
||||
#define WriteToFile_WriteToFile_h__
|
||||
|
||||
#include "MayaIncludes.h"
|
||||
#include "OutputData.h"
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
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