/// <summary> /// Mod_LoadModel /// Loads a model into the cache /// </summary> private ModelData Load(ModelData mod, Boolean crash, ModelType type) { var name = mod.Name; if (mod.Type != type) { ModelData newMod = null; switch (type) { case ModelType.Brush: newMod = new BrushModelData(Host.Model.SubdivideSize, Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; case ModelType.Alias: newMod = new AliasModelData(Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; case ModelType.Sprite: newMod = new SpriteModelData(Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; } newMod.Name = mod.Name; Remove(name); mod = newMod; Add(mod.Name, mod); } if (!mod.IsLoadRequired) { if (mod.Type == ModelType.Alias) { if (Host.Cache.Check(mod.cache) != null) { return(mod); } } else { return(mod); // not cached at all } } // Load the file var buf = FileSystem.LoadFile(mod.Name); if (buf == null) { if (crash) { Utilities.Error("Mod_NumForName: {0} not found", mod.Name); } return(null); } // Allocate a new model Allocate(mod, buf); return(mod); }
private static int FanLength(AliasModelData m, int starttri, int startv) { mesh._Used[starttri] = 2; var triangles = m.Triangles; //last = &triangles[starttri]; var vidx = triangles[starttri].vertindex; mesh._StripVerts[0] = vidx[startv % 3]; mesh._StripVerts[1] = vidx[(startv + 1) % 3]; mesh._StripVerts[2] = vidx[(startv + 2) % 3]; mesh._StripTris[0] = starttri; mesh._StripCount = 1; var m1 = vidx[(startv + 0) % 3]; var m2 = vidx[(startv + 2) % 3]; var lastfacesfront = triangles[starttri].facesfront; // look for a matching triangle nexttri: for (var j = starttri + 1; j < mesh._AliasHdr.numtris; j++) //, check++) { vidx = triangles[j].vertindex; if (triangles[j].facesfront != lastfacesfront) { continue; } for (var k = 0; k < 3; k++) { if (vidx[k] != m1) { continue; } if (vidx[(k + 1) % 3] != m2) { continue; } // this is the next part of the fan // if we can't use this triangle, this tristrip is done if (mesh._Used[j] != 0) { goto done; } // the new edge m2 = vidx[(k + 2) % 3]; mesh._StripVerts[mesh._StripCount + 2] = m2; mesh._StripTris[mesh._StripCount] = j; mesh._StripCount++; mesh._Used[j] = 2; goto nexttri; } } done: // clear the temp used flags for (var j = starttri + 1; j < mesh._AliasHdr.numtris; j++) { if (mesh._Used[j] == 2) { mesh._Used[j] = 0; } } return(mesh._StripCount); }
/// <summary> /// Mod_LoadModel /// Loads a model into the cache /// </summary> public ModelData LoadModel(ModelData mod, Boolean crash, ModelType type) { var name = mod.Name; if (mod.Type != type) { ModelData newMod = null; switch (type) { case ModelType.mod_brush: newMod = new BrushModelData(Host.Model.SubdivideSize, Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; case ModelType.mod_alias: newMod = new AliasModelData(Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; case ModelType.mod_sprite: newMod = new SpriteModelData(Host.RenderContext.NoTextureMip); newMod.CopyFrom(mod); break; } newMod.Name = mod.Name; ModelCache.RemoveAll(k => k.Name == name); mod = newMod; ModelCache.Add(mod); } if (!mod.IsLoadRequired) { if (mod.Type == ModelType.mod_alias) { if (Host.Cache.Check(mod.cache) != null) { return(mod); } } else { return(mod); // not cached at all } } // // load the file // var buf = FileSystem.LoadFile(mod.Name); if (buf == null) { if (crash) { Utilities.Error("Mod_NumForName: {0} not found", mod.Name); } return(null); } // // allocate a new model // CurrentModel = mod; mod.IsLoadRequired = false; switch (BitConverter.ToUInt32(buf, 0)) // LittleLong(*(unsigned *)buf)) { case ModelDef.IDPOLYHEADER: LoadAliasModel(( AliasModelData )mod, buf); break; case ModelDef.IDSPRITEHEADER: LoadSpriteModel(( SpriteModelData )mod, buf); break; default: LoadBrushModel(( BrushModelData )mod, buf); break; } return(mod); }
/// <summary> /// BuildTris /// Generate a list of trifans or strips for the model, which holds for all frames /// </summary> private static void BuildTris(AliasModelData m) { var bestverts = new int[1024]; var besttris = new int[1024]; // Uze // All references to pheader from model.c changed to _AliasHdr (former paliashdr) // // build tristrips // var stverts = m.STVerts; var triangles = m.Triangles; mesh._NumOrder = 0; mesh._NumCommands = 0; Array.Clear(mesh._Used, 0, mesh._Used.Length); // memset (used, 0, sizeof(used)); int besttype = 0, len; for (var i = 0; i < mesh._AliasHdr.numtris; i++) { // pick an unused triangle and start the trifan if (mesh._Used[i] != 0) { continue; } var bestlen = 0; for (var type = 0; type < 2; type++) { for (var startv = 0; startv < 3; startv++) { if (type == 1) { len = mesh.StripLength(m, i, startv); } else { len = mesh.FanLength(m, i, startv); } if (len > bestlen) { besttype = type; bestlen = len; for (var j = 0; j < bestlen + 2; j++) { bestverts[j] = mesh._StripVerts[j]; } for (var j = 0; j < bestlen; j++) { besttris[j] = mesh._StripTris[j]; } } } } // mark the tris on the best strip as used for (var j = 0; j < bestlen; j++) { mesh._Used[besttris[j]] = 1; } if (besttype == 1) { mesh._Commands[mesh._NumCommands++] = bestlen + 2; } else { mesh._Commands[mesh._NumCommands++] = -(bestlen + 2); } var uval = Union4b.Empty; for (var j = 0; j < bestlen + 2; j++) { // emit a vertex into the reorder buffer var k = bestverts[j]; mesh._VertexOrder[mesh._NumOrder++] = k; // emit s/t coords into the commands stream float s = stverts[k].s; float t = stverts[k].t; if (triangles[besttris[0]].facesfront == 0 && stverts[k].onseam != 0) { s += mesh._AliasHdr.skinwidth / 2; // on back side } s = (s + 0.5f) / mesh._AliasHdr.skinwidth; t = (t + 0.5f) / mesh._AliasHdr.skinheight; uval.f0 = s; mesh._Commands[mesh._NumCommands++] = uval.i0; uval.f0 = t; mesh._Commands[mesh._NumCommands++] = uval.i0; } } mesh._Commands[mesh._NumCommands++] = 0; // end of list marker ConsoleWrapper.DPrint("{0,3} tri {1,3} vert {2,3} cmd\n", mesh._AliasHdr.numtris, mesh._NumOrder, mesh._NumCommands); mesh._AllVerts += mesh._NumOrder; mesh._AllTris += mesh._AliasHdr.numtris; }