public class UserRelativityTracker {
private final static int minimalSliceFactor = 5;
+
+ /**
+ * Points to 0, 0, 0 in object own relative space.
+ */
public Vertex center = new Vertex();
+
+ /**
+ * Points to 10, 0, 0 in object own relative space if orientation tracking is enabled.
+ * It is used to determine the angle between the user and the object.
+ */
public Vertex right;
+
+ /**
+ * Points to 0, 10, 0 in object own relative space if orientation tracking is enabled.
+ * It is used to determine the angle between the user and the object.
+ */
public Vertex down;
public UserRelativityTracker() {
center.calculateLocationRelativeToViewer(transformPipe, renderingContext);
- if (right != null) {
+ if (right != null) { // If orientation tracking is enabled.
right.calculateLocationRelativeToViewer(transformPipe, renderingContext);
down.calculateLocationRelativeToViewer(transformPipe, renderingContext);
}
}
+ /**
+ * Initializes the orientation tracking.
+ * Orientation tracking is used to determine the angle between the user and the object.
+ * Orientation tracking is disabled by default and it is optional.
+ */
public void enableOrientationTracking() {
right = new Vertex(new Point3D(10, 0, 0));
down = new Vertex(new Point3D(0, 10, 0));
}
+ /**
+ * Calculates the angle between the user and the object in the XY plane.
+ * @return the angle between the user and the object in the XY plane.
+ */
public double getAngleXY() {
return center.transformedCoordinate
.getAngleXY(down.transformedCoordinate);
}
+ /**
+ * Calculates the angle between the user and the object in the XZ plane.
+ * @return the angle between the user and the object in the XZ plane.
+ */
public double getAngleXZ() {
return center.transformedCoordinate
.getAngleXZ(right.transformedCoordinate);
}
+ /**
+ * Calculates the angle between the user and the object in the YZ plane.
+ * @return the angle between the user and the object in the YZ plane.
+ */
public double getAngleYZ() {
return center.transformedCoordinate
.getAngleYZ(down.transformedCoordinate);
}
+ /**
+ * Calculates the distance between the user and the object.
+ * Distance to the user can be used to determine object detail level.
+ */
public double getDistanceToUser() {
return center.transformedCoordinate.getVectorLength();
}
import java.awt.*;
import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
+import static java.util.Arrays.sort;
+
+/**
+ * Textured polygon.
+ * <p>
+ *
+ * <pre>
+ * This is how perspective-correct texture rendering is implemented:
+ * If polygon is sufficiently small, it is rendered without perspective correction.
+ * Otherwise, it is sliced into smaller polygons.
+ * </pre>
+ */
public class TexturedPolygon extends AbstractCoordinateShape {
public final Texture texture;
- final PolygonBorderInterpolator[] is = new PolygonBorderInterpolator[]{
- new PolygonBorderInterpolator(), new PolygonBorderInterpolator(),
- new PolygonBorderInterpolator()};
/**
* Polygon texture coordinates.
*/
yBottom = renderBuffer.height - 1;
// paint
- double totalVisibleDistance = projectedPoint1
- .getDistanceTo(projectedPoint2);
+ double totalVisibleDistance = projectedPoint1.getDistanceTo(projectedPoint2);
totalVisibleDistance += projectedPoint1.getDistanceTo(projectedPoint3);
totalVisibleDistance += projectedPoint2.getDistanceTo(projectedPoint3);
final TextureBitmap zoomedBitmap = texture.getZoomedBitmap(scaleFactor);
+ final PolygonBorderInterpolator[] is = new PolygonBorderInterpolator[]{
+ new PolygonBorderInterpolator(), new PolygonBorderInterpolator(),
+ new PolygonBorderInterpolator()};
+
is[0].setPoints(projectedPoint1, projectedPoint2, texturePoint1,
texturePoint2);
is[1].setPoints(projectedPoint1, projectedPoint3, texturePoint1,
is[2].setPoints(projectedPoint2, projectedPoint3, texturePoint2,
texturePoint3);
- java.util.Arrays.sort(is);
+ sort(is);
for (int y = yTop; y < yBottom; y++)
if (is[0].containsY(y)) {
import java.util.List;
import java.util.stream.Collectors;
-/**
- * In order to get perspective correct textures, large textured polygons are
- * sliced into smaller ones.
- */
-
public class AbstractCompositeShape extends AbstractShape {
private final List<SubShape> originalSubShapes = new ArrayList<>();
private final UserRelativityTracker relativityTracker;
});
}
- private boolean isReslicingNeeded(double sliceFactor1, double sliceFactor2) {
+ private boolean isReslicingNeeded(double proposedNewSliceFactor, double currentSliceFactor) {
if (slicingOutdated)
return true;
- if (sliceFactor1 > sliceFactor2) {
- final double tmp = sliceFactor1;
- sliceFactor1 = sliceFactor2;
- sliceFactor2 = tmp;
+ // reslice if there is significant difference between proposed and current slice factor
+ if (proposedNewSliceFactor > currentSliceFactor) {
+ final double tmp = proposedNewSliceFactor;
+ proposedNewSliceFactor = currentSliceFactor;
+ currentSliceFactor = tmp;
}
- return (sliceFactor2 / sliceFactor1) > 1.5d;
-
+ return (currentSliceFactor / proposedNewSliceFactor) > 1.5d;
}
public void removeGroup(final String groupIdentifier) {
private void resliceIfNeeded() {
- final double proposedSliceFactor = relativityTracker
- .proposeSliceFactor();
+ final double proposedSliceFactor = relativityTracker.proposeSliceFactor();
if (isReslicingNeeded(proposedSliceFactor, currentSliceFactor)) {
currentSliceFactor = proposedSliceFactor;
- slice();
+ reslice();
}
}
});
}
- private void slice() {
+ private void reslice() {
slicingOutdated = false;
final List<AbstractShape> result = new ArrayList<>();
* Polygon coordinate.
* This class is used to store coordinates of a point in 3D space and its
* texture coordinate.
+ *
+ * TODO: Refactor this class out of existence. Use Vertex instead. Texture coordinates should be moved to Vertex.
*/
public class PolygonCoordinate {