14e213c63174657e77189d2965c48bfdf7c04e1d
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / shapes / basic / GlowingPoint.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko. 
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic;
6
7 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
8 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
9 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
10
11 import java.util.Collections;
12 import java.util.Set;
13 import java.util.WeakHashMap;
14
15 import static java.lang.Math.pow;
16 import static java.lang.Math.sqrt;
17
18 public class GlowingPoint extends ForwardOrientedTexture {
19
20     private static final int TEXTURE_RESOLUTION_PIXELS = 100;
21     /**
22      * A set of all existing glowing points.
23      * Used to reuse textures of glowing points of the same color.
24      */
25     private static final Set<GlowingPoint> glowingPoints = Collections.newSetFromMap(new WeakHashMap<>());
26     private final Color color;
27
28     public GlowingPoint(final Point3D point, final double pointSize,
29                         final Color color) {
30         super(point, computeScale(pointSize), getTexture(color));
31         this.color = color;
32
33         synchronized (glowingPoints) {
34             glowingPoints.add(this);
35         }
36     }
37
38
39     private static double computeScale(double pointSize) {
40         return pointSize / ((double) (TEXTURE_RESOLUTION_PIXELS / 50f));
41     }
42
43     /**
44      * Returns a texture for a glowing point of the given color.
45      * The texture is a circle with a gradient from transparent to the given color.
46      */
47     private static Texture getTexture(final Color color) {
48         // attempt to reuse texture from existing glowing point of the same color
49         synchronized (glowingPoints) {
50             for (GlowingPoint glowingPoint : glowingPoints)
51                 if (color.equals(glowingPoint.color))
52                     return glowingPoint.texture;
53         }
54
55         // existing texture not found, creating new one
56         return createTexture(color);
57     }
58
59     /**
60      * Creates a texture for a glowing point of the given color.
61      * The texture is a circle with a gradient from transparent to the given color.
62      */
63     private static Texture createTexture(final Color color) {
64         final Texture texture = new Texture(TEXTURE_RESOLUTION_PIXELS, TEXTURE_RESOLUTION_PIXELS, 1);
65         int halfResolution = TEXTURE_RESOLUTION_PIXELS / 2;
66
67         for (int x = 0; x < TEXTURE_RESOLUTION_PIXELS; x++)
68             for (int y = 0; y < TEXTURE_RESOLUTION_PIXELS; y++) {
69                 int address = texture.primaryBitmap.getAddress(x, y);
70
71                 final int distanceFromCenter = (int) sqrt(pow (halfResolution - x, 2) + pow (halfResolution - y, 2));
72
73                 int alpha = 255 - ((270 * distanceFromCenter) / halfResolution);
74                 if (alpha < 0)
75                     alpha = 0;
76
77                 texture.primaryBitmap.bytes[address] = (byte) alpha;
78                 address++;
79                 texture.primaryBitmap.bytes[address] = (byte) color.b;
80                 address++;
81                 texture.primaryBitmap.bytes[address] = (byte) color.g;
82                 address++;
83                 texture.primaryBitmap.bytes[address] = (byte) color.r;
84             }
85
86         return texture;
87     }
88
89 }