//should be ok. public static void WriteDir(sizebuf_t sb, float[] dir) { int i, best; float d, bestd; if (dir == null) { MSG.WriteByte(sb, 0); return; } bestd = 0; best = 0; for (i = 0; i < Defines.NUMVERTEXNORMALS; i++) { d = Math3D.DotProduct(dir, Globals.bytedirs[i]); if (d > bestd) { bestd = d; best = i; } } MSG.WriteByte(sb, best); }
/* * =============== * Mod_PointInLeaf * =============== */ protected mleaf_t Mod_PointInLeaf(float[] p, model_t model) { mnode_t node; float d; cplane_t plane; if (model == null || model.nodes == null) { Com.Error(Defines.ERR_DROP, "Mod_PointInLeaf: bad model"); } node = model.nodes[0]; // root node while (true) { if (node.contents != -1) { return((mleaf_t)node); } plane = node.plane; d = Math3D.DotProduct(p, plane.normal) - plane.dist; if (d > 0) { node = node.children[0]; } else { node = node.children[1]; } } // never reached }
public override void Touch(edict_t self, edict_t other, cplane_t plane, csurface_t surf) { if (other.client != null) { if ((self.spawnflags & 2) != 0) { return; } } else if ((other.svflags & Defines.SVF_MONSTER) != 0) { if (0 == (self.spawnflags & 1)) { return; } } else { return; } if (!Math3D.VectorEquals(self.movedir, Globals.vec3_origin)) { float[] forward = new float[] { 0, 0, 0 }; Math3D.AngleVectors(other.s.angles, forward, null, null); if (Math3D.DotProduct(forward, self.movedir) < 0) { return; } } self.activator = other; Multi_trigger(self); }
public static void WriteDir(sizebuf_t sb, Single[] dir) { Int32 i, best; Single d, bestd; if (dir == null) { WriteByte(sb, 0); return; } bestd = 0; best = 0; for (i = 0; i < NUMVERTEXNORMALS; i++) { d = Math3D.DotProduct(dir, bytedirs[i]); if (d > bestd) { bestd = d; best = i; } } WriteByte(sb, best); }
public override mleaf_t Mod_PointInLeaf(Single[] p, model_t model) { mnode_t node; Single d; cplane_t plane; if (model == null || model.nodes == null) { Com.Error(Defines.ERR_DROP, "Mod_PointInLeaf: bad model"); } node = model.nodes[0]; while (true) { if (node.contents != -1) { return(( mleaf_t )node); } plane = node.plane; d = Math3D.DotProduct(p, plane.normal) - plane.dist; if (d > 0) { node = node.children[0]; } else { node = node.children[1]; } } }
public static void PM_AirAccelerate(Single[] wishdir, Single wishspeed, Single accel) { Int32 i; Single addspeed, accelspeed, currentspeed, wishspd = wishspeed; if (wishspd > 30) { wishspd = 30; } currentspeed = Math3D.DotProduct(pml.velocity, wishdir); addspeed = wishspd - currentspeed; if (addspeed <= 0) { return; } accelspeed = accel * wishspeed * pml.frametime; if (accelspeed > addspeed) { accelspeed = addspeed; } for (i = 0; i < 3; i++) { pml.velocity[i] += accelspeed * wishdir[i]; } }
public static int ClipVelocity(float[] in_renamed, float[] normal, float[] out_renamed, float overbounce) { float backoff; float change; int i, blocked; blocked = 0; if (normal[2] > 0) { blocked |= 1; } if (normal[2] == 0F) { blocked |= 2; } backoff = Math3D.DotProduct(in_renamed, normal) * overbounce; for (i = 0; i < 3; i++) { change = normal[i] * backoff; out_renamed[i] = in_renamed[i] - change; if (out_renamed[i] > -STOP_EPSILON && out_renamed[i] < STOP_EPSILON) { out_renamed[i] = 0; } } return(blocked); }
public virtual void R_DrawInlineBModel( ) { if (gl_flashblend.value == 0) { dlight_t lt; for (var k = 0; k < r_newrefdef.num_dlights; k++) { lt = r_newrefdef.dlights[k]; R_MarkLights(lt, 1 << k, currentmodel.nodes[currentmodel.firstnode]); } } var psurfp = currentmodel.firstmodelsurface; msurface_t[] surfaces = currentmodel.surfaces; if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) { GL.Enable(EnableCap.Blend); GL.Color4(1, 1, 1, 0.25F); GL_TexEnv(( Int32 )All.Modulate); } msurface_t psurf; cplane_t pplane; Single dot; for (var i = 0; i < currentmodel.nummodelsurfaces; i++) { psurf = surfaces[psurfp++]; pplane = psurf.plane; dot = Math3D.DotProduct(modelorg, pplane.normal) - pplane.dist; if (((psurf.flags & Defines.SURF_PLANEBACK) != 0 && (dot < -BACKFACE_EPSILON)) || ((psurf.flags & Defines.SURF_PLANEBACK) == 0 && (dot > BACKFACE_EPSILON))) { if ((psurf.texinfo.flags & (Defines.SURF_TRANS33 | Defines.SURF_TRANS66)) != 0) { psurf.texturechain = r_alpha_surfaces; r_alpha_surfaces = psurf; } else if ((psurf.flags & Defines.SURF_DRAWTURB) == 0) { GL_RenderLightmappedPoly(psurf); } else { GL_EnableMultitexture(false); R_RenderBrushPoly(psurf); GL_EnableMultitexture(true); } } } if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) { GL.Disable(EnableCap.Blend); GL.Color4(1, 1, 1, 1); GL_TexEnv(( Int32 )All.Replace); } }
public virtual void GL_BuildPolygonFromSurface(msurface_t fa) { Int32 lindex, lnumverts; medge_t[] pedges; medge_t r_pedge; Single[] vec; Single s, t; glpoly_t poly; Single[] total = new Single[] { 0, 0, 0 }; pedges = currentmodel.edges; lnumverts = fa.numedges; Math3D.VectorClear(total); poly = Polygon.Create(lnumverts); poly.next = fa.polys; poly.flags = fa.flags; fa.polys = poly; for (var i = 0; i < lnumverts; i++) { lindex = currentmodel.surfedges[fa.firstedge + i]; if (lindex > 0) { r_pedge = pedges[lindex]; vec = currentmodel.vertexes[r_pedge.v[0]].position; } else { r_pedge = pedges[-lindex]; vec = currentmodel.vertexes[r_pedge.v[1]].position; } s = Math3D.DotProduct(vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3]; s /= fa.texinfo.image.width; t = Math3D.DotProduct(vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3]; t /= fa.texinfo.image.height; Math3D.VectorAdd(total, vec, total); poly.X(i, vec[0]); poly.Y(i, vec[1]); poly.Z(i, vec[2]); poly.S1(i, s); poly.T1(i, t); s = Math3D.DotProduct(vec, fa.texinfo.vecs[0]) + fa.texinfo.vecs[0][3]; s -= fa.texturemins[0]; s += fa.light_s * 16; s += 8; s /= BLOCK_WIDTH * 16; t = Math3D.DotProduct(vec, fa.texinfo.vecs[1]) + fa.texinfo.vecs[1][3]; t -= fa.texturemins[1]; t += fa.light_t * 16; t += 8; t /= BLOCK_HEIGHT * 16; poly.S2(i, s); poly.T2(i, t); } }
/* * ============================================================================= * * DYNAMIC LIGHTS * * ============================================================================= */ /* * ============= R_MarkLights ============= */ protected void R_MarkLights(dlight_t light, int bit, mnode_t node) { cplane_t splitplane; float dist; msurface_t surf; int i; int sidebit; if (node.contents != -1) { return; } splitplane = node.plane; dist = Math3D.DotProduct(light.origin, splitplane.normal) - splitplane.dist; if (dist > light.intensity - OpenGLRenderApi.DLIGHT_CUTOFF) { this.R_MarkLights(light, bit, node.children[0]); return; } if (dist < -light.intensity + OpenGLRenderApi.DLIGHT_CUTOFF) { this.R_MarkLights(light, bit, node.children[1]); return; } // mark the polygons for (i = 0; i < node.numsurfaces; i++) { surf = this.r_worldmodel.surfaces[node.firstsurface + i]; dist = Math3D.DotProduct(light.origin, surf.plane.normal) - surf.plane.dist; sidebit = dist >= 0 ? 0 : Defines.SURF_PLANEBACK; if ((surf.flags & Defines.SURF_PLANEBACK) != sidebit) { continue; } if (surf.dlightframe != this.r_dlightframecount) { surf.dlightbits = 0; surf.dlightframe = this.r_dlightframecount; } surf.dlightbits |= bit; } this.R_MarkLights(light, bit, node.children[0]); this.R_MarkLights(light, bit, node.children[1]); }
public virtual void R_SetFrustum( ) { Math3D.RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90F - r_newrefdef.fov_x / 2F)); Math3D.RotatePointAroundVector(frustum[1].normal, vup, vpn, 90F - r_newrefdef.fov_x / 2F); Math3D.RotatePointAroundVector(frustum[2].normal, vright, vpn, 90F - r_newrefdef.fov_y / 2F); Math3D.RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90F - r_newrefdef.fov_y / 2F)); for (var i = 0; i < 4; i++) { frustum[i].type = Defines.PLANE_ANYZ; frustum[i].dist = Math3D.DotProduct(r_origin, frustum[i].normal); frustum[i].signbits = ( Byte )SignbitsForPlane(frustum[i]); } }
/* * =============== CL_TrackerTrail =============== */ public static void TrackerTrail(float[] start, float[] end, int particleColor) { float len; cparticle_t p; int dec; float dist; Math3D.VectorCopy(start, CL_newfx.move); Math3D.VectorSubtract(end, start, CL_newfx.vec); len = Math3D.VectorNormalize(CL_newfx.vec); Math3D.VectorCopy(CL_newfx.vec, CL_newfx.forward); Math3D.vectoangles(CL_newfx.forward, CL_newfx.angle_dir); Math3D.AngleVectors(CL_newfx.angle_dir, CL_newfx.forward, CL_newfx.right, CL_newfx.up); dec = 3; Math3D.VectorScale(CL_newfx.vec, 3, CL_newfx.vec); // FIXME: this is a really silly way to have a loop while (len > 0) { len -= dec; if (CL_fx.free_particles == null) { return; } p = CL_fx.free_particles; CL_fx.free_particles = p.next; p.next = CL_fx.active_particles; CL_fx.active_particles = p; Math3D.VectorClear(p.accel); p.time = Globals.cl.time; p.alpha = 1.0f; p.alphavel = -2.0f; p.color = particleColor; dist = Math3D.DotProduct(CL_newfx.move, CL_newfx.forward); Math3D.VectorMA(CL_newfx.move, (float)(8 * Math.Cos(dist)), CL_newfx.up, p.org); for (var j = 0; j < 3; j++) { p.vel[j] = 0; p.accel[j] = 0; } p.vel[2] = 5; Math3D.VectorAdd(CL_newfx.move, CL_newfx.vec, CL_newfx.move); } }
public static bool Infront(edict_t self, edict_t other) { float[] vec = new float[] { 0, 0, 0 }; float dot; float[] forward = new float[] { 0, 0, 0 }; Math3D.AngleVectors(self.s.angles, forward, null, null); Math3D.VectorSubtract(other.s.origin, self.s.origin, vec); Math3D.VectorNormalize(vec); dot = Math3D.DotProduct(vec, forward); if (dot > 0.3) { return(true); } return(false); }
public override void R_MarkLights(dlight_t light, Int32 bit, mnode_t node) { cplane_t splitplane; Single dist; msurface_t surf; Int32 i; Int32 sidebit; if (node.contents != -1) { return; } splitplane = node.plane; dist = Math3D.DotProduct(light.origin, splitplane.normal) - splitplane.dist; if (dist > light.intensity - DLIGHT_CUTOFF) { R_MarkLights(light, bit, node.children[0]); return; } if (dist < -light.intensity + DLIGHT_CUTOFF) { R_MarkLights(light, bit, node.children[1]); return; } for (i = 0; i < node.numsurfaces; i++) { surf = r_worldmodel.surfaces[node.firstsurface + i]; dist = Math3D.DotProduct(light.origin, surf.plane.normal) - surf.plane.dist; sidebit = (dist >= 0) ? 0 : Defines.SURF_PLANEBACK; if ((surf.flags & Defines.SURF_PLANEBACK) != sidebit) { continue; } if (surf.dlightframe != r_dlightframecount) { surf.dlightbits = 0; surf.dlightframe = r_dlightframecount; } surf.dlightbits |= bit; } R_MarkLights(light, bit, node.children[0]); R_MarkLights(light, bit, node.children[1]); }
static void SpatializeOrigin(Single[] origin, Single master_vol, Single dist_mult, channel_t ch) { Single dot; Single dist; Single lscale, rscale, scale; Single[] source_vec = new Single[] { 0, 0, 0 }; if (cls.state != ca_active) { ch.leftvol = ch.rightvol = 255; return; } Math3D.VectorSubtract(origin, listener_origin, source_vec); dist = Math3D.VectorNormalize(source_vec); dist -= SOUND_FULLVOLUME; if (dist < 0) { dist = 0; } dist *= dist_mult; dot = Math3D.DotProduct(listener_right, source_vec); if (dma.channels == 1 || dist_mult == 0F) { rscale = 1F; lscale = 1F; } else { rscale = 0.5F * (1F + dot); lscale = 0.5F * (1F - dot); } scale = (1F - dist) * rscale; ch.rightvol = ( Int32 )(master_vol * scale); if (ch.rightvol < 0) { ch.rightvol = 0; } scale = (1F - dist) * lscale; ch.leftvol = ( Int32 )(master_vol * scale); if (ch.leftvol < 0) { ch.leftvol = 0; } }
public static void PM_ClipVelocity(Single[] in_renamed, Single[] normal, Single[] out_renamed, Single overbounce) { Single backoff; Single change; Int32 i; backoff = Math3D.DotProduct(in_renamed, normal) * overbounce; for (i = 0; i < 3; i++) { change = normal[i] * backoff; out_renamed[i] = in_renamed[i] - change; if (out_renamed[i] > -Defines.MOVE_STOP_EPSILON && out_renamed[i] < Defines.MOVE_STOP_EPSILON) { out_renamed[i] = 0; } } }
public static void TrackerTrail(float[] start, float[] end, int particleColor) { float len; cparticle_t p; int dec; float dist; Math3D.VectorCopy(start, move); Math3D.VectorSubtract(end, start, vec); len = Math3D.VectorNormalize(vec); Math3D.VectorCopy(vec, forward); Math3D.Vectoangles(forward, angle_dir); Math3D.AngleVectors(angle_dir, forward, right, up); dec = 3; Math3D.VectorScale(vec, 3, vec); while (len > 0) { len -= dec; if (CL_fx.free_particles == null) { return; } p = CL_fx.free_particles; CL_fx.free_particles = p.next; p.next = CL_fx.active_particles; CL_fx.active_particles = p; Math3D.VectorClear(p.accel); p.time = Globals.cl.time; p.alpha = 1F; p.alphavel = -2F; p.color = particleColor; dist = Math3D.DotProduct(move, forward); Math3D.VectorMA(move, (float)(8 * Math.Cos(dist)), up, p.org); for (int j = 0; j < 3; j++) { p.vel[j] = 0; p.accel[j] = 0; } p.vel[2] = 5; Math3D.VectorAdd(move, vec, move); } }
public static float SV_CalcRoll(float[] angles, float[] velocity) { float sign; float side; float value; side = Math3D.DotProduct(velocity, right); sign = side < 0 ? -1 : 1; side = Math.Abs(side); value = GameBase.sv_rollangle.value; if (side < GameBase.sv_rollspeed.value) { side = side * value / GameBase.sv_rollspeed.value; } else { side = value; } return(side * sign); }
public void WriteDir(float[] dir) { if (dir == null) { WriteByte(0); return; } float bestd = 0; byte best = 0; for (byte index = 0; index < Math3D.VertexNormals.Length; index++) { float d = Math3D.DotProduct(dir, Math3D.VertexNormals[index]); if (d > bestd) { bestd = d; best = index; } } WriteByte(best); }
public override void R_DrawBrushModel(entity_t e) { if (currentmodel.nummodelsurfaces == 0) { return; } currententity = e; gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1; System.Boolean rotated; if (e.angles[0] != 0 || e.angles[1] != 0 || e.angles[2] != 0) { rotated = true; for (var i = 0; i < 3; i++) { mins[i] = e.origin[i] - currentmodel.radius; maxs[i] = e.origin[i] + currentmodel.radius; } } else { rotated = false; Math3D.VectorAdd(e.origin, currentmodel.mins, mins); Math3D.VectorAdd(e.origin, currentmodel.maxs, maxs); } if (R_CullBox(mins, maxs)) { return; } GL.Color3(1, 1, 1); Math3D.VectorSubtract(r_newrefdef.vieworg, e.origin, modelorg); if (rotated) { Math3D.VectorCopy(modelorg, org); Math3D.AngleVectors(e.angles, forward, right, up); modelorg[0] = Math3D.DotProduct(org, forward); modelorg[1] = -Math3D.DotProduct(org, right); modelorg[2] = Math3D.DotProduct(org, up); } GL.PushMatrix(); e.angles[0] = -e.angles[0]; e.angles[2] = -e.angles[2]; R_RotateForEntity(e); e.angles[0] = -e.angles[0]; e.angles[2] = -e.angles[2]; GL_EnableMultitexture(true); GL_SelectTexture(TextureUnit.Texture0); GL_TexEnv(( Int32 )All.Replace); GL.InterleavedArrays(InterleavedArrayFormat.T2fV3f, glpoly_t.BYTE_STRIDE, globalPolygonInterleavedBuf.Array); GL_SelectTexture(TextureUnit.Texture1); GL_TexEnv(( Int32 )All.Modulate); new Pinnable(globalPolygonTexCoord1Buf, (ptr) => { GL.TexCoordPointer(2, TexCoordPointerType.Float, glpoly_t.BYTE_STRIDE, ptr); }); GL.EnableClientState(ArrayCap.TextureCoordArray); R_DrawInlineBModel(); GL.ClientActiveTexture(TextureUnit.Texture1); GL.DisableClientState(ArrayCap.TextureCoordArray); GL_EnableMultitexture(false); GL.PopMatrix(); }
public static void PM_FlyMove(Boolean doclip) { Single speed, drop, friction, control, newspeed; Single currentspeed, addspeed, accelspeed; Int32 i; Single[] wishvel = new Single[] { 0, 0, 0 }; Single fmove, smove; Single[] wishdir = new Single[] { 0, 0, 0 }; Single wishspeed; Single[] end = new Single[] { 0, 0, 0 }; trace_t trace; pm.viewheight = 22; speed = Math3D.VectorLength(pml.velocity); if (speed < 1) { Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); } else { drop = 0; friction = pm_friction * 1.5F; control = speed < pm_stopspeed ? pm_stopspeed : speed; drop += control * friction * pml.frametime; newspeed = speed - drop; if (newspeed < 0) { newspeed = 0; } newspeed /= speed; Math3D.VectorScale(pml.velocity, newspeed, pml.velocity); } fmove = pm.cmd.forwardmove; smove = pm.cmd.sidemove; Math3D.VectorNormalize(pml.forward); Math3D.VectorNormalize(pml.right); for (i = 0; i < 3; i++) { wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove; } wishvel[2] += pm.cmd.upmove; Math3D.VectorCopy(wishvel, wishdir); wishspeed = Math3D.VectorNormalize(wishdir); if (wishspeed > pm_maxspeed) { Math3D.VectorScale(wishvel, pm_maxspeed / wishspeed, wishvel); wishspeed = pm_maxspeed; } currentspeed = Math3D.DotProduct(pml.velocity, wishdir); addspeed = wishspeed - currentspeed; if (addspeed <= 0) { return; } accelspeed = pm_accelerate * pml.frametime * wishspeed; if (accelspeed > addspeed) { accelspeed = addspeed; } for (i = 0; i < 3; i++) { pml.velocity[i] += accelspeed * wishdir[i]; } if (doclip) { for (i = 0; i < 3; i++) { end[i] = pml.origin[i] + pml.frametime * pml.velocity[i]; } trace = pm.trace.Trace(pml.origin, pm.mins, pm.maxs, end); Math3D.VectorCopy(trace.endpos, pml.origin); } else { Math3D.VectorMA(pml.origin, pml.frametime, pml.velocity, pml.origin); } }
public static void PM_StepSlideMove_( ) { Int32 bumpcount, numbumps; Single[] dir = new Single[] { 0, 0, 0 }; Single d; Int32 numplanes; Single[] primal_velocity = new Single[] { 0, 0, 0 }; Int32 i, j; trace_t trace; Single[] end = new Single[] { 0, 0, 0 }; Single time_left; numbumps = 4; Math3D.VectorCopy(pml.velocity, primal_velocity); numplanes = 0; time_left = pml.frametime; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) { end[i] = pml.origin[i] + time_left * pml.velocity[i]; } trace = pm.trace.Trace(pml.origin, pm.mins, pm.maxs, end); if (trace.allsolid) { pml.velocity[2] = 0; return; } if (trace.fraction > 0) { Math3D.VectorCopy(trace.endpos, pml.origin); numplanes = 0; } if (trace.fraction == 1) { break; } if (pm.numtouch < Defines.MAXTOUCH && trace.ent != null) { pm.touchents[pm.numtouch] = trace.ent; pm.numtouch++; } time_left -= time_left * trace.fraction; if (numplanes >= SV.MAX_CLIP_PLANES) { Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } Math3D.VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; for (i = 0; i < numplanes; i++) { PM_ClipVelocity(pml.velocity, planes[i], pml.velocity, 1.01F); for (j = 0; j < numplanes; j++) { if (j != i) { if (Math3D.DotProduct(pml.velocity, planes[j]) < 0) { break; } } } if (j == numplanes) { break; } } if (i != numplanes) { } else { if (numplanes != 2) { Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } Math3D.CrossProduct(planes[0], planes[1], dir); d = Math3D.DotProduct(dir, pml.velocity); Math3D.VectorScale(dir, d, pml.velocity); } if (Math3D.DotProduct(pml.velocity, primal_velocity) <= 0) { Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } } if (pm.s.pm_time != 0) { Math3D.VectorCopy(primal_velocity, pml.velocity); } }
public virtual System.Boolean R_CullAliasModel(Single[][] bbox, entity_t e) { Int32 i; Single[] mins = new Single[] { 0, 0, 0 }; Single[] maxs = new Single[] { 0, 0, 0 }; qfiles.dmdl_t paliashdr; Single[][] vectors = new Single[][] { new Single[] { 0, 0, 0 }, new Single[] { 0, 0, 0 }, new Single[] { 0, 0, 0 } }; Single[] thismins = new Single[] { 0, 0, 0 }; Single[] oldmins = new Single[] { 0, 0, 0 }; Single[] thismaxs = new Single[] { 0, 0, 0 }; Single[] oldmaxs = new Single[] { 0, 0, 0 }; qfiles.daliasframe_t pframe, poldframe; Single[] angles = new Single[] { 0, 0, 0 }; paliashdr = (qfiles.dmdl_t)currentmodel.extradata; if ((e.frame >= paliashdr.num_frames) || (e.frame < 0)) { VID.Printf(Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such frame " + e.frame + '\\'); e.frame = 0; } if ((e.oldframe >= paliashdr.num_frames) || (e.oldframe < 0)) { VID.Printf(Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such oldframe " + e.oldframe + '\\'); e.oldframe = 0; } pframe = paliashdr.aliasFrames[e.frame]; poldframe = paliashdr.aliasFrames[e.oldframe]; if (pframe == poldframe) { for (i = 0; i < 3; i++) { mins[i] = pframe.translate[i]; maxs[i] = mins[i] + pframe.scale[i] * 255; } } else { for (i = 0; i < 3; i++) { thismins[i] = pframe.translate[i]; thismaxs[i] = thismins[i] + pframe.scale[i] * 255; oldmins[i] = poldframe.translate[i]; oldmaxs[i] = oldmins[i] + poldframe.scale[i] * 255; if (thismins[i] < oldmins[i]) { mins[i] = thismins[i]; } else { mins[i] = oldmins[i]; } if (thismaxs[i] > oldmaxs[i]) { maxs[i] = thismaxs[i]; } else { maxs[i] = oldmaxs[i]; } } } for (i = 0; i < 8; i++) { Single[] tmp = new Single[] { 0, 0, 0 }; if ((i & 1) != 0) { tmp[0] = mins[0]; } else { tmp[0] = maxs[0]; } if ((i & 2) != 0) { tmp[1] = mins[1]; } else { tmp[1] = maxs[1]; } if ((i & 4) != 0) { tmp[2] = mins[2]; } else { tmp[2] = maxs[2]; } Math3D.VectorCopy(tmp, bbox[i]); } Math3D.VectorCopy(e.angles, angles); angles[YAW] = -angles[YAW]; Math3D.AngleVectors(angles, vectors[0], vectors[1], vectors[2]); for (i = 0; i < 8; i++) { Single[] tmp = new Single[] { 0, 0, 0 }; Math3D.VectorCopy(bbox[i], tmp); bbox[i][0] = Math3D.DotProduct(vectors[0], tmp); bbox[i][1] = -Math3D.DotProduct(vectors[1], tmp); bbox[i][2] = Math3D.DotProduct(vectors[2], tmp); Math3D.VectorAdd(e.origin, bbox[i], bbox[i]); } { Int32 p, f; var aggregatemask = ~0; for (p = 0; p < 8; p++) { var mask = 0; for (f = 0; f < 4; f++) { var dp = Math3D.DotProduct(frustum[f].normal, bbox[p]); if ((dp - frustum[f].dist) < 0) { mask |= (1 << f); } } aggregatemask &= mask; } if (aggregatemask != 0) { return(true); } return(false); } }
public void ComputeVertex(VertexInput v1) { #region Завернуть в шейдер var worldCoord1 = _modelMatrix * v1.Position; var vector1 = _transformMatrix * worldCoord1; //var vector2 = _transformMatrix * worldCoord2; //var vector3 = _transformMatrix * worldCoord3; var decartvector1 = Math3D.ConvertToDecart(vector1); //var decartvector2 = Math3D.ConvertToDecart(vector2); //var decartvector3 = Math3D.ConvertToDecart(vector3); //Vector3f faceNormalInWorldCoord = Math3D.CalculateNormal(Math3D.ConvertToDecart(worldCoord1), Math3D.ConvertToDecart(worldCoord2), Math3D.ConvertToDecart(worldCoord3)); Vector3f faceNormalInProjectionCoord = SimpleRender.Math.Vector3f.CrossProductLeft((decartvector3 - decartvector1), (decartvector2 - decartvector1)); faceNormalInProjectionCoord = faceNormalInProjectionCoord.Normalize(); var viewDirection = new Vector4(0, 0, -1, 1); double intensity = Math3D.DotProduct(faceNormalInProjectionCoord, viewDirection); //TODO Подумать нужноли это в шейдере if (intensity <= 0) { continue; } //ambient = Ka, //diffuse = Kd * cos(N, L), //specular = Ks * pow(cos(R, V), Ns), //intensity = ambient + amp * (diffuse + specular). //----------------- //http://www.gamedev.ru/code/articles/HLSL?page=4 //Lighting: //Lambert (ambient lighting) //Diffuse (diffuse lighting model) //Phong (specular lighting model), Blinn (blinn specular lighting model) //Sum of this //Реалистичное освещение на основе Кука-Торренса //------------- var ligthSource = scene.LightSources.First(); var globalLightPosition = ligthSource.Position.Normalize(); double illuminationIntensity = Math3D.DotProduct(faceNormalInWorldCoord, globalLightPosition); var diffuseColor = new Vector4( _material.DiffuseColor.X * ligthSource.Color.X, _material.Mategial.DiffuseColor.Y * ligthSource.Color.Y, _material.Mategial.DiffuseColor.Z * ligthSource.Color.Z, 1) * illuminationIntensity; //var reflection = (Vector3f.CrossProductLeft(faceNormalInWorldCoord , // (Vector3f.CrossProductLeft(faceNormalInWorldCoord ,globalLightPosition) * 2.0f)) - // globalLightPosition).Normalize(); // reflected light var sampleColor = _ambientColor + diffuseColor * ligthSource.Intensity; #endregion }
/* * =============== * P_DamageFeedback * * Handles color blends and view kicks * =============== */ public static void P_DamageFeedback(edict_t player) { gclient_t client; float side; float realcount, count, kick; float[] v = { 0, 0, 0 }; int r, l; float[] power_color = { 0.0f, 1.0f, 0.0f }; float[] acolor = { 1.0f, 1.0f, 1.0f }; float[] bcolor = { 1.0f, 0.0f, 0.0f }; client = player.client; // flash the backgrounds behind the status numbers client.ps.stats[Defines.STAT_FLASHES] = 0; if (client.damage_blood != 0) { client.ps.stats[Defines.STAT_FLASHES] |= 1; } if (client.damage_armor != 0 && 0 == (player.flags & Defines.FL_GODMODE) && client.invincible_framenum <= GameBase.level.framenum) { client.ps.stats[Defines.STAT_FLASHES] |= 2; } // total points of damage shot at the player this frame count = client.damage_blood + client.damage_armor + client.damage_parmor; if (count == 0) { return; // didn't take any damage } // start a pain animation if still in the player model if ((client.anim_priority < Defines.ANIM_PAIN) & (player.s.modelindex == 255)) { client.anim_priority = Defines.ANIM_PAIN; if ((client.ps.pmove.pm_flags & pmove_t.PMF_DUCKED) != 0) { player.s.frame = M_Player.FRAME_crpain1 - 1; client.anim_end = M_Player.FRAME_crpain4; } else { PlayerView.xxxi = (PlayerView.xxxi + 1) % 3; switch (PlayerView.xxxi) { case 0: player.s.frame = M_Player.FRAME_pain101 - 1; client.anim_end = M_Player.FRAME_pain104; break; case 1: player.s.frame = M_Player.FRAME_pain201 - 1; client.anim_end = M_Player.FRAME_pain204; break; case 2: player.s.frame = M_Player.FRAME_pain301 - 1; client.anim_end = M_Player.FRAME_pain304; break; } } } realcount = count; if (count < 10) { count = 10; // always make a visible effect } // play an apropriate pain sound if (GameBase.level.time > player.pain_debounce_time && 0 == (player.flags & Defines.FL_GODMODE) && client.invincible_framenum <= GameBase.level.framenum) { r = 1 + (Lib.rand() & 1); player.pain_debounce_time = GameBase.level.time + 0.7f; if (player.health < 25) { l = 25; } else if (player.health < 50) { l = 50; } else if (player.health < 75) { l = 75; } else { l = 100; } GameBase.gi.sound(player, Defines.CHAN_VOICE, GameBase.gi.soundindex("*pain" + l + "_" + r + ".wav"), 1, Defines.ATTN_NORM, 0); } // the total alpha of the blend is always proportional to count if (client.damage_alpha < 0) { client.damage_alpha = 0; } client.damage_alpha += count * 0.01f; if (client.damage_alpha < 0.2f) { client.damage_alpha = 0.2f; } if (client.damage_alpha > 0.6f) { client.damage_alpha = 0.6f; // don't go too saturated } // the color of the blend will vary based on how much was absorbed // by different armors // Math3D.VectorClear(v); if (client.damage_parmor != 0) { Math3D.VectorMA(v, (float)client.damage_parmor / realcount, power_color, v); } if (client.damage_armor != 0) { Math3D.VectorMA(v, (float)client.damage_armor / realcount, acolor, v); } if (client.damage_blood != 0) { Math3D.VectorMA(v, (float)client.damage_blood / realcount, bcolor, v); } Math3D.VectorCopy(v, client.damage_blend); // // calculate view angle kicks // kick = Math.Abs(client.damage_knockback); if (kick != 0 && player.health > 0) // kick of 0 means no view adjust at // all { kick = kick * 100 / player.health; if (kick < count * 0.5) { kick = count * 0.5f; } if (kick > 50) { kick = 50; } Math3D.VectorSubtract(client.damage_from, player.s.origin, v); Math3D.VectorNormalize(v); side = Math3D.DotProduct(v, PlayerView.right); client.v_dmg_roll = kick * side * 0.3f; side = -Math3D.DotProduct(v, PlayerView.forward); client.v_dmg_pitch = kick * side * 0.3f; client.v_dmg_time = GameBase.level.time + Defines.DAMAGE_TIME; } // // clear totals // client.damage_blood = 0; client.damage_armor = 0; client.damage_parmor = 0; client.damage_knockback = 0; }
public virtual void R_RecursiveWorldNode(mnode_t node) { if (node.contents == Defines.CONTENTS_SOLID) { return; } if (node.visframe != r_visframecount) { return; } if (R_CullBox(node.mins, node.maxs)) { return; } Int32 c; msurface_t mark; if (node.contents != -1) { mleaf_t pleaf = ( mleaf_t )node; if (r_newrefdef.areabits != null) { if (((r_newrefdef.areabits[pleaf.area >> 3] & 0xFF) & (1 << (pleaf.area & 7))) == 0) { return; } } var markp = 0; mark = pleaf.GetMarkSurface(markp); c = pleaf.nummarksurfaces; if (c != 0) { do { mark.visframe = r_framecount; mark = pleaf.GetMarkSurface(++markp); }while (--c != 0); } return; } cplane_t plane = node.plane; Single dot; switch (plane.type) { case Defines.PLANE_X: dot = modelorg[0] - plane.dist; break; case Defines.PLANE_Y: dot = modelorg[1] - plane.dist; break; case Defines.PLANE_Z: dot = modelorg[2] - plane.dist; break; default: dot = Math3D.DotProduct(modelorg, plane.normal) - plane.dist; break; } Int32 side, sidebit; if (dot >= 0F) { side = 0; sidebit = 0; } else { side = 1; sidebit = Defines.SURF_PLANEBACK; } R_RecursiveWorldNode(node.children[side]); msurface_t surf; image_t image; for (c = 0; c < node.numsurfaces; c++) { surf = r_worldmodel.surfaces[node.firstsurface + c]; if (surf.visframe != r_framecount) { continue; } if ((surf.flags & Defines.SURF_PLANEBACK) != sidebit) { continue; } if ((surf.texinfo.flags & Defines.SURF_SKY) != 0) { R_AddSkySurface(surf); } else if ((surf.texinfo.flags & (Defines.SURF_TRANS33 | Defines.SURF_TRANS66)) != 0) { surf.texturechain = r_alpha_surfaces; r_alpha_surfaces = surf; } else { if ((surf.flags & Defines.SURF_DRAWTURB) == 0) { GL_RenderLightmappedPoly(surf); } else { image = R_TextureAnimation(surf.texinfo); surf.texturechain = image.texturechain; image.texturechain = surf; } } } R_RecursiveWorldNode(node.children[1 - side]); }
public virtual void SubdividePolygon(int numverts, float[][] verts) { int i, j, k; float[] mins = new float[] { 0, 0, 0 }; float[] maxs = new float[] { 0, 0, 0 }; float m; float[] v = new float[] { 0, 0, 0 }; float[][] front = Lib.CreateJaggedArray <float[][]>(64, 3); float[][] back = Lib.CreateJaggedArray <float[][]>(64, 3); int f, b; float[] dist = new float[64]; float frac; float s, t; float[] total = new float[] { 0, 0, 0 }; float total_s, total_t; if (numverts > 60) { Com.Error(Defines.ERR_DROP, "numverts = " + numverts); } BoundPoly(numverts, verts, mins, maxs); for (i = 0; i < 3; i++) { m = (mins[i] + maxs[i]) * 0.5F; m = SUBDIVIDE_SIZE * (float)Math.Floor(m / SUBDIVIDE_SIZE + 0.5F); if (maxs[i] - m < 8) { continue; } if (m - mins[i] < 8) { continue; } for (j = 0; j < numverts; j++) { dist[j] = verts[j][i] - m; } dist[j] = dist[0]; Math3D.VectorCopy(verts[0], verts[numverts]); f = b = 0; for (j = 0; j < numverts; j++) { v = verts[j]; if (dist[j] >= 0) { Math3D.VectorCopy(v, front[f]); f++; } if (dist[j] <= 0) { Math3D.VectorCopy(v, back[b]); b++; } if (dist[j] == 0 || dist[j + 1] == 0) { continue; } if ((dist[j] > 0) != (dist[j + 1] > 0)) { frac = dist[j] / (dist[j] - dist[j + 1]); for (k = 0; k < 3; k++) { front[f][k] = back[b][k] = v[k] + frac * (verts[j + 1][k] - v[k]); } f++; b++; } } SubdividePolygon(f, front); SubdividePolygon(b, back); return; } glpoly_t poly = Polygon.Create(numverts + 2); poly.next = warpface.polys; warpface.polys = poly; Math3D.VectorClear(total); total_s = 0; total_t = 0; for (i = 0; i < numverts; i++) { poly.X(i + 1, verts[i][0]); poly.Y(i + 1, verts[i][1]); poly.Z(i + 1, verts[i][2]); s = Math3D.DotProduct(verts[i], warpface.texinfo.vecs[0]); t = Math3D.DotProduct(verts[i], warpface.texinfo.vecs[1]); total_s += s; total_t += t; Math3D.VectorAdd(total, verts[i], total); poly.S1(i + 1, s); poly.T1(i + 1, t); } float scale = 1F / numverts; poly.X(0, total[0] * scale); poly.Y(0, total[1] * scale); poly.Z(0, total[2] * scale); poly.S1(0, total_s * scale); poly.T1(0, total_t * scale); poly.X(i + 1, poly.X(1)); poly.Y(i + 1, poly.Y(1)); poly.Z(i + 1, poly.Z(1)); poly.S1(i + 1, poly.S1(1)); poly.T1(i + 1, poly.T1(1)); poly.S2(i + 1, poly.S2(1)); poly.T2(i + 1, poly.T2(1)); }
public virtual void ClipSkyPolygon(int nump, float[][] vecs, int stage) { float[] norm; float[] v; bool front, back; float d, e; int[] newc = new[] { 0, 0 }; int i, j; if (nump > MAX_CLIP_VERTS - 2) { Com.Error(Defines.ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); } if (stage == 6) { DrawSkyPolygon(nump, vecs); return; } front = back = false; norm = skyclip[stage]; for (i = 0; i < nump; i++) { d = Math3D.DotProduct(vecs[i], norm); if (d > ON_EPSILON) { front = true; sides[i] = SIDE_FRONT; } else if (d < -ON_EPSILON) { back = true; sides[i] = SIDE_BACK; } else { sides[i] = SIDE_ON; } dists[i] = d; } if (!front || !back) { ClipSkyPolygon(nump, vecs, stage + 1); return; } sides[i] = sides[0]; dists[i] = dists[0]; Math3D.VectorCopy(vecs[0], vecs[i]); newc[0] = newc[1] = 0; for (i = 0; i < nump; i++) { v = vecs[i]; switch (sides[i]) { case SIDE_FRONT: Math3D.VectorCopy(v, newv[stage][0][newc[0]]); newc[0]++; break; case SIDE_BACK: Math3D.VectorCopy(v, newv[stage][1][newc[1]]); newc[1]++; break; case SIDE_ON: Math3D.VectorCopy(v, newv[stage][0][newc[0]]); newc[0]++; Math3D.VectorCopy(v, newv[stage][1][newc[1]]); newc[1]++; break; } if (sides[i] == SIDE_ON || sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { continue; } d = dists[i] / (dists[i] - dists[i + 1]); for (j = 0; j < 3; j++) { e = v[j] + d * (vecs[i + 1][j] - v[j]); newv[stage][0][newc[0]][j] = e; newv[stage][1][newc[1]][j] = e; } newc[0]++; newc[1]++; } ClipSkyPolygon(newc[0], newv[stage][0], stage + 1); ClipSkyPolygon(newc[1], newv[stage][1], stage + 1); }
public virtual void GL_DrawAliasFrameLerp(qfiles.dmdl_t paliashdr, Single backlerp) { Single l; qfiles.daliasframe_t frame, oldframe; Int32[] v, ov; Int32[] order; var orderIndex = 0; Int32 count; Single frontlerp; Single alpha; Single[] move = new Single[] { 0, 0, 0 }; Single[][] vectors = new Single[][] { new Single[] { 0, 0, 0 }, new Single[] { 0, 0, 0 }, new Single[] { 0, 0, 0 } }; Single[] frontv = new Single[] { 0, 0, 0 }; Single[] backv = new Single[] { 0, 0, 0 }; Int32 i; Int32 index_xyz; frame = paliashdr.aliasFrames[currententity.frame]; v = frame.verts; oldframe = paliashdr.aliasFrames[currententity.oldframe]; ov = oldframe.verts; order = paliashdr.glCmds; if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) { alpha = currententity.alpha; } else { alpha = 1F; } if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { GL.Disable(EnableCap.Texture2D); } frontlerp = 1F - backlerp; Math3D.VectorSubtract(currententity.oldorigin, currententity.origin, frontv); Math3D.AngleVectors(currententity.angles, vectors[0], vectors[1], vectors[2]); move[0] = Math3D.DotProduct(frontv, vectors[0]); move[1] = -Math3D.DotProduct(frontv, vectors[1]); move[2] = Math3D.DotProduct(frontv, vectors[2]); Math3D.VectorAdd(move, oldframe.translate, move); for (i = 0; i < 3; i++) { move[i] = backlerp * move[i] + frontlerp * frame.translate[i]; frontv[i] = frontlerp * frame.scale[i]; backv[i] = backlerp * oldframe.scale[i]; } if (gl_vertex_arrays.value != 0F) { GL_LerpVerts(paliashdr.num_xyz, ov, v, move, frontv, backv); GL.EnableClientState(ArrayCap.VertexArray); new Pinnable(vertexArrayBuf.Array, (ptr) => { GL.VertexPointer(3, VertexPointerType.Float, 0, ptr); }); if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { GL.DisableClientState(ArrayCap.ColorArray); GL.Color4(shadelight[0], shadelight[1], shadelight[2], alpha); } else { GL.EnableClientState(ArrayCap.ColorArray); new Pinnable(colorArrayBuf.Array, (ptr) => { GL.ColorPointer(4, ColorPointerType.Float, 0, ptr); }); SingleBuffer color = colorArrayBuf; var j = 0; for (i = 0; i < paliashdr.num_xyz; i++) { l = shadedots[(v[i] >> 24) & 0xFF]; color.Put(j++, l * shadelight[0]); color.Put(j++, l * shadelight[1]); color.Put(j++, l * shadelight[2]); color.Put(j++, alpha); } } //if (qglLockArraysEXT) // gl.GlLockArraysEXT(0, paliashdr.num_xyz); while (true) { count = order[orderIndex++]; if (count == 0) { break; } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.TriangleStrip); } if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { do { index_xyz = order[orderIndex + 2]; orderIndex += 3; GL.ArrayElement(index_xyz); }while (--count != 0); } else { do { GL.TexCoord2(BitConverter.ToSingle(BitConverter.GetBytes(order[orderIndex + 0])), BitConverter.ToSingle(BitConverter.GetBytes(order[orderIndex + 1]))); index_xyz = order[orderIndex + 2]; orderIndex += 3; GL.ArrayElement(index_xyz); }while (--count != 0); } GL.End(); } // if (qglLockArraysEXT) // gl.GlUnlockArraysEXT(); } else { GL_LerpVerts(paliashdr.num_xyz, ov, v, s_lerped, move, frontv, backv); Single[] tmp; while (true) { count = order[orderIndex++]; if (count == 0) { break; } if (count < 0) { count = -count; GL.Begin(PrimitiveType.TriangleFan); } else { GL.Begin(PrimitiveType.TriangleStrip); } if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE)) != 0) { do { index_xyz = order[orderIndex + 2]; orderIndex += 3; GL.Color4(shadelight[0], shadelight[1], shadelight[2], alpha); tmp = s_lerped[index_xyz]; GL.Vertex3(tmp[0], tmp[1], tmp[2]); }while (--count != 0); } else { do { GL.TexCoord2(BitConverter.ToSingle(BitConverter.GetBytes(order[orderIndex + 0])), BitConverter.ToSingle(BitConverter.GetBytes(order[orderIndex + 1]))); index_xyz = order[orderIndex + 2]; orderIndex += 3; l = shadedots[(v[index_xyz] >> 24) & 0xFF]; GL.Color4(l * shadelight[0], l * shadelight[1], l * shadelight[2], alpha); tmp = s_lerped[index_xyz]; GL.Vertex3(tmp[0], tmp[1], tmp[2]); }while (--count != 0); } GL.End(); } } if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { GL.Enable(EnableCap.Texture2D); } }
/** * * fall from 128: 400 = 160000 * fall from 256: 580 = 336400 * fall from 384: 720 = 518400 * fall from 512: 800 = 640000 * fall from 640: 960 = * damage = deltavelocity*deltavelocity * 0.0001 */ public static void SV_CalcViewOffset(edict_t ent) { float[] angles = { 0, 0, 0 }; float bob; float ratio; float delta; float[] v = { 0, 0, 0 }; // base angles angles = ent.client.ps.kick_angles; // if dead, fix the angle and don't add any kick if (ent.deadflag != 0) { Math3D.VectorClear(angles); ent.client.ps.viewangles[Defines.ROLL] = 40; ent.client.ps.viewangles[Defines.PITCH] = -15; ent.client.ps.viewangles[Defines.YAW] = ent.client.killer_yaw; } else { // add angles based on weapon kick Math3D.VectorCopy(ent.client.kick_angles, angles); // add angles based on damage kick ratio = (ent.client.v_dmg_time - GameBase.level.time) / Defines.DAMAGE_TIME; if (ratio < 0) { ratio = 0; ent.client.v_dmg_pitch = 0; ent.client.v_dmg_roll = 0; } angles[Defines.PITCH] += ratio * ent.client.v_dmg_pitch; angles[Defines.ROLL] += ratio * ent.client.v_dmg_roll; // add pitch based on fall kick ratio = (ent.client.fall_time - GameBase.level.time) / Defines.FALL_TIME; if (ratio < 0) { ratio = 0; } angles[Defines.PITCH] += ratio * ent.client.fall_value; // add angles based on velocity delta = Math3D.DotProduct(ent.velocity, PlayerView.forward); angles[Defines.PITCH] += delta * GameBase.run_pitch.value; delta = Math3D.DotProduct(ent.velocity, PlayerView.right); angles[Defines.ROLL] += delta * GameBase.run_roll.value; // add angles based on bob delta = PlayerView.bobfracsin * GameBase.bob_pitch.value * PlayerView.xyspeed; if ((ent.client.ps.pmove.pm_flags & pmove_t.PMF_DUCKED) != 0) { delta *= 6; // crouching } angles[Defines.PITCH] += delta; delta = PlayerView.bobfracsin * GameBase.bob_roll.value * PlayerView.xyspeed; if ((ent.client.ps.pmove.pm_flags & pmove_t.PMF_DUCKED) != 0) { delta *= 6; // crouching } if ((PlayerView.bobcycle & 1) != 0) { delta = -delta; } angles[Defines.ROLL] += delta; } // base origin Math3D.VectorClear(v); // add view height v[2] += ent.viewheight; // add fall height ratio = (ent.client.fall_time - GameBase.level.time) / Defines.FALL_TIME; if (ratio < 0) { ratio = 0; } v[2] -= ratio * ent.client.fall_value * 0.4f; // add bob height bob = PlayerView.bobfracsin * PlayerView.xyspeed * GameBase.bob_up.value; if (bob > 6) { bob = 6; } //gi.DebugGraph (bob *2, 255); v[2] += bob; // add kick offset Math3D.VectorAdd(v, ent.client.kick_origin, v); // absolutely bound offsets // so the view can never be outside the player box if (v[0] < -14) { v[0] = -14; } else if (v[0] > 14) { v[0] = 14; } if (v[1] < -14) { v[1] = -14; } else if (v[1] > 14) { v[1] = 14; } if (v[2] < -22) { v[2] = -22; } else if (v[2] > 30) { v[2] = 30; } Math3D.VectorCopy(v, ent.client.ps.viewoffset); }