private static int _StripCount; // stripcount /// <summary> /// GL_MakeAliasModelDisplayLists /// </summary> public static void MakeAliasModelDisplayLists(AliasModelData m) { mesh._AliasModel = m; mesh._AliasHdr = m.Header; // // build it from scratch // mesh.BuildTris(m); // trifans or lists // // save the data out // mesh._AliasHdr.poseverts = mesh._NumOrder; var cmds = new int[mesh._NumCommands]; //Hunk_Alloc (numcommands * 4); mesh._AliasHdr.commands = cmds; // in bytes??? // (byte*)cmds - (byte*)paliashdr; Buffer.BlockCopy(mesh._Commands, 0, cmds, 0, mesh._NumCommands * 4); //memcpy (cmds, commands, numcommands * 4); var poseverts = m.PoseVerts; var verts = new trivertx_t[mesh._AliasHdr.numposes * mesh._AliasHdr.poseverts]; // Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t) ); mesh._AliasHdr.posedata = verts; // (byte*)verts - (byte*)paliashdr; var offset = 0; for (var i = 0; i < mesh._AliasHdr.numposes; i++) { for (var j = 0; j < mesh._NumOrder; j++) { verts[offset++] = poseverts[i][mesh._VertexOrder[j]]; // *verts++ = poseverts[i][vertexorder[j]]; } } }
public static void GL_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(); } }
public static void PrintFrameName(model_t m, int frame) { aliashdr_t hdr = Mod_Extradata(m); if (hdr == null) { return; } Con_Printf("frame {0}: {1}\n", frame, hdr.frames[frame].name); }
protected override void DrawAliasShadow(aliashdr_t paliashdr, Int32 posenum, Single lightSpotZ, Vector3 shadeVector) { var lheight = Desc.Origin.Z - lightSpotZ; Single height = 0; var verts = paliashdr.posedata; var voffset = posenum * paliashdr.poseverts; var order = paliashdr.commands; height = -lheight + 1.0f; var orderOffset = 0; while (true) { // get the vertex count and primitive type var count = order[orderOffset++]; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.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 var 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.X, point.Y, point.Z); voffset++; } while (--count > 0); GL.End( ); } }
public static void GL_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 { float[] v = { (float)verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2] }; // 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(v[0], v[1], v[2]); vertsOffset++; } while (--count > 0); GL.End(); } }
/// <summary> /// GL_DrawAliasFrame /// </summary> protected override void DrawAliasFrame(float shadeLight, float[] shadeDots, aliashdr_t paliashdr, int posenum) { this.AliasDesc.LastPoseNumber = posenum; var verts = paliashdr.posedata; var vertsOffset = posenum * paliashdr.poseverts; var order = paliashdr.commands; var orderOffset = 0; while (true) { // get the vertex count and primitive type var count = order[orderOffset++]; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.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 var 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( ); } }
public static void R_SetupAliasFrame(int frame, aliashdr_t paliashdr) { if ((frame >= paliashdr.numframes) || (frame < 0)) { Con_DPrintf("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)(cl.time / interval) % numposes; } GL_DrawAliasFrame(paliashdr, pose); }
public override void DrawAliasModel(Single shadeLight, Vector3 shadeVector, Single[] shadeDots, Single lightSpotZ, aliashdr_t paliashdr, Double realTime, Double time, ref Int32 poseNum, ref Int32 poseNum2, ref Single frameStartTime, ref Single frameInterval, ref Vector3 origin1, ref Vector3 origin2, ref Single translateStartTime, ref Vector3 angles1, ref Vector3 angles2, ref Single rotateStartTime, System.Boolean shadows = true, System.Boolean smoothModels = true, System.Boolean affineModels = false, System.Boolean noColours = false, System.Boolean isEyes = false, System.Boolean useInterpolation = true) { Device.DisableMultitexture( ); GL.Enable(EnableCap.Texture2D); GL.PushMatrix( ); if (useInterpolation) { Device.BlendedRotateForEntity(Desc.Origin, Desc.EulerAngles, realTime, ref origin1, ref origin2, ref translateStartTime, ref angles1, ref angles2, ref rotateStartTime); } else { Device.RotateForEntity(Desc.Origin, Desc.EulerAngles); } if (isEyes) { var v = Desc.ScaleOrigin; v.Z -= (22 + 8); GL.Translate(v.X, v.Y, v.Z); // double size of eyes, since they are really hard to see in gl var s = Desc.Scale * 2.0f; GL.Scale(s.X, s.Y, s.Z); } else { GL.Translate(Desc.ScaleOrigin.X, Desc.ScaleOrigin.Y, Desc.ScaleOrigin.Z); GL.Scale(Desc.Scale.X, Desc.Scale.Y, Desc.Scale.Z); } var anim = ( Int32 )(time * 10) & 3; //var texture = Host.Model.SkinTextures[paliashdr.gl_texturenum[_CurrentEntity.skinnum, anim]]; Desc.Texture.Bind( ); // we can't dynamically colormap textures, so they are cached // seperately for the players. Heads are just uncolored. //if ( _CurrentEntity.colormap != Host.Screen.vid.colormap && !noColours && playernum >= 1 ) //{ // PlayerTextures[playernum > 0 ? playernum - 1 : playernum].Bind( ); // //Host.DrawingContext.Bind( _PlayerTextures - 1 + playernum ); //} if (smoothModels) { GL.ShadeModel(ShadingModel.Smooth); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, ( Int32 )TextureEnvMode.Modulate); if (affineModels) { GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Fastest); } //SetupAliasFrame( shadeLight, Desc.AliasFrame, time, paliashdr, shadeDots ); SetupAliasBlendedFrame(shadeLight, AliasDesc.AliasFrame, realTime, time, paliashdr, shadeDots, ref poseNum, ref poseNum2, ref frameStartTime, ref frameInterval); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, ( Int32 )TextureEnvMode.Replace); GL.ShadeModel(ShadingModel.Flat); if (affineModels) { GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); } GL.PopMatrix( ); if (shadows) { GL.PushMatrix( ); Device.RotateForEntity(Desc.Origin, Desc.EulerAngles); GL.Disable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.Color4(0, 0, 0, 0.5f); DrawAliasShadow(paliashdr, AliasDesc.LastPoseNumber, lightSpotZ, shadeVector); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.Blend); GL.Color4(1f, 1, 1, 1); GL.PopMatrix( ); } GL.Disable(EnableCap.Texture2D); }
/* * ============= * GL_DrawAliasBlendedFrame * * [email protected]: model animation interpolation * ============= */ protected override void DrawAliasBlendedFrame(Single shadeLight, Single[] shadeDots, aliashdr_t paliashdr, Int32 posenum, Int32 posenum2, Single blend) { AliasDesc.LastPoseNumber0 = posenum; AliasDesc.LastPoseNumber = posenum2; var verts = paliashdr.posedata; var vert2 = verts; var vertsOffset = posenum * paliashdr.poseverts; var verts2Offset = posenum2 * paliashdr.poseverts; var order = paliashdr.commands; var orderOffset = 0; while (true) { if (orderOffset >= order.Length) { break; } // get the vertex count and primitive type var count = order[orderOffset]; orderOffset++; if (count == 0) { break; // done } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.TriangleStrip); } Union4b u1 = Union4b.Empty, u2 = Union4b.Empty; do { if (orderOffset + 1 >= order.Length) { break; } // 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 // blend the light intensity from the two frames together Vector3 d = Vector3.Zero; if (vertsOffset >= verts.Length) { count = 0; break; } d.X = shadeDots[vert2[verts2Offset].lightnormalindex] - shadeDots[verts[vertsOffset].lightnormalindex]; //var l = shadeDots[verts[vertsOffset].lightnormalindex] * shadeLight; var l = shadeLight * (shadeDots[verts[vertsOffset].lightnormalindex] + (blend * d.X)); GL.Color3(l, l, l); var v = new Vector3(verts[vertsOffset].v[0], verts[vertsOffset].v[1], verts[vertsOffset].v[2]); var v2 = new Vector3(vert2[verts2Offset].v[0], vert2[verts2Offset].v[1], verts[verts2Offset].v[2]); d = v2 - v; GL.Vertex3(( Single )verts[vertsOffset].v[0] + (blend * d[0]), verts[vertsOffset].v[1] + (blend * d[1]), verts[vertsOffset].v[2] + (blend * d[2])); vertsOffset++; verts2Offset++; } while (--count > 0); GL.End( ); } }
public static BaseAliasModel Create(BaseDevice device, String identifier, BaseTexture texture, Type modelType, Type descType, aliashdr_t aliasHeader) { if (ModelPool.ContainsKey(identifier)) { return(( BaseAliasModel )ModelPool[identifier]); } var desc = ( BaseAliasModelDesc )Activator.CreateInstance(descType); desc.Name = identifier; desc.Texture = texture; desc.AliasHeader = aliasHeader; var model = ( BaseAliasModel )Activator.CreateInstance(modelType, device, desc); model.Initialise(); return(model); }
/* ================= Mod_LoadAliasSkinGroup ================= */ static void Mod_LoadAliasSkinGroup(bspfile.ByteBuffer pin, ref object pskinindex, int skinsize, aliashdr_t pheader) { daliasskingroup_t pinskingroup; maliasskingroup_t paliasskingroup; int i, numskins; double[] poutskinintervals; pinskingroup = (daliasskingroup_t)pin; numskins = pinskingroup.numskins; paliasskingroup = new maliasskingroup_t(); paliasskingroup.skindescs = new maliasskindesc_t[numskins]; for(int kk = 0; kk < numskins; kk++) paliasskingroup.skindescs[kk] = new maliasskindesc_t(); paliasskingroup.numskins = numskins; pskinindex = (object)paliasskingroup; pin.ofs += sizeof_daliasskingroup_t; poutskinintervals = new double[numskins]; paliasskingroup.intervals = poutskinintervals; for (i = 0; i < numskins; i++) { poutskinintervals[i] = BitConverter.ToSingle(pin.buffer, pin.ofs); pin.ofs += sizeof(Single); if (poutskinintervals[i] <= 0.0) sys_linux.Sys_Error("Mod_LoadAliasSkinGroup: interval<=0"); } for (i=0 ; i<numskins ; i++) { Mod_LoadAliasSkin (pin, ref paliasskingroup.skindescs[i].skin, skinsize, pheader); } }
/* ================= Mod_LoadAliasSkin ================= */ static void Mod_LoadAliasSkin(bspfile.ByteBuffer pin, ref object pskinindex, int skinsize, aliashdr_t pheader) { int i; byte[] pskin; pskin = new byte[skinsize * render.r_pixbytes]; pskinindex = (object)pskin; if (render.r_pixbytes == 1) { Buffer.BlockCopy(pin.buffer, pin.ofs, pskin, 0, skinsize); } else if (render.r_pixbytes == 2) { } else { sys_linux.Sys_Error("Mod_LoadAliasSkin: driver set invalid r_pixbytes: " + render.r_pixbytes + "\n"); } pin.ofs += skinsize; }
/* ================= Mod_LoadAliasModel ================= */ static void Mod_LoadAliasModel(model_t mod, byte[] buffer) { int i; mdl_t pmodel, pinmodel; stvert_t[] pstverts; stvert_t pinstverts; aliashdr_t pheader; mtriangle_t[] ptri; dtriangle_t pintriangles; int version, numframes, numskins; daliasframetype_t pframetype; daliasskintype_t pskintype; maliasskindesc_t[] pskindesc; int skinsize; int start, end, total; bspfile.ByteBuffer aux = new bspfile.ByteBuffer(buffer, 0); pinmodel = (mdl_t)buffer; version = pinmodel.version; if (version != ALIAS_VERSION) sys_linux.Sys_Error (mod.name + " has wrong version number (" + version + " should be " + ALIAS_VERSION + ")"); // // allocate space for a working header, plus all the data except the frames, // skin and group info // pheader = new aliashdr_t(); pmodel = new mdl_t(); // mod.cache = pheader; mod.flags = pinmodel.flags; // // endian-adjust and copy the data, starting with the alias model header // pmodel.boundingradius = pinmodel.boundingradius; pmodel.numskins = pinmodel.numskins; pmodel.skinwidth = pinmodel.skinwidth; pmodel.skinheight = pinmodel.skinheight; if (pmodel.skinheight > draw.MAX_LBM_HEIGHT) sys_linux.Sys_Error("model " + mod.name + " has a skin taller than " + draw.MAX_LBM_HEIGHT); pmodel.numverts = pinmodel.numverts; if (pmodel.numverts <= 0) sys_linux.Sys_Error("model " + mod.name + " has no vertices"); if (pmodel.numverts > render.MAXALIASVERTS) sys_linux.Sys_Error("model " + mod.name + " has too many vertices"); pmodel.numtris = pinmodel.numtris; if (pmodel.numtris <= 0) sys_linux.Sys_Error("model " + mod.name + " has no triangles"); pmodel.numframes = pinmodel.numframes; pmodel.size = pinmodel.size * render.ALIAS_BASE_SIZE_RATIO; mod.synctype = pinmodel.synctype; mod.numframes = pmodel.numframes; for (i = 0; i < 3; i++) { pmodel.scale[i] = pinmodel.scale[i]; pmodel.scale_origin[i] = pinmodel.scale_origin[i]; pmodel.eyeposition[i] = pinmodel.eyeposition[i]; } numskins = pmodel.numskins; numframes = pmodel.numframes; if ((pmodel.skinwidth & 0x03) != 0) sys_linux.Sys_Error("Mod_LoadAliasModel: skinwidth not multiple of 4"); pheader.model = pmodel; // // load the skins // skinsize = pmodel.skinheight * pmodel.skinwidth; if (numskins < 1) sys_linux.Sys_Error("Mod_LoadAliasModel: Invalid # of skins: " + numskins + "\n"); aux.ofs += sizeof_mdl_t; pskindesc = new maliasskindesc_t[numskins]; for(int kk = 0; kk < numskins; kk++) pskindesc[kk] = new maliasskindesc_t(); pheader.skindesc = pskindesc; for (i = 0; i < numskins; i++) { aliasskintype_t skintype; pskintype = (daliasskintype_t)aux; skintype = pskintype.type; pskindesc[i].type = skintype; if (skintype == aliasskintype_t.ALIAS_SKIN_SINGLE) { aux.ofs += sizeof_daliasskintype_t; Mod_LoadAliasSkin(aux, ref pskindesc[i].skin, skinsize, pheader); } else { aux.ofs += sizeof_daliasskintype_t; Mod_LoadAliasSkinGroup(aux, ref pskindesc[i].skin, skinsize, pheader); } } // // set base s and t vertices // pstverts = new stvert_t[pmodel.numverts]; pheader.stverts = pstverts; for (i = 0; i < pmodel.numverts; i++) { pinstverts = (stvert_t)aux; pstverts[i] = new stvert_t(); pstverts[i].onseam = pinstverts.onseam; // put s and t in 16.16 format pstverts[i].s = pinstverts.s << 16; pstverts[i].t = pinstverts.t << 16; aux.ofs += sizeof_stvert_t; } // // set up the triangles // ptri = new mtriangle_t[pmodel.numtris]; pheader.triangles = ptri; for (i = 0; i < pmodel.numtris; i++) { int j; pintriangles = (dtriangle_t)aux; ptri[i] = new mtriangle_t(); ptri[i].facesfront = pintriangles.facesfront; for (j = 0; j < 3; j++) { ptri[i].vertindex[j] = pintriangles.vertindex[j]; } aux.ofs += sizeof_dtriangle_t; } // // load the frames // if (numframes < 1) sys_linux.Sys_Error("Mod_LoadAliasModel: Invalid # of frames: " + numframes + "\n"); pheader.frames = new maliasframedesc_t[numframes]; for (i = 0; i < numframes; i++) { aliasframetype_t frametype; pframetype = (daliasframetype_t)aux; frametype = pframetype.type; pheader.frames[i] = new maliasframedesc_t(); pheader.frames[i].type = frametype; if (frametype == aliasframetype_t.ALIAS_SINGLE) { aux.ofs += sizeof_daliasframetype_t; Mod_LoadAliasFrame(aux, ref pheader.frames[i].frame, pmodel.numverts, pheader.frames[i].bboxmin, pheader.frames[i].bboxmax, pheader, pheader.frames[i].name); } else { aux.ofs += sizeof_daliasframetype_t; Mod_LoadAliasGroup(aux, ref pheader.frames[i].frame, pmodel.numverts, pheader.frames[i].bboxmin, pheader.frames[i].bboxmax, pheader, pheader.frames[i].name); } } mod.type = modtype_t.mod_alias; // FIXME: do this right mod.mins[0] = mod.mins[1] = mod.mins[2] = -16; mod.maxs[0] = mod.maxs[1] = mod.maxs[2] = 16; // // move the complete, relocatable alias model to the cache // mod.cache = pheader; }
/// <summary> /// R_SetupAliasFrame /// </summary> protected virtual void SetupAliasFrame(Single shadeLight, Int32 frame, Double time, aliashdr_t paliashdr, Single[] shadeDots) { if ((frame >= paliashdr.numframes) || (frame < 0)) { ConsoleWrapper.Print("R_AliasSetupFrame: no such frame {0}\n", frame); frame = 0; } var pose = paliashdr.frames[frame].firstpose; var numposes = paliashdr.frames[frame].numposes; if (numposes > 1) { var interval = paliashdr.frames[frame].interval; pose += ( Int32 )(time / interval) % numposes; } DrawAliasFrame(shadeLight, shadeDots, paliashdr, pose); }
protected virtual void DrawAliasBlendedFrame(float shadeLight, float[] shadeDots, aliashdr_t paliashdr, int posenum, int posenum2, float blend) { throw new NotImplementedException( ); }
/// <summary> /// R_DrawAliasModel /// </summary> public virtual void DrawAliasModel(float shadeLight, Vector3 shadeVector, float[] shadeDots, float lightSpotZ, aliashdr_t paliashdr, double realTime, double time, ref int poseNum, ref int poseNum2, ref float frameStartTime, ref float frameInterval, ref Vector3 origin1, ref Vector3 origin2, ref float translateStartTime, ref Vector3 angles1, ref Vector3 angles2, ref float rotateStartTime, bool shadows = true, bool smoothModels = true, bool affineModels = false, bool noColours = false, bool isEyes = false, bool useInterpolation = true) { throw new NotImplementedException( ); }
/// <summary> /// R_DrawAliasModel /// </summary> public virtual void DrawAliasModel(Single shadeLight, Vector3 shadeVector, Single[] shadeDots, Single lightSpotZ, aliashdr_t paliashdr, Double realTime, Double time, ref Int32 poseNum, ref Int32 poseNum2, ref Single frameStartTime, ref Single frameInterval, ref Vector3 origin1, ref Vector3 origin2, ref Single translateStartTime, ref Vector3 angles1, ref Vector3 angles2, ref Single rotateStartTime, Boolean shadows = true, Boolean smoothModels = true, Boolean affineModels = false, Boolean noColours = false, Boolean isEyes = false, Boolean useInterpolation = true) { throw new NotImplementedException( ); }
public static void R_DrawAliasModel(entity_t e) { model_t clmodel = currententity.model; Vector3 mins = currententity.origin + clmodel.mins; Vector3 maxs = currententity.origin + clmodel.maxs; if (R_CullBox(ref mins, ref maxs)) { return; } r_entorigin = currententity.origin; modelorg = r_origin - r_entorigin; // // get lighting information // ambientlight = shadelight = R_LightPoint(ref currententity.origin); // allways give the gun some light if (e == cl.viewent && ambientlight < 24) { ambientlight = shadelight = 24; } for (int lnum = 0; lnum < q_shared.MAX_DLIGHTS; lnum++) { if (cl_dlights[lnum].die >= cl.time) { Vector3 dist = currententity.origin - cl_dlights[lnum].origin; float add = cl_dlights[lnum].radius - dist.Length; if (add > 0) { ambientlight += add; //ZOID models should be affected by dlights as well shadelight += add; } } } // clamp lighting so it doesn't overbright as much if (ambientlight > 128) { ambientlight = 128; } if (ambientlight + shadelight > 192) { shadelight = 192 - ambientlight; } // ZOID: never allow players to go totally black int playernum = Array.IndexOf(cl_entities, currententity, 0, cl.maxclients); if (playernum >= 1)// && i <= cl.maxclients) { if (ambientlight < 8) { ambientlight = shadelight = 8; } } // HACK HACK HACK -- no fullbright colors, so make torches full light if (clmodel.name == "progs/flame2.mdl" || clmodel.name == "progs/flame.mdl") { ambientlight = shadelight = 256; } shadedots = anorm_dots[((int)(e.angles.Y * (q_shared.SHADEDOT_QUANT / 360.0))) & (q_shared.SHADEDOT_QUANT - 1)]; shadelight = shadelight / 200.0f; double an = e.angles.Y / 180.0 * Math.PI; shadevector.X = (float)Math.Cos(-an); shadevector.Y = (float)Math.Sin(-an); shadevector.Z = 1; Mathlib.Normalize(ref shadevector); // // locate the proper data // aliashdr_t paliashdr = Mod_Extradata(currententity.model); c_alias_polys += paliashdr.numtris; // // draw all the triangles // GL_DisableMultitexture(); GL.PushMatrix(); R_RotateForEntity(e); if (clmodel.name == "progs/eyes.mdl" && gl_doubleeys.value != 0) { Vector3 v = paliashdr.scale_origin; v.Z -= (22 + 8); GL.Translate(v); // double size of eyes, since they are really hard to see in gl GL.Scale(paliashdr.scale * 2.0f); } else { GL.Translate(paliashdr.scale_origin); GL.Scale(paliashdr.scale); } int anim = (int)(cl.time * 10) & 3; GL_Bind(paliashdr.gl_texturenum[currententity.skinnum, anim]); // we can't dynamically colormap textures, so they are cached // seperately for the players. Heads are just uncolored. if (currententity.colormap != vid.colormap && gl_nocolors.value == 0 && playernum >= 1) { GL_Bind(playertextures - 1 + playernum); } if (gl_smoothmodels.value != 0) { GL.ShadeModel(ShadingModel.Smooth); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); if (gl_affinemodels.value != 0) { GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Fastest); } R_SetupAliasFrame(currententity.frame, paliashdr); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); GL.ShadeModel(ShadingModel.Flat); if (gl_affinemodels.value != 0) { GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); } GL.PopMatrix(); if (r_shadows.value != 0) { GL.PushMatrix(); R_RotateForEntity(e); GL.Disable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.Color4(0, 0, 0, 0.5f); GL_DrawAliasShadow(paliashdr, lastposenum); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.Blend); GL.Color4(1f, 1, 1, 1); GL.PopMatrix(); } }
public static void R_TranslatePlayerSkin(int playernum) { GL_DisableMultitexture(); int top = cl.scores[playernum].colors & 0xf0; int bottom = (cl.scores[playernum].colors & 15) << 4; byte[] translate = new byte[256]; for (int i = 0; i < 256; i++) { translate[i] = (byte)i; } for (int i = 0; i < 16; i++) { if (top < 128) // the artists made some backwards ranges. sigh. { translate[TOP_RANGE + i] = (byte)(top + i); } else { translate[TOP_RANGE + i] = (byte)(top + 15 - i); } if (bottom < 128) { translate[BOTTOM_RANGE + i] = (byte)(bottom + i); } else { translate[BOTTOM_RANGE + i] = (byte)(bottom + 15 - i); } } // // locate the original skin pixels // currententity = cl_entities[1 + playernum]; model_t model = currententity.model; if (model == null) { return; // player doesn't have a model yet } if (model.type != modtype_t.mod_alias) { return; // only translate skins on alias models } aliashdr_t paliashdr = Mod_Extradata(model); int s = paliashdr.skinwidth * paliashdr.skinheight; if ((s & 3) != 0) { Sys_Error("R_TranslateSkin: s&3"); } byte[] original; if (currententity.skinnum < 0 || currententity.skinnum >= paliashdr.numskins) { Con_Printf("({0}): Invalid player skin #{1}\n", playernum, currententity.skinnum); original = (byte[])paliashdr.texels[0];// (byte *)paliashdr + paliashdr.texels[0]; } else { original = (byte[])paliashdr.texels[currententity.skinnum]; } int inwidth = paliashdr.skinwidth; int inheight = paliashdr.skinheight; // because this happens during gameplay, do it fast // instead of sending it through gl_upload 8 GL_Bind(playertextures + playernum); int scaled_width = (int)(gl_max_size.value < 512 ? gl_max_size.value : 512); int scaled_height = (int)(gl_max_size.value < 256 ? gl_max_size.value : 256); // allow users to crunch sizes down even more if they want scaled_width >>= (int)gl_playermip.value; scaled_height >>= (int)gl_playermip.value; uint fracstep, frac; int destOffset; uint[] translate32 = new uint[256]; for (int i = 0; i < 256; i++) { translate32[i] = d_8to24table[translate[i]]; } uint[] dest = new uint[512 * 256]; destOffset = 0; fracstep = (uint)(inwidth * 0x10000 / scaled_width); for (int i = 0; i < scaled_height; i++, destOffset += scaled_width) { int srcOffset = inwidth * (i * inheight / scaled_height); frac = fracstep >> 1; for (int j = 0; j < scaled_width; j += 4) { dest[destOffset + j] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 1] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 2] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 3] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; } } GCHandle handle = GCHandle.Alloc(dest, GCHandleType.Pinned); try { GL.TexImage2D(TextureTarget.Texture2D, 0, gl_solid_format, scaled_width, scaled_height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, handle.AddrOfPinnedObject()); } finally { handle.Free(); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); }
public void Load(UInt32[] table8to24, String name, Byte[] buffer, Func <String, ByteArraySegment, aliashdr_t, Int32> onLoadSkinTexture, Action <AliasModelData, aliashdr_t> onMakeAliasModelDisplayList) { Name = name; Buffer = buffer; var pinmodel = Utilities.BytesToStructure <mdl_t>(Buffer, 0); var version = EndianHelper.LittleLong(pinmodel.version); if (version != ModelDef.ALIAS_VERSION) { Utilities.Error("{0} has wrong version number ({1} should be {2})", Name, version, ModelDef.ALIAS_VERSION); } // // allocate space for a working header, plus all the data except the frames, // skin and group info // Header = new aliashdr_t( ); Flags = ( EntityFlags )EndianHelper.LittleLong(pinmodel.flags); // // endian-adjust and copy the data, starting with the alias model header // Header.boundingradius = EndianHelper.LittleFloat(pinmodel.boundingradius); Header.numskins = EndianHelper.LittleLong(pinmodel.numskins); Header.skinwidth = EndianHelper.LittleLong(pinmodel.skinwidth); Header.skinheight = EndianHelper.LittleLong(pinmodel.skinheight); if (Header.skinheight > ModelDef.MAX_LBM_HEIGHT) { Utilities.Error("model {0} has a skin taller than {1}", Name, ModelDef.MAX_LBM_HEIGHT); } Header.numverts = EndianHelper.LittleLong(pinmodel.numverts); if (Header.numverts <= 0) { Utilities.Error("model {0} has no vertices", Name); } if (Header.numverts > ModelDef.MAXALIASVERTS) { Utilities.Error("model {0} has too many vertices", Name); } Header.numtris = EndianHelper.LittleLong(pinmodel.numtris); if (Header.numtris <= 0) { Utilities.Error("model {0} has no triangles", Name); } Header.numframes = EndianHelper.LittleLong(pinmodel.numframes); var numframes = Header.numframes; if (numframes < 1) { Utilities.Error("Mod_LoadAliasModel: Invalid # of frames: {0}\n", numframes); } Header.size = EndianHelper.LittleFloat(pinmodel.size) * ModelDef.ALIAS_BASE_SIZE_RATIO; SyncType = ( SyncType )EndianHelper.LittleLong(( Int32 )pinmodel.synctype); FrameCount = Header.numframes; Header.scale = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.scale)); Header.scale_origin = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.scale_origin)); Header.eyeposition = EndianHelper.LittleVector(Utilities.ToVector(ref pinmodel.eyeposition)); // // load the skins // var offset = LoadAllSkins(table8to24, Header.numskins, new ByteArraySegment(buffer, mdl_t.SizeInBytes), onLoadSkinTexture); // // load base s and t vertices // var stvOffset = offset; // in bytes for (var i = 0; i < Header.numverts; i++, offset += stvert_t.SizeInBytes) { _STVerts[i] = Utilities.BytesToStructure <stvert_t>(buffer, offset); _STVerts[i].onseam = EndianHelper.LittleLong(_STVerts[i].onseam); _STVerts[i].s = EndianHelper.LittleLong(_STVerts[i].s); _STVerts[i].t = EndianHelper.LittleLong(_STVerts[i].t); } // // load triangle lists // var triOffset = stvOffset + Header.numverts * stvert_t.SizeInBytes; offset = triOffset; for (var i = 0; i < Header.numtris; i++, offset += dtriangle_t.SizeInBytes) { _Triangles[i] = Utilities.BytesToStructure <dtriangle_t>(buffer, offset); _Triangles[i].facesfront = EndianHelper.LittleLong(_Triangles[i].facesfront); for (var j = 0; j < 3; j++) { _Triangles[i].vertindex[j] = EndianHelper.LittleLong(_Triangles[i].vertindex[j]); } } // // load the frames // PoseNum = 0; var framesOffset = triOffset + Header.numtris * dtriangle_t.SizeInBytes; Header.frames = new maliasframedesc_t[Header.numframes]; for (var i = 0; i < numframes; i++) { var 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; Type = ModelType.Alias; // FIXME: do this right BoundsMin = -Vector3.One * 16.0f; BoundsMax = -BoundsMin; // // build the draw lists // onMakeAliasModelDisplayList(this, Header); //mesh.MakeAliasModelDisplayLists( mod, Header ); // // move the complete, relocatable alias model to the cache // //cache = Host.Cache.Alloc( aliashdr_t.SizeInBytes * Header.frames.Length * maliasframedesc_t.SizeInBytes, null ); //if ( cache == null ) // return; //cache.data = Header; }
public static BaseAliasModel Create(BaseDevice device, String identifier, BaseTexture texture, aliashdr_t aliasHeader) { return(Create(device, identifier, texture, device.AliasModelType, device.AliasModelDescType, aliasHeader)); }
/// <summary> /// R_SetupAliasFrame /// </summary> protected virtual void SetupAliasFrame(float shadeLight, int frame, double time, aliashdr_t paliashdr, float[] shadeDots) { if (frame >= paliashdr.numframes || frame < 0) { ConsoleWrapper.Print("R_AliasSetupFrame: no such frame {0}\n", frame); frame = 0; } var pose = paliashdr.frames[frame].firstpose; var numposes = paliashdr.frames[frame].numposes; if (numposes > 1) { var interval = paliashdr.frames[frame].interval; pose += ( int )(time / interval) % numposes; } this.DrawAliasFrame(shadeLight, shadeDots, paliashdr, pose); }
protected virtual void DrawAliasBlendedFrame(Single shadeLight, Single[] shadeDots, aliashdr_t paliashdr, Int32 posenum, Int32 posenum2, Single blend) { throw new NotImplementedException( ); }
/// <summary> /// GL_DrawAliasShadow /// </summary> protected virtual void DrawAliasShadow(aliashdr_t paliashdr, int posenum, float lightSpotZ, Vector3 shadeVector) { throw new NotImplementedException( ); }
/* ================= Mod_LoadAliasSkin ================= */ static object Mod_LoadAliasSkin(bspfile.ByteBuffer pin, object pskinindex, int skinsize, aliashdr_t pheader) { int i; Uint8Array pskin; pskin = new Uint8Array(skinsize * render.r_pixbytes); pskinindex = (object)pskin; if (render.r_pixbytes == 1) { Buffer.BlockCopy(pin.buffer, pin.ofs, pskin, 0, skinsize); } else if (render.r_pixbytes == 2) { } else { sys_linux.Sys_Error("Mod_LoadAliasSkin: driver set invalid r_pixbytes: " + render.r_pixbytes + "\n"); } pin.ofs += skinsize; return pskinindex; }
/* * ================= * R_SetupAliasBlendedFrame * * [email protected]: model animation interpolation * ================= */ protected virtual void SetupAliasBlendedFrame(float shadeLight, int frame, double realTime, double time, aliashdr_t paliashdr, float[] shadeDots, ref int poseNum, ref int poseNum2, ref float frameStartTime, ref float frameInterval) { if (frame >= paliashdr.numframes || frame < 0) { ConsoleWrapper.Print("R_AliasSetupFrame: no such frame {0}\n", frame); frame = 0; } var pose = paliashdr.frames[frame].firstpose; var numposes = paliashdr.frames[frame].numposes; if (numposes > 1) { var interval = paliashdr.frames[frame].interval; pose += ( int )(time / interval) % numposes; frameInterval = interval; } else { /* One tenth of a second is a good for most Quake animations. * If the nextthink is longer then the animation is usually meant to pause * ( e.g.check out the shambler magic animation in shambler.qc). If its * shorter then things will still be smoothed partly, and the jumps will be * less noticable because of the shorter time.So, this is probably a good * assumption. */ frameInterval = 0.1f; } var blend = 0f; var e = paliashdr.frames[frame]; if (poseNum2 != pose) { frameStartTime = ( float )realTime; poseNum = poseNum2; poseNum2 = pose; blend = 0; } else { blend = ( float )((realTime - frameStartTime) / frameInterval); } // wierd things start happening if blend passes 1 if (/*cl.paused || */ blend > 1) { blend = 1; } this.DrawAliasBlendedFrame(shadeLight, shadeDots, paliashdr, poseNum, poseNum2, blend); }
/* ============================================================================== ALIAS MODELS ============================================================================== */ /* ================= Mod_LoadAliasFrame ================= */ static void Mod_LoadAliasFrame(bspfile.ByteBuffer pin, ref object pframeindex, int numv, trivertx_t pbboxmin, trivertx_t pbboxmax, aliashdr_t pheader, string name) { trivertx_t[] pframe; trivertx_t pinframe; int i, j; daliasframe_t pdaliasframe; pdaliasframe = (daliasframe_t)pin; name = pdaliasframe.name; for (i=0 ; i<3 ; i++) { // these are byte values, so we don't have to worry about // endianness pbboxmin.v[i] = pdaliasframe.bboxmin.v[i]; pbboxmax.v[i] = pdaliasframe.bboxmax.v[i]; } pin.ofs += sizeof_daliasframe_t; pframe = new trivertx_t[numv]; pframeindex = (object)pframe; for (j=0 ; j<numv ; j++) { int k; pinframe = (trivertx_t)pin; // these are all byte values, so no need to deal with endianness pframe[j] = new trivertx_t(); pframe[j].lightnormalindex = pinframe.lightnormalindex; for (k=0 ; k<3 ; k++) { pframe[j].v[k] = pinframe.v[k]; } pin.ofs += sizeof_trivertx_t; } }
public static void GL_MakeAliasModelDisplayLists(model_t m, aliashdr_t hdr) { aliasmodel = m; paliashdr = hdr; // // look for a cached version // string path = Path.ChangeExtension("glquake/" + Path.GetFileNameWithoutExtension(m.name), ".ms2"); DisposableWrapper <BinaryReader> file; COM_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_Printf("meshing {0}...\n", m.name); BuildTris(); // trifans or lists // // save out the cached version // string fullpath = Path.Combine(com_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 // paliashdr.poseverts = numorder; int[] cmds = new int[numcommands]; //Hunk_Alloc (numcommands * 4); paliashdr.commands = cmds; // in bytes??? // (byte*)cmds - (byte*)paliashdr; Buffer.BlockCopy(commands, 0, cmds, 0, numcommands * 4); //memcpy (cmds, commands, numcommands * 4); trivertx_t[] verts = new trivertx_t[paliashdr.numposes * paliashdr.poseverts]; // Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t) ); paliashdr.posedata = verts; // (byte*)verts - (byte*)paliashdr; int offset = 0; for (int i = 0; i < paliashdr.numposes; i++) { for (int j = 0; j < numorder; j++) { verts[offset++] = poseverts[i][vertexorder[j]]; // *verts++ = poseverts[i][vertexorder[j]]; } } }
/* ================= Mod_LoadAliasGroup ================= */ static void Mod_LoadAliasGroup(bspfile.ByteBuffer pin, ref object pframeindex, int numv, trivertx_t pbboxmin, trivertx_t pbboxmax, aliashdr_t pheader, string name) { daliasgroup_t pingroup; maliasgroup_t paliasgroup; int i, numframes; double[] poutintervals; pingroup = (daliasgroup_t)pin; numframes = pingroup.numframes; paliasgroup = new maliasgroup_t(); paliasgroup.frames = new maliasgroupframedesc_t[numframes]; for (int kk = 0; kk < numframes; kk++) paliasgroup.frames[kk] = new maliasgroupframedesc_t(); paliasgroup.numframes = numframes; for (i=0 ; i<3 ; i++) { // these are byte values, so we don't have to worry about endianness pbboxmin.v[i] = pingroup.bboxmin.v[i]; pbboxmax.v[i] = pingroup.bboxmax.v[i]; } pframeindex = (object)paliasgroup; pin.ofs += sizeof_daliasgroup_t; poutintervals = new double[numframes]; paliasgroup.intervals = poutintervals; for (i = 0; i < numframes; i++) { poutintervals[i] = BitConverter.ToSingle(pin.buffer, pin.ofs); pin.ofs += sizeof(Single); if (poutintervals[i] <= 0.0) sys_linux.Sys_Error("Mod_LoadAliasGroup: interval<=0"); } for (i=0 ; i<numframes ; i++) { Mod_LoadAliasFrame (pin, ref paliasgroup.frames[i].frame, numv, paliasgroup.frames[i].bboxmin, paliasgroup.frames[i].bboxmax, pheader, name); } }