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.renderer.raster.shapes.AbstractCoordinateShape;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
15 * Texture object that is always oriented towards the viewer.
17 public class ForwardOrientedTexture extends AbstractCoordinateShape {
19 private static final double SCALE_MULTIPLIER = 0.005;
20 public final Texture texture;
23 * Scale of the texture object.
25 * Object rendered visible size on the screen depends on underlying texture size and scale.
27 * 0 means that object will be infinitely small.
28 * 1 in recommended value to maintain sharpness of the texture as seen by the viewer.
32 public ForwardOrientedTexture(final Point3D point, final double scale,
33 final Texture texture) {
35 this.texture = texture;
40 * Paint the texture on the screen (targetRenderingArea)
42 * @param targetRenderingArea the screen to paint on
45 public void paint(final RenderingContext targetRenderingArea) {
47 // distance from camera/viewer to center of the texture
48 final double z = coordinates[0].transformedCoordinate.z;
50 // compute forward oriented texture visible distance from center
51 final double visibleHorizontalDistanceFromCenter = (targetRenderingArea.width
52 * scale * texture.primaryBitmap.width) / z;
54 final double visibleVerticalDistanceFromCenter = (targetRenderingArea.width
55 * scale * texture.primaryBitmap.height) / z;
57 // compute visible pixel density, and get appropriate bitmap
58 final double zoom = (visibleHorizontalDistanceFromCenter * 2)
59 / texture.primaryBitmap.width;
61 final TextureBitmap textureBitmap = texture.getZoomedBitmap(zoom);
63 final Point2D onScreenCoordinate = coordinates[0].onScreenCoordinate;
66 final int onScreenUncappedYStart = (int) (onScreenCoordinate.y - visibleVerticalDistanceFromCenter);
67 final int onScreenUncappedYEnd = (int) (onScreenCoordinate.y + visibleVerticalDistanceFromCenter);
68 final int onScreenUncappedHeight = onScreenUncappedYEnd - onScreenUncappedYStart;
70 int onScreenCappedYStart = onScreenUncappedYStart;
71 int onScreenCappedYEnd = onScreenUncappedYEnd;
73 // cap Y to upper screen border
74 if (onScreenCappedYStart < 0)
75 onScreenCappedYStart = 0;
77 // cap Y to lower screen border
78 if (onScreenCappedYEnd > targetRenderingArea.height)
79 onScreenCappedYEnd = targetRenderingArea.height;
82 final int onScreenUncappedXStart = (int) (onScreenCoordinate.x - visibleHorizontalDistanceFromCenter);
83 final int onScreenUncappedXEnd = (int) (onScreenCoordinate.x + visibleHorizontalDistanceFromCenter);
84 final int onScreenUncappedWidth = onScreenUncappedXEnd - onScreenUncappedXStart;
86 // cap X to left screen border
87 int onScreenCappedXStart = onScreenUncappedXStart;
88 if (onScreenCappedXStart < 0)
89 onScreenCappedXStart = 0;
91 // cap X to right screen border
92 int onScreenCappedXEnd = onScreenUncappedXEnd;
93 if (onScreenCappedXEnd > targetRenderingArea.width)
94 onScreenCappedXEnd = targetRenderingArea.width;
96 final byte[] targetRenderingAreaBytes = targetRenderingArea.pixels;
98 final int textureWidth = textureBitmap.width;
100 for (int y = onScreenCappedYStart; y < onScreenCappedYEnd; y++) {
102 final int sourceBitmapScanlinePixel = ((textureBitmap.height * (y - onScreenUncappedYStart)) / onScreenUncappedHeight)
105 int targetRenderingAreaOffset = ((y * targetRenderingArea.width) + onScreenCappedXStart) * 4;
107 for (int x = onScreenCappedXStart; x < onScreenCappedXEnd; x++) {
109 final int sourceBitmapPixelAddress = (sourceBitmapScanlinePixel + ((textureWidth * (x - onScreenUncappedXStart)) / onScreenUncappedWidth)) * 4;
111 textureBitmap.drawPixel(sourceBitmapPixelAddress, targetRenderingAreaBytes, targetRenderingAreaOffset);
113 targetRenderingAreaOffset += 4;
119 * Set the scale of the texture
121 * @param scale the scale of the texture
123 public void setScale(final double scale) {
124 this.scale = scale * SCALE_MULTIPLIER;
127 public Point3D getLocation() {
128 return coordinates[0].coordinate;