bool Intersects(pcs_polygon &polygon, vector3d plane_point, vector3d plane_normal) { if (polygon.verts.size() < 3) return false; // um.. this is a line not a polygon bool infront = InFrontofPlane(polygon.verts[0].point, plane_point, plane_normal); for (unsigned int i = 1; i < polygon.verts.size(); i++) { if (DistanceToPlane(polygon.verts[i].point, plane_point, plane_normal) != 0 && // if it's on the plane we don't care infront != InFrontofPlane(polygon.verts[i].point, plane_point, plane_normal)) return true; } return false; }
float DistanceToPolygon(const vec3& p, tvector<vec3>& v, vec3 n) { float flPlaneDistance = DistanceToPlane(p, v[0], n); size_t i; bool bFoundPoint = false; for (i = 0; i < v.size()-2; i++) { if (PointInTriangle(p, v[0], v[i+1], v[i+2])) { bFoundPoint = true; break; } } if (bFoundPoint) return flPlaneDistance; float flClosestPoint = -1; for (i = 0; i < v.size(); i++) { float flPointDistance = (v[i] - p).Length(); if (flClosestPoint == -1 || (flPointDistance < flClosestPoint)) flClosestPoint = flPointDistance; float flLineDistance; if (i == v.size() - 1) flLineDistance = DistanceToLineSegment(p, v[i], v[0]); else flLineDistance = DistanceToLineSegment(p, v[i], v[i+1]); if (flClosestPoint == -1 || (flLineDistance < flClosestPoint)) flClosestPoint = flLineDistance; } return flClosestPoint; }
bool InFrontofPlane(vector3d point, vector3d plane_point, vector3d plane_normal) { return DistanceToPlane(point, plane_point, plane_normal) >= 0; }
void SplitPolygon(std::vector<pcs_polygon> &polygons, int polynum, vector3d plane_point, vector3d plane_normal, std::vector<pcs_polygon> &newpolys) { std::vector<pcs_polygon> splitpolys(2); // 0 = front vert, 1 = back vert std::vector<int> pairs; std::vector<pcs_vertex> points; pairs.resize(polygons[polynum].verts.size() * 2); pcs_vertex temp; unsigned int i, j = 0; float uvdelta; for (i = 0; i < polygons[polynum].verts.size() * 2; i += 2) { pairs[i] = j % polygons[polynum].verts.size(); pairs[i+1] = (j+1) % polygons[polynum].verts.size(); j++; } float dtempa, dtempb; // compile the new list of points for (i = 0; i < pairs.size(); i += 2) { dtempa = DistanceToPlane(polygons[polynum].verts[pairs[i]].point, plane_point, plane_normal); dtempb = DistanceToPlane(polygons[polynum].verts[pairs[i+1]].point, plane_point, plane_normal); if ((dtempa <= 0.0001 && dtempa >= -0.0001) || (dtempb <= 0.0001 && dtempb >= -0.0001)) // one of these points lays on the plane... add them both without modification { AddIfNotInList(points, polygons[polynum].verts[pairs[i]]); AddIfNotInList(points, polygons[polynum].verts[pairs[i+1]]); } else // neither of them was not on the plane.. are they on the same side? { if (InFrontofPlane(polygons[polynum].verts[pairs[i]].point, plane_point, plane_normal) == InFrontofPlane(polygons[polynum].verts[pairs[i+1]].point, plane_point, plane_normal)) // both on same side - add them { AddIfNotInList(points, polygons[polynum].verts[pairs[i]]); AddIfNotInList(points, polygons[polynum].verts[pairs[i+1]]); } else // different sides - cut and add { uvdelta = FindIntersection(temp.point, polygons[polynum].verts[pairs[i]].point, polygons[polynum].verts[pairs[i+1]].point, plane_point, plane_normal); temp.norm = polygons[polynum].norm; temp.u = uvdelta * (polygons[polynum].verts[pairs[i]].u - polygons[polynum].verts[pairs[i+1]].u); temp.v = uvdelta * (polygons[polynum].verts[pairs[i]].v - polygons[polynum].verts[pairs[i+1]].v); AddIfNotInList(points, polygons[polynum].verts[pairs[i]]); AddIfNotInList(points, temp); AddIfNotInList(points, polygons[polynum].verts[pairs[i+1]]); } } } // split the polygons with the list we have int in = 0; for (i = 0; i < points.size(); i++) { dtempa = DistanceToPlane(points[i].point, plane_point, plane_normal) ; if (dtempa <= 0.0001 && dtempa >= -0.0001) // there WILL be two points in the list this is true for { AddIfNotInList(splitpolys[0].verts, points[i]); AddIfNotInList(splitpolys[1].verts, points[i]); if (in == 0) in = 1; else in = 0; } else { AddIfNotInList(splitpolys[in].verts, points[i]); } } // triangle our new polylist TriangulateMesh(splitpolys); // replace our current poly with polygon zero - add the others polygons[polynum] = splitpolys[0]; in = newpolys.size(); newpolys.resize(in+splitpolys.size()); for (i = 1; i < splitpolys.size(); i++) { newpolys[in+i] = splitpolys[i]; } }
// -------------------------------------------------------------------- // add_track_mark // -------------------------------------------------------------------- void add_track_mark (CControl *ctrl, int *id) { TVector3 width_vector; TVector3 left_vector; TVector3 right_vector; double magnitude; track_quad_t *q, *qprev, *qprevprev; TVector3 vel; double speed; TVector3 left_wing, right_wing; double left_y, right_y; double dist_from_surface; TPlane surf_plane; double comp_depth; double tex_end; double dist_from_last_mark; TVector3 vector_from_last_mark; TTerrType *TerrList = Course.TerrList; if (param.perf_level < 3) return; q = &track_marks.quads[track_marks.current_mark%MAX_TRACK_MARKS]; qprev = &track_marks.quads[(track_marks.current_mark-1)%MAX_TRACK_MARKS]; qprevprev = &track_marks.quads[(track_marks.current_mark-2)%MAX_TRACK_MARKS]; vector_from_last_mark = SubtractVectors (ctrl->cpos, track_marks.last_mark_pos); dist_from_last_mark = NormVector (&vector_from_last_mark); *id = Course.GetTerrainIdx (ctrl->cpos.x, ctrl->cpos.z, 0.5); if (*id < 1) { break_track_marks(); return; } if (TerrList[*id].trackmarks < 1) { break_track_marks(); return; } vel = ctrl->cvel; speed = NormVector (&vel); if (speed < SPEED_TO_START_TRENCH) { break_track_marks(); return; } width_vector = CrossProduct (ctrl->cdirection, MakeVector (0, 1, 0)); magnitude = NormVector (&width_vector); if (magnitude == 0) { break_track_marks(); return; } left_vector = ScaleVector (TRACK_WIDTH/2.0, width_vector); right_vector = ScaleVector (-TRACK_WIDTH/2.0, width_vector); left_wing = SubtractVectors (ctrl->cpos, left_vector); right_wing = SubtractVectors (ctrl->cpos, right_vector); left_y = Course.FindYCoord (left_wing.x, left_wing.z); right_y = Course.FindYCoord (right_wing.x, right_wing.z); if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) { break_track_marks(); return; } surf_plane = Course.GetLocalCoursePlane (ctrl->cpos); dist_from_surface = DistanceToPlane (surf_plane, ctrl->cpos); // comp_depth = get_compression_depth(Snow); comp_depth = 0.1; if (dist_from_surface >= (2 * comp_depth)) { break_track_marks(); return; } if (!continuing_track) { break_track_marks(); q->track_type = TRACK_HEAD; q->v1 = MakeVector (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z); q->v2 = MakeVector (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z); q->n1 = Course.FindCourseNormal (q->v1.x, q->v1.z); q->n2 = Course.FindCourseNormal (q->v2.x, q->v2.z); q->t1 = MakeVector2(0.0, 0.0); q->t2 = MakeVector2(1.0, 0.0); track_marks.next_mark = track_marks.current_mark + 1; } else { if (track_marks.next_mark == track_marks.current_mark) { q->v1 = qprev->v3; q->v2 = qprev->v4; q->n1 = qprev->n3; q->n2 = qprev->n4; q->t1 = qprev->t3; q->t2 = qprev->t4; if (qprev->track_type != TRACK_HEAD) qprev->track_type = TRACK_MARK; q->track_type = TRACK_MARK; } q->v3 = MakeVector (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z); q->v4 = MakeVector (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z); q->n3 = Course.FindCourseNormal (q->v3.x, q->v3.z); q->n4 = Course.FindCourseNormal (q->v4.x, q->v4.z); tex_end = speed*g_game.time_step/TRACK_WIDTH; if (q->track_type == TRACK_HEAD) { q->t3= MakeVector2 (0.0, 1.0); q->t4= MakeVector2 (1.0, 1.0); } else { q->t3 = MakeVector2 (0.0, q->t1.y + tex_end); q->t4 = MakeVector2 (1.0, q->t2.y + tex_end); } track_marks.current_mark++; track_marks.next_mark = track_marks.current_mark; } q->alpha = min ((2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0); track_marks.last_mark_time = g_game.time; continuing_track = true; }
void CLaser::OnSetOwner(CBaseEntity* pOwner) { BaseClass::OnSetOwner(pOwner); CDigitank* pTank = dynamic_cast<CDigitank*>(pOwner); if (!pTank) return; SetGlobalAngles(VectorAngles((pTank->GetLastAim() - GetGlobalOrigin()).Normalized())); SetGlobalOrigin(pOwner->GetGlobalOrigin()); SetGlobalVelocity(Vector(0,0,0)); SetGlobalGravity(Vector(0,0,0)); m_flTimeExploded = GameServer()->GetGameTime(); Vector vecForward, vecRight; AngleVectors(GetGlobalAngles(), &vecForward, &vecRight, NULL); for (size_t i = 0; i < GameServer()->GetMaxEntities(); i++) { CBaseEntity* pEntity = CBaseEntity::GetEntity(i); if (!pEntity) continue; if (!pEntity->TakesDamage()) continue; if (pEntity->GetOwner() == pOwner->GetOwner()) continue; float flDistance = DistanceToPlane(pEntity->GetGlobalOrigin(), GetGlobalOrigin(), vecRight); if (flDistance > 4 + pEntity->GetBoundingRadius()) continue; // Cull objects behind if (vecForward.Dot(pEntity->GetGlobalOrigin() - GetGlobalOrigin()) < 0) continue; if (pEntity->Distance(GetGlobalOrigin()) > LaserLength()) continue; pEntity->TakeDamage(pOwner, this, DAMAGE_LASER, m_flDamage, flDistance < pEntity->GetBoundingRadius()-2); CDigitank* pTank = dynamic_cast<CDigitank*>(pEntity); if (pTank) { float flRockIntensity = 0.5f; Vector vecDirection = (pTank->GetGlobalOrigin() - pOwner->GetGlobalOrigin()).Normalized(); pTank->RockTheBoat(flRockIntensity, vecDirection); } } CDigitanksPlayer* pCurrentTeam = DigitanksGame()->GetCurrentLocalDigitanksPlayer(); if (pCurrentTeam && pCurrentTeam->GetVisibilityAtPoint(GetGlobalOrigin()) < 0.1f) { if (pCurrentTeam->GetVisibilityAtPoint(GetGlobalOrigin() + AngleVector(GetGlobalAngles())*LaserLength()) < 0.1f) { // If the start and end points are both in the fog of war, delete it now that we've aready done the damage so it doesn't get rendered later. if (GameNetwork()->IsHost()) Delete(); } } }
// -------------------------------------------------------------------- // add_track_mark // -------------------------------------------------------------------- void add_track_mark(const CControl *ctrl, int *id) { if (param.perf_level < 3) return; TTerrType *TerrList = &Course.TerrList[0]; *id = Course.GetTerrainIdx (ctrl->cpos.x, ctrl->cpos.z, 0.5); if (*id < 1) { break_track_marks(); return; } if (!TerrList[*id].trackmarks) { break_track_marks(); return; } TVector3 vel = ctrl->cvel; double speed = NormVector (vel); if (speed < SPEED_TO_START_TRENCH) { break_track_marks(); return; } TVector3 width_vector = CrossProduct (ctrl->cdirection, TVector3 (0, 1, 0)); double magnitude = NormVector (width_vector); if (magnitude == 0) { break_track_marks(); return; } TVector3 left_vector = ScaleVector (TRACK_WIDTH/2.0, width_vector); TVector3 right_vector = ScaleVector (-TRACK_WIDTH/2.0, width_vector); TVector3 left_wing = SubtractVectors (ctrl->cpos, left_vector); TVector3 right_wing = SubtractVectors (ctrl->cpos, right_vector); double left_y = Course.FindYCoord (left_wing.x, left_wing.z); double right_y = Course.FindYCoord (right_wing.x, right_wing.z); if (fabs(left_y-right_y) > MAX_TRACK_DEPTH) { break_track_marks(); return; } TPlane surf_plane = Course.GetLocalCoursePlane (ctrl->cpos); double dist_from_surface = DistanceToPlane (surf_plane, ctrl->cpos); // comp_depth = get_compression_depth(Snow); double comp_depth = 0.1; if (dist_from_surface >= (2 * comp_depth)) { break_track_marks(); return; } if(track_marks.quads.size() < MAX_TRACK_MARKS) track_marks.quads.push_back(track_quad_t()); list<track_quad_t>::iterator qprev = track_marks.current_mark; if(track_marks.current_mark == track_marks.quads.end()) track_marks.current_mark = track_marks.quads.begin(); else track_marks.current_mark = incrementRingIterator(track_marks.current_mark); list<track_quad_t>::iterator q = track_marks.current_mark; if (!continuing_track) { q->track_type = TRACK_HEAD; q->v1 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z); q->v2 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z); q->v3 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z); q->v4 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z); q->n1 = Course.FindCourseNormal (q->v1.x, q->v1.z); q->n2 = Course.FindCourseNormal (q->v2.x, q->v2.z); q->t1 = TVector2(0.0, 0.0); q->t2 = TVector2(1.0, 0.0); } else { q->track_type = TRACK_TAIL; if (qprev != track_marks.quads.end()) { q->v1 = qprev->v3; q->v2 = qprev->v4; q->n1 = qprev->n3; q->n2 = qprev->n4; q->t1 = qprev->t3; q->t2 = qprev->t4; if (qprev->track_type == TRACK_TAIL) qprev->track_type = TRACK_MARK; } q->v3 = TVector3 (left_wing.x, left_y + TRACK_HEIGHT, left_wing.z); q->v4 = TVector3 (right_wing.x, right_y + TRACK_HEIGHT, right_wing.z); q->n3 = Course.FindCourseNormal (q->v3.x, q->v3.z); q->n4 = Course.FindCourseNormal (q->v4.x, q->v4.z); double tex_end = speed*g_game.time_step/TRACK_WIDTH; if (q->track_type == TRACK_HEAD) { q->t3= TVector2 (0.0, 1.0); q->t4= TVector2 (1.0, 1.0); } else { q->t3 = TVector2 (0.0, q->t1.y + tex_end); q->t4 = TVector2 (1.0, q->t2.y + tex_end); } } q->alpha = min ((2*comp_depth-dist_from_surface)/(4*comp_depth), 1.0); continuing_track = true; }
const bool Plane::PointOnPlane(Vector3d & point) { double d = 0; return DistanceToPlane(point) == d; }