package primitives3D;
import graphicsUtilities.Polygon2D;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import math3D.Window3D;
/**
* A 3D polygon.
*
* @author Curran Kelleher
*
*/
public class Polygon3D extends Object3D {
/**
* When true, all Polygon3D objects are shaded using their normals
*/
public static boolean shade = true;
/**
* Vectors used for shading calculations; the normal and a re-usable vector
* for calculating rotations of the normal.
*/
Vector3D normal = new Vector3D(0, 0, 0), rotatedNormal = new Vector3D(0, 0,
0);
/**
* The array containing the points which bound the 3D polygon.
*/
Vector3D[] polygonPoints;
/**
* The x points of the 2D triangle used to draw this 3D triangle.
*/
float[] xPoints;
/**
* The y points of the 2D triangle used to draw this 3D triangle.
*/
float[] yPoints;
/**
* The 2D polygon used to draw this 3D polygon.
*/
Polygon2D polygon = new Polygon2D();
/**
* A Point object used as a temporary variable in rotation calculations.
*/
Point2D.Float tempPoint = new Point2D.Float();
/**
* The color of this object when shaded.
*/
Color shadedColor;
public Polygon3D(Vector3D[] polygonPoints, Color color) {
if (polygonPoints.length < 3)
(new Exception(
"polygonPoints must have at least 3 points to make a polygon!"))
.printStackTrace();
this.polygonPoints = polygonPoints;
xPoints = new float[polygonPoints.length];
yPoints = new float[polygonPoints.length];
for (int i = 0; i < polygonPoints.length; i++) {
xPoints[i] = 0;
yPoints[i] = 0;
}
polygon.xpoints = xPoints;
polygon.ypoints = yPoints;
polygon.npoints = polygonPoints.length;
this.color = color;
shadedColor = color;
}
/**
* Draws this Object3D onto the specified Graphics.
*
* @param g
* the Graphics on which to draw this 3D object
*/
public void drawOnThis(Graphics2D g) {
// If the rotated Vector3D is not drawable on the screen, the x
// coordinate of pointToPutResultIn gets set to Integer.MIN_VALUE by the
// method Window.getPixelFromTranslatedVector3D
g.setColor(shade ? shadedColor : color);
g.fill(polygon);
}
/**
* )Called on each object before sorting and drawing them, allows them to
* calculate the rotated points and whatever else would help.
*
* @param window
* the window used for the rotation (use
* window.getRotatedVector3D(Vector3D p))
*/
public void calculateRotation(Window3D w) {
w.getRotatedVector3D(polygonPoints[0], centerPoint);
w.getPixelFromRotatedPoint3D(centerPoint, tempPoint);
xPoints[0] = tempPoint.x;
yPoints[0] = tempPoint.y;
for (int i = 1; i < polygonPoints.length; i++) {
w.getPixelFromVector3D(polygonPoints[i], tempPoint);
xPoints[i] = tempPoint.x;
yPoints[i] = tempPoint.y;
}
if (w.drawFor3D) {
if (shade)
calculateShading(w);
} else
shadedColor = color;
}
int[] initColorComponents = new int[3];
int[] colorComponents = new int[3];
private void calculateShading(Window3D w) {
/**
* if(polygonPoints.length == 4) { Vector3D tempA=new Vector3D();
* Vector3D tempB=new Vector3D();
*
* polygonPoints[2].minus(polygonPoints[0],tempA);
* polygonPoints[3].minus(polygonPoints[1],tempB);
*
* tempA.cross(tempB,normal); } else
*/
Vector3D.calculateNormal(polygonPoints[0], polygonPoints[1],
polygonPoints[2], normal);
w.getRotatedVector3D(normal, rotatedNormal);
double thetaX = Math.atan2(rotatedNormal.x, rotatedNormal.z);
double thetaY = Math.atan2(rotatedNormal.y, rotatedNormal.z);
double sunX = 0;
double sunY = 0;
double angleAwayFromSunX = Math.abs(thetaX - sunX);
double angleAwayFromSunY = Math.abs(thetaY - sunY);
double AngleAwayFromSun = Math.sqrt(angleAwayFromSunX
* angleAwayFromSunX + angleAwayFromSunY * angleAwayFromSunY);
double maxAngleAwayFromSun = Math.sqrt(2) * Math.PI;
// 1 is closest, 0 is farthest away
double scaledAngleAwayFromSun = 1 - AngleAwayFromSun
/ maxAngleAwayFromSun;
// 1 is brightest, 0 is darkest
double usableAngleAwayFromSun = 2 * Math
.abs(scaledAngleAwayFromSun - .5);
initColorComponents[0] = color.getRed();
initColorComponents[1] = color.getGreen();
initColorComponents[2] = color.getBlue();
for (int i = 0; i < 3; i++) {
colorComponents[i] = (int) ((double) initColorComponents[i] * (usableAngleAwayFromSun + .2));
if (colorComponents[i] > 255)
colorComponents[i] = 255;
if (colorComponents[i] < 0)
colorComponents[i] = 0;
}
shadedColor = new Color(colorComponents[0], colorComponents[1],
colorComponents[2], color.getAlpha());
}
}