private Drawable TryConvertDrawable(FbxDocument fdoc, string name) { var rootnodes = fdoc.GetSceneNodes(); var mlists = new List <List <FbxModel> >(); var mlistall = new List <FbxModel>(); foreach (var node in rootnodes) { if (node.Name == "Model") { var mlist = TryConvertModels(node); //flatten any models structure with depth >2 if (mlist != null) { mlists.Add(mlist); mlistall.AddRange(mlist); } } } var mlHigh = new List <DrawableModel>(); var mlMed = new List <DrawableModel>(); var mlLow = new List <DrawableModel>(); var mlVlow = new List <DrawableModel>(); var mlUnks = new List <DrawableModel>(); var mlAll = new List <DrawableModel>(); foreach (var m in mlistall) { var mnl = m.Name.ToLowerInvariant(); if (mnl.EndsWith("_vlow")) { mlVlow.Add(m.Model); } else if (mnl.EndsWith("_low")) { mlLow.Add(m.Model); } else if (mnl.EndsWith("_med")) { mlMed.Add(m.Model); } else if (mnl.EndsWith("_high")) { mlHigh.Add(m.Model); } else { mlUnks.Add(m.Model); } } if (mlHigh.Count == 0)//mlUnks could be embedded collisions... ignore for now { mlHigh.AddRange(mlUnks); } mlAll.AddRange(mlHigh); mlAll.AddRange(mlMed); mlAll.AddRange(mlLow); mlAll.AddRange(mlVlow); var allVerts = new List <Vector3>(); var bbMin = new Vector3(float.MaxValue); var bbMax = new Vector3(float.MinValue); var bsCen = Vector3.Zero; var bsRad = 0.0f; foreach (var m in mlistall) { if (m?.Model?.Geometries == null) { continue; } foreach (var g in m.Model.Geometries) { var vb = g.VertexData.VertexBytes; var vs = g.VertexData.VertexStride; var vc = g.VertexData.VertexCount; for (int i = 0; i < vc; i++) { var vp = MetaTypes.ConvertData <Vector3>(vb, i * vs);//position offset should always be 0! allVerts.Add(vp); bbMin = Vector3.Min(bbMin, vp); bbMax = Vector3.Max(bbMax, vp); //bsCen += vp; } } } if (allVerts.Count > 0) { //bsCen = bsCen / allVerts.Count; bsCen = (bbMin + bbMax) * 0.5f; foreach (var vp in allVerts) { bsRad = Math.Max(bsRad, (vp - bsCen).Length()); } } var sgrp = new ShaderGroup(); var slist = new List <ShaderFX>(); var smapp = new List <ushort>(); foreach (var m in mlAll) { if (m?.Geometries == null) { continue; } smapp.Clear(); foreach (var g in m.Geometries) { smapp.Add((ushort)slist.Count); slist.Add(g.Shader); } m.ShaderMapping = smapp.ToArray();//TODO: re-use shaders!! } sgrp.Shaders = new ResourcePointerArray64 <ShaderFX>(); sgrp.Shaders.data_items = slist.ToArray(); sgrp.ShadersCount1 = (ushort)slist.Count; sgrp.ShadersCount2 = (ushort)slist.Count; sgrp.VFT = 1080113376; //is this needed? sgrp.Unknown_4h = 1; sgrp.Unknown_30h = (uint)(8 + slist.Count * 3); //WTF is this? var d = new Drawable(); d.Name = name + ".#dr"; d.ShaderGroup = sgrp; d.BoundingCenter = bsCen; d.BoundingSphereRadius = bsRad; d.BoundingBoxMin = bbMin; d.BoundingBoxMax = bbMax; d.LodDistHigh = 9998;//lod dist defaults d.LodDistMed = 9998; d.LodDistLow = 9998; d.LodDistVlow = 9998; d.Unknown_9Ah = 33;//WTF is this??? d.FileVFT = 1079446584; d.FileUnknown = 1; d.DrawableModels = new DrawableModelsBlock(); if (mlHigh.Count > 0) { d.DrawableModels.High = mlHigh.ToArray(); d.FlagsHigh = 1;//what flags should be used?? } if (mlMed.Count > 0) { d.DrawableModels.Med = mlMed.ToArray(); d.LodDistHigh = bsRad * 2.0f; //when med models present, generate a high lod dist.. d.FlagsMed = 1; } if (mlLow.Count > 0) { d.DrawableModels.Low = mlLow.ToArray(); d.LodDistMed = bsRad * 8.0f; //when low models present, generate a med lod dist.. d.FlagsLow = 1; } if (mlVlow.Count > 0) { d.DrawableModels.VLow = mlVlow.ToArray(); d.LodDistLow = bsRad * 32.0f; //when vlow models present, generate a low lod dist.. d.FlagsVlow = 1; } d.BuildRenderMasks(); d.LightAttributes = new ResourceSimpleList64_s <LightAttributes_s>(); //todo: light attributes? return(d); }