Improved code readability
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Wed, 22 Feb 2023 21:23:52 +0000 (23:23 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Wed, 22 Feb 2023 21:23:52 +0000 (23:23 +0200)
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/shapes/basic/ForwardOrientedTexture.java
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/shapes/basic/GlowingPoint.java
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/texture/Texture.java
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/texture/TextureBitmap.java

index 9467e92..7f13783 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Sixth 3D engine. Author: Svjatoslav Agejenko. 
+ * Sixth 3D engine. Author: Svjatoslav Agejenko.
  * This project is released under Creative Commons Zero (CC0) license.
  */
 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic;
@@ -13,8 +13,17 @@ import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
 
 public class ForwardOrientedTexture extends AbstractCoordinateShape {
 
-    private static final double SIZE_MULTIPLIER = 0.005;
+    private static final double SCALE_MULTIPLIER = 0.005;
     public final Texture texture;
+
+    /**
+     * Scale of the texture object.
+     *
+     * Object rendered visible size on the screen depends on underlying texture size and scale.
+     *
+     * 0 means that object will be infinitely small.
+     * 1 in recommended value to maintain sharpness of the texture as seen by the viewer.
+     */
     private double scale;
 
     public ForwardOrientedTexture(final Point3D point, final double scale,
@@ -24,18 +33,23 @@ public class ForwardOrientedTexture extends AbstractCoordinateShape {
         setScale(scale);
     }
 
+    /**
+     * Paint the texture on the screen (targetRenderingArea)
+     *
+     * @param targetRenderingArea the screen to paint on
+     */
     @Override
     public void paint(final RenderingContext targetRenderingArea) {
 
+        // distance from camera/viewer to center of the texture
         final double z = coordinates[0].transformedCoordinate.z;
 
+        // compute forward oriented texture visible distance from center
         final double visibleHorizontalDistanceFromCenter = (targetRenderingArea.width
-                * scale * texture.primaryBitmap.width)
-                / z;
+                * scale * texture.primaryBitmap.width) / z;
 
         final double visibleVerticalDistanceFromCenter = (targetRenderingArea.width
-                * scale * texture.primaryBitmap.height)
-                / z;
+                * scale * texture.primaryBitmap.height) / z;
 
         // compute visible pixel density, and get appropriate bitmap
         final double zoom = (visibleHorizontalDistanceFromCenter * 2)
@@ -43,61 +57,68 @@ public class ForwardOrientedTexture extends AbstractCoordinateShape {
 
         final TextureBitmap textureBitmap = texture.getZoomedBitmap(zoom);
 
-        final Point2D onScreenLocation = coordinates[0].onScreenCoordinate;
+        final Point2D onScreenCoordinate = coordinates[0].onScreenCoordinate;
 
         // compute Y
-        final int initialYStart = (int) (onScreenLocation.y - visibleVerticalDistanceFromCenter);
-        final int initialYEnd = (int) (onScreenLocation.y + visibleVerticalDistanceFromCenter);
-        final int maxYDistance = initialYEnd - initialYStart;
+        final int onScreenUncappedYStart = (int) (onScreenCoordinate.y - visibleVerticalDistanceFromCenter);
+        final int onScreenUncappedYEnd = (int) (onScreenCoordinate.y + visibleVerticalDistanceFromCenter);
+        final int onScreenUncappedHeight = onScreenUncappedYEnd - onScreenUncappedYStart;
 
-        int yStart = initialYStart;
-        int yEnd = initialYEnd;
+        int onScreenCappedYStart = onScreenUncappedYStart;
+        int onScreenCappedYEnd = onScreenUncappedYEnd;
 
-        if (yStart < 0)
-            yStart = 0;
+        // cap Y to upper screen border
+        if (onScreenCappedYStart < 0)
+            onScreenCappedYStart = 0;
 
-        if (yEnd > targetRenderingArea.height)
-            yEnd = targetRenderingArea.height;
+        // cap Y to lower screen border
+        if (onScreenCappedYEnd > targetRenderingArea.height)
+            onScreenCappedYEnd = targetRenderingArea.height;
 
         // compute X
-        final int initialXStart = (int) (onScreenLocation.x - visibleHorizontalDistanceFromCenter);
-        final int initialXEnd = (int) (onScreenLocation.x + visibleHorizontalDistanceFromCenter);
-        final int maxXDistance = initialXEnd - initialXStart;
-
-        int xStart = initialXStart;
-        int xEnd = initialXEnd;
+        final int onScreenUncappedXStart = (int) (onScreenCoordinate.x - visibleHorizontalDistanceFromCenter);
+        final int onScreenUncappedXEnd = (int) (onScreenCoordinate.x + visibleHorizontalDistanceFromCenter);
+        final int onScreenUncappedWidth = onScreenUncappedXEnd - onScreenUncappedXStart;
 
-        if (xStart < 0)
-            xStart = 0;
+        // cap X to left screen border
+        int onScreenCappedXStart = onScreenUncappedXStart;
+        if (onScreenCappedXStart < 0)
+            onScreenCappedXStart = 0;
 
-        if (xEnd > targetRenderingArea.width)
-            xEnd = targetRenderingArea.width;
+        // cap X to right screen border
+        int onScreenCappedXEnd = onScreenUncappedXEnd;
+        if (onScreenCappedXEnd > targetRenderingArea.width)
+            onScreenCappedXEnd = targetRenderingArea.width;
 
         final byte[] targetRenderingAreaBytes = targetRenderingArea.pixels;
 
         final int textureWidth = textureBitmap.width;
 
-        for (int y = yStart; y < yEnd; y++) {
+        for (int y = onScreenCappedYStart; y < onScreenCappedYEnd; y++) {
 
-            final int relativeTextureOffset = ((textureBitmap.height * (y - initialYStart)) / maxYDistance)
+            final int sourceBitmapScanlinePixel = ((textureBitmap.height * (y - onScreenUncappedYStart)) / onScreenUncappedHeight)
                     * textureWidth;
 
-            int targetRenderingAreaOffset = ((y * targetRenderingArea.width) + xStart) * 4;
+            int targetRenderingAreaOffset = ((y * targetRenderingArea.width) + onScreenCappedXStart) * 4;
 
-            for (int x = xStart; x < xEnd; x++) {
+            for (int x = onScreenCappedXStart; x < onScreenCappedXEnd; x++) {
 
-                final int textureOffset = (relativeTextureOffset + ((textureWidth * (x - initialXStart)) / maxXDistance)) * 4;
+                final int sourceBitmapPixelAddress = (sourceBitmapScanlinePixel + ((textureWidth * (x - onScreenUncappedXStart)) / onScreenUncappedWidth)) * 4;
 
-                textureBitmap.drawPixel(textureOffset,
-                        targetRenderingAreaBytes, targetRenderingAreaOffset);
+                textureBitmap.drawPixel(sourceBitmapPixelAddress, targetRenderingAreaBytes, targetRenderingAreaOffset);
 
                 targetRenderingAreaOffset += 4;
             }
         }
     }
 
+    /**
+     * Set the scale of the texture
+     *
+     * @param scale the scale of the texture
+     */
     public void setScale(final double scale) {
-        this.scale = scale * SIZE_MULTIPLIER;
+        this.scale = scale * SCALE_MULTIPLIER;
     }
 
     public Point3D getLocation() {
index a7b4784..14e213c 100644 (file)
@@ -18,6 +18,10 @@ import static java.lang.Math.sqrt;
 public class GlowingPoint extends ForwardOrientedTexture {
 
     private static final int TEXTURE_RESOLUTION_PIXELS = 100;
+    /**
+     * A set of all existing glowing points.
+     * Used to reuse textures of glowing points of the same color.
+     */
     private static final Set<GlowingPoint> glowingPoints = Collections.newSetFromMap(new WeakHashMap<>());
     private final Color color;
 
@@ -31,10 +35,15 @@ public class GlowingPoint extends ForwardOrientedTexture {
         }
     }
 
+
     private static double computeScale(double pointSize) {
         return pointSize / ((double) (TEXTURE_RESOLUTION_PIXELS / 50f));
     }
 
+    /**
+     * Returns a texture for a glowing point of the given color.
+     * The texture is a circle with a gradient from transparent to the given color.
+     */
     private static Texture getTexture(final Color color) {
         // attempt to reuse texture from existing glowing point of the same color
         synchronized (glowingPoints) {
@@ -47,6 +56,10 @@ public class GlowingPoint extends ForwardOrientedTexture {
         return createTexture(color);
     }
 
+    /**
+     * Creates a texture for a glowing point of the given color.
+     * The texture is a circle with a gradient from transparent to the given color.
+     */
     private static Texture createTexture(final Color color) {
         final Texture texture = new Texture(TEXTURE_RESOLUTION_PIXELS, TEXTURE_RESOLUTION_PIXELS, 1);
         int halfResolution = TEXTURE_RESOLUTION_PIXELS / 2;
index 0a677bd..6009bb8 100644 (file)
@@ -11,6 +11,8 @@ import java.awt.image.BufferedImage;
 import java.awt.image.DataBufferByte;
 import java.awt.image.WritableRaster;
 
+import static java.util.Arrays.fill;
+
 public class Texture {
 
     public final TextureBitmap primaryBitmap;
@@ -59,6 +61,12 @@ public class Texture {
         return upSampled.length - 1;
     }
 
+    /**
+     * Downscale given bitmap by factor of 2.
+     *
+     * @param originalBitmap Bitmap to downscale.
+     * @return Downscaled bitmap.
+     */
     public TextureBitmap downscaleBitmap(final TextureBitmap originalBitmap) {
         int newWidth = originalBitmap.width / 2;
         int newHeight = originalBitmap.height / 2;
@@ -103,6 +111,11 @@ public class Texture {
         return downSampled[scaleFactor];
     }
 
+    /**
+     * Returns the bitmap that should be used for rendering at the given zoom
+     * @param scaleFactor The upscale factor
+     * @return The bitmap
+     */
     public TextureBitmap getUpscaledBitmap(final int scaleFactor) {
         if (upSampled[scaleFactor] == null) {
 
@@ -118,6 +131,11 @@ public class Texture {
         return upSampled[scaleFactor];
     }
 
+    /**
+     * Returns the bitmap that should be used for rendering at the given zoom
+     * @param zoomLevel The zoom level
+     * @return The bitmap
+     */
     public TextureBitmap getZoomedBitmap(final double zoomLevel) {
 
         if (zoomLevel < 1) {
@@ -136,14 +154,20 @@ public class Texture {
         return primaryBitmap;
     }
 
+    /**
+     * Resets the cache of resampled bitmaps
+     */
     public void resetResampledBitmapCache() {
-        for (int i = 0; i < upSampled.length; i++)
-            upSampled[i] = null;
+        fill(upSampled, null);
 
-        for (int i = 0; i < downSampled.length; i++)
-            downSampled[i] = null;
+        fill(downSampled, null);
     }
 
+    /**
+     * Upscales the given bitmap by a factor of 2
+     * @param originalBitmap The bitmap to upscale
+     * @return The upscaled bitmap
+     */
     public TextureBitmap upscaleBitmap(final TextureBitmap originalBitmap) {
         final int newWidth = originalBitmap.width * 2;
         final int newHeight = originalBitmap.height * 2;
@@ -180,10 +204,22 @@ public class Texture {
         return upScaled;
     }
 
-    public class ColorAccumulator {
+    /**
+     * A helper class that accumulates color values for a given area of a bitmap
+     */
+    public static class ColorAccumulator {
+        // Accumulated color values
         public int r, g, b, a;
+
+        // Number of pixels that have been accumulated
         public int pixelCount = 0;
 
+        /**
+         * Accumulates the color values of the given pixel
+         * @param bitmap The bitmap
+         * @param x The x coordinate of the pixel
+         * @param y The y coordinate of the pixel
+         */
         public void accumulate(final TextureBitmap bitmap, final int x,
                                final int y) {
             int address = bitmap.getAddress(x, y);
@@ -202,6 +238,9 @@ public class Texture {
             pixelCount++;
         }
 
+        /**
+         * Resets the accumulator
+         */
         public void reset() {
             a = 0;
             r = 0;
@@ -210,6 +249,12 @@ public class Texture {
             pixelCount = 0;
         }
 
+        /**
+         * Stores the accumulated color values in the given bitmap
+         * @param bitmap The bitmap
+         * @param x The x coordinate of the pixel
+         * @param y The y coordinate of the pixel
+         */
         public void storeResult(final TextureBitmap bitmap, final int x,
                                 final int y) {
             int address = bitmap.getAddress(x, y);
index 00d0625..fe1e304 100644 (file)
@@ -9,7 +9,7 @@ import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
 public class TextureBitmap {
 
     /**
-     * Byte order: ABGR
+     * Byte order: Alpha, Blue, Green, Red
      */
     public final byte[] bytes;
 
@@ -34,47 +34,54 @@ public class TextureBitmap {
         this(width, height, new byte[width * height * 4], multiplicationFactor);
     }
 
-    public void drawPixel(int textureOffset,
-                          final byte[] targetRenderingAreaBytes, int targetRenderingAreaOffset) {
+    /**
+     * Transfer (render) one pixel from current {@link TextureBitmap} to target raster bitmap.
+     *
+     * @param sourceBitmapPixelAddress Pixel address within current {@link TextureBitmap} as indicated by its offset.
+     * @param targetBitmap Bitmap of the target image where pixel should be rendered to.
+     * @param targetBitmapPixelAddress Pixel location within target image where pixel should be rendered to.
+     */
+    public void drawPixel(int sourceBitmapPixelAddress,
+                          final byte[] targetBitmap, int targetBitmapPixelAddress) {
 
-        final int textureAlpha = bytes[textureOffset] & 0xff;
+        final int textureAlpha = bytes[sourceBitmapPixelAddress] & 0xff;
 
         if (textureAlpha == 0)
             return;
 
         if (textureAlpha == 255) {
             // skip reading of background for fully opaque pixels
-            targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) 255;
+            targetBitmap[targetBitmapPixelAddress] = (byte) 255;
 
-            targetRenderingAreaOffset++;
-            textureOffset++;
-            targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
+            targetBitmapPixelAddress++;
+            sourceBitmapPixelAddress++;
+            targetBitmap[targetBitmapPixelAddress] = bytes[sourceBitmapPixelAddress];
 
-            targetRenderingAreaOffset++;
-            textureOffset++;
-            targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
+            targetBitmapPixelAddress++;
+            sourceBitmapPixelAddress++;
+            targetBitmap[targetBitmapPixelAddress] = bytes[sourceBitmapPixelAddress];
 
-            targetRenderingAreaOffset++;
-            textureOffset++;
-            targetRenderingAreaBytes[targetRenderingAreaOffset] = bytes[textureOffset];
+            targetBitmapPixelAddress++;
+            sourceBitmapPixelAddress++;
+            targetBitmap[targetBitmapPixelAddress] = bytes[sourceBitmapPixelAddress];
             return;
         }
 
         final int backgroundAlpha = 255 - textureAlpha;
-        textureOffset++;
+        sourceBitmapPixelAddress++;
 
-        targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) 255;
-        targetRenderingAreaOffset++;
+        targetBitmap[targetBitmapPixelAddress] = (byte) 255;
+        targetBitmapPixelAddress++;
 
-        targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
-        textureOffset++;
-        targetRenderingAreaOffset++;
+        targetBitmap[targetBitmapPixelAddress] = (byte) ((((targetBitmap[targetBitmapPixelAddress] & 0xff) * backgroundAlpha) + ((bytes[sourceBitmapPixelAddress] & 0xff) * textureAlpha)) / 256);
+        sourceBitmapPixelAddress++;
+        targetBitmapPixelAddress++;
 
-        targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
-        textureOffset++;
-        targetRenderingAreaOffset++;
+        targetBitmap[targetBitmapPixelAddress] = (byte) ((((targetBitmap[targetBitmapPixelAddress] & 0xff) * backgroundAlpha) + ((bytes[sourceBitmapPixelAddress] & 0xff) * textureAlpha)) / 256);
+        sourceBitmapPixelAddress++;
+        targetBitmapPixelAddress++;
 
-        targetRenderingAreaBytes[targetRenderingAreaOffset] = (byte) ((((targetRenderingAreaBytes[targetRenderingAreaOffset] & 0xff) * backgroundAlpha) + ((bytes[textureOffset] & 0xff) * textureAlpha)) / 256);
+        targetBitmap[targetBitmapPixelAddress] = (byte) ((((targetBitmap[targetBitmapPixelAddress] & 0xff) * backgroundAlpha) + ((bytes[sourceBitmapPixelAddress] & 0xff) * textureAlpha)) / 256);
     }
 
     public void drawPixel(final int x, final int y, final Color color) {