@ -1,4 +1,5 @@
using UnityEngine ;
using UnityEngine ;
using UnityEngine.Rendering ;
public partial class RenderModule
public partial class RenderModule
{
{
@ -17,43 +18,64 @@ public partial class RenderModule
{
{
Debug . Log ( $"Alias model '{name}' with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s)" ) ;
Debug . Log ( $"Alias model '{name}' with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s)" ) ;
// TODO: convert Quake poses into Mesh blend shapes with AddBlendShapeFrame
ConvertVertices ( poseVertices [ 0 ] , boundsMin . ToVector3 ( ) , boundsMax . ToVector3 ( ) , out var vertices , out var normals ) ;
ConvertVertices ( header , poseVertices [ 0 ] , out var vertices , out var normals ) ;
ConvertTriangles ( triangles , out var indices ) ;
ConvertTriangles ( triangles , out var indices ) ;
ConvertUVs ( stVertices , header . skinWidth , header . skinHeight , out var uvs ) ;
ConvertUVs ( stVertices , header . skinWidth , header . skinHeight , out var uvs ) ;
var mesh = new Mesh { name = name } ;
var mesh = new Mesh { name = name } ;
mesh . SetVertices ( vertices ) ;
mesh . SetVertices ( vertices ) ;
mesh . SetNormals ( normals ) ;
mesh . SetNormals ( normals ) ;
mesh . SetIndices ( indices , MeshTopology . Triangles , 0 ) ;
mesh . SetIndices ( indices , MeshTopology . Triangles , 0 , false ) ;
mesh . SetUVs ( 0 , uvs ) ;
mesh . SetUVs ( 0 , uvs ) ;
CreateBlendShapes ( mesh , vertices , normals , header , poseVertices ) ;
mesh . Optimize ( ) ; // This ensures that triangles will be properly fused and organized in the best possible way
mesh . Optimize ( ) ; // This ensures that triangles will be properly fused and organized in the best possible way
mesh . RecalculateBounds ( ) ;
mesh . UploadMeshData ( true ) ;
mesh . UploadMeshData ( true ) ;
var go = new GameObject ( System . IO . Path . GetFileNameWithoutExtension ( name ) ) ;
var go = new GameObject ( System . IO . Path . GetFileNameWithoutExtension ( name ) ) ;
go . transform . SetPositionAndRotation ( new Vector3 ( xPos , 0 , 0 ) , Quaternion . Euler ( - 9 0 , 9 0 , 0 ) ) ;
go . transform . SetPositionAndRotation ( new Vector3 ( xPos , 0 , 0 ) , Quaternion . Euler ( - 9 0 , 9 0 , 0 ) ) ;
go . transform . localScale = Vector3 . one * 0.01f ;
var mf = go . AddComponent < MeshFilter > ( ) ;
mf . sharedMesh = mesh ;
var mr = go . AddComponent < MeshRenderer > ( ) ;
mr . material = new Material ( Shader . Find ( "Universal Render Pipeline/Simple Lit" ) ) ;
xPos + = 1f ;
if ( header . numFrames > 1 )
{
var mr = go . AddComponent < SkinnedMeshRenderer > ( ) ;
mr . material = new Material ( Shader . Find ( "Universal Render Pipeline/Simple Lit" ) ) ;
mr . sharedMesh = mesh ;
mr . shadowCastingMode = ShadowCastingMode . Off ;
mr . receiveShadows = false ;
mr . lightProbeUsage = LightProbeUsage . Off ;
mr . reflectionProbeUsage = ReflectionProbeUsage . Off ;
go . AddComponent < AliasModelAnimator > ( ) ;
}
else
{
var mf = go . AddComponent < MeshFilter > ( ) ;
mf . sharedMesh = mesh ;
var mr = go . AddComponent < MeshRenderer > ( ) ;
mr . material = new Material ( Shader . Find ( "Universal Render Pipeline/Simple Lit" ) ) ;
mr . shadowCastingMode = ShadowCastingMode . Off ;
mr . receiveShadows = false ;
mr . lightProbeUsage = LightProbeUsage . Off ;
mr . reflectionProbeUsage = ReflectionProbeUsage . Off ;
}
xPos + = 0.5f ;
return 1 ;
return 1 ;
}
}
private static void ConvertVertices ( QTriVertex [ ] triVerts , Vector3 boundsMin , Vector3 boundsMax , out Vector3 [ ] vertices , out Vector3 [ ] normals )
private static void ConvertVertices ( QAliasHeader header , QTriVertex [ ] triVerts , out Vector3 [ ] vertices , out Vector3 [ ] normals )
{
{
int numVerts = triVerts . Length ;
int numVerts = triVerts . Length ;
vertices = new Vector3 [ numVerts ] ;
vertices = new Vector3 [ numVerts ] ;
normals = new Vector3 [ numVerts ] ;
normals = new Vector3 [ numVerts ] ;
Vector3 scale = header . scale . ToVector3 ( ) ;
Vector3 origin = header . scaleOrigin . ToVector3 ( ) ;
for ( int i = 0 ; i < numVerts ; + + i )
for ( int i = 0 ; i < numVerts ; + + i )
{
{
byte [ ] v = triVerts [ i ] . v ;
Vector3 vec = new Vector3 ( v [ 0 ] / 2 5 5f , v [ 1 ] / 2 5 5f , v [ 2 ] / 2 5 5f ) ;
vertices [ i ] = boundsMin + Vector3 . Scale ( boundsMax - boundsMin , vec ) ;
vertices [ i ] = Vector3 . Scale ( triVerts [ i ] . ToVector3 ( ) , scale ) ;
normals [ i ] = QLightNormals . Get ( triVerts [ i ] . lightNormalIndex ) ;
normals [ i ] = QLightNormals . Get ( triVerts [ i ] . lightNormalIndex ) ;
}
}
}
}
@ -86,4 +108,30 @@ public partial class RenderModule
uvs [ i ] = Vector2 . Scale ( new Vector2 ( stVerts [ i ] . s , skinHeight - stVerts [ i ] . t ) , scale ) ;
uvs [ i ] = Vector2 . Scale ( new Vector2 ( stVerts [ i ] . s , skinHeight - stVerts [ i ] . t ) , scale ) ;
}
}
}
}
private static void CreateBlendShapes (
Mesh mesh , Vector3 [ ] baseVertices , Vector3 [ ] baseNormals ,
QAliasHeader header , QTriVertex [ ] [ ] poseVertices )
{
var deltaVertices = new Vector3 [ header . numVerts ] ;
var deltaNormals = new Vector3 [ header . numVerts ] ;
Vector3 scale = header . scale . ToVector3 ( ) ;
Vector3 origin = header . scaleOrigin . ToVector3 ( ) ;
// Frame 0 is the base pose, so we start with frame 1
for ( int frameIdx = 1 ; frameIdx < header . numFrames ; + + frameIdx )
{
var poseVerts = poseVertices [ frameIdx ] ;
for ( int vertIdx = 0 ; vertIdx < header . numVerts ; + + vertIdx )
{
Vector3 vert = Vector3 . Scale ( poseVerts [ vertIdx ] . ToVector3 ( ) , scale ) ;
deltaVertices [ vertIdx ] = vert - baseVertices [ vertIdx ] ;
deltaNormals [ vertIdx ] = QLightNormals . Get ( poseVerts [ vertIdx ] . lightNormalIndex ) - baseNormals [ vertIdx ] ;
}
mesh . AddBlendShapeFrame ( mesh . name , ( float ) frameIdx / ( header . numFrames - 1 ) , deltaVertices , deltaNormals , null ) ;
}
}
}
}