Beispiel #1
0
  /** R_SetFrustum */
  void R_SetFrustum() {
    // rotate VPN right by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90f - r_newrefdef.fov_x / 2f));
    // rotate VPN left by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[1].normal, vup, vpn, 90f - r_newrefdef.fov_x / 2f);
    // rotate VPN up by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[2].normal, vright, vpn, 90f - r_newrefdef.fov_y / 2f);
    // rotate VPN down by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90f - r_newrefdef.fov_y / 2f));

    for (int 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]);
    }
  }
Beispiel #2
0
  /** Objects need to be moved back on a failed push, otherwise riders would continue to slide. */
  public static boolean SV_Push(edict_t pusher, float[] move, float[] amove) {
    int i, e;
    edict_t check, block[];
    float[] mins = {0, 0, 0};
    float[] maxs = {0, 0, 0};
    pushed_t p;
    float[] org = {0, 0, 0};
    float[] org2 = {0, 0, 0};
    float[] move2 = {0, 0, 0};
    float[] forward = {0, 0, 0};
    float[] right = {0, 0, 0};
    float[] up = {0, 0, 0};

    // clamp the move to 1/8 units, so the position will
    // be accurate for client side prediction
    for (i = 0; i < 3; i++) {
      float temp;
      temp = move[i] * 8.0f;
      if (temp > 0.0) temp += 0.5;
      else temp -= 0.5;
      move[i] = 0.125f * (int) temp;
    }

    // find the bounding box
    for (i = 0; i < 3; i++) {
      mins[i] = pusher.absmin[i] + move[i];
      maxs[i] = pusher.absmax[i] + move[i];
    }

    //	   we need this for pushing things later
    Math3D.VectorSubtract(Globals.vec3_origin, amove, org);
    Math3D.AngleVectors(org, forward, right, up);

    //	   save the pusher's original position
    GameBase.pushed[GameBase.pushed_p].ent = pusher;
    Math3D.VectorCopy(pusher.s.origin, GameBase.pushed[GameBase.pushed_p].origin);
    Math3D.VectorCopy(pusher.s.angles, GameBase.pushed[GameBase.pushed_p].angles);

    if (pusher.client != null)
      GameBase.pushed[GameBase.pushed_p].deltayaw =
          pusher.client.ps.pmove.delta_angles[Defines.YAW];

    GameBase.pushed_p++;

    //	   move the pusher to it's final position
    Math3D.VectorAdd(pusher.s.origin, move, pusher.s.origin);
    Math3D.VectorAdd(pusher.s.angles, amove, pusher.s.angles);
    GameBase.gi.linkentity(pusher);

    //	   see if any solid entities are inside the final position

    // check= g_edicts + 1;
    for (e = 1; e < GameBase.num_edicts; e++) {
      check = GameBase.g_edicts[e];
      if (!check.inuse) continue;
      if (check.movetype == Defines.MOVETYPE_PUSH
          || check.movetype == Defines.MOVETYPE_STOP
          || check.movetype == Defines.MOVETYPE_NONE
          || check.movetype == Defines.MOVETYPE_NOCLIP) continue;

      if (check.area.prev == null) continue; // not linked in anywhere

      // if the entity is standing on the pusher, it will definitely be
      // moved
      if (check.groundentity != pusher) {
        // see if the ent needs to be tested
        if (check.absmin[0] >= maxs[0]
            || check.absmin[1] >= maxs[1]
            || check.absmin[2] >= maxs[2]
            || check.absmax[0] <= mins[0]
            || check.absmax[1] <= mins[1]
            || check.absmax[2] <= mins[2]) continue;

        // see if the ent's bbox is inside the pusher's final position
        if (SV_TestEntityPosition(check) == null) continue;
      }

      if ((pusher.movetype == Defines.MOVETYPE_PUSH) || (check.groundentity == pusher)) {
        // move this entity
        GameBase.pushed[GameBase.pushed_p].ent = check;
        Math3D.VectorCopy(check.s.origin, GameBase.pushed[GameBase.pushed_p].origin);
        Math3D.VectorCopy(check.s.angles, GameBase.pushed[GameBase.pushed_p].angles);
        GameBase.pushed_p++;

        // try moving the contacted entity
        Math3D.VectorAdd(check.s.origin, move, check.s.origin);
        if (check.client != null) { // FIXME: doesn't rotate monsters?
          check.client.ps.pmove.delta_angles[Defines.YAW] += amove[Defines.YAW];
        }

        // figure movement due to the pusher's amove
        Math3D.VectorSubtract(check.s.origin, pusher.s.origin, org);
        org2[0] = Math3D.DotProduct(org, forward);
        org2[1] = -Math3D.DotProduct(org, right);
        org2[2] = Math3D.DotProduct(org, up);
        Math3D.VectorSubtract(org2, org, move2);
        Math3D.VectorAdd(check.s.origin, move2, check.s.origin);

        // may have pushed them off an edge
        if (check.groundentity != pusher) check.groundentity = null;

        block = SV_TestEntityPosition(check);
        if (block == null) { // pushed ok
          GameBase.gi.linkentity(check);
          // impact?
          continue;
        }

        // if it is ok to leave in the old position, do it
        // this is only relevent for riding entities, not pushed
        // FIXME: this doesn't acount for rotation
        Math3D.VectorSubtract(check.s.origin, move, check.s.origin);
        block = SV_TestEntityPosition(check);

        if (block == null) {
          GameBase.pushed_p--;
          continue;
        }
      }

      // save off the obstacle so we can call the block function
      GameBase.obstacle = check;

      // move back any entities we already moved
      // go backwards, so if the same entity was pushed
      // twice, it goes back to the original position
      for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--) {
        p = GameBase.pushed[ip];
        Math3D.VectorCopy(p.origin, p.ent.s.origin);
        Math3D.VectorCopy(p.angles, p.ent.s.angles);
        if (p.ent.client != null) {
          p.ent.client.ps.pmove.delta_angles[Defines.YAW] = (short) p.deltayaw;
        }
        GameBase.gi.linkentity(p.ent);
      }
      return false;
    }

    //	  FIXME: is there a better way to handle this?
    // see if anything we moved has touched a trigger
    for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--)
      GameBase.G_TouchTriggers(GameBase.pushed[ip].ent);

    return true;
  }
Beispiel #3
0
  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;
  }