Model Structure #1

Merged
cosmonaut merged 15 commits from PBR into main 2020-08-05 20:51:03 +00:00
8 changed files with 136 additions and 137 deletions

View File

@ -7,18 +7,18 @@ namespace Smuggler
{ {
public static class Importer public static class Importer
{ {
public static Model ImportGLB(GraphicsDevice graphicsDevice, Stream stream) public static ModelData ImportGLB(GraphicsDevice graphicsDevice, Stream stream)
{ {
var sharpModel = SharpGLTF.Schema2.ModelRoot.ReadGLB(stream); var sharpModel = SharpGLTF.Schema2.ModelRoot.ReadGLB(stream);
var vertexType = InferVertexType(sharpModel); var vertexType = InferVertexType(sharpModel);
if (vertexType == null) { return null; } if (vertexType == null) { return null; }
var meshes = new List<Mesh>(); var meshes = new List<MeshData>();
foreach (var mesh in sharpModel.LogicalMeshes) foreach (var mesh in sharpModel.LogicalMeshes)
{ {
var meshParts = new List<MeshPart>(); var meshParts = new List<MeshPartData>();
foreach (var primitive in mesh.Primitives) foreach (var primitive in mesh.Primitives)
{ {
@ -27,18 +27,10 @@ namespace Smuggler
); );
} }
meshes.Add(new Mesh(meshParts.ToArray())); meshes.Add(new MeshData(meshParts.ToArray()));
} }
var model = new Model(meshes.ToArray()); var model = new ModelData(meshes.ToArray());
/* TODO: BasicEffect only supports one texture but GLTF supports several */
if (sharpModel.LogicalTextures.Count > 0)
{
var fnaTexture = Texture2D.FromStream(graphicsDevice, sharpModel.LogicalTextures[0].PrimaryImage.Content.Open());
model.SetTexture(fnaTexture);
}
return model; return model;
} }
@ -106,7 +98,7 @@ namespace Smuggler
return null; return null;
} }
private static MeshPart ImportMeshPart(GraphicsDevice graphicsDevice, System.Type vertexType, SharpGLTF.Schema2.MeshPrimitive primitive) private static MeshPartData ImportMeshPart(GraphicsDevice graphicsDevice, System.Type vertexType, SharpGLTF.Schema2.MeshPrimitive primitive)
{ {
var indices = Indices(primitive); var indices = Indices(primitive);
var positions = Positions(primitive); var positions = Positions(primitive);
@ -145,19 +137,66 @@ namespace Smuggler
ImportVertexPositionTexture(primitive, vertexBuffer, indices, positions); ImportVertexPositionTexture(primitive, vertexBuffer, indices, positions);
} }
/* TODO: We need a new Effect subclass to support some GLTF features */ var meshPartData = new MeshPartData(
var effect = new BasicEffect(graphicsDevice);
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
return new MeshPart(
vertexBuffer, vertexBuffer,
indexBuffer, indexBuffer,
positions, positions,
triangles, triangles
effect
); );
if (primitive.Material != null)
{
var normalChannel = primitive.Material.FindChannel("Normal");
if (normalChannel.HasValue)
{
if (normalChannel.Value.Texture != null)
{
meshPartData.NormalTexture = Texture2D.FromStream(
graphicsDevice,
normalChannel.Value.Texture.PrimaryImage.Content.Open()
);
}
}
var albedoChannel = primitive.Material.FindChannel("BaseColor");
if (albedoChannel.HasValue)
{
if (albedoChannel.Value.Texture != null)
{
meshPartData.AlbedoTexture = Texture2D.FromStream(
graphicsDevice,
albedoChannel.Value.Texture.PrimaryImage.Content.Open()
);
}
var parameter = albedoChannel.Value.Parameter;
meshPartData.Albedo = new Vector3(
parameter.X,
parameter.Y,
parameter.Z
);
}
var metallicRoughnessChannel = primitive.Material.FindChannel("MetallicRoughness");
if (metallicRoughnessChannel.HasValue)
{
if (metallicRoughnessChannel.Value.Texture != null)
{
meshPartData.MetallicRoughnessTexture = Texture2D.FromStream(
graphicsDevice,
metallicRoughnessChannel.Value.Texture.PrimaryImage.Content.Open()
);
}
var parameter = metallicRoughnessChannel.Value.Parameter;
meshPartData.Metallic = parameter.X;
meshPartData.Roughness = parameter.Y;
}
}
return meshPartData;
} }
/* Attribute Getters */ /* Attribute Getters */
@ -198,7 +237,7 @@ namespace Smuggler
for (int i = 0; i < normals.Length; i++) for (int i = 0; i < normals.Length; i++)
{ {
var normal = normalAccessor[i]; var normal = normalAccessor[i];
normals[i] = -new Vector3(normal.X, normal.Z, normal.Y); normals[i] = new Vector3(-normal.X, -normal.Z, normal.Y);
} }
return normals; return normals;
@ -221,7 +260,7 @@ namespace Smuggler
private static Triangle[] Triangles(SharpGLTF.Schema2.MeshPrimitive primitive) private static Triangle[] Triangles(SharpGLTF.Schema2.MeshPrimitive primitive)
{ {
var triangles = new List<Triangle>(); var triangles = new List<Triangle>();
foreach (var (a, b, c) in primitive.GetTriangleIndices()) foreach (var (a, b, c) in primitive.GetTriangleIndices())
{ {
triangles.Add(new Triangle(a, b, c)); triangles.Add(new Triangle(a, b, c));
@ -250,7 +289,8 @@ namespace Smuggler
VertexBuffer vertexBuffer, VertexBuffer vertexBuffer,
uint[] indices, uint[] indices,
Vector3[] positions Vector3[] positions
) { )
{
var colors = Colors(primitive); var colors = Colors(primitive);
var vertices = new VertexPositionColor[positions.Length]; var vertices = new VertexPositionColor[positions.Length];
@ -274,7 +314,8 @@ namespace Smuggler
VertexBuffer vertexBuffer, VertexBuffer vertexBuffer,
uint[] indices, uint[] indices,
Vector3[] positions Vector3[] positions
) { )
{
var colors = Colors(primitive); var colors = Colors(primitive);
var texcoords = TexCoords(primitive); var texcoords = TexCoords(primitive);
@ -301,7 +342,8 @@ namespace Smuggler
VertexBuffer vertexBuffer, VertexBuffer vertexBuffer,
uint[] indices, uint[] indices,
Vector3[] positions Vector3[] positions
) { )
{
var normals = Normals(primitive); var normals = Normals(primitive);
var texcoords = TexCoords(primitive); var texcoords = TexCoords(primitive);
@ -328,7 +370,8 @@ namespace Smuggler
VertexBuffer vertexBuffer, VertexBuffer vertexBuffer,
uint[] indices, uint[] indices,
Vector3[] positions Vector3[] positions
) { )
{
var texcoords = TexCoords(primitive); var texcoords = TexCoords(primitive);
var vertices = new VertexPositionTexture[positions.Length]; var vertices = new VertexPositionTexture[positions.Length];

23
Mesh.cs
View File

@ -1,23 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public class Mesh
{
public MeshPart[] MeshParts { get; }
public Mesh(MeshPart[] meshParts)
{
MeshParts = meshParts;
}
public void Draw(GraphicsDevice graphicsDevice, Matrix world, Matrix view, Matrix projection)
{
foreach (var meshPart in MeshParts)
{
meshPart.Draw(graphicsDevice, world, view, projection);
}
}
}
}

12
MeshData.cs Normal file
View File

@ -0,0 +1,12 @@
namespace Smuggler
{
public class MeshData
{
public MeshPartData[] MeshParts { get; }
public MeshData(MeshPartData[] meshParts)
{
MeshParts = meshParts;
}
}
}

View File

@ -1,47 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public class MeshPart
{
public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; }
public Triangle[] Triangles { get; }
public BasicEffect Effect { get; }
public Vector3[] Positions { get; }
public MeshPart(VertexBuffer vertexBuffer, IndexBuffer indexBuffer, Vector3[] positions, Triangle[] triangles, BasicEffect effect)
{
VertexBuffer = vertexBuffer;
IndexBuffer = indexBuffer;
Positions = positions;
Triangles = triangles;
Effect = effect;
}
public void Draw(GraphicsDevice graphicsDevice, Matrix world, Matrix view, Matrix projection)
{
graphicsDevice.SetVertexBuffer(VertexBuffer);
graphicsDevice.Indices = IndexBuffer;
Effect.World = world;
Effect.View = view;
Effect.Projection = projection;
foreach (var pass in Effect.CurrentTechnique.Passes)
{
pass.Apply();
graphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
VertexBuffer.VertexCount,
0,
Triangles.Length
);
}
}
}
}

34
MeshPartData.cs Normal file
View File

@ -0,0 +1,34 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public class MeshPartData
{
public IndexBuffer IndexBuffer { get; }
public VertexBuffer VertexBuffer { get; }
public Triangle[] Triangles { get; }
public Vector3[] Positions { get; }
public Texture2D AlbedoTexture { get; set; } = null;
public Texture2D NormalTexture { get; set; } = null;
public Texture2D MetallicRoughnessTexture { get; set; } = null;
public Vector3 Albedo { get; set; } = Vector3.One;
public float Metallic { get; set; } = 0.5f;
public float Roughness { get; set; } = 0.5f;
public MeshPartData(
VertexBuffer vertexBuffer,
IndexBuffer indexBuffer,
Vector3[] positions,
Triangle[] triangles
)
{
VertexBuffer = vertexBuffer;
IndexBuffer = indexBuffer;
Positions = positions;
Triangles = triangles;
}
}
}

View File

@ -1,36 +0,0 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public class Model
{
public Mesh[] Meshes { get; }
public Texture2D[] Textures { get; }
public Model(Mesh[] meshes)
{
Meshes = meshes;
}
public void SetTexture(Texture2D texture)
{
foreach (var mesh in Meshes)
{
foreach (var meshPart in mesh.MeshParts)
{
meshPart.Effect.TextureEnabled = true;
meshPart.Effect.Texture = texture;
}
}
}
public void Draw(GraphicsDevice graphicsDevice, Matrix world, Matrix view, Matrix projection)
{
foreach (var mesh in Meshes)
{
mesh.Draw(graphicsDevice, world, view, projection);
}
}
}
}

15
ModelData.cs Normal file
View File

@ -0,0 +1,15 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Smuggler
{
public class ModelData
{
public MeshData[] Meshes { get; }
public ModelData(MeshData[] meshes)
{
Meshes = meshes;
}
}
}

View File

@ -8,6 +8,7 @@
<Copyright>Cassandra Lugo and Evan Hemsley 2020</Copyright> <Copyright>Cassandra Lugo and Evan Hemsley 2020</Copyright>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<AssemblyName>Smuggler</AssemblyName> <AssemblyName>Smuggler</AssemblyName>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -15,7 +16,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FNA\FNA.Core.csproj"/> <ProjectReference Include="..\FNA\FNA.Core.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>