49af48cd56128061f84c77621c3f4199fe922477
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / shapes / basic / ForwardOrientedTexture.java
1 /*
2  * Sixth - System for data storage, computation, exploration and interaction.
3  * Copyright ©2012-2016, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 3 of the GNU Lesser General Public License
7  * or later as published by the Free Software Foundation.
8  */
9
10 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic;
11
12 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
13 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
14 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
15 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
16 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
17 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
18
19 public class ForwardOrientedTexture extends AbstractCoordinateShape {
20
21     public static final double SIZE_MULTIPLIER = 0.005;
22     public Texture texture;
23     private double scale;
24
25     public ForwardOrientedTexture(final Point3D point, final double scale,
26                                   final Texture texture) {
27         super(point);
28         this.texture = texture;
29         setScale(scale);
30     }
31
32     @Override
33     public void paint(final RenderingContext targetRenderingArea) {
34
35         final double z = coordinates[0].transformedCoordinate.z;
36
37         final double visibleHorizontalDistanceFromCenter = (targetRenderingArea.width
38                 * scale * texture.primaryBitmap.width)
39                 / z;
40
41         final double visibleVerticalDistanceFromCenter = (targetRenderingArea.width
42                 * scale * texture.primaryBitmap.height)
43                 / z;
44
45         // compute visible pixel density, and get appropriate bitmap
46         final double zoom = (visibleHorizontalDistanceFromCenter * 2)
47                 / texture.primaryBitmap.width;
48
49         final TextureBitmap textureBitmap = texture.getZoomedBitmap(zoom);
50
51         final Point2D onScreenLocation = coordinates[0].onScreenCoordinate;
52
53         // compute Y
54         final int initialYStart = (int) (onScreenLocation.y - visibleVerticalDistanceFromCenter);
55         final int initialYEnd = (int) (onScreenLocation.y + visibleVerticalDistanceFromCenter);
56         final int maxYDistance = initialYEnd - initialYStart;
57
58         int yStart = initialYStart;
59         int yEnd = initialYEnd;
60
61         if (yStart < 0)
62             yStart = 0;
63
64         if (yEnd > targetRenderingArea.height)
65             yEnd = targetRenderingArea.height;
66
67         // compute X
68         final int initialXStart = (int) (onScreenLocation.x - visibleHorizontalDistanceFromCenter);
69         final int initialXEnd = (int) (onScreenLocation.x + visibleHorizontalDistanceFromCenter);
70         final int maxXDistance = initialXEnd - initialXStart;
71
72         int xStart = initialXStart;
73         int xEnd = initialXEnd;
74
75         if (xStart < 0)
76             xStart = 0;
77
78         if (xEnd > targetRenderingArea.width)
79             xEnd = targetRenderingArea.width;
80
81         final byte[] targetRenderingAreaBytes = targetRenderingArea.bytes;
82
83         final int textureWidth = textureBitmap.width;
84
85         for (int y = yStart; y < yEnd; y++) {
86
87             final int relativeTextureOffset = ((textureBitmap.height * (y - initialYStart)) / maxYDistance)
88                     * textureWidth;
89
90             int targetRenderingAreaOffset = ((y * targetRenderingArea.width) + xStart) * 4;
91
92             for (int x = xStart; x < xEnd; x++) {
93
94                 final int textureOffset = (relativeTextureOffset + ((textureWidth * (x - initialXStart)) / maxXDistance)) * 4;
95
96                 textureBitmap.drawPixel(textureOffset,
97                         targetRenderingAreaBytes, targetRenderingAreaOffset);
98
99                 targetRenderingAreaOffset += 4;
100             }
101         }
102     }
103
104     public void setScale(final double scale) {
105         this.scale = scale * SIZE_MULTIPLIER;
106     }
107
108 }