public void stay_field(PlanetariaCollider field) { if (OnFieldStay.exists) { OnFieldStay.data(field); } }
public void enter_field(PlanetariaCollider field) { if (OnFieldEnter.exists) { OnFieldEnter.data(field); } }
internal void notify_enter_field(PlanetariaCollider field) { foreach (PlanetariaMonoBehaviour observer in observers) { observer.enter_field(field); } }
public void exit_field(PlanetariaCollider field) { if (OnFieldExit.exists) { OnFieldExit.data(field); } }
public void enter_field(PlanetariaCollider field) { if (on_field_enter.exists) { on_field_enter.data(field); } }
public void stay_field(PlanetariaCollider field) { if (on_field_stay.exists) { on_field_stay.data(field); } }
public void exit_field(PlanetariaCollider field) { if (on_field_exit.exists) { on_field_exit.data(field); } }
//barycentricCoordinate The barycentric coordinate of the triangle we hit. // RESEARCH: are there any equivalents to triangles I should be creating? //lightmapCoord The uv lightmap coordinate at the impact point. //textureCoord The uv texture coordinate at the collision location. //textureCoord2 The secondary uv texture coordinate at the impact point. //triangleIndex The index of the triangle that was hit. /// <summary> /// Constructor - creates the Planetaria equivalent of UnityEngine.RaycastHit /// </summary> /// <param name="raycast_arc">The path along which the raycast (inverse path for negative distances).</param> /// <param name="geometry_arc">The arc which intersects the raycast (i.e. the arc hit).</param> /// <param name="intersection_point">The intersection point of two circular arcs in 3D space.</param> /// <returns>The result of a point sweep / raycast in spherical 2D space.</returns> private PlanetariaRaycastHit(Arc raycast_arc, PlanetariaCollider planetaria_collider, Arc geometry_arc, Vector3 intersection_point, float raycast_distance) { arc = geometry_arc; collider = planetaria_collider; distance = raycast_arc.position_to_angle(intersection_point) * (raycast_arc.length() / raycast_arc.angle()); // TODO: verify distance += raycast_arc.length() / 2; if (raycast_distance < 0) { distance = raycast_arc.length() - distance; } positive_face_collision = true; // FIXME: HACK: LAZY: // also dynamic changes Transform internal_transform = collider.gameObject.internal_game_object.GetComponent <Transform>(); Quaternion arc_to_world = internal_transform.rotation; Quaternion world_to_arc = Quaternion.Inverse(arc_to_world); Vector3 local_intersection_point = world_to_arc * intersection_point; float angle = raycast_arc.position_to_angle(local_intersection_point); Vector3 local_normal = raycast_arc.normal(angle); normal = arc_to_world * local_normal; point = intersection_point; rigidbody = collider.GetComponent <PlanetariaRigidbody>(); transform = Miscellaneous.GetOrAddComponent <PlanetariaTransform>(collider); }
public static void prepare(PlanetariaCollider collider) { discontinuities = new Dictionary <Arc, List <Discontinuity> >(); find_discontinuities(collider); sort_discontinuities(); collider_variable = collider; }
/// <summary> /// Inspector - Finds the collision points between an arc extrapolated to be distance long (the PlanetariaRaycastHit structs have no particular order) /// </summary> /// <param name="arc">A fragment that defines the arc in space (might not be fully used or return collisions after the end of the arc).</param> /// <param name="distance">The distance to raycast (may be greater than or less than the length of the arc - or negative).</param> /// <param name="layer_mask">The collision mask that defines which objects will be ignored.</param> /// <returns>All of the collision points of the Raycast (listed exactly once).</returns> private static PlanetariaRaycastHit[] unordered_raycast_all(Arc arc, float distance, int layer_mask, bool collide_with_fields) { //float angle = arc.angle(); // this would determine the intersections for the un-modified arc (ignoring distance) // desired_angle = desired_length * (partial_angle/partial_length) i.e. length * length_to_angle ratio float desired_angle = distance * (arc.angle() / arc.length()); // TODO: verify negative distances go backwards desired_angle = Mathf.Clamp(desired_angle, -2 * Mathf.PI, 2 * Mathf.PI); // primative arc points Vector3 arc_left = arc.position(-arc.angle() / 2); Vector3 arc_center = arc.position(-arc.angle() / 2 + desired_angle / 2); Vector3 arc_right = arc.position(-arc.angle() / 2 + desired_angle); SerializedArc ray_arc = ArcFactory.curve(arc_left, arc_center, arc_right); PlanetariaShape ray_shape = PlanetariaShape.Create(new List <SerializedArc> { ray_arc }, false); // composites Vector3 arc_boundary_midpoint = (arc_left + arc_right) / 2; // if the arc is like a wooden bow, this is the midpoint of the string Vector3 arc_forward = (arc_center - arc_boundary_midpoint).normalized; // the direction a hypothetical arrow would travel Vector3 arc_up = arc.floor().normal; // orthogonal/perpendicular to the imaginary "bow" // UnityEngine.Physics.OverlapBox() requirements // FIXME: OPTIMIZE: half_extents currently provides unnecessary false positives because the "width" of plane (the depth into the distance and zero height are fine) Vector3 half_extents = new Vector3(1, 0, 1); // The largest collision "box" for a unit sphere is a radius of 1 in the x-z plane; height along y is 0. Vector3 center = arc_boundary_midpoint + arc_forward * 1; // The center of the "box" must be offset 1 (the radius) along the forward axis from the two arc boundaries. Quaternion rotation = Quaternion.LookRotation(arc_forward, arc_up); // SphereColliders (only) that represent potential collisions (not guaranteed). Collider[] colliders = Physics.OverlapBox(center, half_extents, rotation, layer_mask, QueryTriggerInteraction.Collide); // TODO: verify this casts properly List <PlanetariaRaycastHit> raycast_hits = new List <PlanetariaRaycastHit>(); Debug.Log(colliders.Length); foreach (SphereCollider sphere_collider in colliders) { PlanetariaCollider planetaria_collider = PlanetariaCache.collider_fetch(sphere_collider); if (planetaria_collider.is_field && !collide_with_fields) { Debug.LogError("Why?"); continue; } Quaternion geometry_rotation = planetaria_collider.gameObject.internal_game_object.transform.rotation; Debug.Log("Found a collider with " + planetaria_collider.shape.Length + " arcs."); foreach (Arc geometry_arc in ray_shape.block_collision(planetaria_collider.shape, geometry_rotation)) { Vector3[] intersections = PlanetariaIntersection.raycast_intersection(arc, geometry_arc, distance, geometry_rotation); // TODO: verify distance is indeed the angle in this scenario Debug.Log("Found an arc with " + intersections.Length + " intersections."); foreach (Vector3 intersection in intersections) { PlanetariaRaycastHit single_collision = PlanetariaRaycastHit.hit(arc, planetaria_collider, geometry_arc, intersection, distance); raycast_hits.Add(single_collision); } } } return(raycast_hits.ToArray()); }
internal void notify_exit_field(PlanetariaCollider field) { foreach (PlanetariaMonoBehaviour observer in observers) { observer.exit_field(field); } //current_fields.Remove(field); // Don't want invalidated iterators - swap at end of loop }
public static PlanetariaCollider collider_fetch(SphereCollider key) { if (!collider_cache.ContainsKey(key)) { PlanetariaCollider planetaria_collider = key.GetComponent <PlanetariaCollider>(); Debug.Assert(planetaria_collider, "SphereColliders must be matched with PlanetariaColliders"); collider_cache.Add(key, planetaria_collider); } return(collider_cache[key]); }
public void initialize(PlanetariaCollider observed, PlanetariaMonoBehaviour[] observers) { this.planetaria_collider = observed; this.planetaria_rigidbody = observed.GetComponent <PlanetariaRigidbody>(); this.planetaria_transformation = observed.GetComponent <PlanetariaTransform>(); foreach (PlanetariaMonoBehaviour observer in observers) { if (!this.observers.Contains(observer)) { this.observers.Add(observer); } } }
/// <summary> /// Mutator - find all intersections along x=0 or z=0 arcs in southern hemisphere. /// </summary> /// <param name="block">The block (set of arcs) to be inspected.</param> private static void find_discontinuities(PlanetariaCollider collider) { foreach (Arc arc in collider.shape.arcs) { for (int dimension = 0; dimension < 2; ++dimension) // Intersect already gets quadrants 3-4 by proxy { float angle = (Mathf.PI / 2) * dimension; Vector3 begin = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)); Vector3 end = Vector3.down; Vector3[] intersections = PlanetariaIntersection.arc_path_intersections(arc, begin, end, 0); add_intersections(arc, intersections); } } }
public static optional <TextAsset> render(PlanetariaCollider collider, float width) { VectorGraphicsWriter.begin_canvas(); VectorGraphicsWriter.begin_shape(); BlockRendererIterator.prepare(collider); foreach (ArcIterator arc_iterator in BlockRendererIterator.arc_iterator()) { ShapeRenderer.partition_arc(arc_iterator.arc, arc_iterator.begin, arc_iterator.end); } VectorGraphicsWriter.end_shape(Color.black, width); return(VectorGraphicsWriter.end_canvas()); }
private static bool platform_collision(Arc arc, PlanetariaCollider collider, PlanetariaTransform transformation, PlanetariaRigidbody rigidbody, optional <Vector3> intersection_point) { Vector3 velocity = Bearing.attractor(rigidbody.get_previous_position(), rigidbody.get_position()); if (intersection_point.exists) { float arc_angle = arc.position_to_angle(intersection_point.data); Vector3 normal = arc.normal(arc_angle); bool upward_facing_normal = Vector3.Dot(normal, rigidbody.get_acceleration()) <= 0; bool moving_toward = Vector3.Dot(normal, velocity) <= 0; if (upward_facing_normal && moving_toward) { return(true); } } return(false); }
public void potential_block_collision(Arc arc, PlanetariaCollider collider) { if (planetaria_rigidbody.exists) { if (current_collisions.Count == 0 || current_collisions[0].other != collider) { optional <BlockCollision> collision = BlockCollision.block_collision(this, arc, collider, planetaria_transformation, planetaria_rigidbody.data); if (collision.exists) { if (planetaria_rigidbody.exists) { if (planetaria_rigidbody.data.collide(collision.data, this)) { collision_candidates.Add(collision.data); } } } } } }
private static void draw_planetaria_collider_gizmos(PlanetariaCollider self, GizmoType gizmo_type) { PlanetariaShapeEditor.draw_shape(self.shape, self.gameObject.internal_game_object.transform.rotation); /* * if (!self.is_field) * { * PlanetariaArcColliderEditor.draw_arc(self.shape.block_list[arc_identifier], * self.gameObject.internal_game_object.transform.rotation, mask); * } * else * { * for (int index = 0; index < self.shape.field_list.Length; ++index) * { * if (!mask[index]) * { * PlanetariaSphereColliderEditor.draw_sphere(self.shape.field_list[index], * self.gameObject.internal_game_object.transform.rotation); * } * } * } */ }
/// <summary> /// Named Constructor - creates the Planetaria equivalent of UnityEngine.RaycastHit /// </summary> /// <returns>The result of a point sweep / raycast in spherical 2D space.</returns> public static PlanetariaRaycastHit hit(Arc raycast_arc, PlanetariaCollider planetaria_collider, Arc geometry_arc, Vector3 intersection_point, float raycast_distance) { return(new PlanetariaRaycastHit(raycast_arc, planetaria_collider, geometry_arc, intersection_point, raycast_distance)); }
public static optional <BlockCollision> block_collision(CollisionObserver observer, Arc arc, PlanetariaCollider collider, PlanetariaTransform transformation, PlanetariaRigidbody rigidbody) { optional <ArcVisitor> arc_visitor = collider.shape.arc_visitor(arc); if (!arc_visitor.exists) { Debug.LogError("This should never happen"); return(new optional <BlockCollision>()); } Quaternion block_to_world = collider.gameObject.internal_game_object.transform.rotation; Quaternion world_to_block = Quaternion.Inverse(block_to_world); Vector3 last_position = world_to_block * rigidbody.get_previous_position(); Vector3 current_position = world_to_block * rigidbody.get_position(); float extrusion = transformation.scale / 2; optional <Vector3> intersection_point = PlanetariaIntersection.arc_path_intersection(arc, last_position, current_position, extrusion); if (!intersection_point.exists) // theoretically only happens with moving objects for discrete collision checks { // these functions are general inverses of one another, but also serve to constrain/normalize the position to the arc path. float intersection_angle = arc.position_to_angle(current_position); if (Mathf.Abs(intersection_angle) <= arc.angle() / 2) // if the intersection is valid { intersection_point = arc.position(intersection_angle); // set the collision to the extruded collision point } } if (!intersection_point.exists) { Debug.LogError("Research why this happened."); return(new optional <BlockCollision>()); } BlockCollision result = new BlockCollision(); float angle = arc.position_to_angle(intersection_point.data); result.geometry_visitor = ShapeVisitor.geometry_visitor(arc_visitor.data, angle, extrusion, collider.gameObject.internal_game_object.transform); intersection_point.data = block_to_world * intersection_point.data; result.distance = Vector3.Angle(intersection_point.data, rigidbody.get_previous_position()) * Mathf.Deg2Rad; result.overshoot = Vector3.Angle(intersection_point.data, rigidbody.get_position()) * Mathf.Deg2Rad; result.observer = observer; result.self = observer.collider(); result.other = collider; PlanetariaPhysicMaterial self = result.self.material; PlanetariaPhysicMaterial other = result.other.material; result.elasticity = PlanetariaPhysics.blend( self.elasticity, self.elasticity_combine, other.elasticity, other.elasticity_combine); result.friction = PlanetariaPhysics.blend( self.friction, self.friction_combine, other.friction, other.friction_combine); result.magnetism = -(self.magnetism - other.magnetism * self.induced_magnetism_multiplier) * (other.magnetism - self.magnetism * other.induced_magnetism_multiplier); return(result); }
public void potential_field_collision(PlanetariaCollider field) { field_candidates.Add(field); }
public static void cache(PlanetariaCollider collider) { PlanetariaCache.collider_cache.Add(collider.get_sphere_collider(), collider); }
public static void uncache(PlanetariaCollider collider) { PlanetariaCache.collider_cache.Remove(collider.get_sphere_collider()); }