126 lines
3.0 KiB
C#
126 lines
3.0 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation. For more information,
|
|
* see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using OpenRA.FileFormats;
|
|
|
|
namespace OpenRA.Graphics
|
|
{
|
|
struct Limb
|
|
{
|
|
public float Scale;
|
|
public float[] Bounds;
|
|
public byte[] Size;
|
|
public VoxelRenderData RenderData;
|
|
}
|
|
|
|
public class Voxel
|
|
{
|
|
Limb[] limbData;
|
|
float[] transforms;
|
|
|
|
public readonly uint Frames;
|
|
public readonly uint Limbs;
|
|
|
|
public Voxel(VoxelLoader loader, VxlReader vxl, HvaReader hva)
|
|
{
|
|
if (vxl.LimbCount != hva.LimbCount)
|
|
throw new InvalidOperationException("Voxel and hva limb counts don't match");
|
|
|
|
transforms = hva.Transforms;
|
|
Frames = hva.FrameCount;
|
|
Limbs = hva.LimbCount;
|
|
|
|
limbData = new Limb[vxl.LimbCount];
|
|
for (var i = 0; i < vxl.LimbCount; i++)
|
|
{
|
|
var vl = vxl.Limbs[i];
|
|
var l = new Limb();
|
|
l.Scale = vl.Scale;
|
|
l.Bounds = (float[])vl.Bounds.Clone();
|
|
l.Size = (byte[])vl.Size.Clone();
|
|
l.RenderData = loader.GenerateRenderData(vxl.Limbs[i]);
|
|
limbData[i] = l;
|
|
}
|
|
}
|
|
|
|
public float[] TransformationMatrix(uint limb, uint frame)
|
|
{
|
|
if (frame >= Frames)
|
|
throw new ArgumentOutOfRangeException("frame", "Only {0} frames exist.".F(Frames));
|
|
if (limb >= Limbs)
|
|
throw new ArgumentOutOfRangeException("limb", "Only {1} limbs exist.".F(Limbs));
|
|
|
|
var l = limbData[limb];
|
|
var t = new float[16];
|
|
Array.Copy(transforms, 16*(Limbs*frame + limb), t, 0, 16);
|
|
|
|
// Fix limb position
|
|
t[12] *= l.Scale*(l.Bounds[3] - l.Bounds[0]) / l.Size[0];
|
|
t[13] *= l.Scale*(l.Bounds[4] - l.Bounds[1]) / l.Size[1];
|
|
t[14] *= l.Scale*(l.Bounds[5] - l.Bounds[2]) / l.Size[2];
|
|
|
|
// Center, flip and scale
|
|
t = Util.MatrixMultiply(t, Util.TranslationMatrix(l.Bounds[0], l.Bounds[1], l.Bounds[2]));
|
|
t = Util.MatrixMultiply(Util.ScaleMatrix(l.Scale, -l.Scale, l.Scale), t);
|
|
|
|
return t;
|
|
}
|
|
|
|
public VoxelRenderData RenderData(uint limb)
|
|
{
|
|
return limbData[limb].RenderData;
|
|
}
|
|
|
|
public float[] Size
|
|
{
|
|
get
|
|
{
|
|
return limbData.Select(a => a.Size.Select(b => a.Scale*b).ToArray())
|
|
.Aggregate((a,b) => new float[]
|
|
{
|
|
Math.Max(a[0], b[0]),
|
|
Math.Max(a[1], b[1]),
|
|
Math.Max(a[2], b[2])
|
|
});
|
|
}
|
|
}
|
|
|
|
public float[] Bounds(uint frame)
|
|
{
|
|
var ret = new float[] {float.MaxValue,float.MaxValue,float.MaxValue,
|
|
float.MinValue,float.MinValue,float.MinValue};
|
|
|
|
for (uint j = 0; j < Limbs; j++)
|
|
{
|
|
var l = limbData[j];
|
|
var b = new float[]
|
|
{
|
|
0, 0, 0,
|
|
(l.Bounds[3] - l.Bounds[0]),
|
|
(l.Bounds[4] - l.Bounds[1]),
|
|
(l.Bounds[5] - l.Bounds[2])
|
|
};
|
|
|
|
// Calculate limb bounding box
|
|
var bb = Util.MatrixAABBMultiply(TransformationMatrix(j, frame), b);
|
|
for (var i = 0; i < 3; i++)
|
|
{
|
|
ret[i] = Math.Min(ret[i], bb[i]);
|
|
ret[i+3] = Math.Max(ret[i+3], bb[i+3]);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
}
|