Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 50 additions & 60 deletions Prowl.Runtime/AssetImporting/ModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ private Model BuildModel(Assimp.Scene scene, string assetPath, DirectoryInfo? pa
// Build the model structure
model.RootNode = BuildModelNode(scene.RootNode, scale);

var rootTransform = scene.RootNode.Transform;
Float4x4 rootMatrix = new Float4x4(
rootTransform.A1, rootTransform.A2, rootTransform.A3, rootTransform.A4,
rootTransform.B1, rootTransform.B2, rootTransform.B3, rootTransform.B4,
rootTransform.C1, rootTransform.C2, rootTransform.C3, rootTransform.C4,
rootTransform.D1, rootTransform.D2, rootTransform.D3, rootTransform.D4
);

rootMatrix.Translation *= (float)scale;

model.GlobalInverseTransform = rootMatrix.Invert();

// Load materials and meshes into the model
if (scene.HasMaterials)
LoadMaterials(scene, parentDir, model.Materials);
Expand All @@ -132,27 +144,9 @@ private Model BuildModel(Assimp.Scene scene, string assetPath, DirectoryInfo? pa
LoadMeshes(assetPath, settings, scene, scale, model.Materials, model.Meshes);

// Animations
List<AnimationClip> anims = [];
if (scene.HasAnimations)
LoadAnimations(scene, scale, model.Animations);

//if (CullEmpty)
//{
// // Remove Empty GameObjects
// List<(MeshRenderer, Node)> GOsToRemove = [];
// foreach (var go in GOs)
// {
// if (go.Item1.GetEntitiesInChildren<MeshRenderer>().Count(x => x.Mesh.IsAvailable) == 0)
// GOsToRemove.Add(go);
// }
// foreach (var go in GOsToRemove)
// {
// if (!go.Item1.IsDestroyed)
// go.Item1.DestroyImmediate();
// GOs.Remove(go);
// }
//}

return model;
}

Expand All @@ -177,7 +171,6 @@ private void LoadMaterials(Assimp.Scene? scene, DirectoryInfo? parentDir, List<M
}
else
{

mat.SetFloat("_EmissionIntensity", 0f);
mat.SetColor("_EmissiveColor", Color.black);
}
Expand Down Expand Up @@ -261,7 +254,6 @@ private void LoadMeshes(string assetPath, ModelImporterSettings settings, Assimp
continue;
}


Mesh mesh = new();
mesh.Name = m.Name;
int vertexCount = m.VertexCount;
Expand Down Expand Up @@ -317,10 +309,6 @@ private void LoadMeshes(string assetPath, ModelImporterSettings settings, Assimp
}

mesh.Indices = m.GetUnsignedIndices();

//if(!m.HasTangentBasis)
// mesh.RecalculateTangents();

mesh.RecalculateBounds();

if (m.HasBones)
Expand All @@ -329,6 +317,7 @@ private void LoadMeshes(string assetPath, ModelImporterSettings settings, Assimp
mesh.boneNames = new string[m.Bones.Count];
mesh.BoneIndices = new Float4[vertexCount];
mesh.BoneWeights = new Float4[vertexCount];

for (var i = 0; i < m.Bones.Count; i++)
{
var bone = m.Bones[i];
Expand All @@ -338,16 +327,13 @@ private void LoadMeshes(string assetPath, ModelImporterSettings settings, Assimp

var offsetMatrix = bone.OffsetMatrix;
Float4x4 bindPose = new Float4x4(
offsetMatrix.A1, offsetMatrix.B1, offsetMatrix.C1, offsetMatrix.D1,
offsetMatrix.A2, offsetMatrix.B2, offsetMatrix.C2, offsetMatrix.D2,
offsetMatrix.A3, offsetMatrix.B3, offsetMatrix.C3, offsetMatrix.D3,
offsetMatrix.A4, offsetMatrix.B4, offsetMatrix.C4, offsetMatrix.D4
offsetMatrix.A1, offsetMatrix.A2, offsetMatrix.A3, offsetMatrix.A4,
offsetMatrix.B1, offsetMatrix.B2, offsetMatrix.B3, offsetMatrix.B4,
offsetMatrix.C1, offsetMatrix.C2, offsetMatrix.C3, offsetMatrix.C4,
offsetMatrix.D1, offsetMatrix.D2, offsetMatrix.D3, offsetMatrix.D4
);

// Adjust translation by scale
bindPose.Translation *= (float)scale;
//var translate = Float4x4.CreateScale((float)scale);
//bindPose = Maths.Mul(translate, bindPose);

mesh.bindPoses[i] = bindPose;

Expand Down Expand Up @@ -448,83 +434,87 @@ private static void LoadAnimations(Assimp.Scene? scene, double scale, List<Anima
animation.Duration = anim.DurationInTicks / (anim.TicksPerSecond != 0 ? anim.TicksPerSecond : 25.0);
animation.TicksPerSecond = anim.TicksPerSecond;
animation.DurationInTicks = anim.DurationInTicks;

foreach (var channel in anim.NodeAnimationChannels)
{
Assimp.Node boneNode = scene.RootNode.FindNode(channel.NodeName);

var animBone = new AnimationClip.AnimBone();
animBone.BoneName = boneNode.Name;

// construct full path from RootNode to this bone
// RootNode -> Parent -> Parent -> ... -> Parent -> Bone
Assimp.Node target = boneNode;
string path = target.Name;
//while (target.Parent != null)
//{
// target = target.Parent;
// path = target.Name + "/" + path;
// if (target.Name == scene.RootNode.Name) // TODO: Can we just do reference comparison here instead of string comparison?
// break;
//}


if (channel.HasPositionKeys)
{
var xCurve = new AnimationCurve();
var yCurve = new AnimationCurve();
var zCurve = new AnimationCurve();

xCurve.Keys.Clear();
yCurve.Keys.Clear();
zCurve.Keys.Clear();

foreach (var posKey in channel.PositionKeys)
{
double time = (posKey.Time / anim.DurationInTicks) * animation.Duration;
xCurve.Keys.Add(new(time, posKey.Value.X * scale));
yCurve.Keys.Add(new(time, posKey.Value.Y * scale));
zCurve.Keys.Add(new(time, posKey.Value.Z * scale));
xCurve.Keys.Add(new KeyFrame(time, posKey.Value.X * scale));
yCurve.Keys.Add(new KeyFrame(time, posKey.Value.Y * scale));
zCurve.Keys.Add(new KeyFrame(time, posKey.Value.Z * scale));
}
animBone.PosX = xCurve;
animBone.PosY = yCurve;
animBone.PosZ = zCurve;
}

if (channel.HasRotationKeys)
{
var xCurve = new AnimationCurve();
var yCurve = new AnimationCurve();
var zCurve = new AnimationCurve();
var wCurve = new AnimationCurve();

xCurve.Keys.Clear();
yCurve.Keys.Clear();
zCurve.Keys.Clear();
wCurve.Keys.Clear();

foreach (var rotKey in channel.RotationKeys)
{
double time = (rotKey.Time / anim.DurationInTicks) * animation.Duration;
xCurve.Keys.Add(new(time, rotKey.Value.X));
yCurve.Keys.Add(new(time, rotKey.Value.Y));
zCurve.Keys.Add(new(time, rotKey.Value.Z));
wCurve.Keys.Add(new(time, rotKey.Value.W));
xCurve.Keys.Add(new KeyFrame(time, rotKey.Value.X));
yCurve.Keys.Add(new KeyFrame(time, rotKey.Value.Y));
zCurve.Keys.Add(new KeyFrame(time, rotKey.Value.Z));
wCurve.Keys.Add(new KeyFrame(time, rotKey.Value.W));
}
animBone.RotX = xCurve;
animBone.RotY = yCurve;
animBone.RotZ = zCurve;
animBone.RotW = wCurve;
}

if (channel.HasScalingKeys)
{
var xCurve = new AnimationCurve();
var yCurve = new AnimationCurve();
var zCurve = new AnimationCurve();

xCurve.Keys.Clear();
yCurve.Keys.Clear();
zCurve.Keys.Clear();

foreach (var scaleKey in channel.ScalingKeys)
{
double time = (scaleKey.Time / anim.DurationInTicks) * animation.Duration;
xCurve.Keys.Add(new(time, scaleKey.Value.X));
yCurve.Keys.Add(new(time, scaleKey.Value.Y));
zCurve.Keys.Add(new(time, scaleKey.Value.Z));
xCurve.Keys.Add(new KeyFrame(time, scaleKey.Value.X));
yCurve.Keys.Add(new KeyFrame(time, scaleKey.Value.Y));
zCurve.Keys.Add(new KeyFrame(time, scaleKey.Value.Z));
}
animBone.ScaleX = xCurve;
animBone.ScaleY = yCurve;
animBone.ScaleZ = zCurve;
}

animation.AddBone(animBone);
}

animation.EnsureQuaternionContinuity();
animations.Add(animation);
}
Expand Down
84 changes: 84 additions & 0 deletions Prowl.Runtime/Assets/Defaults/Line.shader
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
Shader "Default/Line"

Properties
{
_MainTex ("Texture", Texture2D) = "white"
_StartColor ("Start Color", Color) = (1.0, 1.0, 1.0, 1.0)
_EndColor ("End Color", Color) = (1.0, 1.0, 1.0, 1.0)
}

Pass "Line"
{
Tags { "RenderOrder" = "Transparent" }
Cull Off
Blend Alpha

GLSLPROGRAM
Vertex
{
#include "Fragment"
#include "VertexAttributes"

out vec2 texCoord0;
out vec3 worldPos;
out vec4 currentPos;
out vec4 previousPos;
out float fogCoord;
out vec4 vColor;

void main()
{
gl_Position = PROWL_MATRIX_MVP * vec4(vertexPosition, 1.0);
fogCoord = gl_Position.z;
currentPos = gl_Position;
texCoord0 = vertexTexCoord0;

vec4 prevWorldPos = PROWL_MATRIX_M_PREVIOUS * vec4(vertexPosition, 1.0);
previousPos = PROWL_MATRIX_VP_PREVIOUS * prevWorldPos;

worldPos = (PROWL_MATRIX_M * vec4(vertexPosition, 1.0)).xyz;
vColor = vertexColor;
}
}

Fragment
{
#include "Fragment"

layout (location = 0) out vec4 gAlbedo;
layout (location = 1) out vec4 gMotionVector;
layout (location = 2) out vec4 gNormal;
layout (location = 3) out vec4 gSurface;

in vec2 texCoord0;
in vec3 worldPos;
in vec4 currentPos;
in vec4 previousPos;
in float fogCoord;
in vec4 vColor;

uniform sampler2D _MainTex;

void main()
{
vec2 curNDC = (currentPos.xy / currentPos.w) - _CameraJitter;
vec2 prevNDC = (previousPos.xy / previousPos.w) - _CameraPreviousJitter;
gMotionVector = vec4((curNDC - prevNDC) * 0.5, 0.0, 1.0);

vec4 albedo = texture(_MainTex, texCoord0) * vColor;

// Lines don't have meaningful normals in billboarded mode
gNormal = vec4(0.0, 0.0, 1.0, 1.0);

// Unlit surface properties
gSurface = vec4(1.0, 0.0, 0.0, 1.0);

vec3 baseColor = albedo.rgb;
baseColor.rgb = GammaToLinearSpace(baseColor.rgb);

gAlbedo = vec4(baseColor, albedo.a);
gAlbedo.rgb = ApplyFog(fogCoord, gAlbedo.rgb);
}
}
ENDGLSL
}
Loading
Loading