/** GL_DrawParticles */ void GL_DrawParticles(int num_particles) { float origin_x, origin_y, origin_z; Math3D.VectorScale(vup, 1.5f, up); Math3D.VectorScale(vright, 1.5f, right); GL_Bind(r_particletexture.texnum); GL11.glDepthMask(false); // no z buffering GL11.glEnable(GL11.GL_BLEND); GL_TexEnv(GL11.GL_MODULATE); GL11.glBegin(GL11.GL_TRIANGLES); FloatBuffer sourceVertices = particle_t.vertexArray; IntBuffer sourceColors = particle_t.colorArray; float scale; int color; for (int j = 0, i = 0; i < num_particles; i++) { origin_x = sourceVertices.get(j++); origin_y = sourceVertices.get(j++); origin_z = sourceVertices.get(j++); // hack a scale up to keep particles from disapearing scale = (origin_x - r_origin[0]) * vpn[0] + (origin_y - r_origin[1]) * vpn[1] + (origin_z - r_origin[2]) * vpn[2]; scale = (scale < 20) ? 1 : 1 + scale * 0.004f; color = sourceColors.get(i); GL11.glColor4ub( (byte) ((color) & 0xFF), (byte) ((color >> 8) & 0xFF), (byte) ((color >> 16) & 0xFF), (byte) ((color >>> 24))); // first vertex GL11.glTexCoord2f(0.0625f, 0.0625f); GL11.glVertex3f(origin_x, origin_y, origin_z); // second vertex GL11.glTexCoord2f(1.0625f, 0.0625f); GL11.glVertex3f(origin_x + up[0] * scale, origin_y + up[1] * scale, origin_z + up[2] * scale); // third vertex GL11.glTexCoord2f(0.0625f, 1.0625f); GL11.glVertex3f( origin_x + right[0] * scale, origin_y + right[1] * scale, origin_z + right[2] * scale); } GL11.glEnd(); GL11.glDisable(GL11.GL_BLEND); GL11.glColor4f(1, 1, 1, 1); GL11.glDepthMask(true); // back to normal Z buffering GL_TexEnv(GL11.GL_REPLACE); }
/** R_DrawBeam */ void R_DrawBeam(entity_t e) { oldorigin[0] = e.oldorigin[0]; oldorigin[1] = e.oldorigin[1]; oldorigin[2] = e.oldorigin[2]; origin[0] = e.origin[0]; origin[1] = e.origin[1]; origin[2] = e.origin[2]; normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; if (Math3D.VectorNormalize(normalized_direction) == 0.0f) return; Math3D.PerpendicularVector(perpvec, normalized_direction); Math3D.VectorScale(perpvec, e.frame / 2, perpvec); for (int i = 0; i < 6; i++) { Math3D.RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0f / NUM_BEAM_SEGS) * i); Math3D.VectorAdd(start_points[i], origin, start_points[i]); Math3D.VectorAdd(start_points[i], direction, end_points[i]); } GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glDepthMask(false); float r = (d_8to24table[e.skinnum & 0xFF]) & 0xFF; float g = (d_8to24table[e.skinnum & 0xFF] >> 8) & 0xFF; float b = (d_8to24table[e.skinnum & 0xFF] >> 16) & 0xFF; r *= 1 / 255.0f; g *= 1 / 255.0f; b *= 1 / 255.0f; GL11.glColor4f(r, g, b, e.alpha); GL11.glBegin(GL11.GL_TRIANGLE_STRIP); float[] v; for (int i = 0; i < NUM_BEAM_SEGS; i++) { v = start_points[i]; GL11.glVertex3f(v[0], v[1], v[2]); v = end_points[i]; GL11.glVertex3f(v[0], v[1], v[2]); v = start_points[(i + 1) % NUM_BEAM_SEGS]; GL11.glVertex3f(v[0], v[1], v[2]); v = end_points[(i + 1) % NUM_BEAM_SEGS]; GL11.glVertex3f(v[0], v[1], v[2]); } GL11.glEnd(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_BLEND); GL11.glDepthMask(true); }
/** Bmodel objects don't interact with each other, but push all box objects. */ public static void SV_Physics_Pusher(edict_t ent) { float[] move = {0, 0, 0}; float[] amove = {0, 0, 0}; edict_t part, mv; // if not a team captain, so movement will be handled elsewhere if ((ent.flags & Defines.FL_TEAMSLAVE) != 0) return; // make sure all team slaves can move before commiting // any moves or calling any think functions // if the move is blocked, all moved objects will be backed out // retry: GameBase.pushed_p = 0; for (part = ent; part != null; part = part.teamchain) { if (part.velocity[0] != 0 || part.velocity[1] != 0 || part.velocity[2] != 0 || part.avelocity[0] != 0 || part.avelocity[1] != 0 || part.avelocity[2] != 0) { // object // is // moving Math3D.VectorScale(part.velocity, Defines.FRAMETIME, move); Math3D.VectorScale(part.avelocity, Defines.FRAMETIME, amove); if (!SV_Push(part, move, amove)) break; // move was blocked } } if (GameBase.pushed_p > Defines.MAX_EDICTS) SV_GAME.PF_error(Defines.ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted"); if (part != null) { // the move failed, bump all nextthink times and back out moves for (mv = ent; mv != null; mv = mv.teamchain) { if (mv.nextthink > 0) mv.nextthink += Defines.FRAMETIME; } // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (part.blocked != null) part.blocked.blocked(part, GameBase.obstacle); } else { // the move succeeded, so call all think functions for (part = ent; part != null; part = part.teamchain) { SV_RunThink(part); } } }
/** Toss, bounce, and fly movement. When onground, do nothing. */ public static void SV_Physics_Toss(edict_t ent) { trace_t trace; float[] move = {0, 0, 0}; float backoff; edict_t slave; boolean wasinwater; boolean isinwater; float[] old_origin = {0, 0, 0}; // regular thinking SV_RunThink(ent); // if not a team captain, so movement will be handled elsewhere if ((ent.flags & Defines.FL_TEAMSLAVE) != 0) return; if (ent.velocity[2] > 0) ent.groundentity = null; // check for the groundentity going away if (ent.groundentity != null) if (!ent.groundentity.inuse) ent.groundentity = null; // if onground, return without moving if (ent.groundentity != null) return; Math3D.VectorCopy(ent.s.origin, old_origin); SV_CheckVelocity(ent); // add gravity if (ent.movetype != Defines.MOVETYPE_FLY && ent.movetype != Defines.MOVETYPE_FLYMISSILE) SV_AddGravity(ent); // move angles Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles); // move origin Math3D.VectorScale(ent.velocity, Defines.FRAMETIME, move); trace = SV_PushEntity(ent, move); if (!ent.inuse) return; if (trace.fraction < 1) { if (ent.movetype == Defines.MOVETYPE_BOUNCE) backoff = 1.5f; else backoff = 1; GameBase.ClipVelocity(ent.velocity, trace.plane.normal, ent.velocity, backoff); // stop if on ground if (trace.plane.normal[2] > 0.7) { if (ent.velocity[2] < 60 || ent.movetype != Defines.MOVETYPE_BOUNCE) { ent.groundentity = trace.ent; ent.groundentity_linkcount = trace.ent.linkcount; Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); Math3D.VectorCopy(Globals.vec3_origin, ent.avelocity); } } // if (ent.touch) // ent.touch (ent, trace.ent, &trace.plane, trace.surface); } // check for water transition wasinwater = (ent.watertype & Defines.MASK_WATER) != 0; ent.watertype = GameBase.gi.pointcontents.pointcontents(ent.s.origin); isinwater = (ent.watertype & Defines.MASK_WATER) != 0; if (isinwater) ent.waterlevel = 1; else ent.waterlevel = 0; if (!wasinwater && isinwater) GameBase.gi.positioned_sound( old_origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) GameBase.gi.positioned_sound( ent.s.origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); // move teamslaves for (slave = ent.teamchain; slave != null; slave = slave.teamchain) { Math3D.VectorCopy(ent.s.origin, slave.s.origin); GameBase.gi.linkentity(slave); } }
public static int SV_FlyMove(edict_t ent, float time, int mask) { edict_t hit; int bumpcount, numbumps; float[] dir = {0.0f, 0.0f, 0.0f}; float d; int numplanes; float[][] planes = new float[MAX_CLIP_PLANES][3]; float[] primal_velocity = {0.0f, 0.0f, 0.0f}; float[] original_velocity = {0.0f, 0.0f, 0.0f}; float[] new_velocity = {0.0f, 0.0f, 0.0f}; int i, j; trace_t trace; float[] end = {0.0f, 0.0f, 0.0f}; float time_left; int blocked; numbumps = 4; blocked = 0; Math3D.VectorCopy(ent.velocity, original_velocity); Math3D.VectorCopy(ent.velocity, primal_velocity); numplanes = 0; time_left = time; ent.groundentity = null; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) end[i] = ent.s.origin[i] + time_left * ent.velocity[i]; trace = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, end, ent, mask); if (trace.allsolid) { // entity is trapped in another solid Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 3; } if (trace.fraction > 0) { // actually covered some distance Math3D.VectorCopy(trace.endpos, ent.s.origin); Math3D.VectorCopy(ent.velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance hit = trace.ent; if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor if (hit.solid == Defines.SOLID_BSP) { ent.groundentity = hit; ent.groundentity_linkcount = hit.linkcount; } } if (trace.plane.normal[2] == 0.0f) { blocked |= 2; // step } // // run the impact function // SV_Impact(ent, trace); if (!ent.inuse) break; // removed by the impact function time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't // really happen Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 3; } Math3D.VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // for (i = 0; i < numplanes; i++) { GameBase.ClipVelocity(original_velocity, planes[i], new_velocity, 1); for (j = 0; j < numplanes; j++) if ((j != i) && !Math3D.VectorEquals(planes[i], planes[j])) { if (Math3D.DotProduct(new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane Math3D.VectorCopy(new_velocity, ent.velocity); } else { // go along the crease if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == // %i\n",numplanes); Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return 7; } Math3D.CrossProduct(planes[0], planes[1], dir); d = Math3D.DotProduct(dir, ent.velocity); Math3D.VectorScale(dir, d, ent.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Math3D.DotProduct(ent.velocity, primal_velocity) <= 0) { Math3D.VectorCopy(Globals.vec3_origin, ent.velocity); return blocked; } } return blocked; }