2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic;
7 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
8 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
9 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
10 import eu.svjatoslav.sixth.e3d.math.Vertex;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
16 * Texture object that is always oriented towards the viewer.
18 public class ForwardOrientedTexture extends AbstractCoordinateShape {
20 private static final double SCALE_MULTIPLIER = 0.005;
21 public final Texture texture;
24 * Scale of the texture object.
26 * Object rendered visible size on the screen depends on underlying texture size and scale.
28 * 0 means that object will be infinitely small.
29 * 1 in recommended value to maintain sharpness of the texture as seen by the viewer.
33 public ForwardOrientedTexture(final Point3D point, final double scale,
34 final Texture texture) {
35 super(new Vertex(point));
36 this.texture = texture;
41 * Paint the texture on the screen (targetRenderingArea)
43 * @param targetRenderingArea the screen to paint on
46 public void paint(final RenderingContext targetRenderingArea) {
48 // distance from camera/viewer to center of the texture
49 final double z = coordinates[0].transformedCoordinate.z;
51 // compute forward oriented texture visible distance from center
52 final double visibleHorizontalDistanceFromCenter = (targetRenderingArea.width
53 * scale * texture.primaryBitmap.width) / z;
55 final double visibleVerticalDistanceFromCenter = (targetRenderingArea.width
56 * scale * texture.primaryBitmap.height) / z;
58 // compute visible pixel density, and get appropriate bitmap
59 final double zoom = (visibleHorizontalDistanceFromCenter * 2)
60 / texture.primaryBitmap.width;
62 final TextureBitmap textureBitmap = texture.getZoomedBitmap(zoom);
64 final Point2D onScreenCoordinate = coordinates[0].onScreenCoordinate;
67 final int onScreenUncappedYStart = (int) (onScreenCoordinate.y - visibleVerticalDistanceFromCenter);
68 final int onScreenUncappedYEnd = (int) (onScreenCoordinate.y + visibleVerticalDistanceFromCenter);
69 final int onScreenUncappedHeight = onScreenUncappedYEnd - onScreenUncappedYStart;
71 int onScreenCappedYStart = onScreenUncappedYStart;
72 int onScreenCappedYEnd = onScreenUncappedYEnd;
74 // cap Y to upper screen border
75 if (onScreenCappedYStart < 0)
76 onScreenCappedYStart = 0;
78 // cap Y to lower screen border
79 if (onScreenCappedYEnd > targetRenderingArea.height)
80 onScreenCappedYEnd = targetRenderingArea.height;
83 final int onScreenUncappedXStart = (int) (onScreenCoordinate.x - visibleHorizontalDistanceFromCenter);
84 final int onScreenUncappedXEnd = (int) (onScreenCoordinate.x + visibleHorizontalDistanceFromCenter);
85 final int onScreenUncappedWidth = onScreenUncappedXEnd - onScreenUncappedXStart;
87 // cap X to left screen border
88 int onScreenCappedXStart = onScreenUncappedXStart;
89 if (onScreenCappedXStart < 0)
90 onScreenCappedXStart = 0;
92 // cap X to right screen border
93 int onScreenCappedXEnd = onScreenUncappedXEnd;
94 if (onScreenCappedXEnd > targetRenderingArea.width)
95 onScreenCappedXEnd = targetRenderingArea.width;
97 final byte[] targetRenderingAreaBytes = targetRenderingArea.pixels;
99 final int textureWidth = textureBitmap.width;
101 for (int y = onScreenCappedYStart; y < onScreenCappedYEnd; y++) {
103 final int sourceBitmapScanlinePixel = ((textureBitmap.height * (y - onScreenUncappedYStart)) / onScreenUncappedHeight)
106 int targetRenderingAreaOffset = ((y * targetRenderingArea.width) + onScreenCappedXStart) * 4;
108 for (int x = onScreenCappedXStart; x < onScreenCappedXEnd; x++) {
110 final int sourceBitmapPixelAddress = (sourceBitmapScanlinePixel + ((textureWidth * (x - onScreenUncappedXStart)) / onScreenUncappedWidth)) * 4;
112 textureBitmap.drawPixel(sourceBitmapPixelAddress, targetRenderingAreaBytes, targetRenderingAreaOffset);
114 targetRenderingAreaOffset += 4;
120 * Set the scale of the texture
122 * @param scale the scale of the texture
124 public void setScale(final double scale) {
125 this.scale = scale * SCALE_MULTIPLIER;
128 public Point3D getLocation() {
129 return coordinates[0].coordinate;