public void avoid(ArrayList obstacles) { // Make a vector that will be the position of the object // relative to the Boid rotated in the direction of boid's velocity PVector closestRotated = new PVector(sight + 1, sight + 1); float closestDistance = 99999; Obstacle avoid = null; // Let's look at each obstacle for (int i = 0; i < obstacles.size(); i++) { Obstacle o = (Obstacle) obstacles.get(i); float d = PVector.dist(loc, o.loc); PVector dir = vel.get(); dir.normalize(); PVector diff = PVector.sub(o.loc, loc); // Now we use the dot product to rotate the vector that points from boid to obstacle // Velocity is the new x-axis PVector rotated = new PVector(diff.dot(dir), diff.dot(getNormal(dir))); // Is the obstacle in our path? if (PApplet.abs(rotated.y) < (o.radius + r)) { // Is it the closest obstacle? if ((rotated.x > 0) && (rotated.x < closestRotated.x)) { closestRotated = rotated; avoid = o; } } } // Can we actually see the closest one? if (PApplet.abs(closestRotated.x) < sight) { // The desired vector should point away from the obstacle // The closer to the obstacle, the more it should steer PVector desired = new PVector(closestRotated.x, -closestRotated.y * sight / closestRotated.x); desired.normalize(); desired.mult(closestDistance); desired.limit(maxspeed); // Rotate back to the regular coordinate system rotateVector(desired, vel.heading2D()); // Draw some debugging stuff if (debug) { stroke(0); line(loc.x, loc.y, loc.x + desired.x * 10, loc.y + desired.y * 10); avoid.highlight(true); } // Apply Reynolds steering rules desired.sub(vel); desired.limit(maxforce); acc.add(desired); } }
public boolean isInView(PVector vect) { PVector z = getZAxis(); PVector v1 = PVector.sub(vect, getTranslation()); float dotP = PVector.dot(v1, z) / (z.mag() * v1.mag()); if ((acos(dotP) * 180 / PI) <= fov) { return true; } return false; }
/** * Given two points p1, p2 and a line passing through a,b check whether p1 and p2 are on the * same side of the line. In our case a,b are characters and p1, p2 are cameras */ public boolean isInSameHalfPlane(PVector p1, PVector p2, PVector a, PVector b) { PVector copyP1 = new PVector(p1.x, p1.y, p1.z); PVector copyP2 = new PVector(p2.x, p2.y, p2.z); PVector copyA = new PVector(a.x, a.y, a.z); PVector copyB = new PVector(b.x, b.y, b.z); copyB.sub(copyA); copyP1.sub(copyA); copyP2.sub(copyA); PVector p1a = copyB.cross(copyP1); PVector p2a = copyB.cross(copyP2); if (p1a.dot(p2a) > 0) { return true; } return false; }
/** * Sets the Quaternion as a rotation from the {@code from} direction to the {@code to} direction. * * <p><b>Attention:</b> this rotation is not uniquely defined. The selected axis is usually * orthogonal to {@code from} and {@code to}, minimizing the rotation angle. This method is robust * and can handle small or almost identical vectors. * * @see #fromAxisAngle(PVector, float) */ public void fromTo(PVector from, PVector to) { float fromSqNorm = MathUtils.squaredNorm(from); float toSqNorm = MathUtils.squaredNorm(to); // Identity Quaternion when one vector is null if ((fromSqNorm < 1E-10f) || (toSqNorm < 1E-10f)) { this.x = this.y = this.z = 0.0f; this.w = 1.0f; } else { PVector axis = from.cross(to); float axisSqNorm = MathUtils.squaredNorm(axis); // Aligned vectors, pick any axis, not aligned with from or to if (axisSqNorm < 1E-10f) axis = MathUtils.orthogonalVector(from); float angle = PApplet.asin(PApplet.sqrt(axisSqNorm / (fromSqNorm * toSqNorm))); if (from.dot(to) < 0.0) angle = PI - angle; fromAxisAngle(axis, angle); } }
public void checkThirtyDegreeRule( ArrayList<Cam> cameras, ArrayList<Character> characters, int selectedIdx) { if (cameras == null || cameras.isEmpty()) { println("No cameras in the scene!"); } if (characters.size() != 2) { println("Only two characters supported for now"); // TODO (sanjeet): Hack! Fix this once more characters are allowed } Cam selectedCamera = cameras.get(selectedIdx); // TODO The characters.get results in a runtime error because there aren't currently any // characters allocated in the input file. Character ch1 = characters.get(0); Character ch2 = characters.get(1); // Obtaining (x,y,z) for characters and selected camera PVector ch1Location = ch1.getTranslation(); PVector ch2Location = ch2.getTranslation(); PVector selectedCameraLocation = selectedCamera.getTranslation(); PVector cameraPoint = new PVector(); cameraPoint.add(selectedCameraLocation); for (int i = 0; i < 100; i++) { cameraPoint.add(selectedCamera.getZAxis()); } PVector intersection = getTwoLinesIntersection( new PVector(ch1Location.x, ch1Location.z), new PVector(ch2Location.x, ch2Location.z), new PVector(selectedCameraLocation.x, selectedCameraLocation.z), new PVector(cameraPoint.x, cameraPoint.z)); PVector diff = PVector.sub(selectedCameraLocation, intersection); diff.normalize(); FloatBuffer fb = selectedCamera.modelViewMatrix; float[] mat = fb.array(); float[] fbMatrix = new float[mat.length]; for (int i = 0; i < fbMatrix.length; i++) { fbMatrix[i] = mat[i]; } fbMatrix[0] = -diff.x; fbMatrix[1] = diff.y; fbMatrix[2] = -diff.z; fbMatrix[9] = diff.x; fbMatrix[10] = diff.y; fbMatrix[11] = diff.z; fbMatrix[13] = intersection.x; fbMatrix[14] = intersection.y; fbMatrix[15] = intersection.z; PMatrix3D matrix = new PMatrix3D(); matrix.set(fbMatrix); matrix.transpose(); pushMatrix(); applyMatrix(matrix); rotateY(radians(30)); line(0, 0, 0, 0, 0, 1000); rotateY(radians(-2 * 30)); line(0, 0, 0, 0, 0, 1000); popMatrix(); for (int i = 0; i < cameras.size(); i++) { if (i == selectedIdx) { continue; } if (!cameras.get(i).isInView(ch1Location) && !cameras.get(i).isInView(ch2Location)) { continue; } PVector currCamLocation = cameras.get(i).getTranslation(); PVector vect1 = PVector.sub(currCamLocation, intersection); PVector vect2 = PVector.sub(selectedCameraLocation, intersection); float dotP = vect1.dot(vect2) / (vect1.mag() * vect2.mag()); if (acos(dotP) <= PI / 6) { cameras.get(i).setColor(255, 0, 0); } else { cameras.get(i).setColor(0, 0, 255); } } }