private static void PrintFrameName(model_t m, int frame) { aliashdr_t hdr = Mod.GetExtraData(m); if (hdr == null) { return; } Con.Print("frame {0}: {1}\n", frame, hdr.frames[frame].name); }
static int _StripCount; // stripcount /// <summary> /// GL_MakeAliasModelDisplayLists /// </summary> public static void MakeAliasModelDisplayLists(model_t m, aliashdr_t hdr) { _AliasModel = m; _AliasHdr = hdr; // // look for a cached version // string path = Path.ChangeExtension("glquake/" + Path.GetFileNameWithoutExtension(m.name), ".ms2"); DisposableWrapper <BinaryReader> file; Common.FOpenFile(path, out file); if (file != null) { using (file) { BinaryReader reader = file.Object; _NumCommands = reader.ReadInt32(); _NumOrder = reader.ReadInt32(); for (int i = 0; i < _NumCommands; i++) { _Commands[i] = reader.ReadInt32(); } for (int i = 0; i < _NumOrder; i++) { _VertexOrder[i] = reader.ReadInt32(); } } } else { // // build it from scratch // Con.Print("meshing {0}...\n", m.name); BuildTris(); // trifans or lists // // save out the cached version // string fullpath = Path.Combine(Common.GameDir, path); Stream fs = Sys.FileOpenWrite(fullpath, true); if (fs != null) { using (BinaryWriter writer = new BinaryWriter(fs, Encoding.ASCII)) { writer.Write(_NumCommands); writer.Write(_NumOrder); for (int i = 0; i < _NumCommands; i++) { writer.Write(_Commands[i]); } for (int i = 0; i < _NumOrder; i++) { writer.Write(_VertexOrder[i]); } } } } // // save the data out // _AliasHdr.poseverts = _NumOrder; int[] cmds = new int[_NumCommands]; //Hunk_Alloc (numcommands * 4); _AliasHdr.commands = cmds; // in bytes??? // (byte*)cmds - (byte*)paliashdr; Buffer.BlockCopy(_Commands, 0, cmds, 0, _NumCommands * 4); //memcpy (cmds, commands, numcommands * 4); trivertx_t[][] poseverts = Mod.PoseVerts; trivertx_t[] verts = new trivertx_t[_AliasHdr.numposes * _AliasHdr.poseverts]; // Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t) ); _AliasHdr.posedata = verts; // (byte*)verts - (byte*)paliashdr; int offset = 0; for (int i = 0; i < _AliasHdr.numposes; i++) { for (int j = 0; j < _NumOrder; j++) { verts[offset++] = poseverts[i][_VertexOrder[j]]; // *verts++ = poseverts[i][vertexorder[j]]; } } }
static int[] _VertexOrder = new int[MAX_COMMANDS]; // vertexorder #endregion Fields #region Methods /// <summary> /// GL_MakeAliasModelDisplayLists /// </summary> public static void MakeAliasModelDisplayLists(model_t m, aliashdr_t hdr) { _AliasModel = m; _AliasHdr = hdr; // // look for a cached version // string path = Path.ChangeExtension("glquake/" + Path.GetFileNameWithoutExtension(m.name), ".ms2"); DisposableWrapper<BinaryReader> file; Common.FOpenFile(path, out file); if (file != null) { using (file) { BinaryReader reader = file.Object; _NumCommands = reader.ReadInt32(); _NumOrder = reader.ReadInt32(); for (int i = 0; i < _NumCommands; i++) _Commands[i] = reader.ReadInt32(); for (int i = 0; i < _NumOrder; i++) _VertexOrder[i] = reader.ReadInt32(); } } else { // // build it from scratch // Con.Print("meshing {0}...\n", m.name); BuildTris(); // trifans or lists // // save out the cached version // string fullpath = Path.Combine(Common.GameDir, path); Stream fs = Sys.FileOpenWrite(fullpath, true); if (fs != null) using (BinaryWriter writer = new BinaryWriter(fs, Encoding.ASCII)) { writer.Write(_NumCommands); writer.Write(_NumOrder); for (int i = 0; i < _NumCommands; i++) writer.Write(_Commands[i]); for (int i = 0; i < _NumOrder; i++) writer.Write(_VertexOrder[i]); } } // // save the data out // _AliasHdr.poseverts = _NumOrder; int[] cmds = new int[_NumCommands]; //Hunk_Alloc (numcommands * 4); _AliasHdr.commands = cmds; // in bytes??? // (byte*)cmds - (byte*)paliashdr; Buffer.BlockCopy(_Commands, 0, cmds, 0, _NumCommands * 4); //memcpy (cmds, commands, numcommands * 4); trivertx_t[][] poseverts = Mod.PoseVerts; trivertx_t[] verts = new trivertx_t[_AliasHdr.numposes * _AliasHdr.poseverts]; // Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t) ); _AliasHdr.posedata = verts; // (byte*)verts - (byte*)paliashdr; int offset = 0; for (int i = 0; i < _AliasHdr.numposes; i++) for (int j = 0; j < _NumOrder; j++) { verts[offset++] = poseverts[i][_VertexOrder[j]]; // *verts++ = poseverts[i][vertexorder[j]]; } }
/// <summary> /// GL_DrawAliasShadow /// </summary> static void DrawAliasShadow(aliashdr_t paliashdr, int posenum) { float lheight = _CurrentEntity.origin.Z - _LightSpot.Z; float height = 0; trivertx_t[] verts = paliashdr.posedata; int voffset = posenum * paliashdr.poseverts; int[] order = paliashdr.commands; height = -lheight + 1.0f; int orderOffset = 0; while (true) { // get the vertex count and primitive type int count = order[orderOffset++]; if (count == 0) break; // done if (count < 0) { count = -count; GL.Begin(BeginMode.TriangleFan); } else GL.Begin(BeginMode.TriangleStrip); do { // texture coordinates come from the draw list // (skipped for shadows) glTexCoord2fv ((float *)order); orderOffset += 2; // normals and vertexes come from the frame list Vector3 point = new Vector3( verts[voffset].v[0] * paliashdr.scale.X + paliashdr.scale_origin.X, verts[voffset].v[1] * paliashdr.scale.Y + paliashdr.scale_origin.Y, verts[voffset].v[2] * paliashdr.scale.Z + paliashdr.scale_origin.Z ); point.X -= _ShadeVector.X * (point.Z + lheight); point.Y -= _ShadeVector.Y * (point.Z + lheight); point.Z = height; GL.Vertex3(point); voffset++; } while (--count > 0); GL.End(); } }
/// <summary> /// GL_DrawAliasFrame /// </summary> static void DrawAliasFrame(aliashdr_t paliashdr, int posenum) { _LastPoseNum = posenum; trivertx_t[] verts = paliashdr.posedata; int vertsOffset = posenum * paliashdr.poseverts; int[] order = paliashdr.commands; int orderOffset = 0; while (true) { // get the vertex count and primitive type int count = order[orderOffset++]; if (count == 0) break; // done if (count < 0) { count = -count; GL.Begin(BeginMode.TriangleFan); } else GL.Begin(BeginMode.TriangleStrip); Union4b u1 = Union4b.Empty, u2 = Union4b.Empty; do { // texture coordinates come from the draw list u1.i0 = order[orderOffset + 0]; u2.i0 = order[orderOffset + 1]; orderOffset += 2; GL.TexCoord2(u1.f0, u2.f0); // normals and vertexes come from the frame list float l = _ShadeDots[verts[vertsOffset].lightnormalindex] * _ShadeLight; GL.Color3(l, l, l); GL.Vertex3((float)verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2]); vertsOffset++; } while (--count > 0); GL.End(); } }
/// <summary> /// R_SetupAliasFrame /// </summary> static void SetupAliasFrame(int frame, aliashdr_t paliashdr) { if ((frame >= paliashdr.numframes) || (frame < 0)) { Con.DPrint("R_AliasSetupFrame: no such frame {0}\n", frame); frame = 0; } int pose = paliashdr.frames[frame].firstpose; int numposes = paliashdr.frames[frame].numposes; if (numposes > 1) { float interval = paliashdr.frames[frame].interval; pose += (int)(Client.cl.time / interval) % numposes; } DrawAliasFrame(paliashdr, pose); }
/// <summary> /// Mod_LoadAliasModel /// </summary> public static void LoadAliasModel(model_t mod, byte[] buffer) { mdl_t pinmodel = Sys.BytesToStructure<mdl_t>(buffer, 0); int version = Common.LittleLong(pinmodel.version); if (version != ALIAS_VERSION) Sys.Error("{0} has wrong version number ({1} should be {2})", mod.name, version, ALIAS_VERSION); // // allocate space for a working header, plus all the data except the frames, // skin and group info // _Header = new aliashdr_t(); mod.flags = Common.LittleLong(pinmodel.flags); // // endian-adjust and copy the data, starting with the alias model header // _Header.boundingradius = Common.LittleFloat(pinmodel.boundingradius); _Header.numskins = Common.LittleLong(pinmodel.numskins); _Header.skinwidth = Common.LittleLong(pinmodel.skinwidth); _Header.skinheight = Common.LittleLong(pinmodel.skinheight); if (_Header.skinheight > MAX_LBM_HEIGHT) Sys.Error("model {0} has a skin taller than {1}", mod.name, MAX_LBM_HEIGHT); _Header.numverts = Common.LittleLong(pinmodel.numverts); if (_Header.numverts <= 0) Sys.Error("model {0} has no vertices", mod.name); if (_Header.numverts > MAXALIASVERTS) Sys.Error("model {0} has too many vertices", mod.name); _Header.numtris = Common.LittleLong(pinmodel.numtris); if (_Header.numtris <= 0) Sys.Error("model {0} has no triangles", mod.name); _Header.numframes = Common.LittleLong(pinmodel.numframes); int numframes = _Header.numframes; if (numframes < 1) Sys.Error("Mod_LoadAliasModel: Invalid # of frames: {0}\n", numframes); _Header.size = Common.LittleFloat(pinmodel.size) * ALIAS_BASE_SIZE_RATIO; mod.synctype = (synctype_t)Common.LittleLong((int)pinmodel.synctype); mod.numframes = _Header.numframes; _Header.scale = Common.LittleVector(Common.ToVector(ref pinmodel.scale)); _Header.scale_origin = Common.LittleVector(Common.ToVector(ref pinmodel.scale_origin)); _Header.eyeposition = Common.LittleVector(Common.ToVector(ref pinmodel.eyeposition)); // // load the skins // int offset = LoadAllSkins(_Header.numskins, new ByteArraySegment(buffer, mdl_t.SizeInBytes)); // // load base s and t vertices // int stvOffset = offset; // in bytes for (int i = 0; i < _Header.numverts; i++, offset += stvert_t.SizeInBytes) { _STVerts[i] = Sys.BytesToStructure<stvert_t>(buffer, offset); _STVerts[i].onseam = Common.LittleLong(_STVerts[i].onseam); _STVerts[i].s = Common.LittleLong(_STVerts[i].s); _STVerts[i].t = Common.LittleLong(_STVerts[i].t); } // // load triangle lists // int triOffset = stvOffset + _Header.numverts * stvert_t.SizeInBytes; offset = triOffset; for (int i = 0; i < _Header.numtris; i++, offset += dtriangle_t.SizeInBytes) { _Triangles[i] = Sys.BytesToStructure<dtriangle_t>(buffer, offset); _Triangles[i].facesfront = Common.LittleLong(_Triangles[i].facesfront); for (int j = 0; j < 3; j++) _Triangles[i].vertindex[j] = Common.LittleLong(_Triangles[i].vertindex[j]); } // // load the frames // _PoseNum = 0; int framesOffset = triOffset + _Header.numtris * dtriangle_t.SizeInBytes; _Header.frames = new maliasframedesc_t[_Header.numframes]; for (int i = 0; i < numframes; i++) { aliasframetype_t frametype = (aliasframetype_t)BitConverter.ToInt32(buffer, framesOffset); framesOffset += 4; if (frametype == aliasframetype_t.ALIAS_SINGLE) { framesOffset = LoadAliasFrame(new ByteArraySegment(buffer, framesOffset), ref _Header.frames[i]); } else { framesOffset = LoadAliasGroup(new ByteArraySegment(buffer, framesOffset), ref _Header.frames[i]); } } _Header.numposes = _PoseNum; mod.type = modtype_t.mod_alias; // FIXME: do this right mod.mins = -Vector3.One * 16.0f; mod.maxs = -mod.mins; // // build the draw lists // Mesh.MakeAliasModelDisplayLists(mod, _Header); // // move the complete, relocatable alias model to the cache // mod.cache = Cache.Alloc(aliashdr_t.SizeInBytes * _Header.frames.Length * maliasframedesc_t.SizeInBytes, null); if (mod.cache == null) return; mod.cache.data = _Header; }