Moved entity light hash generation to YmapEntityDef and added Lights array to entity

This commit is contained in:
dexy 2021-05-02 04:57:24 +10:00
parent 384ad0c9cb
commit e18cf990fe
4 changed files with 158 additions and 235 deletions

View File

@ -1681,6 +1681,9 @@ namespace CodeWalker.GameFiles
public object LodManagerRenderable = null;
public LightInstance[] Lights { get; set; }
public string Name
{
get
@ -2069,6 +2072,129 @@ namespace CodeWalker.GameFiles
return _CEntityDef.ToString() + ((ChildList != null) ? (" (" + ChildList.Count.ToString() + " children) ") : " ") + _CEntityDef.lodLevel.ToString();
}
public void EnsureLights(DrawableBase db)
{
if (Lights != null) return;
if (Archetype == null) return;
if (db == null) return;
var dd = db as Drawable;
var fd = db as FragDrawable;
LightAttributes_s[] lightAttrs = null;
Bounds b = null;
if (dd != null)
{
lightAttrs = dd.LightAttributes?.data_items;
b = dd.Bound;
}
else if (fd != null)
{
lightAttrs = fd.OwnerFragment?.LightAttributes?.data_items;
b = fd.OwnerFragment?.PhysicsLODGroup?.PhysicsLOD1?.Bound;
}
if (lightAttrs == null) return;
var abmin = Vector3.Min(Archetype.BBMin, db.BoundingBoxMin);
var abmax = Vector3.Max(Archetype.BBMax, db.BoundingBoxMax);
if (b != null)
{
abmin = Vector3.Min(abmin, b.BoxMin);
abmax = Vector3.Max(abmax, b.BoxMax);
}
var bb = new BoundingBox(abmin, abmax).Transform(Position, Orientation, Scale);
var ints = new uint[7];
ints[0] = (uint)(bb.Minimum.X * 10.0f);
ints[1] = (uint)(bb.Minimum.Y * 10.0f);
ints[2] = (uint)(bb.Minimum.Z * 10.0f);
ints[3] = (uint)(bb.Maximum.X * 10.0f);
ints[4] = (uint)(bb.Maximum.Y * 10.0f);
ints[5] = (uint)(bb.Maximum.Z * 10.0f);
var lightInsts = new LightInstance[lightAttrs.Length];
for (int i = 0; i < lightAttrs.Length; i++)
{
ints[6] = (uint)(i + 1);
var li = new LightInstance();
li.Attributes = lightAttrs[i];
li.Hash = ComputeLightHash(ints);
lightInsts[i] = li;
}
Lights = lightInsts;
}
public static uint ComputeLightHash(uint[] ints, uint seed = 0)
{
var a2 = ints.Length;
var v3 = a2;
var v5 = (uint)(seed + 0xDEADBEEF + 4 * ints.Length);
var v6 = v5;
var v7 = v5;
var c = 0;
for (var i = 0; i < (ints.Length - 4) / 3 + 1; i++, v3 -= 3, c += 3)
{
var v9 = ints[c + 2] + v5;
var v10 = ints[c + 1] + v6;
var v11 = ints[c] - v9;
var v13 = v10 + v9;
var v14 = (v7 + v11) ^ BitUtil.RotateLeft(v9, 4);
var v15 = v10 - v14;
var v17 = v13 + v14;
var v18 = v15 ^ BitUtil.RotateLeft(v14, 6);
var v19 = v13 - v18;
var v21 = v17 + v18;
var v22 = v19 ^ BitUtil.RotateLeft(v18, 8);
var v23 = v17 - v22;
var v25 = v21 + v22;
var v26 = v23 ^ BitUtil.RotateLeft(v22, 16);
var v27 = v21 - v26;
var v29 = v27 ^ BitUtil.RotateRight(v26, 13);
var v30 = v25 - v29;
v7 = v25 + v26;
v6 = v7 + v29;
v5 = v30 ^ BitUtil.RotateLeft(v29, 4);
}
if (v3 == 3)
{
v5 += ints[c + 2];
}
if (v3 >= 2)
{
v6 += ints[c + 1];
}
if (v3 >= 1)
{
var v34 = (v6 ^ v5) - BitUtil.RotateLeft(v6, 14);
var v35 = (v34 ^ (v7 + ints[c])) - BitUtil.RotateLeft(v34, 11);
var v36 = (v35 ^ v6) - BitUtil.RotateRight(v35, 7);
var v37 = (v36 ^ v34) - BitUtil.RotateLeft(v36, 16);
var v38 = BitUtil.RotateLeft(v37, 4);
var v39 = (((v35 ^ v37) - v38) ^ v36) - BitUtil.RotateLeft((v35 ^ v37) - v38, 14);
return (v39 ^ v37) - BitUtil.RotateRight(v39, 8);
}
return v5;
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class LightInstance
{
public LightAttributes_s Attributes { get; set; } //just for display purposes!
public uint Hash { get; set; }
public override string ToString()
{
return Hash.ToString() + ": " + Attributes.Type.ToString();
}
}
}

View File

@ -267,6 +267,14 @@ namespace CodeWalker
if (flag) return SetBit(value, bit);
else return ClearBit(value, bit);
}
public static uint RotateLeft(uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
public static uint RotateRight(uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
}

View File

@ -94,11 +94,6 @@ namespace CodeWalker.Project.Panels
{
var lights = new List<Light>();
var eemin = new Vector3(float.MaxValue);
var eemax = new Vector3(float.MinValue);
var semin = new Vector3(float.MaxValue);
var semax = new Vector3(float.MinValue);
//var rnd = new Random();
foreach (var ymap in projectYmaps)
{
@ -118,28 +113,17 @@ namespace CodeWalker.Project.Panels
UpdateStatus("Adding lights from " + ent.Archetype.Name + "...");
if (dwbl != null)
{
Drawable ddwbl = dwbl as Drawable;
FragDrawable fdwbl = dwbl as FragDrawable;
LightAttributes_s[] lightAttrs = null;
if (ddwbl != null)
{
lightAttrs = ddwbl.LightAttributes?.data_items;
}
else if (fdwbl != null)
{
lightAttrs = fdwbl.OwnerFragment?.LightAttributes?.data_items;
}
if (lightAttrs != null)
{
eemin = Vector3.Min(eemin, ent.BBMin);
eemax = Vector3.Max(eemax, ent.BBMax);
semin = Vector3.Min(semin, ent.BBMin - ent._CEntityDef.lodDist);
semax = Vector3.Max(semax, ent.BBMax + ent._CEntityDef.lodDist);
var fphys = (dwbl as FragDrawable)?.OwnerFragmentPhys;
ent.EnsureLights(dwbl);
var elights = ent.Lights;
if (elights != null)
{
for (int li = 0; li<lightAttrs.Length;li++)
for (int li = 0; li<elights.Length;li++)
{
var la = lightAttrs[li];
var elight = elights[li];
var la = elight.Attributes;
//transform this light with the entity position and orientation
//generate lights data from it!
@ -164,9 +148,9 @@ namespace CodeWalker.Project.Panels
if (bone != null)
{
var modeltransforms = skeleton.Transformations;
var fragtransforms = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod?.FragTransforms?.Matrices;
var fragtransformid = fdwbl?.OwnerFragmentPhys?.OwnerFragPhysIndex ?? 0;
var fragoffset = new Vector4(fdwbl?.OwnerFragmentPhys?.OwnerFragPhysLod.Unknown_30h ?? Vector3.Zero, 0.0f);
var fragtransforms = fphys?.OwnerFragPhysLod?.FragTransforms?.Matrices;
var fragtransformid = fphys?.OwnerFragPhysIndex ?? 0;
var fragoffset = new Vector4(fphys?.OwnerFragPhysLod.Unknown_30h ?? Vector3.Zero, 0.0f);
if ((fragtransforms != null) && (fragtransformid < fragtransforms.Length))
{
@ -206,9 +190,7 @@ namespace CodeWalker.Project.Panels
uint b = la.ColorB;
uint i = (byte)Math.Min(la.Intensity*4, 255);
uint c = (i << 24) + (r << 16) + (g << 8) + b;
uint h = GetLightHash(ent, dwbl, li);
uint h = elight.Hash;
if (ent._CEntityDef.guid == 91259075)
{ } //h = 2324437992? should be:19112537
@ -375,204 +357,6 @@ namespace CodeWalker.Project.Panels
}
static uint ComputeHash(IReadOnlyList<uint> ints, uint seed = 0)
{
var a2 = ints.Count;
var v3 = a2;
var v5 = (uint)(seed + 0xDEADBEEF + 4 * ints.Count);
var v6 = v5;
var v7 = v5;
var c = 0;
for (var i = 0; i < (ints.Count - 4) / 3 + 1; i++, v3 -= 3, c += 3)
{
var v9 = ints[c + 2] + v5;
var v10 = ints[c + 1] + v6;
var v11 = ints[c] - v9;
var v13 = v10 + v9;
var v14 = (v7 + v11) ^ RotateLeft(v9, 4);
var v15 = v10 - v14;
var v17 = v13 + v14;
var v18 = v15 ^ RotateLeft(v14, 6);
var v19 = v13 - v18;
var v21 = v17 + v18;
var v22 = v19 ^ RotateLeft(v18, 8);
var v23 = v17 - v22;
var v25 = v21 + v22;
var v26 = v23 ^ RotateLeft(v22, 16);
var v27 = v21 - v26;
var v29 = v27 ^ RotateRight(v26, 13);
var v30 = v25 - v29;
v7 = v25 + v26;
v6 = v7 + v29;
v5 = v30 ^ RotateLeft(v29, 4);
}
if (v3 == 3)
{
v5 += ints[c + 2];
}
if (v3 >= 2)
{
v6 += ints[c + 1];
}
if (v3 >= 1)
{
var v34 = (v6 ^ v5) - RotateLeft(v6, 14);
var v35 = (v34 ^ (v7 + ints[c])) - RotateLeft(v34, 11);
var v36 = (v35 ^ v6) - RotateRight(v35, 7);
var v37 = (v36 ^ v34) - RotateLeft(v36, 16);
var v38 = RotateLeft(v37, 4);
var v39 = (((v35 ^ v37) - v38) ^ v36) - RotateLeft((v35 ^ v37) - v38, 14);
return (v39 ^ v37) - RotateRight(v39, 8);
}
return v5;
}
private uint GetLightHash(YmapEntityDef ent, DrawableBase dwbl, int lightIndex)
{
unchecked
{
var len = 7;
var ori = ent.Orientation;
var pos = ent.Position;
var abmin = Vector3.Min(ent.Archetype.BBMin, dwbl.BoundingBoxMin);
var abmax = Vector3.Max(ent.Archetype.BBMax, dwbl.BoundingBoxMax);
Bounds b = null;
if (dwbl is Drawable ddwbl)
{
b = ddwbl.Bound;
}
if (dwbl is FragDrawable fdwbl)
{
b = fdwbl.OwnerFragment?.PhysicsLODGroup?.PhysicsLOD1?.Bound;
}
if (b != null)
{
abmin = Vector3.Min(abmin, b.BoxMin);
abmax = Vector3.Max(abmax, b.BoxMax);
}
Vector3[] c = new Vector3[8];
c[0] = abmin;
c[1] = new Vector3(abmin.X, abmin.Y, abmax.Z);
c[2] = new Vector3(abmin.X, abmax.Y, abmin.Z);
c[3] = new Vector3(abmin.X, abmax.Y, abmax.Z);
c[4] = new Vector3(abmax.X, abmin.Y, abmin.Z);
c[5] = new Vector3(abmax.X, abmin.Y, abmax.Z);
c[6] = new Vector3(abmax.X, abmax.Y, abmin.Z);
c[7] = abmax;
var bbmin = new Vector3(float.MaxValue);
var bbmax = new Vector3(float.MinValue);
for (int j = 0; j < 8; j++)
{
Vector3 corn = ori.Multiply(c[j]) + pos;
bbmin = Vector3.Min(bbmin, corn);
bbmax = Vector3.Max(bbmax, corn);
}
var ints = new uint[len];
ints[0] = (uint)(bbmin.X * 10.0f);
ints[1] = (uint)(bbmin.Y * 10.0f);
ints[2] = (uint)(bbmin.Z * 10.0f);
ints[3] = (uint)(bbmax.X * 10.0f);
ints[4] = (uint)(bbmax.Y * 10.0f);
ints[5] = (uint)(bbmax.Z * 10.0f);
ints[6] = (uint)lightIndex + 1;
return ComputeHash(ints);
}
}
private AABB_s GetAABB(YmapEntityDef ent)
{
var arch = ent.Archetype;
var ori = ent.Orientation;
Vector3 bbmin = ent.Position - ent.BSRadius; //sphere
Vector3 bbmax = ent.Position + ent.BSRadius;
if (arch != null)
{
Vector3[] c = new Vector3[8];
Vector3 abmin = arch.BBMin * ent.Scale; //entity box
Vector3 abmax = arch.BBMax * ent.Scale;
c[0] = abmin;
c[1] = new Vector3(abmin.X, abmin.Y, abmax.Z);
c[2] = new Vector3(abmin.X, abmax.Y, abmin.Z);
c[3] = new Vector3(abmin.X, abmax.Y, abmax.Z);
c[4] = new Vector3(abmax.X, abmin.Y, abmin.Z);
c[5] = new Vector3(abmax.X, abmin.Y, abmax.Z);
c[6] = new Vector3(abmax.X, abmax.Y, abmin.Z);
c[7] = abmax;
bbmin = new Vector3(float.MaxValue);
bbmax = new Vector3(float.MinValue);
for (int j = 0; j < 8; j++)
{
Vector3 corn = ori.Multiply(c[j]) + ent.Position;
bbmin = Vector3.Min(bbmin, corn);
bbmax = Vector3.Max(bbmax, corn);
}
}
AABB_s b = new AABB_s();
b.Min = new Vector4(bbmin, 0f);
b.Max = new Vector4(bbmax, 0f);
return b;
}
private AABB_s GetAABB2(YmapEntityDef ent)
{
var arch = ent.Archetype;
var ori = ent.Orientation;
var pos = ent.Position;
var sca = ent.Scale;
var mat = Matrix.Transformation(Vector3.Zero, Quaternion.Identity, sca, Vector3.Zero, ori, pos);
var matabs = mat;
matabs.Column1 = mat.Column1.Abs();
matabs.Column2 = mat.Column2.Abs();
matabs.Column3 = mat.Column3.Abs();
matabs.Column4 = mat.Column4.Abs();
Vector3 bbmin = pos - ent.BSRadius; //sphere
Vector3 bbmax = pos + ent.BSRadius;
if (arch != null)
{
var bbcenter = (arch.BBMax + arch.BBMin) * 0.5f;
var bbextent = (arch.BBMax - arch.BBMin) * 0.5f;
var ncenter = Vector3.TransformCoordinate(bbcenter, mat);
var nextent = Vector3.TransformNormal(bbextent, matabs);
bbmin = ncenter - nextent;
bbmax = ncenter + nextent;
}
AABB_s b = new AABB_s();
b.Min = new Vector4(bbmin, 0f);
b.Max = new Vector4(bbmax, 0f);
return b;
}
private static uint RotateLeft(uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
private static uint RotateRight(uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static int RotateLeft(int value, int count)
{
return (int)RotateLeft((uint)value, count);
}
private static int RotateRight(int value, int count)
{
return (int)RotateRight((uint)value, count);
}
public class Light
{
public MetaVECTOR3 position { get; set; }

View File

@ -3263,15 +3263,20 @@ namespace CodeWalker.Rendering
}
if (renderlights && shaders.deferred && (rndbl.Lights != null) && interiorent)//only interior ents making lights! todo: fix LOD lights
if (renderlights && shaders.deferred && (rndbl.Lights != null))
{
var linst = new RenderableLightInst();
for (int i = 0; i < rndbl.Lights.Length; i++)
entity?.EnsureLights(rndbl.Key);
if (interiorent)//only interior ents making lights! todo: fix LOD lights
{
linst.EntityPosition = position;
linst.EntityRotation = orientation;
linst.Light = rndbl.Lights[i];
shaders.Enqueue(ref linst);
var linst = new RenderableLightInst();
for (int i = 0; i < rndbl.Lights.Length; i++)
{
linst.EntityPosition = position;
linst.EntityRotation = orientation;
linst.Light = rndbl.Lights[i];
shaders.Enqueue(ref linst);
}
}
}