📄 shadedsurface.java
字号:
package com.brackeen.javagamebook.graphics3D.texture;
import java.lang.ref.SoftReference;
import java.util.List;
import com.brackeen.javagamebook.math3D.*;
/**
A ShadedSurface is a pre-shaded Texture that maps onto a
polygon.
*/
public final class ShadedSurface extends Texture {
public static final int SURFACE_BORDER_SIZE = 1;
public static final int SHADE_RES_BITS = 4;
public static final int SHADE_RES = 1 << SHADE_RES_BITS;
public static final int SHADE_RES_MASK = SHADE_RES - 1;
public static final int SHADE_RES_SQ = SHADE_RES*SHADE_RES;
public static final int SHADE_RES_SQ_BITS = SHADE_RES_BITS*2;
private short[] buffer;
private SoftReference bufferReference;
private boolean dirty;
private ShadedTexture sourceTexture;
private Rectangle3D sourceTextureBounds;
private Rectangle3D surfaceBounds;
private byte[] shadeMap;
private int shadeMapWidth;
private int shadeMapHeight;
// for incrementally calculating shade values
private int shadeValue;
private int shadeValueInc;
/**
Creates a ShadedSurface with the specified width and
height.
*/
public ShadedSurface(int width, int height) {
this(null, width, height);
}
/**
Creates a ShadedSurface with the specified buffer,
width and height.
*/
public ShadedSurface(short[] buffer, int width, int height) {
super(width, height);
this.buffer = buffer;
bufferReference = new SoftReference(buffer);
sourceTextureBounds = new Rectangle3D();
dirty = true;
}
/**
Creates a ShadedSurface for the specified polygon. The
shade map is created from the specified list of point
lights and ambient light intensity.
*/
public static void createShadedSurface(
TexturedPolygon3D poly, ShadedTexture texture,
List lights, float ambientLightIntensity)
{
// create the texture bounds
Vector3D origin = poly.getVertex(0);
Vector3D dv = new Vector3D(poly.getVertex(1));
dv.subtract(origin);
Vector3D du = new Vector3D();
du.setToCrossProduct(poly.getNormal(), dv);
Rectangle3D bounds = new Rectangle3D(origin, du, dv,
texture.getWidth(), texture.getHeight());
createShadedSurface(poly, texture, bounds,
lights, ambientLightIntensity);
}
/**
Creates a ShadedSurface for the specified polygon. The
shade map is created from the specified list of point
lights and ambient light intensity.
*/
public static void createShadedSurface(
TexturedPolygon3D poly, ShadedTexture texture,
Rectangle3D textureBounds,
List lights, float ambientLightIntensity)
{
// create the surface bounds
poly.setTexture(texture, textureBounds);
Rectangle3D surfaceBounds = poly.calcBoundingRectangle();
// give the surfaceBounds a border to correct for
// slight errors when texture mapping
Vector3D du = new Vector3D(surfaceBounds.getDirectionU());
Vector3D dv = new Vector3D(surfaceBounds.getDirectionV());
du.multiply(SURFACE_BORDER_SIZE);
dv.multiply(SURFACE_BORDER_SIZE);
surfaceBounds.getOrigin().subtract(du);
surfaceBounds.getOrigin().subtract(dv);
int width = (int)Math.ceil(surfaceBounds.getWidth() +
SURFACE_BORDER_SIZE*2);
int height = (int)Math.ceil(surfaceBounds.getHeight() +
SURFACE_BORDER_SIZE*2);
surfaceBounds.setWidth(width);
surfaceBounds.setHeight(height);
// create the shaded surface texture
ShadedSurface surface = new ShadedSurface(width, height);
surface.setTexture(texture, textureBounds);
surface.setSurfaceBounds(surfaceBounds);
// create the surface's shade map
surface.buildShadeMap(lights, ambientLightIntensity);
// set the polygon's surface
poly.setTexture(surface, surfaceBounds);
}
/**
Gets the 16-bit color of the pixel at location (x,y) in
the bitmap. The x and y values are assumbed to be within
the bounds of the surface; otherwise an
ArrayIndexOutOfBoundsException occurs.
*/
public short getColor(int x, int y) {
//try {
return buffer[x + y * width];
//}
//catch (ArrayIndexOutOfBoundsException ex) {
// return -2048;
//}
}
/**
Gets the 16-bit color of the pixel at location (x,y) in
the bitmap. The x and y values are checked to be within
the bounds of the surface, and if not, the pixel on the
edge of the texture is returned.
*/
public short getColorChecked(int x, int y) {
if (x < 0) {
x = 0;
}
else if (x >= width) {
x = width-1;
}
if (y < 0) {
y = 0;
}
else if (y >= height) {
y = height-1;
}
return getColor(x,y);
}
/**
Marks whether this surface is dirty. Surfaces marked as
dirty may be cleared externally.
*/
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
/**
Checks wether this surface is dirty. Surfaces marked as
dirty may be cleared externally.
*/
public boolean isDirty() {
return dirty;
}
/**
Creates a new surface and add a SoftReference to it.
*/
protected void newSurface(int width, int height) {
buffer = new short[width*height];
bufferReference = new SoftReference(buffer);
}
/**
Clears this surface, allowing the garbage collector to
remove it from memory if needed.
*/
public void clearSurface() {
buffer = null;
}
/**
Checks if the surface has been cleared.
*/
public boolean isCleared() {
return (buffer == null);
}
/**
If the buffer has been previously built and cleared but
not yet removed from memory by the garbage collector,
then this method attempts to retrieve it. Returns true if
successfull.
*/
public boolean retrieveSurface() {
if (buffer == null) {
buffer = (short[])bufferReference.get();
}
return !(buffer == null);
}
/**
Sets the source texture for this ShadedSurface.
*/
public void setTexture(ShadedTexture texture) {
this.sourceTexture = texture;
sourceTextureBounds.setWidth(texture.getWidth());
sourceTextureBounds.setHeight(texture.getHeight());
}
/**
Sets the source texture and source bounds for this
ShadedSurface.
*/
public void setTexture(ShadedTexture texture,
Rectangle3D bounds)
{
setTexture(texture);
sourceTextureBounds.setTo(bounds);
}
/**
Sets the surface bounds for this ShadedSurface.
*/
public void setSurfaceBounds(Rectangle3D surfaceBounds) {
this.surfaceBounds = surfaceBounds;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -