2017-09-21 18:33:05 +08:00
|
|
|
|
using CodeWalker.GameFiles;
|
|
|
|
|
using SharpDX.Direct3D11;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Device = SharpDX.Direct3D11.Device;
|
|
|
|
|
using Buffer = SharpDX.Direct3D11.Buffer;
|
|
|
|
|
using CodeWalker.World;
|
|
|
|
|
using SharpDX.Direct3D;
|
|
|
|
|
using SharpDX;
|
|
|
|
|
|
|
|
|
|
namespace CodeWalker.Rendering
|
|
|
|
|
{
|
|
|
|
|
public struct RenderableInst
|
|
|
|
|
{
|
|
|
|
|
public Renderable Renderable;
|
|
|
|
|
public Vector3 CamRel;
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
public Vector3 BBMin;
|
|
|
|
|
public Vector3 BBMax;
|
|
|
|
|
public Vector3 BSCenter;
|
|
|
|
|
public float Radius;
|
|
|
|
|
public float Distance;
|
|
|
|
|
public Quaternion Orientation;
|
|
|
|
|
public Vector3 Scale;
|
|
|
|
|
public uint TintPaletteIndex;
|
2019-12-05 00:40:52 +08:00
|
|
|
|
public bool CastShadow;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
public struct RenderableGeometryInst
|
|
|
|
|
{
|
|
|
|
|
public RenderableGeometry Geom;
|
|
|
|
|
public RenderableInst Inst;
|
|
|
|
|
}
|
2019-12-05 00:40:52 +08:00
|
|
|
|
public struct RenderableLightInst
|
|
|
|
|
{
|
|
|
|
|
public RenderableLight Light;
|
|
|
|
|
public Vector3 EntityPosition;
|
|
|
|
|
public Quaternion EntityRotation;
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
public struct RenderableBoundCompositeInst
|
|
|
|
|
{
|
|
|
|
|
public RenderableBoundComposite Renderable;
|
|
|
|
|
public Vector3 CamRel;
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
public Quaternion Orientation;
|
|
|
|
|
public Vector3 Scale;
|
|
|
|
|
}
|
|
|
|
|
public struct RenderableBoundGeometryInst
|
|
|
|
|
{
|
|
|
|
|
public RenderableBoundGeometry Geom;
|
|
|
|
|
public RenderableBoundCompositeInst Inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct RenderableInstanceBatchInst
|
|
|
|
|
{
|
|
|
|
|
public RenderableInstanceBatch Batch;
|
|
|
|
|
public Renderable Renderable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class Renderable : RenderableCacheItem<DrawableBase>
|
|
|
|
|
{
|
2019-01-06 12:51:58 +08:00
|
|
|
|
public YtdFile[] SDtxds;
|
|
|
|
|
public YtdFile[] HDtxds;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public bool AllTexturesLoaded = false;
|
|
|
|
|
|
|
|
|
|
public RenderableModel[] HDModels;
|
2019-01-06 02:04:33 +08:00
|
|
|
|
public RenderableModel[] MedModels;
|
|
|
|
|
public RenderableModel[] LowModels;
|
|
|
|
|
public RenderableModel[] VlowModels;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public RenderableModel[] AllModels;
|
|
|
|
|
//public Dictionary<uint, Texture> TextureDict { get; private set; }
|
|
|
|
|
//public long EmbeddedTextureSize { get; private set; }
|
|
|
|
|
|
2019-11-26 14:00:41 +08:00
|
|
|
|
public Skeleton Skeleton { get; set; } = null;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public bool HasSkeleton;
|
|
|
|
|
public bool HasTransforms;
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
public bool HasAnims = false;
|
|
|
|
|
public double CurrentAnimTime = 0;
|
|
|
|
|
public YcdFile ClipDict;
|
|
|
|
|
public ClipMapEntry ClipMapEntry;
|
2019-11-02 15:14:36 +08:00
|
|
|
|
public Dictionary<ushort, RenderableModel> ModelBoneLinks;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
|
2019-11-14 15:58:20 +08:00
|
|
|
|
public bool EnableRootMotion = false; //used to toggle whether or not to include root motion when playing animations
|
|
|
|
|
|
2019-11-29 17:47:11 +08:00
|
|
|
|
public ClothInstance Cloth;
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
2019-12-05 00:40:52 +08:00
|
|
|
|
public RenderableLight[] Lights;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public override void Init(DrawableBase drawable)
|
|
|
|
|
{
|
|
|
|
|
Key = drawable;
|
|
|
|
|
|
|
|
|
|
DataSize = 0;
|
|
|
|
|
|
2019-03-28 17:33:07 +08:00
|
|
|
|
var hd = Key.DrawableModelsHigh?.data_items ?? Key.AllModels;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
var med = Key.DrawableModelsMedium?.data_items;
|
|
|
|
|
var low = Key.DrawableModelsLow?.data_items;
|
|
|
|
|
var vlow = Key.DrawableModelsVeryLow?.data_items;
|
2019-03-28 17:33:07 +08:00
|
|
|
|
int totmodels = (hd?.Length ?? 0) + (med?.Length ?? 0) + (low?.Length ?? 0) + (vlow?.Length ?? 0);
|
|
|
|
|
int curmodel = hd?.Length ?? 0;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
AllModels = new RenderableModel[totmodels];
|
|
|
|
|
HDModels = new RenderableModel[hd.Length];
|
2019-03-28 17:33:07 +08:00
|
|
|
|
if (hd != null)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-03-28 17:33:07 +08:00
|
|
|
|
for (int i = 0; i < hd.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
HDModels[i] = InitModel(hd[i]);
|
|
|
|
|
AllModels[i] = HDModels[i];
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
if (med != null)
|
|
|
|
|
{
|
2019-01-06 02:04:33 +08:00
|
|
|
|
MedModels = new RenderableModel[med.Length];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
for (int i = 0; i < med.Length; i++)
|
|
|
|
|
{
|
2019-01-06 02:04:33 +08:00
|
|
|
|
MedModels[i] = InitModel(med[i]);
|
|
|
|
|
AllModels[curmodel + i] = MedModels[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
curmodel += med.Length;
|
|
|
|
|
}
|
|
|
|
|
if (low != null)
|
|
|
|
|
{
|
2019-01-06 02:04:33 +08:00
|
|
|
|
LowModels = new RenderableModel[low.Length];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
for (int i = 0; i < low.Length; i++)
|
|
|
|
|
{
|
2019-01-06 02:04:33 +08:00
|
|
|
|
LowModels[i] = InitModel(low[i]);
|
|
|
|
|
AllModels[curmodel + i] = LowModels[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
curmodel += low.Length;
|
|
|
|
|
}
|
|
|
|
|
if (vlow != null)
|
|
|
|
|
{
|
2019-01-06 02:04:33 +08:00
|
|
|
|
VlowModels = new RenderableModel[vlow.Length];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
for (int i = 0; i < vlow.Length; i++)
|
|
|
|
|
{
|
2019-11-02 03:46:45 +08:00
|
|
|
|
VlowModels[i] = InitModel(vlow[i]);
|
2019-01-06 02:04:33 +08:00
|
|
|
|
AllModels[curmodel + i] = VlowModels[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
curmodel += vlow.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var sg = Drawable.ShaderGroup;
|
|
|
|
|
//if ((sg != null) && (sg.TextureDictionary != null))
|
|
|
|
|
//{
|
|
|
|
|
// EmbeddedTextureSize = sg.TextureDictionary.MemoryUsage;
|
|
|
|
|
// TextureDict = sg.TextureDictionary.GetDictionary();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-12-05 00:40:52 +08:00
|
|
|
|
var fd = drawable as FragDrawable;
|
|
|
|
|
var dd = drawable as Drawable;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool hasskeleton = false;
|
|
|
|
|
bool hastransforms = false;
|
|
|
|
|
bool hasbones = false;
|
|
|
|
|
Skeleton skeleton = drawable.Skeleton;
|
|
|
|
|
Matrix[] modeltransforms = null;
|
2018-02-27 00:05:59 +08:00
|
|
|
|
Matrix[] fragtransforms = null;
|
|
|
|
|
Vector4 fragoffset = Vector4.Zero;
|
|
|
|
|
int fragtransformid = 0;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
List<Bone> bones = null;
|
|
|
|
|
bool usepose = false;
|
|
|
|
|
if (skeleton != null)
|
|
|
|
|
{
|
|
|
|
|
hasskeleton = true;
|
|
|
|
|
modeltransforms = skeleton.Transformations;
|
|
|
|
|
|
|
|
|
|
//for fragments, get the default pose from the root fragment...
|
|
|
|
|
if (fd != null)
|
|
|
|
|
{
|
|
|
|
|
var frag = fd.OwnerFragment;
|
2019-11-05 17:47:10 +08:00
|
|
|
|
var pose = frag?.BoneTransforms;
|
|
|
|
|
if ((pose != null) && (pose.Items != null)) //seems to be the default pose
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-11-05 17:47:10 +08:00
|
|
|
|
var posebonecount = pose.Items.Length;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
if ((modeltransforms == null))// || (modeltransforms.Length != posebonecount))
|
|
|
|
|
{
|
|
|
|
|
modeltransforms = new Matrix[posebonecount];
|
|
|
|
|
}
|
|
|
|
|
var modelbonecount = modeltransforms.Length;
|
|
|
|
|
var maxbonecount = Math.Min(posebonecount, modelbonecount);
|
|
|
|
|
for (int i = 0; i < maxbonecount; i++)
|
|
|
|
|
{
|
2019-11-05 17:47:10 +08:00
|
|
|
|
var p = pose.Items[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
Vector4 r1 = p.Row1;
|
|
|
|
|
Vector4 r2 = p.Row2;
|
|
|
|
|
Vector4 r3 = p.Row3;
|
|
|
|
|
modeltransforms[i] = new Matrix(r1.X, r2.X, r3.X, 0.0f, r1.Y, r2.Y, r3.Y, 0.0f, r1.Z, r2.Z, r3.Z, 0.0f, r1.W, r2.W, r3.W, 1.0f);
|
|
|
|
|
}
|
|
|
|
|
usepose = true;
|
|
|
|
|
}
|
2018-02-27 00:05:59 +08:00
|
|
|
|
|
|
|
|
|
var phys = fd.OwnerFragmentPhys;
|
|
|
|
|
if (phys != null)
|
|
|
|
|
{
|
|
|
|
|
if (phys.OwnerFragPhysLod != null)
|
|
|
|
|
{
|
2020-01-22 02:02:14 +08:00
|
|
|
|
fragtransforms = phys.OwnerFragPhysLod.FragTransforms?.Matrices;
|
2018-02-27 00:05:59 +08:00
|
|
|
|
fragtransformid = phys.OwnerFragPhysIndex;
|
2020-01-23 01:05:50 +08:00
|
|
|
|
fragoffset = new Vector4(phys.OwnerFragPhysLod.Unknown_30h, 0.0f);
|
2019-01-13 18:31:33 +08:00
|
|
|
|
|
2019-01-14 09:25:03 +08:00
|
|
|
|
|
|
|
|
|
switch (phys.BoneTag) //right hand side wheel flip!
|
2019-01-13 18:31:33 +08:00
|
|
|
|
{
|
2019-01-14 09:25:03 +08:00
|
|
|
|
//case 27922: //wheel_lf
|
|
|
|
|
//case 29921: //wheel_lm1
|
|
|
|
|
//case 29922: //wheel_lm2
|
|
|
|
|
//case 29923: //wheel_lm3
|
|
|
|
|
//case 27902: //wheel_lr
|
|
|
|
|
case 26418: //wheel_rf
|
|
|
|
|
case 5857: //wheel_rm1
|
|
|
|
|
case 5858: //wheel_rm2
|
|
|
|
|
case 5859: //wheel_rm3
|
|
|
|
|
case 26398: //wheel_rr
|
|
|
|
|
fragtransforms[fragtransformid].M11 = -1;
|
|
|
|
|
fragtransforms[fragtransformid].M12 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M13 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M21 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M22 = 1;
|
|
|
|
|
fragtransforms[fragtransformid].M23 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M31 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M32 = 0;
|
|
|
|
|
fragtransforms[fragtransformid].M33 = -1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2019-01-13 18:31:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-27 00:05:59 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (frag != null)
|
|
|
|
|
{
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-27 00:05:59 +08:00
|
|
|
|
hastransforms = (modeltransforms != null) || (fragtransforms != null);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
hasbones = ((skeleton.Bones != null) && (skeleton.Bones.Data != null));
|
|
|
|
|
bones = hasbones ? skeleton.Bones.Data : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HasSkeleton = hasskeleton;
|
|
|
|
|
HasTransforms = hastransforms;
|
|
|
|
|
|
2019-11-26 14:00:41 +08:00
|
|
|
|
Skeleton = skeleton;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//calculate transforms for the models if there are any. (TODO: move this to a method for re-use...)
|
|
|
|
|
for (int mi = 0; mi < AllModels.Length; mi++)
|
|
|
|
|
{
|
|
|
|
|
var model = AllModels[mi];
|
|
|
|
|
|
|
|
|
|
model.UseTransform = hastransforms;
|
|
|
|
|
if (hastransforms)
|
|
|
|
|
{
|
2018-02-27 00:05:59 +08:00
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
int boneidx = model.BoneIndex;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity;
|
|
|
|
|
Bone bone = (hasbones && (boneidx < bones.Count)) ? bones[boneidx] : null;
|
|
|
|
|
|
2019-11-02 15:14:36 +08:00
|
|
|
|
if (mi < HDModels.Length) //populate bone links map for hd models
|
|
|
|
|
{
|
|
|
|
|
if (bone != null)
|
|
|
|
|
{
|
|
|
|
|
if (ModelBoneLinks == null) ModelBoneLinks = new Dictionary<ushort, RenderableModel>();
|
2019-11-05 17:47:10 +08:00
|
|
|
|
ModelBoneLinks[bone.Tag] = model;
|
2019-11-02 15:14:36 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-02-27 00:05:59 +08:00
|
|
|
|
if ((fragtransforms != null))// && (fragtransformid < fragtransforms.Length))
|
|
|
|
|
{
|
|
|
|
|
if (fragtransformid < fragtransforms.Length)
|
|
|
|
|
{
|
|
|
|
|
trans = fragtransforms[fragtransformid];
|
|
|
|
|
trans.Row4 += fragoffset;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ }
|
|
|
|
|
}
|
|
|
|
|
else if (!usepose) //when using the skeleton's matrices, they need to be transformed by parent
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
|
|
|
|
trans.Column4 = Vector4.UnitW;
|
2019-11-06 01:53:20 +08:00
|
|
|
|
short[] pinds = skeleton.ParentIndices;
|
|
|
|
|
short parentind = ((pinds != null) && (boneidx < pinds.Length)) ? pinds[boneidx] : (short)-1;
|
|
|
|
|
while ((parentind >= 0) && (parentind < pinds.Length))
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
|
|
|
|
Matrix ptrans = (parentind < modeltransforms.Length) ? modeltransforms[parentind] : Matrix.Identity;
|
|
|
|
|
ptrans.Column4 = Vector4.UnitW;
|
|
|
|
|
trans = Matrix.Multiply(ptrans, trans);
|
2019-11-06 01:53:20 +08:00
|
|
|
|
parentind = ((pinds != null) && (parentind < pinds.Length)) ? pinds[parentind] : (short)-1;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
if (model.IsSkinMesh)
|
2017-09-23 19:46:49 +08:00
|
|
|
|
{
|
|
|
|
|
model.Transform = Matrix.Identity;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
model.Transform = trans;
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-03 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-12-05 00:40:52 +08:00
|
|
|
|
var lights = dd?.LightAttributes?.data_items;
|
|
|
|
|
if ((lights == null) && (fd != null) && (fd?.OwnerFragment?.Drawable == fd))
|
|
|
|
|
{
|
|
|
|
|
lights = fd.OwnerFragment.LightAttributes?.data_items;
|
|
|
|
|
}
|
|
|
|
|
if (lights != null)
|
|
|
|
|
{
|
|
|
|
|
var rlights = new RenderableLight[lights.Length];
|
|
|
|
|
for (int i = 0; i < lights.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var rlight = new RenderableLight();
|
|
|
|
|
rlight.Owner = this;
|
|
|
|
|
rlight.Init(ref lights[i]);
|
|
|
|
|
rlights[i] = rlight;
|
|
|
|
|
}
|
|
|
|
|
Lights = rlights;
|
|
|
|
|
}
|
2019-11-03 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
UpdateBoneTransforms();
|
2019-11-03 03:25:20 +08:00
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private RenderableModel InitModel(DrawableModel dm)
|
|
|
|
|
{
|
|
|
|
|
var rmodel = new RenderableModel();
|
|
|
|
|
rmodel.Owner = this;
|
|
|
|
|
rmodel.Init(dm);
|
|
|
|
|
DataSize += rmodel.GeometrySize;
|
|
|
|
|
return rmodel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if (AllModels != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var model in AllModels)
|
|
|
|
|
{
|
|
|
|
|
if (model.Geometries == null) continue;
|
|
|
|
|
foreach (var geom in model.Geometries)
|
|
|
|
|
{
|
|
|
|
|
geom.Load(device);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (AllModels != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var model in AllModels)
|
|
|
|
|
{
|
|
|
|
|
if (model.Geometries == null) continue;
|
|
|
|
|
foreach (var geom in model.Geometries)
|
|
|
|
|
{
|
|
|
|
|
geom.Unload();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LoadQueued = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return Key.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
|
2019-11-08 15:58:56 +08:00
|
|
|
|
public void ResetBoneTransforms()
|
|
|
|
|
{
|
2019-11-26 14:00:41 +08:00
|
|
|
|
if (Skeleton == null) return;
|
|
|
|
|
Skeleton.ResetBoneTransforms();
|
2019-11-08 15:58:56 +08:00
|
|
|
|
UpdateBoneTransforms();
|
|
|
|
|
}
|
2019-11-03 19:43:39 +08:00
|
|
|
|
private void UpdateBoneTransforms()
|
|
|
|
|
{
|
2019-11-26 14:00:41 +08:00
|
|
|
|
if (Skeleton?.Bones?.Data == null) return;
|
|
|
|
|
|
|
|
|
|
Skeleton.UpdateBoneTransforms();
|
|
|
|
|
|
|
|
|
|
var bones = Skeleton.Bones?.Data;
|
|
|
|
|
var bonetransforms = Skeleton.BoneTransforms;
|
2019-11-09 18:07:41 +08:00
|
|
|
|
|
2019-11-14 15:58:20 +08:00
|
|
|
|
var drawbl = Key;
|
|
|
|
|
if (AllModels == null) return;
|
|
|
|
|
for (int i = 0; i < AllModels.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var model = AllModels[i];
|
|
|
|
|
if (model?.Geometries == null) continue;
|
|
|
|
|
for (int g = 0; g < model.Geometries.Length; g++)
|
|
|
|
|
{
|
|
|
|
|
var geom = model.Geometries[g];
|
|
|
|
|
var boneids = geom?.DrawableGeom?.BoneIds;
|
|
|
|
|
if (boneids == null) continue;
|
2019-11-26 14:00:41 +08:00
|
|
|
|
if (boneids.Length != bones.Count)
|
2019-11-14 15:58:20 +08:00
|
|
|
|
{
|
|
|
|
|
var idc = boneids.Length;
|
|
|
|
|
if (geom.BoneTransforms == null)
|
|
|
|
|
{
|
|
|
|
|
geom.BoneTransforms = new Matrix3_s[idc];
|
|
|
|
|
}
|
|
|
|
|
for (int b = 0; b < idc; b++)
|
|
|
|
|
{
|
|
|
|
|
var id = boneids[b];
|
2019-11-26 14:00:41 +08:00
|
|
|
|
if (id < bonetransforms.Length)
|
2019-11-14 15:58:20 +08:00
|
|
|
|
{
|
2019-11-26 14:00:41 +08:00
|
|
|
|
geom.BoneTransforms[b] = bonetransforms[id];
|
2019-11-14 15:58:20 +08:00
|
|
|
|
if (id != b)
|
|
|
|
|
{ }
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-09 18:07:41 +08:00
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
public void UpdateAnims(double realTime)
|
|
|
|
|
{
|
2019-11-25 22:26:28 +08:00
|
|
|
|
if (ClipMapEntry?.OverridePlayTime ?? false)
|
|
|
|
|
{
|
|
|
|
|
realTime = ClipMapEntry.PlayTime;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
if (CurrentAnimTime == realTime) return;//already updated this!
|
|
|
|
|
CurrentAnimTime = realTime;
|
|
|
|
|
|
2019-11-14 15:58:20 +08:00
|
|
|
|
EnableRootMotion = ClipMapEntry?.EnableRootMotion ?? false;
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
if (ClipMapEntry != null)
|
|
|
|
|
{
|
2019-11-02 17:40:14 +08:00
|
|
|
|
UpdateAnim(ClipMapEntry); //animate skeleton/models
|
2019-11-02 03:46:45 +08:00
|
|
|
|
}
|
2019-11-02 17:40:14 +08:00
|
|
|
|
|
2019-11-08 15:58:56 +08:00
|
|
|
|
UpdateBoneTransforms();
|
|
|
|
|
|
2019-11-02 17:40:14 +08:00
|
|
|
|
foreach (var model in HDModels)
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
2019-11-02 17:40:14 +08:00
|
|
|
|
if (model == null) continue;
|
|
|
|
|
foreach (var geom in model.Geometries)
|
|
|
|
|
{
|
|
|
|
|
if (geom == null) continue;
|
|
|
|
|
if (geom.ClipMapEntryUV != null)
|
|
|
|
|
{
|
|
|
|
|
UpdateAnimUV(geom.ClipMapEntryUV, geom); //animate UVs
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-02 03:46:45 +08:00
|
|
|
|
}
|
2019-11-02 17:40:14 +08:00
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
}
|
|
|
|
|
private void UpdateAnim(ClipMapEntry cme)
|
|
|
|
|
{
|
2019-11-14 15:58:20 +08:00
|
|
|
|
|
2019-11-07 20:14:39 +08:00
|
|
|
|
var clipanim = cme.Clip as ClipAnimation;
|
2019-11-08 14:54:46 +08:00
|
|
|
|
if (clipanim?.Animation != null)
|
2019-11-07 20:14:39 +08:00
|
|
|
|
{
|
2019-11-08 14:54:46 +08:00
|
|
|
|
UpdateAnim(clipanim.Animation, clipanim.GetPlaybackTime(CurrentAnimTime));
|
2019-11-07 20:14:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var clipanimlist = cme.Clip as ClipAnimationList;
|
|
|
|
|
if (clipanimlist?.Animations != null)
|
|
|
|
|
{
|
2019-11-07 23:00:16 +08:00
|
|
|
|
foreach (var canim in clipanimlist.Animations)
|
2019-11-07 20:14:39 +08:00
|
|
|
|
{
|
2019-11-07 23:00:16 +08:00
|
|
|
|
if (canim?.Animation == null) continue;
|
2019-11-08 16:53:29 +08:00
|
|
|
|
UpdateAnim(canim.Animation, canim.GetPlaybackTime(CurrentAnimTime));
|
2019-11-07 20:14:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-07 23:00:16 +08:00
|
|
|
|
|
2019-11-07 20:14:39 +08:00
|
|
|
|
}
|
2019-11-07 23:00:16 +08:00
|
|
|
|
private void UpdateAnim(Animation anim, float t)
|
2019-11-07 20:14:39 +08:00
|
|
|
|
{
|
2019-11-02 03:46:45 +08:00
|
|
|
|
if (anim == null)
|
|
|
|
|
{ return; }
|
2019-11-02 15:14:36 +08:00
|
|
|
|
if (anim.BoneIds?.data_items == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
if (anim.Sequences?.data_items == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
|
|
|
|
|
bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't
|
|
|
|
|
|
2019-11-25 17:44:16 +08:00
|
|
|
|
var frame = anim.GetFramePosition(t);
|
2019-11-02 15:14:36 +08:00
|
|
|
|
|
|
|
|
|
var dwbl = this.Key;
|
2019-11-26 14:00:41 +08:00
|
|
|
|
var skel = Skeleton;
|
2019-11-02 15:14:36 +08:00
|
|
|
|
var bones = skel?.Bones;
|
|
|
|
|
if (bones == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
|
2019-11-25 17:44:16 +08:00
|
|
|
|
Vector4 v;
|
|
|
|
|
Quaternion q;
|
2019-11-07 20:14:39 +08:00
|
|
|
|
|
2019-11-02 15:14:36 +08:00
|
|
|
|
for (int i = 0; i < anim.BoneIds.data_items.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var boneiditem = anim.BoneIds.data_items[i];
|
|
|
|
|
var track = boneiditem.Track;
|
|
|
|
|
|
|
|
|
|
Bone bone = null;
|
|
|
|
|
skel?.BonesMap?.TryGetValue(boneiditem.BoneId, out bone);
|
|
|
|
|
if (bone == null)
|
2019-11-25 17:44:16 +08:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
//skel.BoneTagsMap?.TryGetValue(boneiditem.BoneId, out bone);
|
|
|
|
|
//if (bone == null)
|
|
|
|
|
//{ continue; }
|
|
|
|
|
}
|
2019-11-02 15:14:36 +08:00
|
|
|
|
|
2019-11-08 19:55:39 +08:00
|
|
|
|
switch (track)
|
2019-11-02 15:14:36 +08:00
|
|
|
|
{
|
2019-11-08 19:55:39 +08:00
|
|
|
|
case 0: //bone position
|
2019-11-25 17:44:16 +08:00
|
|
|
|
v = anim.EvaluateVector4(frame, i, interpolate);
|
2019-11-08 19:55:39 +08:00
|
|
|
|
bone.AnimTranslation = v.XYZ();
|
|
|
|
|
break;
|
|
|
|
|
case 1: //bone orientation
|
2019-11-25 17:44:16 +08:00
|
|
|
|
q = anim.EvaluateQuaternion(frame, i, interpolate);
|
2019-11-08 19:55:39 +08:00
|
|
|
|
bone.AnimRotation = q;
|
|
|
|
|
break;
|
|
|
|
|
case 2: //scale?
|
2019-11-25 17:44:16 +08:00
|
|
|
|
v = anim.EvaluateVector4(frame, i, interpolate);
|
2019-11-09 23:01:52 +08:00
|
|
|
|
bone.AnimScale = v.XYZ();
|
|
|
|
|
break;
|
|
|
|
|
case 5://root motion vector
|
2019-11-14 15:58:20 +08:00
|
|
|
|
if (EnableRootMotion)
|
|
|
|
|
{
|
2019-11-25 17:44:16 +08:00
|
|
|
|
v = anim.EvaluateVector4(frame, i, interpolate);
|
2019-11-14 15:58:20 +08:00
|
|
|
|
bone.AnimTranslation += v.XYZ();
|
|
|
|
|
}
|
2019-11-08 19:55:39 +08:00
|
|
|
|
break;
|
2019-11-17 19:14:00 +08:00
|
|
|
|
case 6://quaternion... root rotation
|
|
|
|
|
if (EnableRootMotion)
|
|
|
|
|
{
|
2019-11-25 17:44:16 +08:00
|
|
|
|
q = anim.EvaluateQuaternion(frame, i, interpolate);
|
2019-11-17 19:14:00 +08:00
|
|
|
|
bone.AnimRotation = q * bone.AnimRotation;
|
|
|
|
|
}
|
2019-11-09 23:01:52 +08:00
|
|
|
|
break;
|
|
|
|
|
case 7://vector3... (camera position?)
|
2019-11-08 19:55:39 +08:00
|
|
|
|
break;
|
2019-11-09 23:01:52 +08:00
|
|
|
|
case 8://quaternion... (camera rotation?)
|
2019-11-08 19:55:39 +08:00
|
|
|
|
break;
|
2019-11-25 17:44:16 +08:00
|
|
|
|
case 24://face stuff?
|
|
|
|
|
break;
|
|
|
|
|
case 25://face stuff?
|
|
|
|
|
break;
|
|
|
|
|
case 26://face stuff?
|
|
|
|
|
break;
|
2019-11-09 23:01:52 +08:00
|
|
|
|
case 27:
|
|
|
|
|
case 50:
|
2019-11-08 19:55:39 +08:00
|
|
|
|
case 134://single float?
|
|
|
|
|
case 136:
|
|
|
|
|
case 137:
|
|
|
|
|
case 138:
|
|
|
|
|
case 139:
|
|
|
|
|
case 140:
|
2019-11-09 23:01:52 +08:00
|
|
|
|
if (bone.Tag != 0)
|
|
|
|
|
{ }
|
2019-11-08 19:55:39 +08:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2019-11-14 15:58:20 +08:00
|
|
|
|
if (bone.Tag != 0)
|
|
|
|
|
{ }
|
2019-11-08 19:55:39 +08:00
|
|
|
|
break;
|
2019-11-02 15:14:36 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-09 23:01:52 +08:00
|
|
|
|
for (int i = 0; i < bones.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var bone = bones[i];
|
|
|
|
|
var tag = bone.Tag;
|
|
|
|
|
switch (bone.Tag)
|
|
|
|
|
{
|
|
|
|
|
case 23639: tag = 58271; break; //RB_L_ThighRoll: SKEL_L_Thigh
|
|
|
|
|
case 6442: tag = 51826; break; //RB_R_ThighRoll: SKEL_R_Thigh
|
|
|
|
|
//case 61007: tag = 61163; break; //RB_L_ForeArmRoll: SKEL_L_Forearm //NOT GOOD
|
|
|
|
|
//case 5232: tag = 45509; break; //RB_L_ArmRoll: SKEL_L_UpperArm
|
|
|
|
|
}
|
2019-11-29 18:36:20 +08:00
|
|
|
|
if ((tag != bone.Tag) && (tag != bone.Parent?.Tag))
|
2019-11-09 23:01:52 +08:00
|
|
|
|
{
|
|
|
|
|
var obone = bone;
|
|
|
|
|
if (skel.BonesMap.TryGetValue(tag, out obone))
|
|
|
|
|
{
|
|
|
|
|
bone.AnimRotation = obone.AnimRotation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 15:14:36 +08:00
|
|
|
|
for (int i = 0; i < bones.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var bone = bones[i];
|
2019-11-03 19:43:39 +08:00
|
|
|
|
bone.UpdateAnimTransform();
|
2019-11-03 21:04:02 +08:00
|
|
|
|
bone.UpdateSkinTransform();
|
2019-11-03 03:25:20 +08:00
|
|
|
|
|
|
|
|
|
//update model's transform from animated bone
|
|
|
|
|
RenderableModel bmodel = null;
|
2019-11-05 17:47:10 +08:00
|
|
|
|
ModelBoneLinks?.TryGetValue(bone.Tag, out bmodel);
|
2019-11-03 19:43:39 +08:00
|
|
|
|
|
|
|
|
|
|
2019-11-03 03:25:20 +08:00
|
|
|
|
if (bmodel == null)
|
|
|
|
|
{ continue; }
|
2019-11-03 19:43:39 +08:00
|
|
|
|
if (bmodel.IsSkinMesh) //don't transform model for skin mesh
|
2019-11-03 03:25:20 +08:00
|
|
|
|
{ continue; }
|
2019-11-02 15:14:36 +08:00
|
|
|
|
|
2019-11-03 03:25:20 +08:00
|
|
|
|
bmodel.Transform = bone.AnimTransform;
|
2019-11-02 15:14:36 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 03:46:45 +08:00
|
|
|
|
|
|
|
|
|
}
|
2019-11-02 17:40:14 +08:00
|
|
|
|
private void UpdateAnimUV(ClipMapEntry cme, RenderableGeometry rgeom = null)
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
2019-11-07 23:00:16 +08:00
|
|
|
|
var clipanim = cme.Clip as ClipAnimation;
|
|
|
|
|
if (clipanim?.Animation != null)
|
|
|
|
|
{
|
|
|
|
|
UpdateAnimUV(clipanim.Animation, clipanim.GetPlaybackTime(CurrentAnimTime), rgeom);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var clipanimlist = cme.Clip as ClipAnimationList;
|
|
|
|
|
if (clipanimlist?.Animations != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var canim in clipanimlist.Animations)
|
|
|
|
|
{
|
|
|
|
|
if (canim?.Animation == null) continue;
|
2019-11-08 16:53:29 +08:00
|
|
|
|
UpdateAnimUV(canim.Animation, canim.GetPlaybackTime(CurrentAnimTime), rgeom);
|
2019-11-07 23:00:16 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
private void UpdateAnimUV(Animation anim, float t, RenderableGeometry rgeom = null)
|
|
|
|
|
{
|
2019-11-02 03:46:45 +08:00
|
|
|
|
if (anim == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
if (anim.BoneIds?.data_items == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
if (anim.Sequences?.data_items == null)
|
|
|
|
|
{ return; }
|
|
|
|
|
|
|
|
|
|
bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't
|
|
|
|
|
|
2019-11-25 17:44:16 +08:00
|
|
|
|
var frame = anim.GetFramePosition(t);
|
2019-11-02 03:46:45 +08:00
|
|
|
|
|
|
|
|
|
var globalAnimUV0 = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
|
var globalAnimUV1 = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < anim.BoneIds.data_items.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var boneiditem = anim.BoneIds.data_items[i];
|
|
|
|
|
var track = boneiditem.Track;
|
|
|
|
|
if ((track != 17) && (track != 18))
|
|
|
|
|
{ continue; }//17 and 18 would be UV0 and UV1
|
|
|
|
|
|
2019-11-25 17:44:16 +08:00
|
|
|
|
var v = anim.EvaluateVector4(frame, i, interpolate);
|
2019-11-08 19:55:39 +08:00
|
|
|
|
|
|
|
|
|
switch (track)
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
2019-11-08 19:55:39 +08:00
|
|
|
|
case 17: globalAnimUV0 = v; break; //could be overwriting values here...
|
|
|
|
|
case 18: globalAnimUV1 = v; break;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 17:40:14 +08:00
|
|
|
|
if (rgeom != null)
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
2019-11-02 17:40:14 +08:00
|
|
|
|
rgeom.globalAnimUV0 = globalAnimUV0;
|
|
|
|
|
rgeom.globalAnimUV1 = globalAnimUV1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
foreach (var model in HDModels) //TODO: figure out which models/geometries this should be applying to!
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
2019-11-02 17:40:14 +08:00
|
|
|
|
if (model == null) continue;
|
|
|
|
|
foreach (var geom in model.Geometries)
|
2019-11-02 03:46:45 +08:00
|
|
|
|
{
|
2019-11-02 17:40:14 +08:00
|
|
|
|
if (geom == null) continue;
|
|
|
|
|
if (geom.globalAnimUVEnable)
|
|
|
|
|
{
|
|
|
|
|
geom.globalAnimUV0 = globalAnimUV0;
|
|
|
|
|
geom.globalAnimUV1 = globalAnimUV1;
|
|
|
|
|
}
|
2019-11-02 03:46:45 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RenderableModel
|
|
|
|
|
{
|
|
|
|
|
public Renderable Owner;
|
|
|
|
|
public DrawableModel DrawableModel;
|
|
|
|
|
public RenderableGeometry[] Geometries;
|
|
|
|
|
public AABB_s[] GeometryBounds;
|
|
|
|
|
public long GeometrySize { get; private set; }
|
|
|
|
|
|
2019-03-20 18:21:47 +08:00
|
|
|
|
public uint SkeletonBinding;
|
|
|
|
|
public uint RenderMaskFlags; //flags.......
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
public bool UseTransform;
|
|
|
|
|
public Matrix Transform;
|
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
public int BoneIndex = 0;
|
|
|
|
|
public bool IsSkinMesh = false;
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public void Init(DrawableModel dmodel)
|
|
|
|
|
{
|
2019-03-20 18:21:47 +08:00
|
|
|
|
SkeletonBinding = dmodel.SkeletonBinding;//4th byte is bone index, 2nd byte for skin meshes
|
|
|
|
|
RenderMaskFlags = dmodel.RenderMaskFlags; //only the first byte seems be related to this
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
2019-11-03 19:43:39 +08:00
|
|
|
|
IsSkinMesh = ((SkeletonBinding >> 8) & 0xFF) > 0;
|
|
|
|
|
BoneIndex = (int)((SkeletonBinding >> 24) & 0xFF);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
DrawableModel = dmodel;
|
|
|
|
|
long geomcount = dmodel.Geometries.data_items.Length;
|
|
|
|
|
Geometries = new RenderableGeometry[geomcount];
|
|
|
|
|
GeometryBounds = new AABB_s[geomcount];
|
|
|
|
|
|
|
|
|
|
GeometrySize = 0;
|
|
|
|
|
for (int i = 0; i < geomcount; i++)
|
|
|
|
|
{
|
|
|
|
|
var dgeom = dmodel.Geometries.data_items[i];
|
|
|
|
|
var rgeom = new RenderableGeometry();
|
|
|
|
|
rgeom.Init(dgeom);
|
|
|
|
|
rgeom.Owner = this;
|
|
|
|
|
Geometries[i] = rgeom;
|
|
|
|
|
GeometrySize += rgeom.TotalDataSize;
|
|
|
|
|
|
2018-01-04 17:35:38 +08:00
|
|
|
|
if ((dmodel.BoundsData != null) && (i < dmodel.BoundsData.Length))
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2018-01-04 17:35:38 +08:00
|
|
|
|
GeometryBounds[i] = dmodel.BoundsData[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//GeometryBounds[i] = new AABB_s();//what to default to?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Owner.Key is FragDrawable)
|
|
|
|
|
{
|
|
|
|
|
rgeom.IsFragment = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RenderableGeometry
|
|
|
|
|
{
|
|
|
|
|
public RenderableModel Owner;
|
|
|
|
|
public Buffer VertexBuffer { get; set; }
|
|
|
|
|
public Buffer IndexBuffer { get; set; }
|
|
|
|
|
public VertexBufferBinding VBBinding;
|
|
|
|
|
public DrawableGeometry DrawableGeom;
|
|
|
|
|
public VertexType VertexType { get; set; }
|
|
|
|
|
public int VertexStride { get; set; }
|
|
|
|
|
public int VertexCount { get; set; }
|
|
|
|
|
public int IndexCount { get; set; }
|
|
|
|
|
public uint VertexDataSize { get; set; }
|
|
|
|
|
public uint IndexDataSize { get; set; }
|
|
|
|
|
public uint TotalDataSize { get; set; }
|
|
|
|
|
public TextureBase[] Textures;
|
2019-01-06 02:04:33 +08:00
|
|
|
|
public Texture[] TexturesHD;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public RenderableTexture[] RenderableTextures;
|
2019-01-06 02:04:33 +08:00
|
|
|
|
public RenderableTexture[] RenderableTexturesHD;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
public ShaderParamNames[] TextureParamHashes;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public PrimitiveTopology Topology { get; set; }
|
|
|
|
|
public bool IsFragment = false;
|
|
|
|
|
public bool IsEmissive { get; set; } = false;
|
|
|
|
|
public bool EnableWind { get; set; } = false;
|
|
|
|
|
public float HardAlphaBlend { get; set; } = 0.0f;
|
|
|
|
|
public float useTessellation { get; set; } = 0.0f;
|
|
|
|
|
public float wetnessMultiplier { get; set; } = 0.0f;
|
|
|
|
|
public float bumpiness { get; set; } = 1.0f;
|
|
|
|
|
public Vector4 detailSettings { get; set; } = Vector4.Zero;
|
|
|
|
|
public Vector3 specMapIntMask { get; set; } = Vector3.Zero;
|
|
|
|
|
public float specularIntensityMult { get; set; } = 0.0f;
|
|
|
|
|
public float specularFalloffMult { get; set; } = 0.0f;
|
|
|
|
|
public float specularFresnel { get; set; } = 0.0f;
|
|
|
|
|
public float RippleSpeed { get; set; } = 1.0f;
|
|
|
|
|
public float RippleScale { get; set; } = 1.0f;
|
|
|
|
|
public float RippleBumpiness { get; set; } = 1.0f;
|
|
|
|
|
public Vector4 WindGlobalParams { get; set; } = Vector4.Zero;
|
|
|
|
|
public Vector4 WindOverrideParams { get; set; } = Vector4.One;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
public Vector4 globalAnimUV0 { get; set; } = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
|
public Vector4 globalAnimUV1 { get; set; } = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
|
2018-03-07 19:24:37 +08:00
|
|
|
|
public Vector4 DirtDecalMask { get; set; } = Vector4.Zero;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public bool SpecOnly { get; set; } = false;
|
|
|
|
|
public float WaveOffset { get; set; } = 0; //for terrainfoam
|
|
|
|
|
public float WaterHeight { get; set; } = 0; //for terrainfoam
|
|
|
|
|
public float WaveMovement { get; set; } = 0; //for terrainfoam
|
|
|
|
|
public float HeightOpacity { get; set; } = 0; //for terrainfoam
|
2019-01-06 02:04:33 +08:00
|
|
|
|
public bool HDTextureEnable = true;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
public bool globalAnimUVEnable = false;
|
2019-11-02 17:40:14 +08:00
|
|
|
|
public ClipMapEntry ClipMapEntryUV = null;
|
2019-11-08 11:22:10 +08:00
|
|
|
|
public bool isHair = false;
|
|
|
|
|
public bool disableRendering = false;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
2019-11-14 15:58:20 +08:00
|
|
|
|
public Matrix3_s[] BoneTransforms = null;
|
2019-11-09 18:07:41 +08:00
|
|
|
|
|
2019-10-31 14:11:12 +08:00
|
|
|
|
public static ShaderParamNames[] GetTextureSamplerList()
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-10-31 14:11:12 +08:00
|
|
|
|
return new ShaderParamNames[]
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-10-31 14:11:12 +08:00
|
|
|
|
ShaderParamNames.DiffuseSampler, //base diffuse
|
|
|
|
|
ShaderParamNames.SpecSampler, //base specular
|
|
|
|
|
ShaderParamNames.BumpSampler, //base normal
|
|
|
|
|
ShaderParamNames.TintPaletteSampler, // _pal
|
|
|
|
|
ShaderParamNames.DetailSampler, // ENV_
|
|
|
|
|
ShaderParamNames.FlowSampler, //river _flow
|
|
|
|
|
ShaderParamNames.FogSampler, //river _fog , water slod
|
|
|
|
|
ShaderParamNames.TextureSampler_layer0, //CS_RSN_SL_Road_0007
|
|
|
|
|
ShaderParamNames.BumpSampler_layer0, //CS_RSN_SL_Road_0007_n
|
|
|
|
|
ShaderParamNames.heightMapSamplerLayer0, //nxg_cs_rsn_sl_road_0007_h
|
|
|
|
|
ShaderParamNames.TextureSampler_layer1, //IM_Road_009b
|
|
|
|
|
ShaderParamNames.BumpSampler_layer1, //IM_Road_010b_N
|
|
|
|
|
ShaderParamNames.heightMapSamplerLayer1, //nxg_im_road_010b_h
|
|
|
|
|
ShaderParamNames.TextureSampler_layer2, //IM_Concrete10
|
|
|
|
|
ShaderParamNames.BumpSampler_layer2, //IM_Concrete13_N
|
|
|
|
|
ShaderParamNames.heightMapSamplerLayer2, //nxg_im_concrete13_h
|
|
|
|
|
ShaderParamNames.TextureSampler_layer3, //SC1_RSN_NS_ground_0009
|
|
|
|
|
ShaderParamNames.BumpSampler_layer3, //sc1_rsn_ns_ground_0010_n
|
|
|
|
|
ShaderParamNames.heightMapSamplerLayer3, //nxg_sc1_rsn_ns_ground_0010_b_h
|
|
|
|
|
ShaderParamNames.lookupSampler, //TF_RSN_Msk_CS1_DesHill1, bh1_43_golf_blendmap_04_LOD
|
|
|
|
|
ShaderParamNames.heightSampler, //nxg_prop_tree_palm2_displ_l
|
|
|
|
|
ShaderParamNames.FoamSampler, //bj_beachfoam01_lod, CS_RSN_SL_RiverFoam_01_A_lodCS_RSN_SL_RiverFoam_01_A
|
|
|
|
|
ShaderParamNames.DirtSampler,
|
|
|
|
|
ShaderParamNames.DirtBumpSampler,
|
|
|
|
|
ShaderParamNames.DiffuseSampler2,
|
|
|
|
|
ShaderParamNames.DiffuseSampler3,
|
|
|
|
|
ShaderParamNames.DiffuseHfSampler,
|
|
|
|
|
ShaderParamNames.ComboHeightSamplerFur01,
|
|
|
|
|
ShaderParamNames.ComboHeightSamplerFur23,
|
|
|
|
|
ShaderParamNames.ComboHeightSamplerFur45,
|
|
|
|
|
ShaderParamNames.ComboHeightSamplerFur67,
|
|
|
|
|
ShaderParamNames.StippleSampler,
|
|
|
|
|
ShaderParamNames.FurMaskSampler,
|
|
|
|
|
ShaderParamNames.EnvironmentSampler,
|
|
|
|
|
ShaderParamNames.distanceMapSampler,
|
|
|
|
|
ShaderParamNames.textureSamp,
|
2017-09-21 18:33:05 +08:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Init(DrawableGeometry dgeom)
|
|
|
|
|
{
|
|
|
|
|
DrawableGeom = dgeom;
|
|
|
|
|
VertexType = dgeom.VertexData.VertexType;
|
|
|
|
|
VertexStride = dgeom.VertexStride;
|
|
|
|
|
VertexCount = dgeom.VerticesCount;
|
|
|
|
|
IndexCount = (int)dgeom.IndicesCount;
|
|
|
|
|
VertexDataSize = (uint)(VertexCount * VertexStride);
|
|
|
|
|
IndexDataSize = (uint)(IndexCount * 2); //ushort indices...
|
|
|
|
|
TotalDataSize = VertexDataSize + IndexDataSize;
|
|
|
|
|
Topology = PrimitiveTopology.TriangleList;
|
|
|
|
|
|
|
|
|
|
var shader = DrawableGeom.Shader;
|
|
|
|
|
if ((shader != null) && (shader.ParametersList != null))
|
|
|
|
|
{
|
|
|
|
|
if (shader.FileName == 3854885487)//{cable.sps}
|
|
|
|
|
{
|
|
|
|
|
Topology = PrimitiveTopology.LineList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var shaderName = shader.Name;
|
|
|
|
|
var shaderFile = shader.FileName;
|
|
|
|
|
switch (shaderFile.Hash)
|
|
|
|
|
{
|
|
|
|
|
case 2245870123: //trees_normal_diffspec_tnt.sps
|
|
|
|
|
case 3334613197: //trees_tnt.sps
|
|
|
|
|
case 1229591973://{trees_normal_spec_tnt.sps}
|
|
|
|
|
case 2322653400://{trees.sps}
|
|
|
|
|
case 3192134330://{trees_normal.sps}
|
|
|
|
|
case 1224713457://{trees_normal_spec.sps}
|
|
|
|
|
case 4265705004://{trees_normal_diffspec.sps}
|
|
|
|
|
case 1581835696://{default_um.sps}
|
|
|
|
|
case 3326705511://{normal_um.sps}
|
|
|
|
|
case 3085209681://{normal_spec_um.sps}
|
|
|
|
|
case 3190732435://{cutout_um.sps}
|
|
|
|
|
case 748520668://{normal_cutout_um.sps}
|
|
|
|
|
EnableWind = true;
|
|
|
|
|
break;
|
|
|
|
|
case 1332909972://{normal_spec_emissive.sps}
|
|
|
|
|
case 2072061694://{normal_spec_reflect_emissivenight.sps}
|
|
|
|
|
case 2635608835://{emissive.sps}
|
|
|
|
|
case 443538781://{emissive_clip.sps}
|
|
|
|
|
case 2049580179://{emissive_speclum.sps}
|
|
|
|
|
case 1193295596://{emissive_tnt.sps}
|
|
|
|
|
case 1434302180://{emissivenight.sps}
|
|
|
|
|
case 1897917258://{emissivenight_geomnightonly.sps}
|
|
|
|
|
case 140448747://{emissivestrong.sps}
|
|
|
|
|
case 1436689415://{normal_spec_reflect_emissivenight_alpha.sps}
|
|
|
|
|
case 179247185://{emissive_alpha.sps}
|
|
|
|
|
case 1314864030://{emissive_alpha_tnt.sps}
|
|
|
|
|
case 1478174766://{emissive_additive_alpha.sps}
|
|
|
|
|
case 3733846327://{emissivenight_alpha.sps}
|
|
|
|
|
case 3174327089://{emissivestrong_alpha.sps}
|
|
|
|
|
case 3924045432://{glass_emissive.sps}
|
|
|
|
|
case 837003310://{glass_emissivenight.sps}
|
|
|
|
|
case 485710087://{glass_emissivenight_alpha.sps}
|
|
|
|
|
case 2055615352://{glass_emissive_alpha.sps}
|
|
|
|
|
case 2918136469://{decal_emissive_only.sps}
|
|
|
|
|
case 2698880237://{decal_emissivenight_only.sps}
|
|
|
|
|
IsEmissive = true;
|
|
|
|
|
break;
|
|
|
|
|
case 3880384844://{decal_spec_only.sps}
|
|
|
|
|
case 341123999://{decal_normal_only.sps}
|
|
|
|
|
case 600733812://{decal_amb_only.sps}
|
|
|
|
|
SpecOnly = true; //this needs more work.
|
|
|
|
|
break;
|
2019-11-08 11:22:10 +08:00
|
|
|
|
case 100720695://{ped_hair_spiked.sps}
|
|
|
|
|
isHair = true;
|
|
|
|
|
break;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var pl = shader.ParametersList.Parameters;
|
|
|
|
|
var hl = shader.ParametersList.Hashes;
|
|
|
|
|
List<TextureBase> texs = new List<TextureBase>();
|
2019-10-31 14:11:12 +08:00
|
|
|
|
List<ShaderParamNames> phashes = new List<ShaderParamNames>();
|
2017-09-21 18:33:05 +08:00
|
|
|
|
if ((pl != null) && (hl != null))
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; (i < pl.Length) && (i < hl.Length); i++)
|
|
|
|
|
{
|
2019-10-31 14:11:12 +08:00
|
|
|
|
ShaderParamNames pName = (ShaderParamNames)hl[i];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
var param = pl[i];
|
|
|
|
|
if (param.Data is TextureBase)
|
|
|
|
|
{
|
|
|
|
|
texs.Add(param.Data as TextureBase);
|
2019-10-31 14:11:12 +08:00
|
|
|
|
phashes.Add(pName);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-31 14:11:12 +08:00
|
|
|
|
switch (pName)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.HardAlphaBlend:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
HardAlphaBlend = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.useTessellation:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
useTessellation = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.wetnessMultiplier:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
wetnessMultiplier = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.bumpiness: //float
|
2017-09-21 18:33:05 +08:00
|
|
|
|
bumpiness = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.detailSettings: //float4
|
2017-09-21 18:33:05 +08:00
|
|
|
|
detailSettings = (Vector4)param.Data;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.specMapIntMask: //float3
|
2017-09-21 18:33:05 +08:00
|
|
|
|
specMapIntMask = ((Vector4)param.Data).XYZ();
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.specularIntensityMult: //float
|
2017-09-21 18:33:05 +08:00
|
|
|
|
specularIntensityMult = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.specularFalloffMult: //float
|
2017-09-21 18:33:05 +08:00
|
|
|
|
specularFalloffMult = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.specularFresnel: //float
|
2017-09-21 18:33:05 +08:00
|
|
|
|
specularFresnel= ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.WindGlobalParams:
|
|
|
|
|
case ShaderParamNames.umGlobalOverrideParams:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
//WindOverrideParams = ((Vector4)param.Data); //todo...
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.umGlobalParams:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
WindGlobalParams = ((Vector4)param.Data);
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.RippleSpeed:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
RippleSpeed = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.RippleScale:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
RippleScale = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.RippleBumpiness:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
RippleBumpiness = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.globalAnimUV0:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
globalAnimUV0 = (Vector4)param.Data;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
globalAnimUVEnable = true;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.globalAnimUV1:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
globalAnimUV1 = (Vector4)param.Data;
|
2019-11-02 03:46:45 +08:00
|
|
|
|
globalAnimUVEnable = true;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.WaveOffset:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
WaveOffset = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.WaterHeight:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
WaterHeight = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.WaveMovement:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
WaveMovement = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.HeightOpacity:
|
2017-09-21 18:33:05 +08:00
|
|
|
|
HeightOpacity = ((Vector4)param.Data).X;
|
|
|
|
|
break;
|
2019-10-31 14:11:12 +08:00
|
|
|
|
case ShaderParamNames.DirtDecalMask:
|
2018-03-07 19:24:37 +08:00
|
|
|
|
DirtDecalMask = ((Vector4)param.Data);
|
|
|
|
|
break;
|
2019-11-08 11:22:10 +08:00
|
|
|
|
case ShaderParamNames.orderNumber:
|
|
|
|
|
//stops drawing hair geoms that apparently shouldn't be rendered... any better way to do this?
|
|
|
|
|
if (isHair && (((Vector4)param.Data).X > 0.0f)) disableRendering = true;
|
|
|
|
|
break;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (texs.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
TextureParamHashes = phashes.ToArray();
|
|
|
|
|
Textures = texs.ToArray();
|
2019-01-06 02:04:33 +08:00
|
|
|
|
TexturesHD = new Texture[texs.Count];
|
2017-09-21 18:33:05 +08:00
|
|
|
|
RenderableTextures = new RenderableTexture[texs.Count]; //these will get populated at render time.
|
2019-01-06 02:04:33 +08:00
|
|
|
|
RenderableTexturesHD = new RenderableTexture[texs.Count]; //these will get populated at render time.
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, DrawableGeom.VertexData.VertexBytes);
|
|
|
|
|
|
|
|
|
|
//object v = DrawableGeom.VertexData.Vertices;
|
|
|
|
|
//switch (VertexType)
|
|
|
|
|
//{
|
|
|
|
|
// case VertexType.Default:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypeDefault[]);
|
|
|
|
|
// break; //P,N,C,T
|
|
|
|
|
// case VertexType.DefaultEx:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypeDefaultEx[]);
|
|
|
|
|
// break; //P,N,C,T,Ext
|
|
|
|
|
// case VertexType.PNCCT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTTTT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTTT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCCNCCTTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCTTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCCNCCT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCTTTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCTTTX_2:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX_2[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCTTTX_3:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTTX_3[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCTTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCTTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTTX_2:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTX_2[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTTTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTTTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCCNCCTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCCTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCCNCTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCCNCT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCCNCT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNCCTX:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNCCTX[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PTT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePTT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PNC:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePNC[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PCT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePCT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// case VertexType.PT:
|
|
|
|
|
// VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, v as VertexTypePT[]);
|
|
|
|
|
// break;
|
|
|
|
|
// default:
|
|
|
|
|
// break;
|
|
|
|
|
//}
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DrawableGeom.IndexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, DrawableGeom.IndexBuffer.Indices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Unload()
|
|
|
|
|
{
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding.Buffer = null;
|
|
|
|
|
VertexBuffer.Dispose();
|
|
|
|
|
VertexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (IndexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
IndexBuffer.Dispose();
|
|
|
|
|
IndexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
//DrawableGeom = null;
|
|
|
|
|
|
|
|
|
|
if (RenderableTextures != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < RenderableTextures.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
RenderableTextures[i] = null;
|
|
|
|
|
}
|
|
|
|
|
RenderableTextures = null;
|
|
|
|
|
}
|
2019-01-06 02:04:33 +08:00
|
|
|
|
if (RenderableTexturesHD != null)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < RenderableTexturesHD.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
RenderableTexturesHD[i] = null;
|
|
|
|
|
}
|
|
|
|
|
RenderableTexturesHD = null;
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Render(DeviceContext context)
|
|
|
|
|
{
|
|
|
|
|
if ((VertexBuffer == null) || (IndexBuffer == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.InputAssembler.PrimitiveTopology = Topology;
|
|
|
|
|
context.InputAssembler.SetVertexBuffers(0, VBBinding);
|
|
|
|
|
context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0);
|
|
|
|
|
|
|
|
|
|
context.DrawIndexed(IndexCount, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RenderInstanced(DeviceContext context, int instCount)
|
|
|
|
|
{
|
|
|
|
|
if ((VertexBuffer == null) || (IndexBuffer == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.InputAssembler.PrimitiveTopology = Topology;
|
|
|
|
|
context.InputAssembler.SetVertexBuffers(0, VBBinding);
|
|
|
|
|
context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0);
|
|
|
|
|
|
|
|
|
|
context.DrawIndexedInstanced(IndexCount, instCount, 0, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RenderableTexture : RenderableCacheItem<Texture>
|
|
|
|
|
{
|
|
|
|
|
public uint Hash { get; private set; }
|
|
|
|
|
public string Name { get; private set; }
|
|
|
|
|
public Texture2D Texture2D { get; set; }
|
|
|
|
|
public ShaderResourceView ShaderResourceView { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override void Init(Texture tex)
|
|
|
|
|
{
|
|
|
|
|
Key = tex;
|
|
|
|
|
|
|
|
|
|
if ((Key != null) && (Key.Data != null) && (Key.Data.FullData != null))
|
|
|
|
|
{
|
|
|
|
|
DataSize = Key.Data.FullData.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if ((Key != null) && (Key.Data != null) && (Key.Data.FullData != null))
|
|
|
|
|
{
|
|
|
|
|
using (var stream = DataStream.Create(Key.Data.FullData, true, false))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
var format = TextureFormats.GetDXGIFormat(Key.Format);
|
|
|
|
|
var width = Key.Width;
|
|
|
|
|
var height = Key.Height;
|
|
|
|
|
int mips = Key.Levels;
|
|
|
|
|
int rowpitch, slicepitch;
|
|
|
|
|
var totlength = Key.Data.FullData.Length;
|
|
|
|
|
int pxsize = TextureFormats.ByteSize(Key.Format); // SharpDX.DXGI.FormatHelper.SizeOfInBytes(desc.Format);
|
|
|
|
|
|
|
|
|
|
//get databoxes for mips
|
|
|
|
|
int offset = 0;
|
|
|
|
|
int level = 1;
|
|
|
|
|
List<DataBox> boxes = new List<DataBox>();
|
|
|
|
|
for (int i = 0; i < mips; i++)
|
|
|
|
|
{
|
|
|
|
|
if (offset >= totlength) break; //only load as many mips as there are..
|
|
|
|
|
|
|
|
|
|
var mipw = width / level;
|
|
|
|
|
var miph = height / level;
|
|
|
|
|
|
|
|
|
|
TextureFormats.ComputePitch(format, mipw, miph, out rowpitch, out slicepitch, 0);
|
|
|
|
|
var mipbox = new DataBox(stream.DataPointer + offset, rowpitch, slicepitch);
|
|
|
|
|
boxes.Add(mipbox);
|
|
|
|
|
|
|
|
|
|
offset += slicepitch;
|
|
|
|
|
level *= 2;
|
|
|
|
|
}
|
|
|
|
|
mips = boxes.Count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//single mip..
|
|
|
|
|
//TextureFormats.ComputePitch(format, width, height, out rowpitch, out slicepitch, 0);
|
|
|
|
|
//var box = new DataBox(stream.DataPointer, rowpitch, slicepitch);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var desc = new Texture2DDescription()
|
|
|
|
|
{
|
|
|
|
|
ArraySize = 1,
|
|
|
|
|
BindFlags = BindFlags.ShaderResource,
|
|
|
|
|
CpuAccessFlags = CpuAccessFlags.None,
|
|
|
|
|
Format = format,
|
|
|
|
|
Height = Key.Height,
|
|
|
|
|
MipLevels = mips,//Texture.Levels,
|
|
|
|
|
OptionFlags = ResourceOptionFlags.None,
|
|
|
|
|
SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
|
|
|
|
|
Usage = ResourceUsage.Default,
|
|
|
|
|
Width = Key.Width
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//Texture2D = new Texture2D(device, desc, new[] { box }); //single mip
|
|
|
|
|
Texture2D = new Texture2D(device, desc, boxes.ToArray()); //multiple mips
|
|
|
|
|
ShaderResourceView = new ShaderResourceView(device, Texture2D);
|
|
|
|
|
}
|
|
|
|
|
catch //(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
//string str = ex.ToString(); //todo: don't fail silently..
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetVSResource(DeviceContext context, int slot)
|
|
|
|
|
{
|
|
|
|
|
context.VertexShader.SetShaderResource(slot, ShaderResourceView);
|
|
|
|
|
//LastUseTime = DateTime.Now;
|
|
|
|
|
}
|
|
|
|
|
public void SetPSResource(DeviceContext context, int slot)
|
|
|
|
|
{
|
|
|
|
|
context.PixelShader.SetShaderResource(slot, ShaderResourceView);
|
|
|
|
|
//LastUseTime = DateTime.Now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (ShaderResourceView != null)
|
|
|
|
|
{
|
|
|
|
|
ShaderResourceView.Dispose();
|
|
|
|
|
ShaderResourceView = null;
|
|
|
|
|
}
|
|
|
|
|
if (Texture2D != null)
|
|
|
|
|
{
|
|
|
|
|
Texture2D.Dispose();
|
|
|
|
|
Texture2D = null;
|
|
|
|
|
}
|
|
|
|
|
LoadQueued = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return (Key != null) ? Key.ToString() : base.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-05 00:40:52 +08:00
|
|
|
|
public class RenderableLight
|
|
|
|
|
{
|
|
|
|
|
public Renderable Owner;
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
public Vector3 Colour;
|
|
|
|
|
public Vector3 Direction;
|
|
|
|
|
public Vector3 TangentX;
|
|
|
|
|
public Vector3 TangentY;
|
|
|
|
|
public LightType Type;
|
|
|
|
|
public float Intensity;
|
|
|
|
|
public float Falloff;
|
|
|
|
|
public float FalloffExponent;
|
|
|
|
|
public float ConeInnerAngle;
|
|
|
|
|
public float ConeOuterAngle;
|
|
|
|
|
public Vector3 CapsuleExtent;
|
|
|
|
|
public Vector3 CullingPlaneNormal;
|
|
|
|
|
public float CullingPlaneOffset;
|
|
|
|
|
public uint TimeFlags;
|
|
|
|
|
public MetaHash TextureHash;
|
|
|
|
|
|
|
|
|
|
public void Init(ref LightAttributes_s l)
|
|
|
|
|
{
|
|
|
|
|
Position = l.Position;
|
|
|
|
|
Colour = new Vector3(l.ColorR, l.ColorG, l.ColorB) * ((l.Intensity * 5.0f) / 255.0f);
|
|
|
|
|
Direction = l.Direction;
|
|
|
|
|
TangentX = l.Tangent;
|
|
|
|
|
TangentY = Vector3.Cross(l.Direction, l.Tangent);
|
|
|
|
|
Type = l.Type;
|
|
|
|
|
Intensity = l.Intensity;
|
|
|
|
|
Falloff = l.Falloff;
|
2019-12-05 12:04:00 +08:00
|
|
|
|
FalloffExponent = Math.Max(l.FalloffExponent * 0.25f, 0.5f);//is this right?
|
|
|
|
|
ConeInnerAngle = l.ConeInnerAngle * 0.01745329f; //is this right??
|
|
|
|
|
ConeOuterAngle = l.ConeOuterAngle * 0.01745329f; //pi/180
|
2019-12-05 00:40:52 +08:00
|
|
|
|
CapsuleExtent = l.Extent;
|
|
|
|
|
CullingPlaneNormal = l.CullingPlaneNormal;
|
|
|
|
|
CullingPlaneOffset = l.CullingPlaneOffset;
|
|
|
|
|
TimeFlags = l.TimeFlags;
|
|
|
|
|
TextureHash = l.ProjectedTextureHash;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
public class RenderableInstanceBatch : RenderableCacheItem<YmapGrassInstanceBatch>
|
|
|
|
|
{
|
|
|
|
|
public rage__fwGrassInstanceListDef__InstanceData[] GrassInstanceData { get; set; }
|
|
|
|
|
public GpuSBuffer<rage__fwGrassInstanceListDef__InstanceData> GrassInstanceBuffer { get; set; }
|
|
|
|
|
public int InstanceCount { get; set; }
|
2018-12-07 10:41:18 +08:00
|
|
|
|
public Vector3 AABBMin { get; set; }
|
|
|
|
|
public Vector3 AABBMax { get; set; }
|
|
|
|
|
public Vector3 Position { get; set; }
|
|
|
|
|
public Vector3 CamRel { get; set; }
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
public override void Init(YmapGrassInstanceBatch batch)
|
|
|
|
|
{
|
|
|
|
|
Key = batch;
|
|
|
|
|
if (batch.Instances == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InstanceCount = batch.Instances.Length;
|
|
|
|
|
|
|
|
|
|
DataSize = (InstanceCount * 16);
|
|
|
|
|
|
|
|
|
|
GrassInstanceData = batch.Instances;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
2018-12-07 10:41:18 +08:00
|
|
|
|
if (Key != null)
|
|
|
|
|
{
|
|
|
|
|
AABBMin = Key.AABBMin;
|
|
|
|
|
AABBMax = Key.AABBMax;
|
|
|
|
|
Position = Key.Position;
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
if ((GrassInstanceData != null) && (GrassInstanceData.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
GrassInstanceBuffer = new GpuSBuffer<rage__fwGrassInstanceListDef__InstanceData>(device, GrassInstanceData);
|
|
|
|
|
}
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (GrassInstanceBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
GrassInstanceBuffer.Dispose();
|
|
|
|
|
GrassInstanceBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
LoadQueued = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-03 21:52:22 +08:00
|
|
|
|
|
|
|
|
|
public class RenderableLODLights : RenderableCacheItem<YmapFile>
|
|
|
|
|
{
|
|
|
|
|
public struct LODLight
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
public uint Colour;
|
|
|
|
|
public Vector3 Direction;
|
|
|
|
|
public uint TimeAndStateFlags;
|
|
|
|
|
public Vector4 TangentX;
|
|
|
|
|
public Vector4 TangentY;
|
|
|
|
|
public float Falloff;
|
|
|
|
|
public float FalloffExponent;
|
|
|
|
|
public float InnerAngle;//for cone
|
|
|
|
|
public float OuterAngleOrCapExt;//outer angle for cone, cap extent for capsule
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public LODLight[] Points;
|
|
|
|
|
public LODLight[] Spots;
|
|
|
|
|
public LODLight[] Caps;
|
|
|
|
|
|
|
|
|
|
public GpuSBuffer<LODLight> PointsBuffer { get; set; }
|
|
|
|
|
public GpuSBuffer<LODLight> SpotsBuffer { get; set; }
|
|
|
|
|
public GpuSBuffer<LODLight> CapsBuffer { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override void Init(YmapFile key)
|
|
|
|
|
{
|
|
|
|
|
Key = key;
|
|
|
|
|
|
|
|
|
|
var ll = key.LODLights;
|
|
|
|
|
var dll = key.Parent?.DistantLODLights;
|
|
|
|
|
|
|
|
|
|
if (ll == null) return;
|
|
|
|
|
if (dll == null) return;
|
|
|
|
|
|
|
|
|
|
var n = dll.positions?.Length ?? 0;
|
|
|
|
|
n = Math.Min(n, dll.colours?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.direction?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.falloff?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.falloffExponent?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.timeAndStateFlags?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.hash?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.coneInnerAngle?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.coneOuterAngleOrCapExt?.Length ?? 0);
|
|
|
|
|
n = Math.Min(n, ll.coronaIntensity?.Length ?? 0);
|
|
|
|
|
|
|
|
|
|
if (n <= 0)
|
|
|
|
|
{ return; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var points = new List<LODLight>();
|
|
|
|
|
var spots = new List<LODLight>();
|
|
|
|
|
var caps = new List<LODLight>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
var light = new LODLight();
|
|
|
|
|
light.Position = dll.positions[i].ToVector3();
|
|
|
|
|
light.Colour = dll.colours[i];
|
|
|
|
|
light.Direction = ll.direction[i].ToVector3();
|
|
|
|
|
light.TimeAndStateFlags = ll.timeAndStateFlags[i];
|
|
|
|
|
light.TangentX = new Vector4(Vector3.Normalize(light.Direction.GetPerpVec()), 0.0f);
|
|
|
|
|
light.TangentY = new Vector4(Vector3.Cross(light.Direction, light.TangentX.XYZ()), 0.0f);
|
|
|
|
|
light.Falloff = ll.falloff[i];
|
2019-12-03 23:47:20 +08:00
|
|
|
|
light.FalloffExponent = Math.Max(ll.falloffExponent[i]*0.01f, 0.5f);//is this right?
|
2019-12-05 12:04:00 +08:00
|
|
|
|
light.InnerAngle = ll.coneInnerAngle[i] * 0.0087266462f; //pi/360
|
|
|
|
|
light.OuterAngleOrCapExt = ll.coneOuterAngleOrCapExt[i] * 0.0087266462f; //pi/360
|
2019-12-03 21:52:22 +08:00
|
|
|
|
var type = (LightType)((light.TimeAndStateFlags >> 26) & 7);
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case LightType.Point:
|
|
|
|
|
points.Add(light);
|
|
|
|
|
break;
|
|
|
|
|
case LightType.Spot:
|
|
|
|
|
spots.Add(light);
|
|
|
|
|
break;
|
|
|
|
|
case LightType.Capsule:
|
2019-12-12 19:21:18 +08:00
|
|
|
|
light.OuterAngleOrCapExt = ll.coneOuterAngleOrCapExt[i] * 0.25f;
|
2019-12-03 21:52:22 +08:00
|
|
|
|
caps.Add(light);
|
|
|
|
|
break;
|
|
|
|
|
default: break;//just checking...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Points = points.ToArray();
|
|
|
|
|
Spots = spots.ToArray();
|
|
|
|
|
Caps = caps.ToArray();
|
|
|
|
|
|
2019-12-11 22:32:07 +08:00
|
|
|
|
DataSize = (points.Count + spots.Count + caps.Count) * 80;
|
|
|
|
|
|
2019-12-03 21:52:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if ((Points != null) && (Points.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
PointsBuffer = new GpuSBuffer<LODLight>(device, Points);
|
|
|
|
|
}
|
|
|
|
|
if ((Spots != null) && (Spots.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
SpotsBuffer = new GpuSBuffer<LODLight>(device, Spots);
|
|
|
|
|
}
|
|
|
|
|
if ((Caps != null) && (Caps.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
CapsBuffer = new GpuSBuffer<LODLight>(device, Caps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
|
|
|
|
|
if (PointsBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
PointsBuffer.Dispose();
|
|
|
|
|
PointsBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (SpotsBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
SpotsBuffer.Dispose();
|
|
|
|
|
SpotsBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (CapsBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
CapsBuffer.Dispose();
|
|
|
|
|
CapsBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public class RenderableDistantLODLights : RenderableCacheItem<YmapDistantLODLights>
|
|
|
|
|
{
|
|
|
|
|
public struct DistLODLight
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Position;
|
|
|
|
|
public uint Colour;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DistLODLight[] InstanceData { get; set; }
|
|
|
|
|
public GpuSBuffer<DistLODLight> InstanceBuffer { get; set; }
|
|
|
|
|
public int InstanceCount { get; set; }
|
|
|
|
|
public ushort Category { get; set; }
|
|
|
|
|
public ushort NumStreetLights { get; set; }
|
|
|
|
|
public RenderableTexture Texture { get; set; }
|
|
|
|
|
|
|
|
|
|
public override void Init(YmapDistantLODLights key)
|
|
|
|
|
{
|
|
|
|
|
Key = key;
|
|
|
|
|
if ((key.positions == null) || (key.colours == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InstanceCount = Math.Min(key.positions.Length, key.colours.Length);
|
|
|
|
|
|
|
|
|
|
DataSize = InstanceCount * 16;
|
|
|
|
|
|
|
|
|
|
InstanceData = new DistLODLight[InstanceCount];
|
|
|
|
|
for (int i = 0; i < InstanceCount; i++)
|
|
|
|
|
{
|
|
|
|
|
InstanceData[i].Position = key.positions[i].ToVector3();
|
|
|
|
|
InstanceData[i].Colour = key.colours[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Category = key.CDistantLODLight.category;
|
|
|
|
|
NumStreetLights = key.CDistantLODLight.numStreetLights;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if ((InstanceData != null) && (InstanceData.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
InstanceBuffer = new GpuSBuffer<DistLODLight>(device, InstanceData);
|
|
|
|
|
}
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (InstanceBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
InstanceBuffer.Dispose();
|
|
|
|
|
InstanceBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class RenderablePathBatch : RenderableCacheItem<BasePathData>
|
|
|
|
|
{
|
|
|
|
|
public int VertexStride { get { return 16; } }
|
|
|
|
|
|
2017-12-14 19:45:43 +08:00
|
|
|
|
public EditorVertex[] PathVertices;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public int PathVertexCount { get; set; }
|
|
|
|
|
public Buffer PathVertexBuffer { get; set; }
|
|
|
|
|
public VertexBufferBinding PathVBBinding;
|
|
|
|
|
|
2017-12-14 19:45:43 +08:00
|
|
|
|
public EditorVertex[] TriangleVertices;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public int TriangleVertexCount { get; set; }
|
|
|
|
|
public Buffer TriangleVertexBuffer { get; set; }
|
|
|
|
|
public VertexBufferBinding TriangleVBBinding;
|
|
|
|
|
|
|
|
|
|
public Vector4[] Nodes;
|
|
|
|
|
public GpuSBuffer<Vector4> NodeBuffer { get; set; }
|
|
|
|
|
|
|
|
|
|
public override void Init(BasePathData key)
|
|
|
|
|
{
|
|
|
|
|
Key = key;
|
|
|
|
|
|
|
|
|
|
DataSize = 0;
|
|
|
|
|
PathVertices = key.GetPathVertices();
|
|
|
|
|
if (PathVertices != null)
|
|
|
|
|
{
|
|
|
|
|
PathVertexCount = PathVertices.Length;
|
|
|
|
|
DataSize = PathVertices.Length * VertexStride;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TriangleVertices = key.GetTriangleVertices();
|
|
|
|
|
if (TriangleVertices != null)
|
|
|
|
|
{
|
|
|
|
|
TriangleVertexCount = TriangleVertices.Length;
|
|
|
|
|
DataSize += TriangleVertices.Length * VertexStride;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Nodes = key.GetNodePositions();
|
|
|
|
|
if (Nodes != null)
|
|
|
|
|
{
|
|
|
|
|
DataSize += Nodes.Length * 16;//sizeof(Vector4)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if ((PathVertices != null) && (PathVertices.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
PathVertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, PathVertices);
|
|
|
|
|
if (PathVertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
PathVBBinding = new VertexBufferBinding(PathVertexBuffer, VertexStride, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((TriangleVertices != null) && (TriangleVertices.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
TriangleVertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, TriangleVertices);
|
|
|
|
|
if (TriangleVertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
TriangleVBBinding = new VertexBufferBinding(TriangleVertexBuffer, VertexStride, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((Nodes != null) && (Nodes.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
NodeBuffer = new GpuSBuffer<Vector4>(device, Nodes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (PathVertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
PathVBBinding.Buffer = null;
|
|
|
|
|
PathVertexBuffer.Dispose();
|
|
|
|
|
PathVertexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (TriangleVertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
TriangleVBBinding.Buffer = null;
|
|
|
|
|
TriangleVertexBuffer.Dispose();
|
|
|
|
|
TriangleVertexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (NodeBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
NodeBuffer.Dispose();
|
|
|
|
|
NodeBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class RenderableWaterQuad : RenderableCacheItem<WaterQuad>
|
|
|
|
|
{
|
|
|
|
|
public VertexTypePCT[] Vertices;
|
|
|
|
|
public uint[] Indices;
|
|
|
|
|
public int IndexCount { get; set; }
|
|
|
|
|
public int VertexCount { get; set; }
|
|
|
|
|
public int VertexStride { get; set; } = 24;
|
|
|
|
|
public Buffer VertexBuffer { get; set; }
|
|
|
|
|
public Buffer IndexBuffer { get; set; }
|
|
|
|
|
public VertexBufferBinding VBBinding;
|
|
|
|
|
public Vector3 CamRel { get; set; } //verts are in world space, so camrel should just be -campos
|
|
|
|
|
|
|
|
|
|
public override void Init(WaterQuad key)
|
|
|
|
|
{
|
|
|
|
|
Key = key;
|
|
|
|
|
|
|
|
|
|
float sx = key.maxX - key.minX;
|
|
|
|
|
float sy = key.maxY - key.minY;
|
|
|
|
|
|
|
|
|
|
VertexCount = 4;
|
|
|
|
|
Vertices = new VertexTypePCT[4];
|
|
|
|
|
Vertices[0].Position = new Vector3(key.minX, key.minY, key.z);
|
|
|
|
|
Vertices[0].Texcoord = new Vector2(0.0f, 0.0f);
|
|
|
|
|
Vertices[0].Colour = (uint)new Color4(key.a1 / 255.0f).ToRgba();
|
|
|
|
|
Vertices[1].Position = new Vector3(key.maxX, key.minY, key.z);
|
|
|
|
|
Vertices[1].Texcoord = new Vector2(sx, 0.0f);
|
|
|
|
|
Vertices[1].Colour = (uint)new Color4(key.a2 / 255.0f).ToRgba();
|
|
|
|
|
Vertices[2].Position = new Vector3(key.minX, key.maxY, key.z);
|
|
|
|
|
Vertices[2].Texcoord = new Vector2(0.0f, sy);
|
|
|
|
|
Vertices[2].Colour = (uint)new Color4(key.a3 / 255.0f).ToRgba();
|
|
|
|
|
Vertices[3].Position = new Vector3(key.maxX, key.maxY, key.z);
|
|
|
|
|
Vertices[3].Texcoord = new Vector2(sx, sy);
|
|
|
|
|
Vertices[3].Colour = (uint)new Color4(key.a4 / 255.0f).ToRgba();
|
|
|
|
|
|
|
|
|
|
if (key.Type == 0)
|
|
|
|
|
{
|
|
|
|
|
IndexCount = 6;
|
|
|
|
|
Indices = new uint[6];
|
|
|
|
|
Indices[0] = 0;
|
|
|
|
|
Indices[1] = 2;
|
|
|
|
|
Indices[2] = 1;
|
|
|
|
|
Indices[3] = 1;
|
|
|
|
|
Indices[4] = 2;
|
|
|
|
|
Indices[5] = 3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
IndexCount = 3;
|
|
|
|
|
Indices = new uint[3];
|
|
|
|
|
switch (key.Type)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
Indices[0] = 0;
|
|
|
|
|
Indices[1] = 1;
|
|
|
|
|
Indices[2] = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
Indices[0] = 0;
|
|
|
|
|
Indices[1] = 3;
|
|
|
|
|
Indices[2] = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
Indices[0] = 1;
|
|
|
|
|
Indices[1] = 3;
|
|
|
|
|
Indices[2] = 2;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
Indices[0] = 0;
|
|
|
|
|
Indices[1] = 1;
|
|
|
|
|
Indices[2] = 3;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//shouldn't ever get here...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataSize = VertexCount * VertexStride + IndexCount * 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
if ((Vertices != null) && (Vertices.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, Vertices);
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ((Indices != null) && (Indices.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, Indices);
|
|
|
|
|
}
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding.Buffer = null;
|
|
|
|
|
VertexBuffer.Dispose();
|
|
|
|
|
VertexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (IndexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
IndexBuffer.Dispose();
|
|
|
|
|
IndexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
LoadQueued = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Render(DeviceContext context)
|
|
|
|
|
{
|
|
|
|
|
if ((VertexBuffer == null) || (IndexBuffer == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
|
|
|
|
|
context.InputAssembler.SetVertexBuffers(0, VBBinding);
|
|
|
|
|
context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R32_UInt, 0);
|
|
|
|
|
|
|
|
|
|
context.DrawIndexed(IndexCount, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-12-09 14:06:59 +08:00
|
|
|
|
public class RenderableBoundComposite : RenderableCacheItem<Bounds>
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
|
|
|
|
public RenderableBoundGeometry[] Geometries;
|
|
|
|
|
|
|
|
|
|
|
2019-12-09 14:06:59 +08:00
|
|
|
|
public override void Init(Bounds bound)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
|
|
|
|
Key = bound;
|
|
|
|
|
|
2019-12-09 14:06:59 +08:00
|
|
|
|
if (bound is BoundComposite boundcomp)
|
|
|
|
|
{
|
|
|
|
|
InitBoundComp(boundcomp);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var rgeom = new RenderableBoundGeometry(this);
|
|
|
|
|
var xform = Matrix.Identity;
|
|
|
|
|
if (bound is BoundBox boundbox)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(boundbox, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (bound is BoundSphere boundsph)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(boundsph, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (bound is BoundCylinder boundcyl)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(boundcyl, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (bound is BoundCapsule boundcap)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(boundcap, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (bound is BoundDisc boundisc)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(boundisc, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
Geometries = new[] { rgeom };
|
|
|
|
|
DataSize = 64;//just a guesstimate
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitBoundComp(BoundComposite bound)
|
|
|
|
|
{
|
2017-09-21 18:33:05 +08:00
|
|
|
|
if (bound.Children == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RenderableBoundGeometry[] geoms = new RenderableBoundGeometry[bound.Children.data_items.Length];
|
|
|
|
|
long dsize = 0;
|
|
|
|
|
for (int i = 0; i < bound.Children.data_items.Length; i++)
|
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
var rgeom = new RenderableBoundGeometry(this);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
var child = bound.Children.data_items[i];
|
2019-12-10 15:33:45 +08:00
|
|
|
|
var xform = (child != null) ? child.Transform : Matrix.Identity;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
if (child is BoundGeometry bgeom)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rgeom.Init(bgeom);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
2019-12-09 14:06:59 +08:00
|
|
|
|
else if (child is BoundCapsule bcap)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rgeom.Init(bcap, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (child is BoundSphere bsph)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(bsph, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (child is BoundBox bbox)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(bbox, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (child is BoundCylinder bcyl)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(bcyl, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (child is BoundDisc bdisc)
|
|
|
|
|
{
|
|
|
|
|
rgeom.Init(bdisc, ref xform);
|
|
|
|
|
}
|
|
|
|
|
else if (child != null)
|
|
|
|
|
{ }
|
|
|
|
|
if (rgeom.Initialised)
|
|
|
|
|
{
|
|
|
|
|
geoms[i] = rgeom;
|
|
|
|
|
dsize += rgeom.TotalDataSize;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Geometries = geoms;
|
|
|
|
|
|
|
|
|
|
DataSize = dsize;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Load(Device device)
|
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
if (Geometries != null)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
foreach (var geom in Geometries)
|
|
|
|
|
{
|
|
|
|
|
if (geom == null) continue;
|
|
|
|
|
geom.Load(device);
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
//LastUseTime = DateTime.Now; //reset usage timer
|
|
|
|
|
IsLoaded = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Unload()
|
|
|
|
|
{
|
|
|
|
|
IsLoaded = false;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
if (Geometries != null)
|
2017-09-21 18:33:05 +08:00
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
foreach (var geom in Geometries)
|
|
|
|
|
{
|
|
|
|
|
if (geom == null) continue;
|
|
|
|
|
geom.Unload();
|
|
|
|
|
}
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
|
|
|
|
LoadQueued = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return Key.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RenderableBoundGeometry
|
|
|
|
|
{
|
|
|
|
|
public RenderableBoundComposite Owner;
|
|
|
|
|
public Buffer VertexBuffer { get; set; }
|
|
|
|
|
//public Buffer IndexBuffer { get; set; }
|
|
|
|
|
public VertexBufferBinding VBBinding;
|
|
|
|
|
public VertexType VertexType { get; set; } = VertexType.Default;
|
|
|
|
|
public int VertexStride { get; set; } = 36;
|
|
|
|
|
public int VertexCount { get; set; } = 0;
|
|
|
|
|
public uint VertexDataSize { get; set; } = 0;
|
|
|
|
|
public uint TotalDataSize { get; set; } = 0;
|
|
|
|
|
public VertexTypeDefault[] Vertices { get; set; }
|
|
|
|
|
|
|
|
|
|
public RenderableBox[] Boxes { get; set; }
|
|
|
|
|
public RenderableSphere[] Spheres { get; set; }
|
|
|
|
|
public RenderableCapsule[] Capsules { get; set; }
|
|
|
|
|
public RenderableCylinder[] Cylinders { get; set; }
|
|
|
|
|
public GpuSBuffer<RenderableBox> BoxBuffer { get; set; }
|
|
|
|
|
public GpuSBuffer<RenderableSphere> SphereBuffer { get; set; }
|
|
|
|
|
public GpuSBuffer<RenderableCapsule> CapsuleBuffer { get; set; }
|
|
|
|
|
public GpuSBuffer<RenderableCylinder> CylinderBuffer { get; set; }
|
|
|
|
|
|
2019-12-09 14:06:59 +08:00
|
|
|
|
|
|
|
|
|
public Bounds Bound;
|
|
|
|
|
public BoundGeometry BoundGeom;
|
|
|
|
|
public Vector3 CenterGeom;
|
|
|
|
|
public Vector3 BBMin;
|
|
|
|
|
public Vector3 BBMax;
|
|
|
|
|
public Vector3 BBOffset = Vector3.Zero;
|
|
|
|
|
public Quaternion BBOrientation = Quaternion.Identity;
|
|
|
|
|
|
|
|
|
|
public bool Initialised = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public RenderableBoundGeometry(RenderableBoundComposite owner)
|
|
|
|
|
{
|
|
|
|
|
Owner = owner;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
public void Init(BoundGeometry bgeom)
|
|
|
|
|
{
|
2019-12-09 14:06:59 +08:00
|
|
|
|
Bound = bgeom;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
BoundGeom = bgeom;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
CenterGeom = bgeom.CenterGeom;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bgeom.BoxMin;
|
|
|
|
|
BBMax = bgeom.BoxMax;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
if ((bgeom.Polygons == null) || (bgeom.Vertices == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 19:50:23 +08:00
|
|
|
|
//Vector3 vbox = (bgeom.BoxMax - bgeom.BoxMin);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
//var verts = bgeom.Vertices;
|
|
|
|
|
//int vertcount = bgeom.Vertices.Length;
|
|
|
|
|
|
|
|
|
|
int rvertcount = 0, curvert = 0;
|
|
|
|
|
int rboxcount = 0, curbox = 0;
|
|
|
|
|
int rspherecount = 0, cursphere = 0;
|
|
|
|
|
int rcapsulecount = 0, curcapsule = 0;
|
|
|
|
|
int rcylindercount = 0, curcylinder = 0;
|
|
|
|
|
for (int i = 0; i < bgeom.Polygons.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (bgeom.Polygons[i] == null) continue;
|
|
|
|
|
var type = bgeom.Polygons[i].Type;
|
|
|
|
|
switch(type)
|
|
|
|
|
{
|
|
|
|
|
case BoundPolygonType.Triangle: rvertcount += 3;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Sphere: rspherecount++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Capsule: rcapsulecount++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Box: rboxcount++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Cylinder: rcylindercount++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VertexTypeDefault[] rverts = (rvertcount > 0) ? new VertexTypeDefault[rvertcount] : null;
|
|
|
|
|
RenderableBox[] rboxes = (rboxcount > 0) ? new RenderableBox[rboxcount] : null;
|
|
|
|
|
RenderableSphere[] rspheres = (rspherecount > 0) ? new RenderableSphere[rspherecount] : null;
|
|
|
|
|
RenderableCapsule[] rcapsules = (rcapsulecount > 0) ? new RenderableCapsule[rcapsulecount] : null;
|
|
|
|
|
RenderableCylinder[] rcylinders = (rcylindercount > 0) ? new RenderableCylinder[rcylindercount] : null;
|
|
|
|
|
for (int i = 0; i < bgeom.Polygons.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var poly = bgeom.Polygons[i];
|
|
|
|
|
if (poly == null) continue;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BoundMaterial_s mat = poly.Material;
|
2018-04-03 20:27:15 +08:00
|
|
|
|
Color color = BoundsMaterialTypes.GetMaterialColour(mat.Type);
|
2017-09-21 18:33:05 +08:00
|
|
|
|
Vector3 p1, p2, p3, p4, a1, n1;//, n2, n3, p5, p7, p8;
|
|
|
|
|
Vector3 norm = Vector3.Zero;
|
|
|
|
|
uint colour = (uint)color.ToRgba();
|
|
|
|
|
switch (poly.Type)
|
|
|
|
|
{
|
|
|
|
|
case BoundPolygonType.Triangle:
|
|
|
|
|
var ptri = poly as BoundPolygonTriangle;
|
|
|
|
|
p1 = bgeom.GetVertex(ptri.vertIndex1);
|
|
|
|
|
p2 = bgeom.GetVertex(ptri.vertIndex2);
|
|
|
|
|
p3 = bgeom.GetVertex(ptri.vertIndex3);
|
|
|
|
|
n1 = Vector3.Normalize(Vector3.Cross(p2 - p1, p3 - p1));
|
|
|
|
|
AddVertex(p1, n1, colour, rverts, ref curvert);
|
|
|
|
|
AddVertex(p2, n1, colour, rverts, ref curvert);
|
|
|
|
|
AddVertex(p3, n1, colour, rverts, ref curvert);
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Sphere:
|
|
|
|
|
var psph = poly as BoundPolygonSphere;
|
|
|
|
|
rspheres[cursphere].Center = bgeom.GetVertex(psph.sphereIndex);
|
|
|
|
|
rspheres[cursphere].Radius = psph.sphereRadius;// * 0.5f;//diameter?
|
|
|
|
|
rspheres[cursphere].Colour = colour;
|
|
|
|
|
cursphere++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Capsule:
|
|
|
|
|
var bcap = poly as BoundPolygonCapsule;
|
|
|
|
|
p1 = bgeom.GetVertex(bcap.capsuleIndex1);
|
|
|
|
|
p2 = bgeom.GetVertex(bcap.capsuleIndex2);
|
|
|
|
|
a1 = p2 - p1;
|
|
|
|
|
n1 = Vector3.Normalize(a1);
|
2019-12-03 21:52:22 +08:00
|
|
|
|
p3 = Vector3.Normalize(n1.GetPerpVec());
|
2017-09-21 18:33:05 +08:00
|
|
|
|
//p4 = Vector3.Normalize(Vector3.Cross(n1, p3));
|
|
|
|
|
Quaternion q1 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1));
|
|
|
|
|
rcapsules[curcapsule].Point1 = p1;
|
|
|
|
|
rcapsules[curcapsule].Orientation = q1;
|
|
|
|
|
rcapsules[curcapsule].Length = a1.Length();
|
|
|
|
|
rcapsules[curcapsule].Radius = bcap.capsuleRadius;// * 0.5f;//diameter?
|
|
|
|
|
rcapsules[curcapsule].Colour = colour;
|
|
|
|
|
curcapsule++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Box: //(...only 4 inds... = diagonal corners)
|
|
|
|
|
var pbox = poly as BoundPolygonBox;
|
|
|
|
|
p1 = bgeom.GetVertex(pbox.boxIndex1);
|
|
|
|
|
p2 = bgeom.GetVertex(pbox.boxIndex2);
|
|
|
|
|
p3 = bgeom.GetVertex(pbox.boxIndex3);
|
|
|
|
|
p4 = bgeom.GetVertex(pbox.boxIndex4);
|
|
|
|
|
a1 = ((p3 + p4) - (p1 + p2)) * 0.5f;
|
|
|
|
|
p2 = p1 + a1;
|
|
|
|
|
p3 = p3 - a1;
|
|
|
|
|
p4 = p4 - a1;
|
|
|
|
|
rboxes[curbox].Corner = p1;
|
|
|
|
|
rboxes[curbox].Edge1 = (p2 - p1);
|
|
|
|
|
rboxes[curbox].Edge2 = (p3 - p1);
|
|
|
|
|
rboxes[curbox].Edge3 = (p4 - p1);
|
|
|
|
|
rboxes[curbox].Colour = colour;
|
|
|
|
|
curbox++;
|
|
|
|
|
break;
|
|
|
|
|
case BoundPolygonType.Cylinder:
|
|
|
|
|
var pcyl = poly as BoundPolygonCylinder;
|
|
|
|
|
p1 = bgeom.GetVertex(pcyl.cylinderIndex1);
|
|
|
|
|
p2 = bgeom.GetVertex(pcyl.cylinderIndex2);
|
|
|
|
|
a1 = p2 - p1;
|
|
|
|
|
n1 = Vector3.Normalize(a1);
|
2019-12-03 21:52:22 +08:00
|
|
|
|
p3 = Vector3.Normalize(n1.GetPerpVec());
|
2017-09-21 18:33:05 +08:00
|
|
|
|
//p4 = Vector3.Normalize(Vector3.Cross(n1, p3));
|
|
|
|
|
Quaternion q2 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1));
|
|
|
|
|
rcylinders[curcylinder].Point1 = p1;
|
|
|
|
|
rcylinders[curcylinder].Orientation = q2;
|
|
|
|
|
rcylinders[curcylinder].Length = a1.Length();
|
|
|
|
|
rcylinders[curcylinder].Radius = pcyl.cylinderRadius;
|
|
|
|
|
rcylinders[curcylinder].Colour = colour;
|
|
|
|
|
curcylinder++;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vertices = rverts;
|
|
|
|
|
VertexCount = (rverts!=null) ? rverts.Length : 0;
|
|
|
|
|
|
|
|
|
|
Boxes = rboxes;
|
|
|
|
|
Spheres = rspheres;
|
|
|
|
|
Capsules = rcapsules;
|
|
|
|
|
Cylinders = rcylinders;
|
|
|
|
|
|
|
|
|
|
VertexDataSize = (uint)(VertexCount * VertexStride);
|
|
|
|
|
TotalDataSize = VertexDataSize;
|
|
|
|
|
|
2019-12-09 14:06:59 +08:00
|
|
|
|
Initialised = true;
|
2017-09-21 18:33:05 +08:00
|
|
|
|
}
|
2019-12-09 14:06:59 +08:00
|
|
|
|
public void Init(BoundCapsule bcap, ref Matrix xform)
|
|
|
|
|
{
|
|
|
|
|
Matrix rmat = xform;
|
|
|
|
|
rmat.TranslationVector = Vector3.Zero;
|
|
|
|
|
|
|
|
|
|
Bound = bcap;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bcap.BoxMin;
|
|
|
|
|
BBMax = bcap.BoxMax;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
BBOffset = xform.TranslationVector;
|
|
|
|
|
BBOrientation = Quaternion.RotationMatrix(rmat);
|
|
|
|
|
|
|
|
|
|
var mat = (BoundsMaterialType)bcap.MaterialIndex;
|
|
|
|
|
var colourf = BoundsMaterialTypes.GetMaterialColour(mat);
|
|
|
|
|
var colour = (uint)colourf.ToRgba();
|
|
|
|
|
|
2020-01-03 19:50:23 +08:00
|
|
|
|
float extent = bcap.SphereRadius - bcap.Margin;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
|
|
|
|
|
var rcap = new RenderableCapsule();
|
|
|
|
|
rcap.Colour = colour;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rcap.Point1 = Vector3.TransformCoordinate(bcap.SphereCenter - new Vector3(0, extent, 0), xform);
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rcap.Orientation = BBOrientation;
|
|
|
|
|
rcap.Length = extent * 2.0f;
|
|
|
|
|
rcap.Radius = bcap.Margin;
|
|
|
|
|
|
|
|
|
|
Capsules = new[] { rcap };
|
|
|
|
|
|
|
|
|
|
Initialised = true;
|
|
|
|
|
}
|
|
|
|
|
public void Init(BoundSphere bsph, ref Matrix xform)
|
|
|
|
|
{
|
|
|
|
|
Bound = bsph;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bsph.BoxMin;
|
|
|
|
|
BBMax = bsph.BoxMax;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
BBOffset = xform.TranslationVector;
|
|
|
|
|
|
|
|
|
|
var mat = (BoundsMaterialType)bsph.MaterialIndex;
|
|
|
|
|
var colourf = BoundsMaterialTypes.GetMaterialColour(mat);
|
|
|
|
|
var colour = (uint)colourf.ToRgba();
|
|
|
|
|
|
|
|
|
|
var rsph = new RenderableSphere();
|
|
|
|
|
rsph.Colour = colour;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rsph.Center = Vector3.TransformCoordinate(bsph.SphereCenter, xform);
|
|
|
|
|
rsph.Radius = bsph.SphereRadius;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
|
|
|
|
|
Spheres = new[] { rsph };
|
|
|
|
|
|
|
|
|
|
Initialised = true;
|
|
|
|
|
}
|
|
|
|
|
public void Init(BoundBox bbox, ref Matrix xform)
|
|
|
|
|
{
|
|
|
|
|
Matrix rmat = xform;
|
|
|
|
|
rmat.TranslationVector = Vector3.Zero;
|
|
|
|
|
|
|
|
|
|
Bound = bbox;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bbox.BoxMin;
|
|
|
|
|
BBMax = bbox.BoxMax;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
BBOffset = xform.TranslationVector;
|
|
|
|
|
BBOrientation = Quaternion.RotationMatrix(rmat);
|
|
|
|
|
|
|
|
|
|
var mat = (BoundsMaterialType)bbox.MaterialIndex;
|
|
|
|
|
var colourf = BoundsMaterialTypes.GetMaterialColour(mat);
|
|
|
|
|
var colour = (uint)colourf.ToRgba();
|
|
|
|
|
|
2020-01-03 19:50:23 +08:00
|
|
|
|
var extent = (bbox.BoxMax - bbox.BoxMin).Abs();
|
2019-12-09 14:06:59 +08:00
|
|
|
|
|
|
|
|
|
var rbox = new RenderableBox();
|
|
|
|
|
rbox.Colour = colour;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rbox.Corner = Vector3.TransformCoordinate(bbox.BoxMin, xform);
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rbox.Edge1 = Vector3.TransformNormal(new Vector3(extent.X, 0, 0), xform);
|
|
|
|
|
rbox.Edge2 = Vector3.TransformNormal(new Vector3(0, extent.Y, 0), xform);
|
|
|
|
|
rbox.Edge3 = Vector3.TransformNormal(new Vector3(0, 0, extent.Z), xform);
|
|
|
|
|
|
|
|
|
|
Boxes = new[] { rbox };
|
|
|
|
|
|
|
|
|
|
Initialised = true;
|
|
|
|
|
}
|
|
|
|
|
public void Init(BoundCylinder bcyl, ref Matrix xform)
|
|
|
|
|
{
|
|
|
|
|
Matrix rmat = xform;
|
|
|
|
|
rmat.TranslationVector = Vector3.Zero;
|
|
|
|
|
|
|
|
|
|
Bound = bcyl;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bcyl.BoxMin;
|
|
|
|
|
BBMax = bcyl.BoxMax;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
BBOffset = xform.TranslationVector;
|
|
|
|
|
BBOrientation = Quaternion.RotationMatrix(rmat);
|
|
|
|
|
|
|
|
|
|
var mat = (BoundsMaterialType)bcyl.MaterialIndex;
|
|
|
|
|
var colourf = BoundsMaterialTypes.GetMaterialColour(mat);
|
|
|
|
|
var colour = (uint)colourf.ToRgba();
|
|
|
|
|
|
2020-01-03 19:50:23 +08:00
|
|
|
|
var extent = (bcyl.BoxMax - bcyl.BoxMin).Abs();
|
2019-12-09 14:06:59 +08:00
|
|
|
|
var length = extent.Y;
|
|
|
|
|
var radius = extent.X * 0.5f;
|
|
|
|
|
|
|
|
|
|
var rcyl = new RenderableCylinder();
|
|
|
|
|
rcyl.Colour = colour;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rcyl.Point1 = Vector3.TransformCoordinate(bcyl.SphereCenter - new Vector3(0, length * 0.5f, 0), xform);
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rcyl.Orientation = BBOrientation;
|
|
|
|
|
rcyl.Length = length;
|
|
|
|
|
rcyl.Radius = radius;
|
|
|
|
|
|
|
|
|
|
Cylinders = new[] { rcyl };
|
|
|
|
|
|
|
|
|
|
Initialised = true;
|
|
|
|
|
}
|
|
|
|
|
public void Init(BoundDisc bdisc, ref Matrix xform)
|
|
|
|
|
{
|
|
|
|
|
Matrix rmat = xform;
|
|
|
|
|
rmat.TranslationVector = Vector3.Zero;
|
|
|
|
|
|
|
|
|
|
Bound = bdisc;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
BBMin = bdisc.BoxMin;
|
|
|
|
|
BBMax = bdisc.BoxMax;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
BBOffset = xform.TranslationVector;
|
|
|
|
|
BBOrientation = Quaternion.LookAtLH(Vector3.Zero, Vector3.UnitX, Vector3.UnitZ) * Quaternion.RotationMatrix(rmat);
|
|
|
|
|
|
|
|
|
|
var mat = (BoundsMaterialType)bdisc.MaterialIndex;
|
|
|
|
|
var colourf = BoundsMaterialTypes.GetMaterialColour(mat);
|
|
|
|
|
var colour = (uint)colourf.ToRgba();
|
|
|
|
|
|
|
|
|
|
var rcyl = new RenderableCylinder();
|
|
|
|
|
rcyl.Colour = colour;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rcyl.Point1 = Vector3.TransformCoordinate(bdisc.SphereCenter - new Vector3(bdisc.Margin, 0, 0), xform);
|
2019-12-09 14:06:59 +08:00
|
|
|
|
rcyl.Orientation = BBOrientation;
|
|
|
|
|
rcyl.Length = bdisc.Margin * 2.0f;
|
2020-01-03 19:50:23 +08:00
|
|
|
|
rcyl.Radius = bdisc.SphereRadius;
|
2019-12-09 14:06:59 +08:00
|
|
|
|
|
|
|
|
|
Cylinders = new[] { rcyl };
|
|
|
|
|
|
|
|
|
|
Initialised = true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-21 18:33:05 +08:00
|
|
|
|
|
|
|
|
|
private ushort AddVertex(Vector3 pos, Vector3 norm, uint colour, List<VertexTypeDefault> list)
|
|
|
|
|
{
|
|
|
|
|
VertexTypeDefault v = new VertexTypeDefault();
|
|
|
|
|
v.Position = pos;
|
|
|
|
|
v.Normal = norm;
|
|
|
|
|
v.Colour = colour;
|
|
|
|
|
v.Texcoord = Vector2.Zero;
|
|
|
|
|
var rv = list.Count;
|
|
|
|
|
list.Add(v);
|
|
|
|
|
return (ushort)rv;
|
|
|
|
|
}
|
|
|
|
|
private void AddVertex(Vector3 pos, Vector3 norm, uint colour, VertexTypeDefault[] arr, ref int index)
|
|
|
|
|
{
|
|
|
|
|
arr[index].Position = pos;
|
|
|
|
|
arr[index].Normal = norm;
|
|
|
|
|
arr[index].Colour = colour;
|
|
|
|
|
arr[index].Texcoord = Vector2.Zero;
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void Load(Device device)
|
|
|
|
|
{
|
|
|
|
|
//if (Vertices.Length == 0) return; //nothing to see here..
|
|
|
|
|
|
|
|
|
|
if ((Vertices != null) && (Vertices.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, Vertices);
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding = new VertexBufferBinding(VertexBuffer, VertexStride, 0);
|
|
|
|
|
}
|
|
|
|
|
//IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, Indices);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((Boxes != null) && (Boxes.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
BoxBuffer = new GpuSBuffer<RenderableBox>(device, Boxes);
|
|
|
|
|
}
|
|
|
|
|
if ((Spheres != null) && (Spheres.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
SphereBuffer = new GpuSBuffer<RenderableSphere>(device, Spheres);
|
|
|
|
|
}
|
|
|
|
|
if ((Capsules != null) && (Capsules.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
CapsuleBuffer = new GpuSBuffer<RenderableCapsule>(device, Capsules);
|
|
|
|
|
}
|
|
|
|
|
if ((Cylinders != null) && (Cylinders.Length > 0))
|
|
|
|
|
{
|
|
|
|
|
CylinderBuffer = new GpuSBuffer<RenderableCylinder>(device, Cylinders);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Unload()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (VertexBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
VBBinding.Buffer = null;
|
|
|
|
|
VertexBuffer.Dispose();
|
|
|
|
|
VertexBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
//if (IndexBuffer != null)
|
|
|
|
|
//{
|
|
|
|
|
// IndexBuffer.Dispose();
|
|
|
|
|
// IndexBuffer = null;
|
|
|
|
|
//}
|
|
|
|
|
//BoundGeom = null;
|
|
|
|
|
|
|
|
|
|
if (BoxBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
BoxBuffer.Dispose();
|
|
|
|
|
BoxBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (SphereBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
SphereBuffer.Dispose();
|
|
|
|
|
SphereBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (CapsuleBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
CapsuleBuffer.Dispose();
|
|
|
|
|
CapsuleBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
if (CylinderBuffer != null)
|
|
|
|
|
{
|
|
|
|
|
CylinderBuffer.Dispose();
|
|
|
|
|
CylinderBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RenderTriangles(DeviceContext context)
|
|
|
|
|
{
|
|
|
|
|
if ((VertexBuffer == null))// || (IndexBuffer == null))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Owner.LastUseTime = DateTime.Now; //cache timer reset
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
|
|
|
|
|
context.InputAssembler.SetVertexBuffers(0, VBBinding);
|
|
|
|
|
context.InputAssembler.SetIndexBuffer(null, SharpDX.DXGI.Format.R16_UInt, 0);
|
|
|
|
|
//context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R16_UInt, 0);
|
|
|
|
|
|
|
|
|
|
context.Draw(VertexCount, 0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct RenderableBox
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Corner { get; set; }
|
|
|
|
|
public uint Colour { get; set; }
|
|
|
|
|
public Vector3 Edge1 { get; set; }
|
|
|
|
|
public float Pad1 { get; set; }
|
|
|
|
|
public Vector3 Edge2 { get; set; }
|
|
|
|
|
public float Pad2 { get; set; }
|
|
|
|
|
public Vector3 Edge3 { get; set; }
|
|
|
|
|
public float Pad3 { get; set; }
|
|
|
|
|
}
|
|
|
|
|
public struct RenderableSphere
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Center { get; set; }
|
|
|
|
|
public float Radius { get; set; }
|
|
|
|
|
public Vector3 Pad0 { get; set; }
|
|
|
|
|
public uint Colour { get; set; }
|
|
|
|
|
}
|
|
|
|
|
public struct RenderableCapsule
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Point1 { get; set; }
|
|
|
|
|
public float Radius { get; set; }
|
|
|
|
|
public Quaternion Orientation { get; set; }
|
|
|
|
|
public float Length { get; set; }
|
|
|
|
|
public uint Colour { get; set; }
|
|
|
|
|
public float Pad0 { get; set; }
|
|
|
|
|
public float Pad1 { get; set; }
|
|
|
|
|
}
|
|
|
|
|
public struct RenderableCylinder
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Point1 { get; set; }
|
|
|
|
|
public float Radius { get; set; }
|
|
|
|
|
public Quaternion Orientation { get; set; }
|
|
|
|
|
public float Length { get; set; }
|
|
|
|
|
public uint Colour { get; set; }
|
|
|
|
|
public float Pad0 { get; set; }
|
|
|
|
|
public float Pad1 { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public struct RenderableEntity
|
|
|
|
|
{
|
|
|
|
|
public YmapEntityDef Entity;
|
|
|
|
|
public Renderable Renderable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|