/* * ================ * R_DrawSubmodelPolygons * ================ */ static void R_DrawSubmodelPolygons(model.model_t pmodel, int clipflags) { int i; double dot; model.msurface_t psurf; int numsurfaces; model.mplane_t pplane; // FIXME: use bounding-box-based frustum clipping info? numsurfaces = pmodel.nummodelsurfaces; for (i = 0; i < numsurfaces; i++) { psurf = pmodel.surfaces[pmodel.firstmodelsurface + i]; // find which side of the node we are on pplane = psurf.plane; dot = mathlib.DotProduct(modelorg, pplane.normal) - pplane.dist; // draw the polygon if (((psurf.flags & model.SURF_PLANEBACK) != 0 && (dot < -BACKFACE_EPSILON)) || ((psurf.flags & model.SURF_PLANEBACK) == 0 && (dot > BACKFACE_EPSILON))) { r_currentkey = ((model.mleaf_t)currententity.topnode).key; // FIXME: use bounding-box-based frustum clipping info? R_RenderFace(psurf, clipflags); } } }
public server_t() { for (int kk = 0; kk < quakedef.MAX_MODELS; kk++) { models[kk] = new model.model_t(); } }
/* * ================= * CL_ParseBeam * ================= */ static void CL_ParseBeam(model.model_t m) { int ent; double[] start = new double[3], end = new double[3]; beam_t b; int i; ent = common.MSG_ReadShort(); start[0] = common.MSG_ReadCoord(); start[1] = common.MSG_ReadCoord(); start[2] = common.MSG_ReadCoord(); end[0] = common.MSG_ReadCoord(); end[1] = common.MSG_ReadCoord(); end[2] = common.MSG_ReadCoord(); // override any beam with the same entity for (i = 0, b = cl_beams[i]; i < MAX_BEAMS; i++) { b = cl_beams[i]; } if (b.entity == ent) { b.entity = ent; b.model = m; b.endtime = cl.time + 0.2; mathlib.VectorCopy(start, ref b.start); mathlib.VectorCopy(end, ref b.end); return; } // find a free beam for (i = 0, b = cl_beams[i]; i < MAX_BEAMS; i++) { b = cl_beams[i]; if (b.model == null || b.endtime < cl.time) { b.entity = ent; b.model = m; b.endtime = cl.time + 0.2; mathlib.VectorCopy(start, ref b.start); mathlib.VectorCopy(end, ref b.end); return; } } console.Con_Printf("beam list overflow!\n"); }
public server_t() { for(int kk = 0; kk < quakedef.MAX_MODELS; kk++) models[kk] = new model.model_t(); }
/* * ================ * R_ZDrawSubmodelPolys * ================ */ static void R_ZDrawSubmodelPolys(model.model_t pmodel) { }
/* ================ R_AliasCheckBBox ================ */ static bool R_AliasCheckBBox() { int i, flags, frame, numv; model.aliashdr_t pahdr; double zi, v0, v1, frac; double[][] basepts = new double[8][]; draw.finalvert_t pv0, pv1; draw.finalvert_t[] viewpts = new draw.finalvert_t[16]; auxvert_t pa0, pa1; auxvert_t[] viewaux = new auxvert_t[16]; model.maliasframedesc_t pframedesc; bool zclipped, zfullyclipped; uint anyclip, allclip; int minz; int kk; for (kk = 0; kk < 16; kk++) viewpts[kk] = new draw.finalvert_t(); for (kk = 0; kk < 16; kk++) viewaux[kk] = new auxvert_t(); for (kk = 0; kk < 8; kk++) basepts[kk] = new double[3]; // expand, rotate, and translate points into worldspace currententity.trivial_accept = 0; pmodel = currententity.model; pahdr = (model.aliashdr_t)model.Mod_Extradata (pmodel); pmdl = (model.mdl_t)pahdr.model; R_AliasSetUpTransform (0); // construct the base bounding box for this frame frame = currententity.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl.numframes) || (frame < 0)) { console.Con_DPrintf ("No such frame " + frame + " " + pmodel.name + "\n"); frame = 0; } pframedesc = pahdr.frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (double)pframedesc.bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (double)pframedesc.bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (double)pframedesc.bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (double)pframedesc.bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (double)pframedesc.bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (double)pframedesc.bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i=0; i<8 ; i++) { R_AliasTransformVector (basepts[i], ref viewaux[i].fv); if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { // we must clip points that are closer than the near clip plane viewpts[i].flags = ALIAS_Z_CLIP; zclipped = true; } else { if (viewaux[i].fv[2] < minz) minz = (int)viewaux[i].fv[2]; viewpts[i].flags = 0; zfullyclipped = false; } } if (zfullyclipped) { return false; // everything was near-z-clipped } numv = 8; if (zclipped) { // organize points by edges, use edges to get new points (possible trivial // reject) for (i=0 ; i<12 ; i++) { // edge endpoints pv0 = viewpts[aedges[i].index0]; pv1 = viewpts[aedges[i].index1]; pa0 = viewaux[aedges[i].index0]; pa1 = viewaux[aedges[i].index1]; // if one end is clipped and the other isn't, make a new point if ((pv0.flags ^ pv1.flags) != 0) { frac = (ALIAS_Z_CLIP_PLANE - pa0.fv[2]) / (pa1.fv[2] - pa0.fv[2]); viewaux[numv].fv[0] = pa0.fv[0] + (pa1.fv[0] - pa0.fv[0]) * frac; viewaux[numv].fv[1] = pa0.fv[1] + (pa1.fv[1] - pa0.fv[1]) * frac; viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; viewpts[numv].flags = 0; numv++; } } } // project the vertices that remain after clipping anyclip = 0; allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats for (i=0 ; i<numv ; i++) { // we don't need to bother with vertices that were z-clipped if ((viewpts[i].flags & ALIAS_Z_CLIP) != 0) continue; zi = 1.0 / viewaux[i].fv[2]; // FIXME: do with chop mode in ASM, or convert to float v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; flags = 0; if (v0 < r_refdef.fvrectx) flags |= ALIAS_LEFT_CLIP; if (v1 < r_refdef.fvrecty) flags |= ALIAS_TOP_CLIP; if (v0 > r_refdef.fvrectright) flags |= ALIAS_RIGHT_CLIP; if (v1 > r_refdef.fvrectbottom) flags |= ALIAS_BOTTOM_CLIP; anyclip |= (uint)flags; allclip &= (uint)flags; } if (allclip != 0) return false; // trivial reject off one side currententity.trivial_accept = ((anyclip == 0) && !zclipped) ? 1 : 0; if (currententity.trivial_accept != 0) { if (minz > (r_aliastransition + (pmdl.size * r_resfudge))) { currententity.trivial_accept |= 2; } } return true; }
/* * ================ * R_DrawSolidClippedSubmodelPolygons * ================ */ static void R_DrawSolidClippedSubmodelPolygons(model.model_t pmodel) { int i, j, lindex; double dot; model.msurface_t psurf; int numsurfaces; model.mplane_t pplane; model.mvertex_t[] bverts = new model.mvertex_t[MAX_BMODEL_VERTS]; bedge_t[] bedges = new bedge_t[MAX_BMODEL_EDGES]; int pbedge; model.medge_t pedge; model.medge_t[] pedges; int kk; for (kk = 0; kk < MAX_BMODEL_VERTS; kk++) { bverts[kk] = new model.mvertex_t(); } for (kk = 0; kk < MAX_BMODEL_EDGES; kk++) { bedges[kk] = new bedge_t(); } // FIXME: use bounding-box-based frustum clipping info? numsurfaces = pmodel.nummodelsurfaces; pedges = pmodel.edges; for (i = 0; i < numsurfaces; i++) { psurf = pmodel.surfaces[pmodel.firstmodelsurface + i]; // find which side of the node we are on pplane = psurf.plane; dot = mathlib.DotProduct(modelorg, pplane.normal) - pplane.dist; // draw the polygon if (((psurf.flags & model.SURF_PLANEBACK) != 0 && (dot < -BACKFACE_EPSILON)) || ((psurf.flags & model.SURF_PLANEBACK) == 0 && (dot > BACKFACE_EPSILON))) { // FIXME: use bounding-box-based frustum clipping info? // copy the edges to bedges, flipping if necessary so always // clockwise winding // FIXME: if edges and vertices get caches, these assignments must move // outside the loop, and overflow checking must be done here pbverts = bverts; pbedges = bedges; numbverts = numbedges = 0; if (psurf.numedges > 0) { pbedge = numbedges; numbedges += psurf.numedges; for (j = 0; j < psurf.numedges; j++) { lindex = pmodel.surfedges[psurf.firstedge + j]; if (lindex > 0) { pedge = pedges[lindex]; bedges[pbedge + j].v[0] = r_pcurrentvertbase[pedge.v[0]]; bedges[pbedge + j].v[1] = r_pcurrentvertbase[pedge.v[1]]; } else { lindex = -lindex; pedge = pedges[lindex]; bedges[pbedge + j].v[0] = r_pcurrentvertbase[pedge.v[1]]; bedges[pbedge + j].v[1] = r_pcurrentvertbase[pedge.v[0]]; } bedges[pbedge + j].pnext = bedges[pbedge + j + 1]; } bedges[pbedge + j - 1].pnext = null; // mark end of edges R_RecursiveClipBPoly(bedges[pbedge], (model.mnode_t)currententity.topnode, psurf); } else { sys_linux.Sys_Error("no edges in bmodel"); } } } }
/* * ============= * R_BmodelCheckBBox * ============= */ static int R_BmodelCheckBBox(model.model_t clmodel, double[] minmaxs) { int i, pindex, clipflags; double[] acceptpt = new double[3], rejectpt = new double[3]; double d; clipflags = 0; if (currententity.angles[0] != 0 || currententity.angles[1] != 0 || currententity.angles[2] != 0) { for (i = 0; i < 4; i++) { d = mathlib.DotProduct(currententity.origin, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= -clmodel.radius) { return(BMODEL_FULLY_CLIPPED); } if (d <= clmodel.radius) { clipflags |= (1 << i); } } } else { for (i = 0; i < 4; i++) { // generate accept and reject points // FIXME: do with fast look-ups or integer tests based on the sign bit // of the floating point values pindex = pfrustum_indexes[i]; rejectpt[0] = minmaxs[r_frustum_indexes[pindex + 0]]; rejectpt[1] = minmaxs[r_frustum_indexes[pindex + 1]]; rejectpt[2] = minmaxs[r_frustum_indexes[pindex + 2]]; d = mathlib.DotProduct(rejectpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) { return(BMODEL_FULLY_CLIPPED); } acceptpt[0] = minmaxs[r_frustum_indexes[pindex + 3 + 0]]; acceptpt[1] = minmaxs[r_frustum_indexes[pindex + 3 + 1]]; acceptpt[2] = minmaxs[r_frustum_indexes[pindex + 3 + 2]]; d = mathlib.DotProduct(acceptpt, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= 0) { clipflags |= (1 << i); } } } return(clipflags); }
/* * ================ * R_AliasCheckBBox * ================ */ static bool R_AliasCheckBBox() { int i, flags, frame, numv; model.aliashdr_t pahdr; double zi, v0, v1, frac; double[][] basepts = new double[8][]; draw.finalvert_t pv0, pv1; draw.finalvert_t[] viewpts = new draw.finalvert_t[16]; auxvert_t pa0, pa1; auxvert_t[] viewaux = new auxvert_t[16]; model.maliasframedesc_t pframedesc; bool zclipped, zfullyclipped; uint anyclip, allclip; int minz; int kk; for (kk = 0; kk < 16; kk++) { viewpts[kk] = new draw.finalvert_t(); } for (kk = 0; kk < 16; kk++) { viewaux[kk] = new auxvert_t(); } for (kk = 0; kk < 8; kk++) { basepts[kk] = new double[3]; } // expand, rotate, and translate points into worldspace currententity.trivial_accept = 0; pmodel = currententity.model; pahdr = (model.aliashdr_t)model.Mod_Extradata(pmodel); pmdl = (model.mdl_t)pahdr.model; R_AliasSetUpTransform(0); // construct the base bounding box for this frame frame = currententity.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl.numframes) || (frame < 0)) { console.Con_DPrintf("No such frame " + frame + " " + pmodel.name + "\n"); frame = 0; } pframedesc = pahdr.frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (double)pframedesc.bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (double)pframedesc.bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (double)pframedesc.bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (double)pframedesc.bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (double)pframedesc.bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (double)pframedesc.bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i = 0; i < 8; i++) { R_AliasTransformVector(basepts[i], ref viewaux[i].fv); if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { // we must clip points that are closer than the near clip plane viewpts[i].flags = ALIAS_Z_CLIP; zclipped = true; } else { if (viewaux[i].fv[2] < minz) { minz = (int)viewaux[i].fv[2]; } viewpts[i].flags = 0; zfullyclipped = false; } } if (zfullyclipped) { return(false); // everything was near-z-clipped } numv = 8; if (zclipped) { // organize points by edges, use edges to get new points (possible trivial // reject) for (i = 0; i < 12; i++) { // edge endpoints pv0 = viewpts[aedges[i].index0]; pv1 = viewpts[aedges[i].index1]; pa0 = viewaux[aedges[i].index0]; pa1 = viewaux[aedges[i].index1]; // if one end is clipped and the other isn't, make a new point if ((pv0.flags ^ pv1.flags) != 0) { frac = (ALIAS_Z_CLIP_PLANE - pa0.fv[2]) / (pa1.fv[2] - pa0.fv[2]); viewaux[numv].fv[0] = pa0.fv[0] + (pa1.fv[0] - pa0.fv[0]) * frac; viewaux[numv].fv[1] = pa0.fv[1] + (pa1.fv[1] - pa0.fv[1]) * frac; viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; viewpts[numv].flags = 0; numv++; } } } // project the vertices that remain after clipping anyclip = 0; allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats for (i = 0; i < numv; i++) { // we don't need to bother with vertices that were z-clipped if ((viewpts[i].flags & ALIAS_Z_CLIP) != 0) { continue; } zi = 1.0 / viewaux[i].fv[2]; // FIXME: do with chop mode in ASM, or convert to float v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; flags = 0; if (v0 < r_refdef.fvrectx) { flags |= ALIAS_LEFT_CLIP; } if (v1 < r_refdef.fvrecty) { flags |= ALIAS_TOP_CLIP; } if (v0 > r_refdef.fvrectright) { flags |= ALIAS_RIGHT_CLIP; } if (v1 > r_refdef.fvrectbottom) { flags |= ALIAS_BOTTOM_CLIP; } anyclip |= (uint)flags; allclip &= (uint)flags; } if (allclip != 0) { return(false); // trivial reject off one side } currententity.trivial_accept = ((anyclip == 0) && !zclipped) ? 1 : 0; if (currententity.trivial_accept != 0) { if (minz > (r_aliastransition + (pmdl.size * r_resfudge))) { currententity.trivial_accept |= 2; } } return(true); }