diff --git a/android/core/src/processing/core/PGraphics3D.java b/android/core/src/processing/core/PGraphics3D.java deleted file mode 100644 index 7bd438125..000000000 --- a/android/core/src/processing/core/PGraphics3D.java +++ /dev/null @@ -1,4196 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2004-08 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA -*/ - -package processing.core; - -//import java.awt.Toolkit; -//import java.awt.image.*; -import java.util.*; - - -// TODO this just has all mis/image references commented out - - -/** - * Subclass of PGraphics that handles 3D rendering. - * It can render 3D inside a browser window and requires no plug-ins. - *
- * The renderer is mostly set up based on the structure of the OpenGL API, - * if you have questions about specifics that aren't covered here, - * look for reference on the OpenGL implementation of a similar feature. - * - * Lighting and camera implementation by Simon Greenwold. - */ -public class PGraphics3D extends PGraphics { - - /** The depth buffer. */ - public float[] zbuffer; - - // ........................................................ - - /** The modelview matrix. */ - public PMatrix3D modelview; - - /** Inverse modelview matrix, used for lighting. */ - public PMatrix3D modelviewInv; - - /** - * The camera matrix, the modelview will be set to this on beginDraw. - */ - public PMatrix3D camera; - - /** Inverse camera matrix */ - protected PMatrix3D cameraInv; - - /** Camera field of view. */ - public float cameraFOV; - - /** Position of the camera. */ - public float cameraX, cameraY, cameraZ; - public float cameraNear, cameraFar; - /** Aspect ratio of camera's view. */ - public float cameraAspect; - - /** Current projection matrix. */ - public PMatrix3D projection; - - - ////////////////////////////////////////////////////////////// - - - /** - * Maximum lights by default is 8, which is arbitrary for this renderer, - * but is the minimum defined by OpenGL - */ - public static final int MAX_LIGHTS = 8; - - public int lightCount = 0; - - /** Light types */ - public int[] lightType; - - /** Light positions */ - //public float[][] lightPosition; - public PVector[] lightPosition; - - /** Light direction (normalized vector) */ - //public float[][] lightNormal; - public PVector[] lightNormal; - - /** Light falloff */ - public float[] lightFalloffConstant; - public float[] lightFalloffLinear; - public float[] lightFalloffQuadratic; - - /** Light spot angle */ - public float[] lightSpotAngle; - - /** Cosine of light spot angle */ - public float[] lightSpotAngleCos; - - /** Light spot concentration */ - public float[] lightSpotConcentration; - - /** Diffuse colors for lights. - * For an ambient light, this will hold the ambient color. - * Internally these are stored as numbers between 0 and 1. */ - public float[][] lightDiffuse; - - /** Specular colors for lights. - Internally these are stored as numbers between 0 and 1. */ - public float[][] lightSpecular; - - /** Current specular color for lighting */ - public float[] currentLightSpecular; - - /** Current light falloff */ - public float currentLightFalloffConstant; - public float currentLightFalloffLinear; - public float currentLightFalloffQuadratic; - - - ////////////////////////////////////////////////////////////// - - - static public final int TRI_DIFFUSE_R = 0; - static public final int TRI_DIFFUSE_G = 1; - static public final int TRI_DIFFUSE_B = 2; - static public final int TRI_DIFFUSE_A = 3; - static public final int TRI_SPECULAR_R = 4; - static public final int TRI_SPECULAR_G = 5; - static public final int TRI_SPECULAR_B = 6; - static public final int TRI_COLOR_COUNT = 7; - - // ........................................................ - - // Whether or not we have to worry about vertex position for lighting calcs - private boolean lightingDependsOnVertexPosition; - - static final int LIGHT_AMBIENT_R = 0; - static final int LIGHT_AMBIENT_G = 1; - static final int LIGHT_AMBIENT_B = 2; - static final int LIGHT_DIFFUSE_R = 3; - static final int LIGHT_DIFFUSE_G = 4; - static final int LIGHT_DIFFUSE_B = 5; - static final int LIGHT_SPECULAR_R = 6; - static final int LIGHT_SPECULAR_G = 7; - static final int LIGHT_SPECULAR_B = 8; - static final int LIGHT_COLOR_COUNT = 9; - - // Used to shuttle lighting calcs around - // (no need to re-allocate all the time) - protected float[] tempLightingContribution = new float[LIGHT_COLOR_COUNT]; -// protected float[] worldNormal = new float[4]; - - /// Used in lightTriangle(). Allocated here once to avoid re-allocating - protected PVector lightTriangleNorm = new PVector(); - - // ........................................................ - - /** - * This is turned on at beginCamera, and off at endCamera - * Currently we don't support nested begin/end cameras. - * If we wanted to, this variable would have to become a stack. - */ - protected boolean manipulatingCamera; - - float[][] matrixStack = new float[MATRIX_STACK_DEPTH][16]; - float[][] matrixInvStack = new float[MATRIX_STACK_DEPTH][16]; - int matrixStackDepth; - - // These two matrices always point to either the modelview - // or the modelviewInv, but they are swapped during - // when in camera manipulation mode. That way camera transforms - // are automatically accumulated in inverse on the modelview matrix. - protected PMatrix3D forwardTransform; - protected PMatrix3D reverseTransform; - - // Added by ewjordan for accurate texturing purposes. Screen plane is - // not scaled to pixel-size, so these manually keep track of its size - // from frustum() calls. Sorry to add public vars, is there a way - // to compute these from something publicly available without matrix ops? - // (used once per triangle in PTriangle with ENABLE_ACCURATE_TEXTURES) - protected float leftScreen; - protected float rightScreen; - protected float topScreen; - protected float bottomScreen; - protected float nearPlane; //depth of near clipping plane - - /** - * Use PSmoothTriangle for rendering instead of PTriangle? - * Usually set by calling smooth() or noSmooth() - */ - static protected boolean s_enableAccurateTextures = false; //maybe just use smooth instead? - - - // ........................................................ - - // pos of first vertex of current shape in vertices array - protected int shapeFirst; - - // i think vertex_end is actually the last vertex in the current shape - // and is separate from vertexCount for occasions where drawing happens - // on endDraw() with all the triangles being depth sorted - protected int shapeLast; - - // vertices may be added during clipping against the near plane. - protected int shapeLastPlusClipped; - - // used for sorting points when triangulating a polygon - // warning - maximum number of vertices for a polygon is DEFAULT_VERTICES - protected int vertexOrder[] = new int[DEFAULT_VERTICES]; - - // ........................................................ - - // This is done to keep track of start/stop information for lines in the - // line array, so that lines can be shown as a single path, rather than just - // individual segments. Currently only in use inside PGraphicsOpenGL. - protected int pathCount; - protected int[] pathOffset = new int[64]; - protected int[] pathLength = new int[64]; - - // ........................................................ - - // line & triangle fields (note that these overlap) -// static protected final int INDEX = 0; // shape index - static protected final int VERTEX1 = 0; - static protected final int VERTEX2 = 1; - static protected final int VERTEX3 = 2; // (triangles only) - /** used to store the strokeColor int for efficient drawing. */ - static protected final int STROKE_COLOR = 1; // (points only) - static protected final int TEXTURE_INDEX = 3; // (triangles only) - //static protected final int STROKE_MODE = 2; // (lines only) - //static protected final int STROKE_WEIGHT = 3; // (lines only) - - static protected final int POINT_FIELD_COUNT = 2; //4 - static protected final int LINE_FIELD_COUNT = 2; //4 - static protected final int TRIANGLE_FIELD_COUNT = 4; - - // points - static final int DEFAULT_POINTS = 512; - protected int[][] points = new int[DEFAULT_POINTS][POINT_FIELD_COUNT]; - protected int pointCount; - - // lines - static final int DEFAULT_LINES = 512; - public PLine line; // used for drawing - protected int[][] lines = new int[DEFAULT_LINES][LINE_FIELD_COUNT]; - protected int lineCount; - - // triangles - static final int DEFAULT_TRIANGLES = 256; - public PTriangle triangle; - protected int[][] triangles = - new int[DEFAULT_TRIANGLES][TRIANGLE_FIELD_COUNT]; - protected float triangleColors[][][] = - new float[DEFAULT_TRIANGLES][3][TRI_COLOR_COUNT]; - protected int triangleCount; // total number of triangles - - // cheap picking someday - //public int shape_index; - - // ........................................................ - - static final int DEFAULT_TEXTURES = 3; - protected PImage[] textures = new PImage[DEFAULT_TEXTURES]; - int textureIndex; - - // ........................................................ - -// DirectColorModel cm; -// MemoryImageSource mis; - - - ////////////////////////////////////////////////////////////// - - - public PGraphics3D() { } - - - //public void setParent(PApplet parent) - - - //public void setPrimary(boolean primary) - - - //public void setPath(String path) - - - /** - * Called in response to a resize event, handles setting the - * new width and height internally, as well as re-allocating - * the pixel buffer for the new size. - * - * Note that this will nuke any cameraMode() settings. - */ - public void setSize(int iwidth, int iheight) { // ignore - width = iwidth; - height = iheight; - width1 = width - 1; - height1 = height - 1; - - allocate(); - reapplySettings(); - - // init lights (in resize() instead of allocate() b/c needed by opengl) - lightType = new int[MAX_LIGHTS]; - lightPosition = new PVector[MAX_LIGHTS]; - lightNormal = new PVector[MAX_LIGHTS]; - for (int i = 0; i < MAX_LIGHTS; i++) { - lightPosition[i] = new PVector(); - lightNormal[i] = new PVector(); - } - lightDiffuse = new float[MAX_LIGHTS][3]; - lightSpecular = new float[MAX_LIGHTS][3]; - lightFalloffConstant = new float[MAX_LIGHTS]; - lightFalloffLinear = new float[MAX_LIGHTS]; - lightFalloffQuadratic = new float[MAX_LIGHTS]; - lightSpotAngle = new float[MAX_LIGHTS]; - lightSpotAngleCos = new float[MAX_LIGHTS]; - lightSpotConcentration = new float[MAX_LIGHTS]; - currentLightSpecular = new float[3]; - - projection = new PMatrix3D(); - modelview = new PMatrix3D(); - modelviewInv = new PMatrix3D(); - -// modelviewStack = new float[MATRIX_STACK_DEPTH][16]; -// modelviewInvStack = new float[MATRIX_STACK_DEPTH][16]; -// modelviewStackPointer = 0; - - forwardTransform = modelview; - reverseTransform = modelviewInv; - - // init perspective projection based on new dimensions - cameraFOV = 60 * DEG_TO_RAD; // at least for now - cameraX = width / 2.0f; - cameraY = height / 2.0f; - cameraZ = cameraY / ((float) Math.tan(cameraFOV / 2.0f)); - cameraNear = cameraZ / 10.0f; - cameraFar = cameraZ * 10.0f; - cameraAspect = (float)width / (float)height; - - camera = new PMatrix3D(); - cameraInv = new PMatrix3D(); - - // set up the default camera - camera(); - - // defaults to perspective, if the user has setup up their - // own projection, they'll need to fix it after resize anyway. - // this helps the people who haven't set up their own projection. - perspective(); - } - - - protected void allocate() { - //System.out.println(this + " allocating for " + width + " " + height); - //new Exception().printStackTrace(); - - pixelCount = width * height; - pixels = new int[pixelCount]; - zbuffer = new float[pixelCount]; - - if (primarySurface) { -// cm = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);; -// mis = new MemoryImageSource(width, height, pixels, 0, width); -// mis.setFullBufferUpdates(true); -// mis.setAnimated(true); -// image = Toolkit.getDefaultToolkit().createImage(mis); - - } else { - // when not the main drawing surface, need to set the zbuffer, - // because there's a possibility that background() will not be called - Arrays.fill(zbuffer, Float.MAX_VALUE); - } - - line = new PLine(this); - triangle = new PTriangle(this); - } - - - //public void dispose() - - - //////////////////////////////////////////////////////////// - - - //public boolean canDraw() - - - public void beginDraw() { - // need to call defaults(), but can only be done when it's ok - // to draw (i.e. for opengl, no drawing can be done outside - // beginDraw/endDraw). - if (!settingsInited) defaultSettings(); - - resetMatrix(); // reset model matrix - - // reset vertices - vertexCount = 0; - - modelview.set(camera); - modelviewInv.set(cameraInv); - - // clear out the lights, they'll have to be turned on again - lightCount = 0; - lightingDependsOnVertexPosition = false; - lightFalloff(1, 0, 0); - lightSpecular(0, 0, 0); - - /* - // reset lines - lineCount = 0; - if (line != null) line.reset(); // is this necessary? - pathCount = 0; - - // reset triangles - triangleCount = 0; - if (triangle != null) triangle.reset(); // necessary? - */ - - shapeFirst = 0; - - // reset textures - textureIndex = 0; - - normal(0, 0, 1); - } - - - /** - * See notes in PGraphics. - * If z-sorting has been turned on, then the triangles will - * all be quicksorted here (to make alpha work more properly) - * and then blit to the screen. - */ - public void endDraw() { - // no need to z order and render - // shapes were already rendered in endShape(); - // (but can't return, since needs to update memimgsrc) - if (hints[ENABLE_DEPTH_SORT]) { - flush(); - } -// if (mis != null) { -// mis.newPixels(pixels, cm, 0, width); -// } - // mark pixels as having been updated, so that they'll work properly - // when this PGraphics is drawn using image(). - updatePixels(); - } - - - //////////////////////////////////////////////////////////// - - - //protected void checkSettings() - - - protected void defaultSettings() { - super.defaultSettings(); - - manipulatingCamera = false; - forwardTransform = modelview; - reverseTransform = modelviewInv; - - perspective(); - - // easiest for beginners - textureMode(IMAGE); - - emissive(0.0f); - specular(0.5f); - shininess(1.0f); - } - - - //protected void reapplySettings() - - - //////////////////////////////////////////////////////////// - - - public void hint(int which) { - if (which == DISABLE_DEPTH_SORT) { - flush(); - } else if (which == DISABLE_DEPTH_TEST) { - if (zbuffer != null) { // will be null in OpenGL and others - Arrays.fill(zbuffer, Float.MAX_VALUE); - } - } - super.hint(which); - } - - - ////////////////////////////////////////////////////////////// - - - //public void beginShape() - - - public void beginShape(int kind) { - shape = kind; - -// shape_index = shape_index + 1; -// if (shape_index == -1) { -// shape_index = 0; -// } - - if (hints[ENABLE_DEPTH_SORT]) { - // continue with previous vertex, line and triangle count - // all shapes are rendered at endDraw(); - shapeFirst = vertexCount; - shapeLast = 0; - - } else { - // reset vertex, line and triangle information - // every shape is rendered at endShape(); - vertexCount = 0; - if (line != null) line.reset(); // necessary? - lineCount = 0; -// pathCount = 0; - if (triangle != null) triangle.reset(); // necessary? - triangleCount = 0; - } - - textureImage = null; - curveVertexCount = 0; - normalMode = NORMAL_MODE_AUTO; -// normalCount = 0; - } - - - //public void normal(float nx, float ny, float nz) - - - //public void textureMode(int mode) - - - public void texture(PImage image) { - textureImage = image; - - if (textureIndex == textures.length - 1) { - textures = (PImage[]) PApplet.expand(textures); - } - if (textures[textureIndex] != null) { // ??? - textureIndex++; - } - textures[textureIndex] = image; - } - - - public void vertex(float x, float y) { - // override so that the default 3D implementation will be used, - // which will pick up all 3D settings (e.g. emissive, ambient) - vertex(x, y, 0); - } - - - //public void vertex(float x, float y, float z) - - - public void vertex(float x, float y, float u, float v) { - // see vertex(x, y) for note - vertex(x, y, 0, u, v); - } - - - //public void vertex(float x, float y, float z, float u, float v) - - - //public void breakShape() - - - //public void endShape() - - - public void endShape(int mode) { - shapeLast = vertexCount; - shapeLastPlusClipped = shapeLast; - - // don't try to draw if there are no vertices - // (fixes a bug in LINE_LOOP that re-adds a nonexistent vertex) - if (vertexCount == 0) { - shape = 0; - return; - } - - // convert points from model (X/Y/Z) to camera space (VX/VY/VZ). - // Do this now because we will be clipping them on add_triangle. - endShapeModelToCamera(shapeFirst, shapeLast); - - if (stroke) { - endShapeStroke(mode); - } - - if (fill) { - endShapeFill(); - } - - // transform, light, and clip - endShapeLighting(lightCount > 0 && fill); - - // convert points from camera space (VX, VY, VZ) to screen space (X, Y, Z) - // (this appears to be wasted time with the OpenGL renderer) - endShapeCameraToScreen(shapeFirst, shapeLastPlusClipped); - - // render shape and fill here if not saving the shapes for later - // if true, the shapes will be rendered on endDraw - if (!hints[ENABLE_DEPTH_SORT]) { - if (fill) { - renderTriangles(0, triangleCount); - if (raw != null) { - rawTriangles(0, triangleCount); - } - triangleCount = 0; - } - if (stroke) { - renderLines(0, lineCount); - if (raw != null) { - rawLines(0, lineCount); - } - lineCount = 0; - } - pathCount = 0; - } - - shape = 0; - } - - - protected void endShapeModelToCamera(int start, int stop) { - for (int i = start; i < stop; i++) { - float vertex[] = vertices[i]; - - vertex[VX] = - modelview.m00*vertex[X] + modelview.m01*vertex[Y] + - modelview.m02*vertex[Z] + modelview.m03; - vertex[VY] = - modelview.m10*vertex[X] + modelview.m11*vertex[Y] + - modelview.m12*vertex[Z] + modelview.m13; - vertex[VZ] = - modelview.m20*vertex[X] + modelview.m21*vertex[Y] + - modelview.m22*vertex[Z] + modelview.m23; - vertex[VW] = - modelview.m30*vertex[X] + modelview.m31*vertex[Y] + - modelview.m32*vertex[Z] + modelview.m33; - - // normalize - if (vertex[VW] != 0 && vertex[VW] != 1) { - vertex[VX] /= vertex[VW]; - vertex[VY] /= vertex[VW]; - vertex[VZ] /= vertex[VW]; - } - vertex[VW] = 1; - } - } - - - protected void endShapeStroke(int mode) { - switch (shape) { - case POINTS: - { - int stop = shapeLast; - for (int i = shapeFirst; i < stop; i++) { - addLineBreak(); // total overkill for points - addLine(i, i); - } - } - break; - - case LINES: - { - // store index of first vertex - int first = lineCount; - int stop = shapeLast - 1; - //increment = (shape == LINES) ? 2 : 1; - - // for LINE_STRIP and LINE_LOOP, make this all one path - if (shape != LINES) addLineBreak(); - - for (int i = shapeFirst; i < stop; i += 2) { - // for LINES, make a new path for each segment - if (shape == LINES) addLineBreak(); - addLine(i, i+1); - } - - // for LINE_LOOP, close the loop with a final segment - //if (shape == LINE_LOOP) { - if (mode == CLOSE) { - addLine(stop, lines[first][VERTEX1]); - } - } - break; - - case TRIANGLES: - { - for (int i = shapeFirst; i < shapeLast-2; i += 3) { - addLineBreak(); - //counter = i - vertex_start; - addLine(i+0, i+1); - addLine(i+1, i+2); - addLine(i+2, i+0); - } - } - break; - - case TRIANGLE_STRIP: - { - // first draw all vertices as a line strip - int stop = shapeLast-1; - - addLineBreak(); - for (int i = shapeFirst; i < stop; i++) { - //counter = i - vertex_start; - addLine(i, i+1); - } - - // then draw from vertex (n) to (n+2) - stop = shapeLast-2; - for (int i = shapeFirst; i < stop; i++) { - addLineBreak(); - addLine(i, i+2); - } - } - break; - - case TRIANGLE_FAN: - { - // this just draws a series of line segments - // from the center to each exterior point - for (int i = shapeFirst + 1; i < shapeLast; i++) { - addLineBreak(); - addLine(shapeFirst, i); - } - - // then a single line loop around the outside. - addLineBreak(); - for (int i = shapeFirst + 1; i < shapeLast-1; i++) { - addLine(i, i+1); - } - // closing the loop - addLine(shapeLast-1, shapeFirst + 1); - } - break; - - case QUADS: - { - for (int i = shapeFirst; i < shapeLast; i += 4) { - addLineBreak(); - //counter = i - vertex_start; - addLine(i+0, i+1); - addLine(i+1, i+2); - addLine(i+2, i+3); - addLine(i+3, i+0); - } - } - break; - - case QUAD_STRIP: - { - for (int i = shapeFirst; i < shapeLast - 3; i += 2) { - addLineBreak(); - addLine(i+0, i+2); - addLine(i+2, i+3); - addLine(i+3, i+1); - addLine(i+1, i+0); - } - } - break; - - case POLYGON: - { - // store index of first vertex - int stop = shapeLast - 1; - - addLineBreak(); - for (int i = shapeFirst; i < stop; i++) { - addLine(i, i+1); - } - if (mode == CLOSE) { - // draw the last line connecting back to the first point in poly - addLine(stop, shapeFirst); //lines[first][VERTEX1]); - } - } - break; - } - } - - - protected void endShapeFill() { - switch (shape) { - case TRIANGLE_FAN: - { - int stop = shapeLast - 1; - for (int i = shapeFirst + 1; i < stop; i++) { - addTriangle(shapeFirst, i, i+1); - } - } - break; - - case TRIANGLES: - { - int stop = shapeLast - 2; - for (int i = shapeFirst; i < stop; i += 3) { - // have to switch between clockwise/counter-clockwise - // otherwise the feller is backwards and renderer won't draw - if ((i % 2) == 0) { - addTriangle(i, i+2, i+1); - } else { - addTriangle(i, i+1, i+2); - } - } - } - break; - - case TRIANGLE_STRIP: - { - int stop = shapeLast - 2; - for (int i = shapeFirst; i < stop; i++) { - // have to switch between clockwise/counter-clockwise - // otherwise the feller is backwards and renderer won't draw - if ((i % 2) == 0) { - addTriangle(i, i+2, i+1); - } else { - addTriangle(i, i+1, i+2); - } - } - } - break; - - case QUADS: - { - int stop = vertexCount-3; - for (int i = shapeFirst; i < stop; i += 4) { - // first triangle - addTriangle(i, i+1, i+2); - // second triangle - addTriangle(i, i+2, i+3); - } - } - break; - - case QUAD_STRIP: - { - int stop = vertexCount-3; - for (int i = shapeFirst; i < stop; i += 2) { - // first triangle - addTriangle(i+0, i+2, i+1); - // second triangle - addTriangle(i+2, i+3, i+1); - } - } - break; - - case POLYGON: - { - addPolygonTriangles(); - } - break; - } - } - - - protected void endShapeLighting(boolean lights) { - if (lights) { - // If the lighting does not depend on vertex position and there is a single - // normal specified for this shape, go ahead and apply the same lighting - // contribution to every vertex in this shape (one lighting calc!) - if (!lightingDependsOnVertexPosition && normalMode == NORMAL_MODE_SHAPE) { - calcLightingContribution(shapeFirst, tempLightingContribution); - for (int tri = 0; tri < triangleCount; tri++) { - lightTriangle(tri, tempLightingContribution); - } - } else { // Otherwise light each triangle individually... - for (int tri = 0; tri < triangleCount; tri++) { - lightTriangle(tri); - } - } - } else { - for (int tri = 0; tri < triangleCount; tri++) { - int index = triangles[tri][VERTEX1]; - copyPrelitVertexColor(tri, index, 0); - index = triangles[tri][VERTEX2]; - copyPrelitVertexColor(tri, index, 1); - index = triangles[tri][VERTEX3]; - copyPrelitVertexColor(tri, index, 2); - } - } - } - - - protected void endShapeCameraToScreen(int start, int stop) { - for (int i = start; i < stop; i++) { - float vx[] = vertices[i]; - - float ox = - projection.m00*vx[VX] + projection.m01*vx[VY] + - projection.m02*vx[VZ] + projection.m03*vx[VW]; - float oy = - projection.m10*vx[VX] + projection.m11*vx[VY] + - projection.m12*vx[VZ] + projection.m13*vx[VW]; - float oz = - projection.m20*vx[VX] + projection.m21*vx[VY] + - projection.m22*vx[VZ] + projection.m23*vx[VW]; - float ow = - projection.m30*vx[VX] + projection.m31*vx[VY] + - projection.m32*vx[VZ] + projection.m33*vx[VW]; - - if (ow != 0 && ow != 1) { - ox /= ow; oy /= ow; oz /= ow; - } - - vx[TX] = width * (1 + ox) / 2.0f; - vx[TY] = height * (1 + oy) / 2.0f; - vx[TZ] = (oz + 1) / 2.0f; - } - } - - - - ///////////////////////////////////////////////////////////////////////////// - - // POINTS - - - protected void addPoint(int a) { - if (pointCount == points.length) { - int[][] temp = new int[pointCount << 1][LINE_FIELD_COUNT]; - System.arraycopy(lines, 0, temp, 0, lineCount); - lines = temp; - } - points[pointCount][VERTEX1] = a; - //points[pointCount][STROKE_MODE] = strokeCap | strokeJoin; - points[pointCount][STROKE_COLOR] = strokeColor; - //points[pointCount][STROKE_WEIGHT] = (int) (strokeWeight + 0.5f); // hmm - pointCount++; - } - - - protected void renderPoints(int start, int stop) { - for (int i = start; i < stop; i++) { - float[] a = vertices[points[i][VERTEX1]]; - int sx = (int) (a[TX] + 0.4999f); - int sy = (int) (a[TY] + 0.4999f); - int index = sy*width + sx; - pixels[index] = points[i][STROKE_COLOR]; - zbuffer[index] = a[TZ]; - } - } - - - // alternative implementations of point rendering code... - - /* - int sx = (int) (screenX(x, y, z) + 0.5f); - int sy = (int) (screenY(x, y, z) + 0.5f); - - int index = sy*width + sx; - pixels[index] = strokeColor; - zbuffer[index] = screenZ(x, y, z); - - */ - - /* - protected void renderPoints(int start, int stop) { - for (int i = start; i < stop; i++) { - float a[] = vertices[points[i][VERTEX1]]; - - line.reset(); - - line.setIntensities(a[SR], a[SG], a[SB], a[SA], - a[SR], a[SG], a[SB], a[SA]); - - line.setVertices(a[TX], a[TY], a[TZ], - a[TX] + 0.5f, a[TY] + 0.5f, a[TZ] + 0.5f); - - line.draw(); - } - } - */ - - /* - // handle points with an actual stroke weight (or scaled by renderer) - private void point3(float x, float y, float z, int color) { - // need to get scaled version of the stroke - float x1 = screenX(x - 0.5f, y - 0.5f, z); - float y1 = screenY(x - 0.5f, y - 0.5f, z); - float x2 = screenX(x + 0.5f, y + 0.5f, z); - float y2 = screenY(x + 0.5f, y + 0.5f, z); - - float weight = (abs(x2 - x1) + abs(y2 - y1)) / 2f; - if (weight < 1.5f) { - int xx = (int) ((x1 + x2) / 2f); - int yy = (int) ((y1 + y2) / 2f); - //point0(xx, yy, z, color); - zbuffer[yy*width + xx] = screenZ(x, y, z); - //stencil? - - } else { - // actually has some weight, need to draw shapes instead - // these will be - } - } - */ - - - protected void rawPoints(int start, int stop) { - raw.colorMode(RGB, 1); - raw.noFill(); - raw.beginShape(POINTS); - - for (int i = start; i < stop; i++) { - float a[] = vertices[lines[i][VERTEX1]]; - - if (raw.is3D()) { - if (a[VW] != 0) { - raw.stroke(a[SR], a[SG], a[SB], a[SA]); - raw.vertex(a[VX] / a[VW], a[VY] / a[VW], a[VZ] / a[VW]); - } - } else { // if is2D() - raw.stroke(a[SR], a[SG], a[SB], a[SA]); - raw.vertex(a[TX], a[TY]); - } - } - raw.endShape(); - } - - - - ///////////////////////////////////////////////////////////////////////////// - - // LINES - - - /** - * Begin a new section of stroked geometry. - */ - protected final void addLineBreak() { - if (pathCount == pathOffset.length) { - pathOffset = PApplet.expand(pathOffset); - pathLength = PApplet.expand(pathLength); - } - pathOffset[pathCount] = lineCount; - pathLength[pathCount] = 0; - pathCount++; - } - - - protected void addLine(int a, int b) { - addLineWithClip(a, b); - } - - - protected final void addLineWithClip(int a, int b) { - float az = vertices[a][VZ]; - float bz = vertices[b][VZ]; - if (az > cameraNear) { - if (bz > cameraNear) { - return; - } - int cb = interpolateClipVertex(a, b); - addLineWithoutClip(cb, b); - return; - } - else { - if (bz <= cameraNear) { - addLineWithoutClip(a, b); - return; - } - int cb = interpolateClipVertex(a, b); - addLineWithoutClip(a, cb); - return; - } - } - - - protected final void addLineWithoutClip(int a, int b) { - if (lineCount == lines.length) { - int temp[][] = new int[lineCount<<1][LINE_FIELD_COUNT]; - System.arraycopy(lines, 0, temp, 0, lineCount); - lines = temp; - } - lines[lineCount][VERTEX1] = a; - lines[lineCount][VERTEX2] = b; - - //lines[lineCount][STROKE_MODE] = strokeCap | strokeJoin; - //lines[lineCount][STROKE_WEIGHT] = (int) (strokeWeight + 0.5f); // hmm - lineCount++; - - // mark this piece as being part of the current path - pathLength[pathCount-1]++; - } - - - protected void renderLines(int start, int stop) { - for (int i = start; i < stop; i++) { - float a[] = vertices[lines[i][VERTEX1]]; - float b[] = vertices[lines[i][VERTEX2]]; - - // 2D hack added by ewjordan 6/13/07 - // Offset coordinates by a little bit if drawing 2D graphics. - // http://dev.processing.org/bugs/show_bug.cgi?id=95 - - // This hack fixes a bug caused by numerical precision issues when - // applying the 3D transformations to coordinates in the screen plane - // that should actually not be altered under said transformations. - // It will not be applied if any transformations other than translations - // are active, nor should it apply in OpenGL mode (PGraphicsOpenGL - // overrides render_lines(), so this should be fine). - // This fix exposes a last-pixel bug in the lineClipCode() function - // of PLine.java, so that fix must remain in place if this one is used. - - // Note: the "true" fix for this bug is to change the pixel coverage - // model so that the threshold for display does not lie on an integer - // boundary. Search "diamond exit rule" for info the OpenGL approach. - - /* - // removing for 0149 with the return of P2D - if (drawing2D() && a[Z] == 0) { - a[TX] += 0.01; - a[TY] += 0.01; - a[VX] += 0.01*a[VW]; - a[VY] += 0.01*a[VW]; - b[TX] += 0.01; - b[TY] += 0.01; - b[VX] += 0.01*b[VW]; - b[VY] += 0.01*b[VW]; - } - */ - // end 2d-hack - - if (a[SW] > 1.25f || a[SW] < 0.75f) { - float ox1 = a[TX]; - float oy1 = a[TY]; - float ox2 = b[TX]; - float oy2 = b[TY]; - - float dX = ox2 - ox1 + EPSILON; - float dY = oy2 - oy1 + EPSILON; - float len = (float) Math.sqrt(dX*dX + dY*dY); - - // TODO strokeWidth should be transformed! - float rh = a[SW] / len; - - float dx0 = rh * dY; - float dy0 = rh * dX; - float dx1 = rh * dY; - float dy1 = rh * dX; - - float ax1 = ox1+dx0; - float ay1 = oy1-dy0; - - float ax2 = ox1-dx0; - float ay2 = oy1+dy0; - - float bx1 = ox2+dx1; - float by1 = oy2-dy1; - - float bx2 = ox2-dx1; - float by2 = oy2+dy1; - - triangle.reset(); - - // render first triangle for thick line - triangle.setVertices(ax1, ay1, a[TZ], - bx2, by2, b[TZ], - ax2, ay2, a[TZ]); - triangle.setIntensities(a[SR], a[SG], a[SB], a[SA], - b[SR], b[SG], b[SB], b[SA], - a[SR], a[SG], a[SB], a[SA]); - triangle.render(); - - // render second triangle for thick line - triangle.setVertices(ax1, ay1, a[TZ], - bx2, by2, b[TZ], - bx1, by1, b[TZ]); - triangle.setIntensities(a[SR], a[SG], a[SB], a[SA], - b[SR], b[SG], b[SB], b[SA], - b[SR], b[SG], b[SB], b[SA]); - triangle.render(); - - } else { - line.reset(); - - line.setIntensities(a[SR], a[SG], a[SB], a[SA], - b[SR], b[SG], b[SB], b[SA]); - - line.setVertices(a[TX], a[TY], a[TZ], - b[TX], b[TY], b[TZ]); - - /* - // Seems okay to remove this because these vertices are not used again, - // but if problems arise, this needs to be uncommented because the above - // change is destructive and may need to be undone before proceeding. - if (drawing2D() && a[MZ] == 0) { - a[X] -= 0.01; - a[Y] -= 0.01; - a[VX] -= 0.01*a[VW]; - a[VY] -= 0.01*a[VW]; - b[X] -= 0.01; - b[Y] -= 0.01; - b[VX] -= 0.01*b[VW]; - b[VY] -= 0.01*b[VW]; - } - */ - - line.draw(); - } - } - } - - - /** - * Handle echoing line data to a raw shape recording renderer. This has been - * broken out of the renderLines() procedure so that renderLines() can be - * optimized per-renderer without having to deal with this code. This code, - * for instance, will stay the same when OpenGL is in use, but renderLines() - * can be optimized significantly. - *- * Note that the camera matrix is *not* the perspective matrix, - * it is in front of the modelview matrix (hence the name "model" - * and "view" for that matrix). - *
- * beginCamera() specifies that all coordinate transforms until endCamera() - * should be pre-applied in inverse to the camera transform matrix. - * Note that this is only challenging when a user specifies an arbitrary - * matrix with applyMatrix(). Then that matrix will need to be inverted, - * which may not be possible. But take heart, if a user is applying a - * non-invertible matrix to the camera transform, then he is clearly - * up to no good, and we can wash our hands of those bad intentions. - *
- * begin/endCamera clauses do not automatically reset the camera transform - * matrix. That's because we set up a nice default camera transform int - * setup(), and we expect it to hold through draw(). So we don't reset - * the camera transform matrix at the top of draw(). That means that an - * innocuous-looking clause like - *
- * beginCamera(); - * translate(0, 0, 10); - * endCamera(); - *- * at the top of draw(), will result in a runaway camera that shoots - * infinitely out of the screen over time. In order to prevent this, - * it is necessary to call some function that does a hard reset of the - * camera transform matrix inside of begin/endCamera. Two options are - *
- * camera(); // sets up the nice default camera transform - * resetMatrix(); // sets up the identity camera transform - *- * So to rotate a camera a constant amount, you might try - *
- * beginCamera(); - * camera(); - * rotateY(PI/8); - * endCamera(); - *- */ - public void beginCamera() { - if (manipulatingCamera) { - throw new RuntimeException("beginCamera() cannot be called again " + - "before endCamera()"); - } else { - manipulatingCamera = true; - forwardTransform = cameraInv; - reverseTransform = camera; - } - } - - - /** - * Record the current settings into the camera matrix, and set - * the matrix mode back to the current transformation matrix. - *
- * Note that this will destroy any settings to scale(), translate(), - * or whatever, because the final camera matrix will be copied - * (not multiplied) into the modelview. - */ - public void endCamera() { - if (!manipulatingCamera) { - throw new RuntimeException("Cannot call endCamera() " + - "without first calling beginCamera()"); - } - // reset the modelview to use this new camera matrix - modelview.set(camera); - modelviewInv.set(cameraInv); - - // set matrix mode back to modelview - forwardTransform = modelview; - reverseTransform = modelviewInv; - - // all done - manipulatingCamera = false; - } - - - /** - * Set camera to the default settings. - *
- * Processing camera behavior: - *
- * Camera behavior can be split into two separate components, camera - * transformation, and projection. The transformation corresponds to the - * physical location, orientation, and scale of the camera. In a physical - * camera metaphor, this is what can manipulated by handling the camera - * body (with the exception of scale, which doesn't really have a physcial - * analog). The projection corresponds to what can be changed by - * manipulating the lens. - *
- * We maintain separate matrices to represent the camera transform and - * projection. An important distinction between the two is that the camera - * transform should be invertible, where the projection matrix should not, - * since it serves to map three dimensions to two. It is possible to bake - * the two matrices into a single one just by multiplying them together, - * but it isn't a good idea, since lighting, z-ordering, and z-buffering - * all demand a true camera z coordinate after modelview and camera - * transforms have been applied but before projection. If the camera - * transform and projection are combined there is no way to recover a - * good camera-space z-coordinate from a model coordinate. - *
- * Fortunately, there are no functions that manipulate both camera - * transformation and projection. - *
- * camera() sets the camera position, orientation, and center of the scene. - * It replaces the camera transform with a new one. This is different from - * gluLookAt(), but I think the only reason that GLU's lookat doesn't fully - * replace the camera matrix with the new one, but instead multiplies it, - * is that GL doesn't enforce the separation of camera transform and - * projection, so it wouldn't be safe (you'd probably stomp your projection). - *
- * The transformation functions are the same ones used to manipulate the - * modelview matrix (scale, translate, rotate, etc.). But they are bracketed - * with beginCamera(), endCamera() to indicate that they should apply - * (in inverse), to the camera transformation matrix. - *
- * This differs considerably from camera transformation in OpenGL. - * OpenGL only lets you say, apply everything from here out to the - * projection or modelview matrix. This makes it very hard to treat camera - * manipulation as if it were a physical camera. Imagine that you want to - * move your camera 100 units forward. In OpenGL, you need to apply the - * inverse of that transformation or else you'll move your scene 100 units - * forward--whether or not you've specified modelview or projection matrix. - * Remember they're just multiplied by model coods one after another. - * So in order to treat a camera like a physical camera, it is necessary - * to pre-apply inverse transforms to a matrix that will be applied to model - * coordinates. OpenGL provides nothing of this sort, but Processing does! - * This is the camera transform matrix. - */ - public void camera() { - camera(cameraX, cameraY, cameraZ, - cameraX, cameraY, 0, - 0, 1, 0); - } - - - /** - * More flexible method for dealing with camera(). - *
- * The actual call is like gluLookat. Here's the real skinny on - * what does what: - *
- * camera(); or - * camera(ex, ey, ez, cx, cy, cz, ux, uy, uz); - *- * do not need to be called from with beginCamera();/endCamera(); - * That's because they always apply to the camera transformation, - * and they always totally replace it. That means that any coordinate - * transforms done before camera(); in draw() will be wiped out. - * It also means that camera() always operates in untransformed world - * coordinates. Therefore it is always redundant to call resetMatrix(); - * before camera(); This isn't technically true of gluLookat, but it's - * pretty much how it's used. - *
- * Now, beginCamera(); and endCamera(); are useful if you want to move - * the camera around using transforms like translate(), etc. They will - * wipe out any coordinate system transforms that occur before them in - * draw(), but they will not automatically wipe out the camera transform. - * This means that they should be at the top of draw(). It also means - * that the following: - *
- * beginCamera(); - * rotateY(PI/8); - * endCamera(); - *- * will result in a camera that spins without stopping. If you want to - * just rotate a small constant amount, try this: - *
- * beginCamera(); - * camera(); // sets up the default view - * rotateY(PI/8); - * endCamera(); - *- * That will rotate a little off of the default view. Note that this - * is entirely equivalent to - *
- * camera(); // sets up the default view - * beginCamera(); - * rotateY(PI/8); - * endCamera(); - *- * because camera() doesn't care whether or not it's inside a - * begin/end clause. Basically it's safe to use camera() or - * camera(ex, ey, ez, cx, cy, cz, ux, uy, uz) as naked calls because - * they do all the matrix resetting automatically. - */ - public void camera(float eyeX, float eyeY, float eyeZ, - float centerX, float centerY, float centerZ, - float upX, float upY, float upZ) { - float z0 = eyeX - centerX; - float z1 = eyeY - centerY; - float z2 = eyeZ - centerZ; - float mag = sqrt(z0*z0 + z1*z1 + z2*z2); - - if (mag != 0) { - z0 /= mag; - z1 /= mag; - z2 /= mag; - } - - float y0 = upX; - float y1 = upY; - float y2 = upZ; - - float x0 = y1*z2 - y2*z1; - float x1 = -y0*z2 + y2*z0; - float x2 = y0*z1 - y1*z0; - - y0 = z1*x2 - z2*x1; - y1 = -z0*x2 + z2*x0; - y2 = z0*x1 - z1*x0; - - mag = sqrt(x0*x0 + x1*x1 + x2*x2); - if (mag != 0) { - x0 /= mag; - x1 /= mag; - x2 /= mag; - } - - mag = sqrt(y0*y0 + y1*y1 + y2*y2); - if (mag != 0) { - y0 /= mag; - y1 /= mag; - y2 /= mag; - } - - // just does an apply to the main matrix, - // since that'll be copied out on endCamera - camera.set(x0, x1, x2, 0, - y0, y1, y2, 0, - z0, z1, z2, 0, - 0, 0, 0, 1); - camera.translate(-eyeX, -eyeY, -eyeZ); - - cameraInv.reset(); - cameraInv.invApply(x0, x1, x2, 0, - y0, y1, y2, 0, - z0, z1, z2, 0, - 0, 0, 0, 1); - cameraInv.translate(eyeX, eyeY, eyeZ); - - modelview.set(camera); - modelviewInv.set(cameraInv); - } - - - /** - * Print the current camera matrix. - */ - public void printCamera() { - camera.print(); - } - - - ////////////////////////////////////////////////////////////// - - // PROJECTION - - - /** - * Calls ortho() with the proper parameters for Processing's - * standard orthographic projection. - */ - public void ortho() { - ortho(0, width, 0, height, -10, 10); - } - - - /** - * Similar to gluOrtho(), but wipes out the current projection matrix. - *
- * Implementation partially based on Mesa's matrix.c. - */ - public void ortho(float left, float right, - float bottom, float top, - float near, float far) { - float x = 2.0f / (right - left); - float y = 2.0f / (top - bottom); - float z = -2.0f / (far - near); - - float tx = -(right + left) / (right - left); - float ty = -(top + bottom) / (top - bottom); - float tz = -(far + near) / (far - near); - - projection.set(x, 0, 0, tx, - 0, y, 0, ty, - 0, 0, z, tz, - 0, 0, 0, 1); - } - - - /** - * Calls perspective() with Processing's standard coordinate projection. - *
- * Projection functions: - *
- * This behavior is pretty much familiar from OpenGL, except where - * functions replace matrices, rather than multiplying against the - * previous. - *
- */ - public void perspective() { - perspective(cameraFOV, cameraAspect, cameraNear, cameraFar); - } - - - /** - * Similar to gluPerspective(). Implementation based on Mesa's glu.c - */ - public void perspective(float fov, float aspect, float zNear, float zFar) { - //float ymax = zNear * tan(fovy * PI / 360.0f); - float ymax = zNear * (float) Math.tan(fov / 2); - float ymin = -ymax; - - float xmin = ymin * aspect; - float xmax = ymax * aspect; - - frustum(xmin, xmax, ymin, ymax, zNear, zFar); - } - - - /** - * Same as glFrustum(), except that it wipes out (rather than - * multiplies against) the current perspective matrix. - *
- * Implementation based on the explanation in the OpenGL blue book. - */ - public void frustum(float left, float right, float bottom, - float top, float znear, float zfar) { - - leftScreen = left; - rightScreen = right; - bottomScreen = bottom; - topScreen = top; - nearPlane = znear; - - //System.out.println(projection); - projection.set((2*znear)/(right-left), 0, (right+left)/(right-left), 0, - 0, (2*znear)/(top-bottom), (top+bottom)/(top-bottom), 0, - 0, 0, -(zfar+znear)/(zfar-znear),-(2*zfar*znear)/(zfar-znear), - 0, 0, -1, 0); - } - - - /** - * Print the current projection matrix. - */ - public void printProjection() { - projection.print(); - } - - - - ////////////////////////////////////////////////////////////// - - // SCREEN AND MODEL COORDS - - - public float screenX(float x, float y) { - return screenX(x, y, 0); - } - - - public float screenY(float x, float y) { - return screenY(x, y, 0); - } - - - public float screenX(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float ox = - projection.m00*ax + projection.m01*ay + - projection.m02*az + projection.m03*aw; - float ow = - projection.m30*ax + projection.m31*ay + - projection.m32*az + projection.m33*aw; - - if (ow != 0) ox /= ow; - return width * (1 + ox) / 2.0f; - } - - - public float screenY(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oy = - projection.m10*ax + projection.m11*ay + - projection.m12*az + projection.m13*aw; - float ow = - projection.m30*ax + projection.m31*ay + - projection.m32*az + projection.m33*aw; - - if (ow != 0) oy /= ow; - return height * (1 + oy) / 2.0f; - } - - - public float screenZ(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oz = - projection.m20*ax + projection.m21*ay + - projection.m22*az + projection.m23*aw; - float ow = - projection.m30*ax + projection.m31*ay + - projection.m32*az + projection.m33*aw; - - if (ow != 0) oz /= ow; - return (oz + 1) / 2.0f; - } - - - public float modelX(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float ox = - cameraInv.m00*ax + cameraInv.m01*ay + - cameraInv.m02*az + cameraInv.m03*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + - cameraInv.m32*az + cameraInv.m33*aw; - - return (ow != 0) ? ox / ow : ox; - } - - - public float modelY(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oy = - cameraInv.m10*ax + cameraInv.m11*ay + - cameraInv.m12*az + cameraInv.m13*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + - cameraInv.m32*az + cameraInv.m33*aw; - - return (ow != 0) ? oy / ow : oy; - } - - - public float modelZ(float x, float y, float z) { - float ax = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - float ay = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - float az = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - float aw = - modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33; - - float oz = - cameraInv.m20*ax + cameraInv.m21*ay + - cameraInv.m22*az + cameraInv.m23*aw; - float ow = - cameraInv.m30*ax + cameraInv.m31*ay + - cameraInv.m32*az + cameraInv.m33*aw; - - return (ow != 0) ? oz / ow : oz; - } - - - - ////////////////////////////////////////////////////////////// - - // STYLE - - // pushStyle(), popStyle(), style() and getStyle() inherited. - - - - ////////////////////////////////////////////////////////////// - - // STROKE CAP/JOIN/WEIGHT - - -// public void strokeWeight(float weight) { -// if (weight != DEFAULT_STROKE_WEIGHT) { -// showMethodWarning("strokeWeight"); -// } -// } - - - public void strokeJoin(int join) { - if (join != DEFAULT_STROKE_JOIN) { - showMethodWarning("strokeJoin"); - } - } - - - public void strokeCap(int cap) { - if (cap != DEFAULT_STROKE_CAP) { - showMethodWarning("strokeCap"); - } - } - - - - ////////////////////////////////////////////////////////////// - - // STROKE COLOR - - // All methods inherited from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // TINT COLOR - - // All methods inherited from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // FILL COLOR - - - protected void fillFromCalc() { - super.fillFromCalc(); - ambientFromCalc(); - } - - - - ////////////////////////////////////////////////////////////// - - // MATERIAL PROPERTIES - - // ambient, specular, shininess, and emissive all inherited. - - - - ////////////////////////////////////////////////////////////// - - // LIGHTS - - - PVector lightPositionVec = new PVector(); - PVector lightDirectionVec = new PVector(); - - /** - * Sets up an ambient and directional light. - *
- * The Lighting Skinny: - * - * The way lighting works is complicated enough that it's worth - * producing a document to describe it. Lighting calculations proceed - * pretty much exactly as described in the OpenGL red book. - * - * Light-affecting material properties: - * - * AMBIENT COLOR - * - multiplies by light's ambient component - * - for believability this should match diffuse color - * - * DIFFUSE COLOR - * - multiplies by light's diffuse component - * - * SPECULAR COLOR - * - multiplies by light's specular component - * - usually less colored than diffuse/ambient - * - * SHININESS - * - the concentration of specular effect - * - this should be set pretty high (20-50) to see really - * noticeable specularity - * - * EMISSIVE COLOR - * - constant additive color effect - * - * Light types: - * - * AMBIENT - * - one color - * - no specular color - * - no direction - * - may have falloff (constant, linear, and quadratic) - * - may have position (which matters in non-constant falloff case) - * - multiplies by a material's ambient reflection - * - * DIRECTIONAL - * - has diffuse color - * - has specular color - * - has direction - * - no position - * - no falloff - * - multiplies by a material's diffuse and specular reflections - * - * POINT - * - has diffuse color - * - has specular color - * - has position - * - no direction - * - may have falloff (constant, linear, and quadratic) - * - multiplies by a material's diffuse and specular reflections - * - * SPOT - * - has diffuse color - * - has specular color - * - has position - * - has direction - * - has cone angle (set to half the total cone angle) - * - has concentration value - * - may have falloff (constant, linear, and quadratic) - * - multiplies by a material's diffuse and specular reflections - * - * Normal modes: - * - * All of the primitives (rect, box, sphere, etc.) have their normals - * set nicely. During beginShape/endShape normals can be set by the user. - * - * AUTO-NORMAL - * - if no normal is set during the shape, we are in auto-normal mode - * - auto-normal calculates one normal per triangle (face-normal mode) - * - * SHAPE-NORMAL - * - if one normal is set during the shape, it will be used for - * all vertices - * - * VERTEX-NORMAL - * - if multiple normals are set, each normal applies to - * subsequent vertices - * - (except for the first one, which applies to previous - * and subsequent vertices) - * - * Efficiency consequences: - * - * There is a major efficiency consequence of position-dependent - * lighting calculations per vertex. (See below for determining - * whether lighting is vertex position-dependent.) If there is no - * position dependency then the only factors that affect the lighting - * contribution per vertex are its colors and its normal. - * There is a major efficiency win if - * - * 1) lighting is not position dependent - * 2) we are in AUTO-NORMAL or SHAPE-NORMAL mode - * - * because then we can calculate one lighting contribution per shape - * (SHAPE-NORMAL) or per triangle (AUTO-NORMAL) and simply multiply it - * into the vertex colors. The converse is our worst-case performance when - * - * 1) lighting is position dependent - * 2) we are in AUTO-NORMAL mode - * - * because then we must calculate lighting per-face * per-vertex. - * Each vertex has a different lighting contribution per face in - * which it appears. Yuck. - * - * Determining vertex position dependency: - * - * If any of the following factors are TRUE then lighting is - * vertex position dependent: - * - * 1) Any lights uses non-constant falloff - * 2) There are any point or spot lights - * 3) There is a light with specular color AND there is a - * material with specular color - * - * So worth noting is that default lighting (a no-falloff ambient - * and a directional without specularity) is not position-dependent. - * We should capitalize. - * - * Simon Greenwold, April 2005 - *- */ - public void lights() { - // need to make sure colorMode is RGB 255 here - int colorModeSaved = colorMode; - colorMode = RGB; - - lightFalloff(1, 0, 0); - lightSpecular(0, 0, 0); - - ambientLight(colorModeX * 0.5f, - colorModeY * 0.5f, - colorModeZ * 0.5f); - directionalLight(colorModeX * 0.5f, - colorModeY * 0.5f, - colorModeZ * 0.5f, - 0, 0, -1); - - colorMode = colorModeSaved; - - lightingDependsOnVertexPosition = false; - } - - - /** - * Turn off all lights. - */ - public void noLights() { - // write any queued geometry, because lighting will be goofed after - flush(); - // set the light count back to zero - lightCount = 0; - } - - - /** - * Add an ambient light based on the current color mode. - */ - public void ambientLight(float r, float g, float b) { - ambientLight(r, g, b, 0, 0, 0); - } - - - /** - * Add an ambient light based on the current color mode. - * This version includes an (x, y, z) position for situations - * where the falloff distance is used. - */ - public void ambientLight(float r, float g, float b, - float x, float y, float z) { - if (lightCount == MAX_LIGHTS) { - throw new RuntimeException("can only create " + MAX_LIGHTS + " lights"); - } - colorCalc(r, g, b); - lightDiffuse[lightCount][0] = calcR; - lightDiffuse[lightCount][1] = calcG; - lightDiffuse[lightCount][2] = calcB; - - lightType[lightCount] = AMBIENT; - lightFalloffConstant[lightCount] = currentLightFalloffConstant; - lightFalloffLinear[lightCount] = currentLightFalloffLinear; - lightFalloffQuadratic[lightCount] = currentLightFalloffQuadratic; - lightPosition(lightCount, x, y, z); - lightCount++; - //return lightCount-1; - } - - - public void directionalLight(float r, float g, float b, - float nx, float ny, float nz) { - if (lightCount == MAX_LIGHTS) { - throw new RuntimeException("can only create " + MAX_LIGHTS + " lights"); - } - colorCalc(r, g, b); - lightDiffuse[lightCount][0] = calcR; - lightDiffuse[lightCount][1] = calcG; - lightDiffuse[lightCount][2] = calcB; - - lightType[lightCount] = DIRECTIONAL; - lightFalloffConstant[lightCount] = currentLightFalloffConstant; - lightFalloffLinear[lightCount] = currentLightFalloffLinear; - lightFalloffQuadratic[lightCount] = currentLightFalloffQuadratic; - lightSpecular[lightCount][0] = currentLightSpecular[0]; - lightSpecular[lightCount][1] = currentLightSpecular[1]; - lightSpecular[lightCount][2] = currentLightSpecular[2]; - lightDirection(lightCount, nx, ny, nz); - lightCount++; - } - - - public void pointLight(float r, float g, float b, - float x, float y, float z) { - if (lightCount == MAX_LIGHTS) { - throw new RuntimeException("can only create " + MAX_LIGHTS + " lights"); - } - colorCalc(r, g, b); - lightDiffuse[lightCount][0] = calcR; - lightDiffuse[lightCount][1] = calcG; - lightDiffuse[lightCount][2] = calcB; - - lightType[lightCount] = POINT; - lightFalloffConstant[lightCount] = currentLightFalloffConstant; - lightFalloffLinear[lightCount] = currentLightFalloffLinear; - lightFalloffQuadratic[lightCount] = currentLightFalloffQuadratic; - lightSpecular[lightCount][0] = currentLightSpecular[0]; - lightSpecular[lightCount][1] = currentLightSpecular[1]; - lightSpecular[lightCount][2] = currentLightSpecular[2]; - lightPosition(lightCount, x, y, z); - lightCount++; - - lightingDependsOnVertexPosition = true; - } - - - public void spotLight(float r, float g, float b, - float x, float y, float z, - float nx, float ny, float nz, - float angle, float concentration) { - if (lightCount == MAX_LIGHTS) { - throw new RuntimeException("can only create " + MAX_LIGHTS + " lights"); - } - colorCalc(r, g, b); - lightDiffuse[lightCount][0] = calcR; - lightDiffuse[lightCount][1] = calcG; - lightDiffuse[lightCount][2] = calcB; - - lightType[lightCount] = SPOT; - lightFalloffConstant[lightCount] = currentLightFalloffConstant; - lightFalloffLinear[lightCount] = currentLightFalloffLinear; - lightFalloffQuadratic[lightCount] = currentLightFalloffQuadratic; - lightSpecular[lightCount][0] = currentLightSpecular[0]; - lightSpecular[lightCount][1] = currentLightSpecular[1]; - lightSpecular[lightCount][2] = currentLightSpecular[2]; - lightPosition(lightCount, x, y, z); - lightDirection(lightCount, nx, ny, nz); - lightSpotAngle[lightCount] = angle; - lightSpotAngleCos[lightCount] = Math.max(0, (float) Math.cos(angle)); - lightSpotConcentration[lightCount] = concentration; - lightCount++; - - lightingDependsOnVertexPosition = true; - } - - - /** - * Set the light falloff rates for the last light that was created. - * Default is lightFalloff(1, 0, 0). - */ - public void lightFalloff(float constant, float linear, float quadratic) { - currentLightFalloffConstant = constant; - currentLightFalloffLinear = linear; - currentLightFalloffQuadratic = quadratic; - - lightingDependsOnVertexPosition = true; - } - - - /** - * Set the specular color of the last light created. - */ - public void lightSpecular(float x, float y, float z) { - colorCalc(x, y, z); - currentLightSpecular[0] = calcR; - currentLightSpecular[1] = calcG; - currentLightSpecular[2] = calcB; - - lightingDependsOnVertexPosition = true; - } - - - /** - * internal function to set the light position - * based on the current modelview matrix. - */ - protected void lightPosition(int num, float x, float y, float z) { - lightPositionVec.set(x, y, z); - modelview.mult(lightPositionVec, lightPosition[num]); - /* - lightPosition[num][0] = - modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03; - lightPosition[num][1] = - modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13; - lightPosition[num][2] = - modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23; - */ - } - - - /** - * internal function to set the light direction - * based on the current modelview matrix. - */ - protected void lightDirection(int num, float x, float y, float z) { - lightNormal[num].set(modelviewInv.m00*x + modelviewInv.m10*y + modelviewInv.m20*z + modelviewInv.m30, - modelviewInv.m01*x + modelviewInv.m11*y + modelviewInv.m21*z + modelviewInv.m31, - modelviewInv.m02*x + modelviewInv.m12*y + modelviewInv.m22*z + modelviewInv.m32); - lightNormal[num].normalize(); - - /* - lightDirectionVec.set(x, y, z); - System.out.println("dir vec " + lightDirectionVec); - //modelviewInv.mult(lightDirectionVec, lightNormal[num]); - modelviewInv.cmult(lightDirectionVec, lightNormal[num]); - System.out.println("cmult vec " + lightNormal[num]); - lightNormal[num].normalize(); - System.out.println("setting light direction " + lightNormal[num]); - */ - - /* - // Multiply by inverse transpose. - lightNormal[num][0] = - modelviewInv.m00*x + modelviewInv.m10*y + - modelviewInv.m20*z + modelviewInv.m30; - lightNormal[num][1] = - modelviewInv.m01*x + modelviewInv.m11*y + - modelviewInv.m21*z + modelviewInv.m31; - lightNormal[num][2] = - modelviewInv.m02*x + modelviewInv.m12*y + - modelviewInv.m22*z + modelviewInv.m32; - - float n = mag(lightNormal[num][0], lightNormal[num][1], lightNormal[num][2]); - if (n == 0 || n == 1) return; - - lightNormal[num][0] /= n; - lightNormal[num][1] /= n; - lightNormal[num][2] /= n; - */ - } - - - - ////////////////////////////////////////////////////////////// - - // BACKGROUND - - // Base background() variations inherited from PGraphics. - - - protected void backgroundImpl(PImage image) { - System.arraycopy(image.pixels, 0, pixels, 0, pixels.length); - Arrays.fill(zbuffer, Float.MAX_VALUE); - } - - - /** - * Clear pixel buffer. With P3D and OPENGL, this also clears the zbuffer. - */ - protected void backgroundImpl() { - Arrays.fill(pixels, backgroundColor); - Arrays.fill(zbuffer, Float.MAX_VALUE); - } - - - - ////////////////////////////////////////////////////////////// - - // COLOR MODE - - // all colorMode() variations inherited from PGraphics. - - - - ////////////////////////////////////////////////////////////// - - // COLOR CALCULATIONS - - // protected colorCalc and colorCalcARGB inherited. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE STUFFING - - // final color() variations inherited. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE EXTRACTION - - // final methods alpha, red, green, blue, - // hue, saturation, and brightness all inherited. - - - - ////////////////////////////////////////////////////////////// - - // COLOR DATATYPE INTERPOLATION - - // both lerpColor variants inherited. - - - - ////////////////////////////////////////////////////////////// - - // BEGIN/END RAW - - // beginRaw, endRaw() both inherited. - - - - ////////////////////////////////////////////////////////////// - - // WARNINGS and EXCEPTIONS - - // showWarning and showException inherited. - - - - ////////////////////////////////////////////////////////////// - - // RENDERER SUPPORT QUERIES - - - //public boolean displayable() - - - public boolean is2D() { - return false; - } - - - public boolean is3D() { - return true; - } - - - - ////////////////////////////////////////////////////////////// - - // PIMAGE METHODS - - // All these methods are inherited, because this render has a - // pixels[] array that can be accessed directly. - - // getImage - // setCache, getCache, removeCache - // isModified, setModified - // loadPixels, updatePixels - // resize - // get, getImpl, set, setImpl - // mask - // filter - // copy - // blendColor, blend - - - - ////////////////////////////////////////////////////////////// - - // MATH (internal use only) - - - private final float sqrt(float a) { - return (float) Math.sqrt(a); - } - - - private final float mag(float a, float b, float c) { - return (float) Math.sqrt(a*a + b*b + c*c); - } - - - private final float clamp(float a) { - return (a < 1) ? a : 1; - } - - - private final float abs(float a) { - return (a < 0) ? -a : a; - } - - - private float dot(float ax, float ay, float az, - float bx, float by, float bz) { - return ax*bx + ay*by + az*bz; - } - - - /* - private final void cross(float a0, float a1, float a2, - float b0, float b1, float b2, - float[] out) { - out[0] = a1*b2 - a2*b1; - out[1] = a2*b0 - a0*b2; - out[2] = a0*b1 - a1*b0; - } - */ - - - private final void cross(float a0, float a1, float a2, - float b0, float b1, float b2, - PVector out) { - out.x = a1*b2 - a2*b1; - out.y = a2*b0 - a0*b2; - out.z = a0*b1 - a1*b0; - } - - - /* - private final void cross(float[] a, float[] b, float[] out) { - out[0] = a[1]*b[2] - a[2]*b[1]; - out[1] = a[2]*b[0] - a[0]*b[2]; - out[2] = a[0]*b[1] - a[1]*b[0]; - } - */ -} - diff --git a/android/core/src/processing/core/PLine.java b/android/core/src/processing/core/PLine.java deleted file mode 100644 index a18afda9c..000000000 --- a/android/core/src/processing/core/PLine.java +++ /dev/null @@ -1,1278 +0,0 @@ -/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Processing project - http://processing.org - - Copyright (c) 2004-07 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General - Public License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, - Boston, MA 02111-1307 USA - */ - -package processing.core; - - -/** - * Code for rendering lines with P2D and P3D. - * @author rocha - * @author fry - */ -public class PLine implements PConstants -{ - private int[] m_pixels; - private float[] m_zbuffer; - //private int[] m_stencil; - - private int m_index; - - static final int R_COLOR = 0x1; - static final int R_ALPHA = 0x2; - static final int R_SPATIAL = 0x8; - static final int R_THICK = 0x4; - static final int R_SMOOTH = 0x10; - - private int SCREEN_WIDTH; - private int SCREEN_HEIGHT; - private int SCREEN_WIDTH1; - private int SCREEN_HEIGHT1; - - public boolean INTERPOLATE_RGB; - public boolean INTERPOLATE_ALPHA; - public boolean INTERPOLATE_Z; - public boolean INTERPOLATE_THICK; - - // antialias - private boolean SMOOTH; - - // blender - //private boolean BLENDER; - - // stroke color - private int m_stroke; - - // draw flags - public int m_drawFlags; - - // vertex coordinates - private float[] x_array; - private float[] y_array; - private float[] z_array; - - // vertex intensity - private float[] r_array; - private float[] g_array; - private float[] b_array; - private float[] a_array; - - // vertex offsets - private int o0; - private int o1; - - // start values - private float m_r0; - private float m_g0; - private float m_b0; - private float m_a0; - private float m_z0; - - // deltas - private float dz; - - // rgba deltas - private float dr; - private float dg; - private float db; - private float da; - - private PGraphics parent; - - - public PLine(PGraphics g) { - INTERPOLATE_Z = false; - - x_array = new float[2]; - y_array = new float[2]; - z_array = new float[2]; - r_array = new float[2]; - g_array = new float[2]; - b_array = new float[2]; - a_array = new float[2]; - - this.parent = g; - } - - - public void reset() { - // reset these in case PGraphics was resized - SCREEN_WIDTH = parent.width; - SCREEN_HEIGHT = parent.height; - SCREEN_WIDTH1 = SCREEN_WIDTH-1; - SCREEN_HEIGHT1 = SCREEN_HEIGHT-1; - - m_pixels = parent.pixels; - //m_stencil = parent.stencil; - if (parent instanceof PGraphics3D) { - m_zbuffer = ((PGraphics3D) parent).zbuffer; - } - - // other things to reset - - INTERPOLATE_RGB = false; - INTERPOLATE_ALPHA = false; - //INTERPOLATE_Z = false; - m_drawFlags = 0; - m_index = 0; - //BLENDER = false; - } - - - public void setVertices(float x0, float y0, float z0, - float x1, float y1, float z1) { - // [rocha] fixed z drawing, so whenever a line turns on - // z interpolation, all the lines are z interpolated - if (z0 != z1 || z0 != 0.0f || z1 != 0.0f || INTERPOLATE_Z) { - INTERPOLATE_Z = true; - m_drawFlags |= R_SPATIAL; - } else { - INTERPOLATE_Z = false; - m_drawFlags &= ~R_SPATIAL; - } - - z_array[0] = z0; - z_array[1] = z1; - - x_array[0] = x0; - x_array[1] = x1; - - y_array[0] = y0; - y_array[1] = y1; - } - - - public void setIntensities(float r0, float g0, float b0, float a0, - float r1, float g1, float b1, float a1) { - a_array[0] = (a0 * 253f + 1.0f) * 65536f; - a_array[1] = (a1 * 253f + 1.0f) * 65536f; - - // check if we need alpha or not? - if ((a0 != 1.0f) || (a1 != 1.0f)) { - INTERPOLATE_ALPHA = true; - m_drawFlags |= R_ALPHA; - } else { - INTERPOLATE_ALPHA = false; - m_drawFlags &= ~R_ALPHA; - } - - // extra scaling added to prevent color "overflood" due to rounding errors - r_array[0] = (r0 * 253f + 1.0f) * 65536f; - r_array[1] = (r1 * 253f + 1.0f) * 65536f; - - g_array[0] = (g0 * 253f + 1.0f) * 65536f; - g_array[1] = (g1 * 253f + 1.0f) * 65536f; - - b_array[0] = (b0 * 253f + 1.0f) * 65536f; - b_array[1] = (b1 * 253f + 1.0f) * 65536f; - - // check if we need to interpolate the intensity values - if (r0 != r1) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_COLOR; - - } else if (g0 != g1) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_COLOR; - - } else if (b0 != b1) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_COLOR; - - } else { - // when plain we use the stroke color of the first vertex - m_stroke = 0xFF000000 | - ((int)(255*r0) << 16) | ((int)(255*g0) << 8) | (int)(255*b0); - INTERPOLATE_RGB = false; - m_drawFlags &= ~R_COLOR; - } - } - - - public void setIndex(int index) { - m_index = index; - //BLENDER = false; - if (m_index != -1) { - //BLENDER = true; - } else { - m_index = 0; - } - } - - - public void draw() { - int xi; - int yi; - int length; - boolean visible = true; - - if (parent.smooth) { - SMOOTH = true; - m_drawFlags |= R_SMOOTH; - - } else { - SMOOTH = false; - m_drawFlags &= ~R_SMOOTH; - } - - /* - // line hack - if (parent.hints[DISABLE_FLYING_POO]) { - float nwidth2 = -SCREEN_WIDTH; - float nheight2 = -SCREEN_HEIGHT; - float width2 = SCREEN_WIDTH * 2; - float height2 = SCREEN_HEIGHT * 2; - if ((x_array[1] < nwidth2) || - (x_array[1] > width2) || - (x_array[0] < nwidth2) || - (x_array[0] > width2) || - (y_array[1] < nheight2) || - (y_array[1] > height2) || - (y_array[0] < nheight2) || - (y_array[0] > height2)) { - return; // this is a bad line - } - } - */ - - /////////////////////////////////////// - // line clipping - visible = lineClipping(); - if (!visible) { - return; - } - - /////////////////////////////////////// - // calculate line values - int shortLen; - int longLen; - boolean yLonger; - int dt; - - yLonger = false; - - // HACK for drawing lines left-to-right for rev 0069 - // some kind of bug exists with the line-stepping algorithm - // that causes strange patterns in the anti-aliasing. - // [040228 fry] - // - // swap rgba as well as the coords.. oops - // [040712 fry] - // - if (x_array[1] < x_array[0]) { - float t; - - t = x_array[1]; x_array[1] = x_array[0]; x_array[0] = t; - t = y_array[1]; y_array[1] = y_array[0]; y_array[0] = t; - t = z_array[1]; z_array[1] = z_array[0]; z_array[0] = t; - - t = r_array[1]; r_array[1] = r_array[0]; r_array[0] = t; - t = g_array[1]; g_array[1] = g_array[0]; g_array[0] = t; - t = b_array[1]; b_array[1] = b_array[0]; b_array[0] = t; - t = a_array[1]; a_array[1] = a_array[0]; a_array[0] = t; - } - - // important - don't change the casts - // is needed this way for line drawing algorithm - longLen = (int)x_array[1] - (int)x_array[0]; - shortLen = (int)y_array[1] - (int)y_array[0]; - - if (Math.abs(shortLen) > Math.abs(longLen)) { - int swap = shortLen; - shortLen = longLen; - longLen = swap; - yLonger = true; - } - - // now we sort points so longLen is always positive - // and we always start drawing from x[0], y[0] - if (longLen < 0) { - // swap order - o0 = 1; - o1 = 0; - - xi = (int) x_array[1]; - yi = (int) y_array[1]; - - length = -longLen; - - } else { - o0 = 0; - o1 = 1; - - xi = (int) x_array[0]; - yi = (int) y_array[0]; - - length = longLen; - } - - // calculate dt - if (length == 0) { - dt = 0; - } else { - dt = (shortLen << 16) / longLen; - } - - m_r0 = r_array[o0]; - m_g0 = g_array[o0]; - m_b0 = b_array[o0]; - - if (INTERPOLATE_RGB) { - dr = (r_array[o1] - r_array[o0]) / length; - dg = (g_array[o1] - g_array[o0]) / length; - db = (b_array[o1] - b_array[o0]) / length; - } else { - dr = 0; - dg = 0; - db = 0; - } - - m_a0 = a_array[o0]; - - if (INTERPOLATE_ALPHA) { - da = (a_array[o1] - a_array[o0]) / length; - } else { - da = 0; - } - - m_z0 = z_array[o0]; - //z0 += -0.001f; // [rocha] ugly fix for z buffer precision - - if (INTERPOLATE_Z) { - dz = (z_array[o1] - z_array[o0]) / length; - } else { - dz = 0; - } - - // draw thin points - if (length == 0) { - if (INTERPOLATE_ALPHA) { - drawPoint_alpha(xi, yi); - } else { - drawPoint(xi, yi); - } - return; - } - - /* - // draw antialias polygon lines for non stroked polygons - if (BLENDER && SMOOTH) { - // fix for endpoints not being drawn - // [rocha] - drawPoint_alpha((int)x_array[0], (int)x_array[0]); - drawPoint_alpha((int)x_array[1], (int)x_array[1]); - - drawline_blender(x_array[0], y_array[0], x_array[1], y_array[1]); - return; - } - */ - - // draw normal strokes - if (SMOOTH) { -// if ((m_drawFlags & R_SPATIAL) != 0) { -// drawLine_smooth_spatial(xi, yi, dt, length, yLonger); -// } else { - drawLine_smooth(xi, yi, dt, length, yLonger); -// } - - } else { - if (m_drawFlags == 0) { - drawLine_plain(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == R_ALPHA) { - drawLine_plain_alpha(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == R_COLOR) { - drawLine_color(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == (R_COLOR + R_ALPHA)) { - drawLine_color_alpha(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == R_SPATIAL) { - drawLine_plain_spatial(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == (R_SPATIAL + R_ALPHA)) { - drawLine_plain_alpha_spatial(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == (R_SPATIAL + R_COLOR)) { - drawLine_color_spatial(xi, yi, dt, length, yLonger); - - } else if (m_drawFlags == (R_SPATIAL + R_COLOR + R_ALPHA)) { - drawLine_color_alpha_spatial(xi, yi, dt, length, yLonger); - } - } - } - - - public boolean lineClipping() { - // new cohen-sutherland clipping code, as old one was buggy [toxi] - // get the "dips" for the points to clip - int code1 = lineClipCode(x_array[0], y_array[0]); - int code2 = lineClipCode(x_array[1], y_array[1]); - int dip = code1 | code2; - - if ((code1 & code2)!=0) { - - return false; - - } else if (dip != 0) { - - // now calculate the clipped points - float a0 = 0, a1 = 1, a = 0; - - for (int i = 0; i < 4; i++) { - if (((dip>>i)%2)==1){ - a = lineSlope(x_array[0], y_array[0], x_array[1], y_array[1], i+1); - if (((code1 >> i) % 2) == 1) { - a0 = (a>a0)?a:a0; // max(a,a0) - } else { - a1 = (a
- * Originally written by sami (www.sumea.com) - */ -public class PTriangle implements PConstants -{ - static final float PIXEL_CENTER = 0.5f; // for polygon aa - - static final int R_GOURAUD = 0x1; - static final int R_TEXTURE8 = 0x2; - static final int R_TEXTURE24 = 0x4; - static final int R_TEXTURE32 = 0x8; - static final int R_ALPHA = 0x10; - - private int[] m_pixels; - private int[] m_texture; - //private int[] m_stencil; - private float[] m_zbuffer; - - private int SCREEN_WIDTH; - private int SCREEN_HEIGHT; - //private int SCREEN_WIDTH1; - //private int SCREEN_HEIGHT1; - - private int TEX_WIDTH; - private int TEX_HEIGHT; - private float F_TEX_WIDTH; - private float F_TEX_HEIGHT; - - public boolean INTERPOLATE_UV; - public boolean INTERPOLATE_RGB; - public boolean INTERPOLATE_ALPHA; - - // the power of 2 that tells how many pixels to interpolate - // for between exactly computed texture coordinates - private static final int DEFAULT_INTERP_POWER = 3; - private static int TEX_INTERP_POWER = DEFAULT_INTERP_POWER; - - // Vertex coordinates - private float[] x_array; - private float[] y_array; - private float[] z_array; - - private float[] camX; - private float[] camY; - private float[] camZ; - - // U,V coordinates - private float[] u_array; - private float[] v_array; - - // Vertex Intensity - private float[] r_array; - private float[] g_array; - private float[] b_array; - private float[] a_array; - - // vertex offsets - private int o0; - private int o1; - private int o2; - - /* rgb & a */ - private float r0; - private float r1; - private float r2; - private float g0; - private float g1; - private float g2; - private float b0; - private float b1; - private float b2; - private float a0; - private float a1; - private float a2; - - /* accurate texture uv coordinates */ - private float u0; - private float u1; - private float u2; - private float v0; - private float v1; - private float v2; - - /* deltas */ - //private float dx0; - //private float dx1; - private float dx2; - private float dy0; - private float dy1; - private float dy2; - private float dz0; - //private float dz1; - private float dz2; - - /* texture deltas */ - private float du0; - //private float du1; - private float du2; - private float dv0; - //private float dv1; - private float dv2; - - /* rgba deltas */ - private float dr0; - //private float dr1; - private float dr2; - private float dg0; - //private float dg1; - private float dg2; - private float db0; - //private float db1; - private float db2; - private float da0; - //private float da1; - private float da2; - - /* */ - private float uleft; - private float vleft; - private float uleftadd; - private float vleftadd; - - /* polyedge positions & adds */ - private float xleft; - private float xrght; - private float xadd1; - private float xadd2; - private float zleft; - private float zleftadd; - - /* rgba positions & adds */ - private float rleft; - private float gleft; - private float bleft; - private float aleft; - private float rleftadd; - private float gleftadd; - private float bleftadd; - private float aleftadd; - - /* other somewhat useful variables :) */ - private float dta; - //private float dta2; - private float temp; - private float width; - - /* integer poly UV adds */ - private int iuadd; - private int ivadd; - private int iradd; - private int igadd; - private int ibadd; - private int iaadd; - private float izadd; - - /* fill color */ - private int m_fill; - - /* draw flags */ - public int m_drawFlags; - - /* current poly number */ -// private int m_index; - - /** */ - private PGraphics3D parent; - - private boolean noDepthTest; - //private boolean argbSurface; - - /** */ - private boolean m_culling; - - /** */ - private boolean m_singleRight; - - /** - * True if using bilinear interpolation for textures. - * Always set to true. If this is ever changed (maybe with a hint()?) - * will need to write code for texture8/24/32 et al that will handle mixing - * the m_fill color in with the texture color. - */ - private boolean m_bilinear = true; // always set to true - - - // Vectors needed in accurate texture code - // We store them as class members to avoid too much code duplication - private float ax,ay,az; - private float bx,by,bz; - private float cx,cy,cz; - private float nearPlaneWidth; - private float nearPlaneHeight; - private float nearPlaneDepth; - private float xmult; - private float ymult; - // optimization vars...not pretty, but save a couple mults per pixel - private float newax,newbx,newcx; - // are we currently drawing the first piece of the triangle, - // or have we already done so? - private boolean firstSegment; - - - public PTriangle(PGraphics3D g) { - x_array = new float[3]; - y_array = new float[3]; - z_array = new float[3]; - u_array = new float[3]; - v_array = new float[3]; - r_array = new float[3]; - g_array = new float[3]; - b_array = new float[3]; - a_array = new float[3]; - - camX = new float[3]; - camY = new float[3]; - camZ = new float[3]; - - this.parent = g; - reset(); - } - - - /** - * Resets polygon attributes - */ - public void reset() { - // reset these in case PGraphics was resized - - SCREEN_WIDTH = parent.width; - SCREEN_HEIGHT = parent.height; - //SCREEN_WIDTH1 = SCREEN_WIDTH-1; - //SCREEN_HEIGHT1 = SCREEN_HEIGHT-1; - - m_pixels = parent.pixels; -// m_stencil = parent.stencil; - m_zbuffer = parent.zbuffer; - - noDepthTest = parent.hints[DISABLE_DEPTH_TEST]; - //argbSurface = parent.format == PConstants.ARGB; - - // other things to reset - - INTERPOLATE_UV = false; - INTERPOLATE_RGB = false; - INTERPOLATE_ALPHA = false; - //m_tImage = null; - m_texture = null; - m_drawFlags = 0; - } - - - /** - * Sets backface culling on/off - */ - public void setCulling(boolean tf) { - m_culling = tf; - } - - - /** - * Sets vertex coordinates for the triangle - */ - public void setVertices(float x0, float y0, float z0, - float x1, float y1, float z1, - float x2, float y2, float z2) { - x_array[0] = x0; - x_array[1] = x1; - x_array[2] = x2; - - y_array[0] = y0; - y_array[1] = y1; - y_array[2] = y2; - - z_array[0] = z0; - z_array[1] = z1; - z_array[2] = z2; - } - - - /** - * Pass camera-space coordinates for the triangle. - * Needed to render if hint(ENABLE_ACCURATE_TEXTURES) enabled. - * Generally this will not need to be called manually, - * currently called from PGraphics3D.render_triangles() - */ - public void setCamVertices(float x0, float y0, float z0, - float x1, float y1, float z1, - float x2, float y2, float z2) { - camX[0] = x0; - camX[1] = x1; - camX[2] = x2; - - camY[0] = y0; - camY[1] = y1; - camY[2] = y2; - - camZ[0] = z0; - camZ[1] = z1; - camZ[2] = z2; - } - - - /** - * Sets the UV coordinates of the texture - */ - public void setUV(float u0, float v0, - float u1, float v1, - float u2, float v2) { - // sets & scales uv texture coordinates to center of the pixel - u_array[0] = (u0 * F_TEX_WIDTH + 0.5f) * 65536f; - u_array[1] = (u1 * F_TEX_WIDTH + 0.5f) * 65536f; - u_array[2] = (u2 * F_TEX_WIDTH + 0.5f) * 65536f; - v_array[0] = (v0 * F_TEX_HEIGHT + 0.5f) * 65536f; - v_array[1] = (v1 * F_TEX_HEIGHT + 0.5f) * 65536f; - v_array[2] = (v2 * F_TEX_HEIGHT + 0.5f) * 65536f; - } - - - /** - * Sets vertex intensities in 0xRRGGBBAA format - */ - public void setIntensities(float r0, float g0, float b0, float a0, - float r1, float g1, float b1, float a1, - float r2, float g2, float b2, float a2) { - // Check if we need alpha or not? - if ((a0 != 1.0f) || (a1 != 1.0f) || (a2 != 1.0f)) { - INTERPOLATE_ALPHA = true; - a_array[0] = (a0 * 253f + 1.0f) * 65536f; - a_array[1] = (a1 * 253f + 1.0f) * 65536f; - a_array[2] = (a2 * 253f + 1.0f) * 65536f; - m_drawFlags|=R_ALPHA; - } else { - INTERPOLATE_ALPHA = false; - m_drawFlags&=~R_ALPHA; - } - - // Check if we need to interpolate the intensity values - if ((r0 != r1) || (r1 != r2)) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_GOURAUD; - } else if ((g0 != g1) || (g1 != g2)) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_GOURAUD; - } else if ((b0 != b1) || (b1 != b2)) { - INTERPOLATE_RGB = true; - m_drawFlags |= R_GOURAUD; - } else { - //m_fill = parent.filli; - m_drawFlags &=~ R_GOURAUD; - } - - // push values to arrays.. some extra scaling is added - // to prevent possible color "overflood" due to rounding errors - r_array[0] = (r0 * 253f + 1.0f) * 65536f; - r_array[1] = (r1 * 253f + 1.0f) * 65536f; - r_array[2] = (r2 * 253f + 1.0f) * 65536f; - - g_array[0] = (g0 * 253f + 1.0f) * 65536f; - g_array[1] = (g1 * 253f + 1.0f) * 65536f; - g_array[2] = (g2 * 253f + 1.0f) * 65536f; - - b_array[0] = (b0 * 253f + 1.0f) * 65536f; - b_array[1] = (b1 * 253f + 1.0f) * 65536f; - b_array[2] = (b2 * 253f + 1.0f) * 65536f; - - // for plain triangles - m_fill = 0xFF000000 | - ((int)(255*r0) << 16) | ((int)(255*g0) << 8) | (int)(255*b0); - } - - - /** - * Sets texture image used for the polygon - */ - public void setTexture(PImage image) { - //m_tImage = image; - m_texture = image.pixels; - TEX_WIDTH = image.width; - TEX_HEIGHT = image.height; - F_TEX_WIDTH = TEX_WIDTH-1; - F_TEX_HEIGHT = TEX_HEIGHT-1; - INTERPOLATE_UV = true; - - if (image.format == ARGB) { - m_drawFlags |= R_TEXTURE32; - } else if (image.format == RGB) { - m_drawFlags |= R_TEXTURE24; - } else if (image.format == ALPHA) { - m_drawFlags |= R_TEXTURE8; - } - } - - - /** - * - */ - public void setUV(float[] u, float[] v) { - if (m_bilinear) { - // sets & scales uv texture coordinates to edges of pixels - u_array[0] = (u[0] * F_TEX_WIDTH) * 65500f; - u_array[1] = (u[1] * F_TEX_WIDTH) * 65500f; - u_array[2] = (u[2] * F_TEX_WIDTH) * 65500f; - v_array[0] = (v[0] * F_TEX_HEIGHT) * 65500f; - v_array[1] = (v[1] * F_TEX_HEIGHT) * 65500f; - v_array[2] = (v[2] * F_TEX_HEIGHT) * 65500f; - } else { - // sets & scales uv texture coordinates to center of the pixel - u_array[0] = (u[0] * TEX_WIDTH) * 65500f; - u_array[1] = (u[1] * TEX_WIDTH) * 65500f; - u_array[2] = (u[2] * TEX_WIDTH) * 65500f; - v_array[0] = (v[0] * TEX_HEIGHT) * 65500f; - v_array[1] = (v[1] * TEX_HEIGHT) * 65500f; - v_array[2] = (v[2] * TEX_HEIGHT) * 65500f; - } - } - - -// public void setIndex(int index) { -// m_index = index; -// } - - - /** - * Renders the polygon - */ - public void render() { - float x0, x1, x2; - float z0, z1, z2; - - float y0 = y_array[0]; - float y1 = y_array[1]; - float y2 = y_array[2]; - - //System.out.println(PApplet.hex(m_drawFlags)); - - // For accurate texture interpolation, need to mark whether - // we've already pre-calculated for the triangle - firstSegment = true; - - // do backface culling? - if (m_culling) { - x0 = x_array[0]; - if ((x_array[2]-x0)*(y1-y0) < (x_array[1]-x0)*(y2-y0)) - return; - } - - /* get vertex order from top -> down */ - if (y0 < y1) { - if (y2 < y1) { - if (y2 < y0) { // 2,0,1 - o0 = 2; - o1 = 0; - o2 = 1; - } else { // 0,2,1 - o0 = 0; - o1 = 2; - o2 = 1; - } - } else { // 0,1,2 - o0 = 0; - o1 = 1; - o2 = 2; - } - } else { - if (y2 > y1) { - if (y2 < y0) { // 1,2,0 - o0 = 1; - o1 = 2; - o2 = 0; - } else { // 1,0,2 - o0 = 1; - o1 = 0; - o2 = 2; - } - } else { // 2,1,0 - o0 = 2; - o1 = 1; - o2 = 0; - } - } - - /** - * o0 = "top" vertex offset - * o1 = "mid" vertex offset - * o2 = "bot" vertex offset - */ - - y0 = y_array[o0]; - int yi0 = (int) (y0 + PIXEL_CENTER); - if (yi0 > SCREEN_HEIGHT) { - return; - } else if (yi0 < 0) { - yi0 = 0; - } - - y2 = y_array[o2]; - int yi2 = (int) (y2 + PIXEL_CENTER); - if (yi2 < 0) { - return; - } else if (yi2 > SCREEN_HEIGHT) { - yi2 = SCREEN_HEIGHT; - } - - // Does the poly actually cross a scanline? - if (yi2 > yi0) { - x0 = x_array[o0]; - x1 = x_array[o1]; - x2 = x_array[o2]; - - // get mid Y and clip it - y1 = y_array[o1]; - int yi1 = (int) (y1 + PIXEL_CENTER); - if (yi1 < 0) - yi1 = 0; - if (yi1 > SCREEN_HEIGHT) - yi1 = SCREEN_HEIGHT; - - // calculate deltas etc. - dx2 = x2 - x0; - dy0 = y1 - y0; - dy2 = y2 - y0; - xadd2 = dx2 / dy2; // xadd for "single" edge - temp = dy0 / dy2; - width = temp * dx2 + x0 - x1; - - // calculate alpha blend interpolation - if (INTERPOLATE_ALPHA) { - a0 = a_array[o0]; - a1 = a_array[o1]; - a2 = a_array[o2]; - da0 = a1-a0; - da2 = a2-a0; - iaadd = (int) ((temp * da2 - da0) / width); // alpha add - } - - // calculate intensity interpolation - if (INTERPOLATE_RGB) { - r0 = r_array[o0]; - r1 = r_array[o1]; - r2 = r_array[o2]; - - g0 = g_array[o0]; - g1 = g_array[o1]; - g2 = g_array[o2]; - - b0 = b_array[o0]; - b1 = b_array[o1]; - b2 = b_array[o2]; - - dr0 = r1-r0; - dg0 = g1-g0; - db0 = b1-b0; - - dr2 = r2-r0; - dg2 = g2-g0; - db2 = b2-b0; - - iradd = (int) ((temp * dr2 - dr0) / width); // r add - igadd = (int) ((temp * dg2 - dg0) / width); // g add - ibadd = (int) ((temp * db2 - db0) / width); // b add - } - - // calculate UV interpolation - if (INTERPOLATE_UV) { - u0 = u_array[o0]; - u1 = u_array[o1]; - u2 = u_array[o2]; - v0 = v_array[o0]; - v1 = v_array[o1]; - v2 = v_array[o2]; - du0 = u1-u0; - dv0 = v1-v0; - du2 = u2-u0; - dv2 = v2-v0; - iuadd = (int) ((temp * du2 - du0) / width); // u add - ivadd = (int) ((temp * dv2 - dv0) / width); // v add - } - - z0 = z_array[o0]; - z1 = z_array[o1]; - z2 = z_array[o2]; - dz0 = z1-z0; - dz2 = z2-z0; - izadd = (temp * dz2 - dz0) / width; - - // draw the upper poly segment if it's visible - if (yi1 > yi0) { - dta = (yi0 + PIXEL_CENTER) - y0; - xadd1 = (x1 - x0) / dy0; - - // we can determine which side is "single" side - // by comparing left/right edge adds - if (xadd2 > xadd1) { - xleft = x0 + dta * xadd1; - xrght = x0 + dta * xadd2; - zleftadd = dz0 / dy0; - zleft = dta*zleftadd+z0; - - if (INTERPOLATE_UV) { - uleftadd = du0 / dy0; - vleftadd = dv0 / dy0; - uleft = dta*uleftadd+u0; - vleft = dta*vleftadd+v0; - } - - if (INTERPOLATE_RGB) { - rleftadd = dr0 / dy0; - gleftadd = dg0 / dy0; - bleftadd = db0 / dy0; - rleft = dta*rleftadd+r0; - gleft = dta*gleftadd+g0; - bleft = dta*bleftadd+b0; - } - - if (INTERPOLATE_ALPHA) { - aleftadd = da0 / dy0; - aleft = dta*aleftadd+a0; - - if (m_drawFlags == R_ALPHA) { - drawsegment_plain_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) { - drawsegment_gouraud_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) { - drawsegment_texture8_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) { - drawsegment_texture24_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) { - drawsegment_texture32_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) { - drawsegment_gouraud_texture8_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) { - drawsegment_gouraud_texture24_alpha(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) { - drawsegment_gouraud_texture32_alpha(xadd1,xadd2, yi0,yi1); - } - } else { - if (m_drawFlags == 0) { - drawsegment_plain(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == R_GOURAUD) { - drawsegment_gouraud(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE8) { - drawsegment_texture8(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE24) { - drawsegment_texture24(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE32) { - drawsegment_texture32(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) { - drawsegment_gouraud_texture8(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) { - drawsegment_gouraud_texture24(xadd1,xadd2, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) { - drawsegment_gouraud_texture32(xadd1,xadd2, yi0,yi1); - } - } - m_singleRight = true; - } else { - xleft = x0 + dta * xadd2; - xrght = x0 + dta * xadd1; - zleftadd = dz2 / dy2; - zleft = dta*zleftadd+z0; - // - if (INTERPOLATE_UV) { - uleftadd = du2 / dy2; - vleftadd = dv2 / dy2; - uleft = dta*uleftadd+u0; - vleft = dta*vleftadd+v0; - } - - // - if (INTERPOLATE_RGB) { - rleftadd = dr2 / dy2; - gleftadd = dg2 / dy2; - bleftadd = db2 / dy2; - rleft = dta*rleftadd+r0; - gleft = dta*gleftadd+g0; - bleft = dta*bleftadd+b0; - } - - - if (INTERPOLATE_ALPHA) { - aleftadd = da2 / dy2; - aleft = dta*aleftadd+a0; - - if (m_drawFlags == R_ALPHA) { - drawsegment_plain_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) { - drawsegment_gouraud_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) { - drawsegment_texture8_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) { - drawsegment_texture24_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) { - drawsegment_texture32_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) { - drawsegment_gouraud_texture8_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) { - drawsegment_gouraud_texture24_alpha(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) { - drawsegment_gouraud_texture32_alpha(xadd2, xadd1, yi0,yi1); - } - } else { - if (m_drawFlags == 0) { - drawsegment_plain(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == R_GOURAUD) { - drawsegment_gouraud(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE8) { - drawsegment_texture8(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE24) { - drawsegment_texture24(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == R_TEXTURE32) { - drawsegment_texture32(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) { - drawsegment_gouraud_texture8(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) { - drawsegment_gouraud_texture24(xadd2, xadd1, yi0,yi1); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) { - drawsegment_gouraud_texture32(xadd2, xadd1, yi0,yi1); - } - } - m_singleRight = false; - } - - // if bottom segment height is zero, return - if (yi2 == yi1) return; - - // calculate xadd 1 - dy1 = y2 - y1; - xadd1 = (x2 - x1) / dy1; - - } else { - // top seg height was zero, calculate & clip single edge X - dy1 = y2 - y1; - xadd1 = (x2 - x1) / dy1; - - // which edge is left? - if (xadd2 < xadd1) { - xrght = ((yi1 + PIXEL_CENTER) - y0) * xadd2 + x0; - m_singleRight = true; - } else { - dta = (yi1 + PIXEL_CENTER) - y0; - xleft = dta * xadd2 + x0; - zleftadd = dz2 / dy2; - zleft = dta * zleftadd + z0; - - if (INTERPOLATE_UV) { - uleftadd = du2 / dy2; - vleftadd = dv2 / dy2; - uleft = dta * uleftadd + u0; - vleft = dta * vleftadd + v0; - } - - if (INTERPOLATE_RGB) { - rleftadd = dr2 / dy2; - gleftadd = dg2 / dy2; - bleftadd = db2 / dy2; - rleft = dta * rleftadd + r0; - gleft = dta * gleftadd + g0; - bleft = dta * bleftadd + b0; - } - - // - if (INTERPOLATE_ALPHA) { - aleftadd = da2 / dy2; - aleft = dta * aleftadd + a0; - } - m_singleRight = false; - } - } - - // draw the lower segment - if (m_singleRight) { - dta = (yi1 + PIXEL_CENTER) - y1; - xleft = dta * xadd1 + x1; - zleftadd = (z2 - z1) / dy1; - zleft = dta * zleftadd + z1; - - if (INTERPOLATE_UV) { - uleftadd = (u2 - u1) / dy1; - vleftadd = (v2 - v1) / dy1; - uleft = dta * uleftadd + u1; - vleft = dta * vleftadd + v1; - } - - if (INTERPOLATE_RGB) { - rleftadd = (r2 - r1) / dy1; - gleftadd = (g2 - g1) / dy1; - bleftadd = (b2 - b1) / dy1; - rleft = dta * rleftadd + r1; - gleft = dta * gleftadd + g1; - bleft = dta * bleftadd + b1; - } - - if (INTERPOLATE_ALPHA) { - aleftadd = (a2 - a1) / dy1; - aleft = dta * aleftadd + a1; - - if (m_drawFlags == R_ALPHA) { - drawsegment_plain_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) { - drawsegment_gouraud_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) { - drawsegment_texture8_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) { - drawsegment_texture24_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) { - drawsegment_texture32_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) { - drawsegment_gouraud_texture8_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) { - drawsegment_gouraud_texture24_alpha(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) { - drawsegment_gouraud_texture32_alpha(xadd1, xadd2, yi1,yi2); - } - } else { - if (m_drawFlags == 0) { - drawsegment_plain(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == R_GOURAUD) { - drawsegment_gouraud(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE8) { - drawsegment_texture8(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE24) { - drawsegment_texture24(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE32) { - drawsegment_texture32(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) { - drawsegment_gouraud_texture8(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) { - drawsegment_gouraud_texture24(xadd1, xadd2, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) { - drawsegment_gouraud_texture32(xadd1, xadd2, yi1,yi2); - } - } - } else { - xrght = ((yi1 + PIXEL_CENTER)- y1) * xadd1 + x1; - - if (INTERPOLATE_ALPHA) { - if (m_drawFlags == R_ALPHA) { - drawsegment_plain_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_ALPHA)) { - drawsegment_gouraud_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE8 + R_ALPHA)) { - drawsegment_texture8_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE24 + R_ALPHA)) { - drawsegment_texture24_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_TEXTURE32 + R_ALPHA)) { - drawsegment_texture32_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8 + R_ALPHA)) { - drawsegment_gouraud_texture8_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24 + R_ALPHA)) { - drawsegment_gouraud_texture24_alpha(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32 + R_ALPHA)) { - drawsegment_gouraud_texture32_alpha(xadd2, xadd1, yi1,yi2); - } - } else { - if (m_drawFlags == 0) { - drawsegment_plain(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == R_GOURAUD) { - drawsegment_gouraud(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE8) { - drawsegment_texture8(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE24) { - drawsegment_texture24(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == R_TEXTURE32) { - drawsegment_texture32(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE8)) { - drawsegment_gouraud_texture8(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE24)) { - drawsegment_gouraud_texture24(xadd2, xadd1, yi1,yi2); - } else if (m_drawFlags == (R_GOURAUD + R_TEXTURE32)) { - drawsegment_gouraud_texture32(xadd2, xadd1, yi1,yi2); - } - } - } - } - } - - - /** - * Accurate texturing code by ewjordan@gmail.com, April 14, 2007 - * The getColorFromTexture() function should be inlined and optimized - * so that most of the heavy lifting happens outside the per-pixel loop. - * The unoptimized generic algorithm looks like this (unless noted, - * all of these variables are vectors, so the actual code will look messier): - * - * p = camera space vector where u == 0, v == 0; - * m = vector from p to location where u == TEX_WIDTH; - * n = vector from p to location where v == TEX_HEIGHT; - * - * A = p cross n; - * B = m cross p; - * C = n cross m; - * A *= texture.width; - * B *= texture.height; - * - * for (scanlines in triangle){ - * float a = S * A; - * float b = S * B; - * float c = S * C; - * for (pixels in scanline){ - * int u = a/c; - * int v = b/c; - * color = texture[v * texture.width + u]; - * a += A.x; - * b += B.x; - * c += C.x; - * } - * } - * - * We don't use this exact algorithm here, however, because of the extra - * overhead from the divides. Instead we compute the exact u and v (labelled - * iu and iv in the code) at the start of each scanline and we perform a - * linear interpolation for every linearInterpLength = 1 << TEX_INTERP_POWER - * pixels. This means that we only perform the true calculation once in a - * while, and the rest of the time the algorithm functions exactly as in the - * fast inaccurate case, at least in theory. In practice, even if we set - * linearInterpLength very high we still incur some speed penalty due to the - * preprocessing that must take place per-scanline. A similar method could - * be applied per scanline to avoid this, but it would only be worthwhile in - * the case that we never compute more than one exact calculation per - * scanline. If we want something like this, however, it would be best to - * create another mode of calculation called "constant-z" interpolation, - * which could be used for things like floors and ceilings where the - * distance from the camera plane never changes over the course of a - * scanline. We could also add the vertical analogue for drawing vertical - * walls. In any case, these are not critical as the current algorithm runs - * fairly well, perhaps ~10% slower than the default perspective-less one. - */ - - /** - * Solve for camera space coordinates of critical texture points and - * set up per-triangle variables for accurate texturing. - * Sets all class variables relevant to accurate texture computation - * Should be called once per triangle - checks firstSegment to see if - * we've already called. - */ - private boolean precomputeAccurateTexturing() { - // rescale u/v_array values when inverting matrix and performing other calcs - float myFact = 65500.0f; - float myFact2 = 65500.0f; - - //Matrix inversion to find affine transform between (u,v,(1)) -> (x,y,z) - - // OPTIMIZE: There should be a way to avoid the inversion here, which is - // quite expensive (~150 mults). Also it might crap out due to loss of - // precision depending on the scaling of the u/v_arrays. Nothing clever - // currently happens if the inversion fails, since this means the - // transformation is degenerate - we just pass false back to the caller - // and let it handle the situation. [There is no good solution to this - // case from within this function, since the way the calculation proceeds - // presumes a non-degenerate transformation matrix between camera space - // and uv space] - - // Obvious optimization: if the vertices are actually at the appropriate - // texture coordinates (e.g. (0,0), (TEX_WIDTH,0), and (0,TEX_HEIGHT)) - // then we can immediately return the right solution without the inversion. - // This is fairly common, so could speed up many cases of drawing. - // [not implemented] - - // Furthermore, we could cache the p,resultT0,result0T vectors in the - // triangle's basis, since we could then do a look-up and generate the - // resulting coordinates very simply. This would include the above - // optimization as a special case - we could pre-populate the cache with - // special cases like that and dynamically add more. The idea here is that - // most people simply paste textures onto triangles and move the triangles - // from frame to frame, so any per-triangle-per-frame code is likely - // wasted effort. [not implemented] - - // Note: o0, o1, and o2 vary depending on view angle to triangle, - // but p, n, and m should not depend on ordering differences - - if (firstSegment){ - PMatrix3D myMatrix = - new PMatrix3D(u_array[o0]/myFact, v_array[o0]/myFact2, 1, 0, - u_array[o1]/myFact, v_array[o1]/myFact2, 1, 0, - u_array[o2]/myFact, v_array[o2]/myFact2, 1, 0, - 0, 0, 0, 1); - // A 3x3 inversion would be more efficient here, - // given that the fourth r/c are unity - myMatrix.invert(); - // if the matrix inversion had trouble, let the caller know - if (myMatrix == null) return false; - - float m00, m01, m02, m10, m11, m12, m20, m21, m22; - m00 = myMatrix.m00*camX[o0]+myMatrix.m01*camX[o1]+myMatrix.m02*camX[o2]; - m01 = myMatrix.m10*camX[o0]+myMatrix.m11*camX[o1]+myMatrix.m12*camX[o2]; - m02 = myMatrix.m20*camX[o0]+myMatrix.m21*camX[o1]+myMatrix.m22*camX[o2]; - m10 = myMatrix.m00*camY[o0]+myMatrix.m01*camY[o1]+myMatrix.m02*camY[o2]; - m11 = myMatrix.m10*camY[o0]+myMatrix.m11*camY[o1]+myMatrix.m12*camY[o2]; - m12 = myMatrix.m20*camY[o0]+myMatrix.m21*camY[o1]+myMatrix.m22*camY[o2]; - m20 = -(myMatrix.m00*camZ[o0]+myMatrix.m01*camZ[o1]+myMatrix.m02*camZ[o2]); - m21 = -(myMatrix.m10*camZ[o0]+myMatrix.m11*camZ[o1]+myMatrix.m12*camZ[o2]); - m22 = -(myMatrix.m20*camZ[o0]+myMatrix.m21*camZ[o1]+myMatrix.m22*camZ[o2]); - - float px = m02; - float py = m12; - float pz = m22; - // Bugfix: possibly we should use F_TEX_WIDTH/HEIGHT instead? - // Seems to read off end of array in that case, though... - float resultT0x = m00*TEX_WIDTH+m02; - float resultT0y = m10*TEX_WIDTH+m12; - float resultT0z = m20*TEX_WIDTH+m22; - float result0Tx = m01*TEX_HEIGHT+m02; - float result0Ty = m11*TEX_HEIGHT+m12; - float result0Tz = m21*TEX_HEIGHT+m22; - float mx = resultT0x-m02; - float my = resultT0y-m12; - float mz = resultT0z-m22; - float nx = result0Tx-m02; - float ny = result0Ty-m12; - float nz = result0Tz-m22; - - //avec = p x n - ax = (py*nz-pz*ny)*TEX_WIDTH; //F_TEX_WIDTH/HEIGHT? - ay = (pz*nx-px*nz)*TEX_WIDTH; - az = (px*ny-py*nx)*TEX_WIDTH; - //bvec = m x p - bx = (my*pz-mz*py)*TEX_HEIGHT; - by = (mz*px-mx*pz)*TEX_HEIGHT; - bz = (mx*py-my*px)*TEX_HEIGHT; - //cvec = n x m - cx = ny*mz-nz*my; - cy = nz*mx-nx*mz; - cz = nx*my-ny*mx; - } - - nearPlaneWidth = parent.rightScreen-parent.leftScreen; - nearPlaneHeight = parent.topScreen-parent.bottomScreen; - nearPlaneDepth = parent.nearPlane; - // one pixel width in nearPlane coordinates - xmult = nearPlaneWidth / SCREEN_WIDTH; - ymult = nearPlaneHeight / SCREEN_HEIGHT; - // Extra scalings to map screen plane units to pixel units - newax = ax*xmult; - newbx = bx*xmult; - newcx = cx*xmult; - return true; - } - - - /** - * Set the power of two used for linear interpolation of texture coordinates. - * A true texture coordinate is computed every 2^pwr pixels along a scanline. - */ - static public void setInterpPower(int pwr) { - //Currently must be invoked from P5 as PTriangle.setInterpPower(...) - TEX_INTERP_POWER = pwr; - } - - - /** - * Plain color - */ - private void drawsegment_plain(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int f = m_fill; -// int p = m_index; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - float iz = izadd * xdiff + zleft; - xstart+=ytop; - xend+=ytop; - - for ( ; xstart < xend; xstart++ ) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - m_zbuffer[xstart] = iz; - m_pixels[xstart] = m_fill; -// m_stencil[xstart] = p; - } - iz+=izadd; - } - - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - zleft+=zleftadd; - } - } - - - /** - * Plain color, interpolated alpha - */ - private void drawsegment_plain_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; - - int pr = m_fill & 0xFF0000; - int pg = m_fill & 0xFF00; - int pb = m_fill & 0xFF; - -// int p = m_index; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - float iz = izadd * xdiff + zleft; - int ia = (int) (iaf * xdiff + aleft); - xstart += ytop; - xend += ytop; - - //int ma0 = 0xFF000000; - - for ( ; xstart < xend; xstart++ ) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - // don't set zbuffer when not fully opaque - //m_zbuffer[xstart] = iz; - - int alpha = ia >> 16; - int mr0 = m_pixels[xstart]; - /* - if (argbSurface) { - ma0 = (((mr0 >>> 24) * alpha) << 16) & 0xFF000000; - if (ma0 == 0) ma0 = alpha << 24; - } - */ - int mg0 = mr0 & 0xFF00; - int mb0 = mr0 & 0xFF; - mr0 &= 0xFF0000; - - mr0 = mr0 + (((pr - mr0) * alpha) >> 8); - mg0 = mg0 + (((pg - mg0) * alpha) >> 8); - mb0 = mb0 + (((pb - mb0) * alpha) >> 8); - - m_pixels[xstart] = 0xFF000000 | - (mr0 & 0xFF0000) | (mg0 & 0xFF00) | (mb0 & 0xFF); - -// m_stencil[xstart] = p; - } - iz += izadd; - ia += iaadd; - } - ytop += SCREEN_WIDTH; - xleft += leftadd; - xrght += rghtadd; - zleft += zleftadd; - } - } - - - /** - * RGB gouraud - */ - private void drawsegment_gouraud(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - for ( ; xstart < xend; xstart++ ) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - m_zbuffer[xstart] = iz; - m_pixels[xstart] = 0xFF000000 | - ((ir & 0xFF0000) | ((ig >> 8) & 0xFF00) | (ib >> 16)); -// m_stencil[xstart] = p; - } - - ir+=iradd; - ig+=igadd; - ib+=ibadd; - iz+=izadd; - } - - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - zleft+=zleftadd; - } - } - - - /** - * RGB gouraud + interpolated alpha - */ - private void drawsegment_gouraud_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - for ( ; xstart < xend; xstart++ ) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - // - int red = (ir & 0xFF0000); - int grn = (ig >> 8) & 0xFF00; - int blu = (ib >> 16); - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - - // blend alpha - int al = ia >> 16; - - // - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); -// m_stencil[xstart] = p; - } - - // - ir+=iradd; - ig+=igadd; - ib+=ibadd; - ia+=iaadd; - iz+=izadd; - } - - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - aleft+=aleftadd; - zleft+=zleftadd; - } - } - - - /** - * 8-bit plain texture - */ - - //THIS IS MESSED UP, NEED TO GRAB ORIGINAL VERSION!!! - private void drawsegment_texture8(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - // Accurate texture mode added - comments stripped from dupe code, - // see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode) { - // see if the precomputation goes well, if so finish the setup - if (precomputeAccurateTexturing()) { - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - // if the matrix inversion screwed up, revert to normal rendering - // (something is degenerate) - accurateMode = false; - } - } - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - - int red = m_fill & 0xFF0000; - int grn = m_fill & 0xFF00; - int blu = m_fill & 0xFF; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode && goingIn) { - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; - iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else { - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ; xstart < xend; xstart++ ) { - if (accurateMode) { - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else { - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - // try-catch just in case pixel offset it out of range - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - int al0; - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = iu & 0xFFFF; - al0 = m_texture[ofs] & 0xFF; - int al1 = m_texture[ofs + 1] & 0xFF; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int al2 = m_texture[ofs] & 0xFF; - int al3 = m_texture[ofs + 1] & 0xFF; - al0 = al0 + (((al1-al0) * iui) >> 16); - al2 = al2 + (((al3-al2) * iui) >> 16); - al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16); - } else { - al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF; - } - - int br = m_pixels[xstart]; - int bg = (br & 0xFF00); - int bb = (br & 0xFF); - br = (br & 0xFF0000); - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al0) >> 8)) & 0xFF); -// m_stencil[xstart] = p; - } - } - catch (Exception e) { - } - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - iz+=izadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - zleft+=zleftadd; - } - } - - - - /** - * 8-bit texutre + alpha - */ - private void drawsegment_texture8_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - // Accurate texture mode added - comments stripped from dupe code, - // see drawsegment_texture24() for details - - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode) { - // see if the precomputation goes well, if so finish the setup - if (precomputeAccurateTexturing()) { - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else { - // if the matrix inversion screwed up, - // revert to normal rendering (something is degenerate) - accurateMode = false; - } - } - ytop*=SCREEN_WIDTH; - ybottom*=SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float iaf = iaadd; - - int red = m_fill & 0xFF0000; - int grn = m_fill & 0xFF00; - int blu = m_fill & 0xFF; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - // try-catch just in case pixel offset it out of range - try - { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - int al0; - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = iu & 0xFFFF; - al0 = m_texture[ofs] & 0xFF; - int al1 = m_texture[ofs + 1] & 0xFF; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int al2 = m_texture[ofs] & 0xFF; - int al3 = m_texture[ofs + 1] & 0xFF; - al0 = al0 + (((al1-al0) * iui) >> 16); - al2 = al2 + (((al3-al2) * iui) >> 16); - al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16); - } else { - al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF; - } - al0 = (al0 * (ia >> 16)) >> 8; - - int br = m_pixels[xstart]; - int bg = (br & 0xFF00); - int bb = (br & 0xFF); - br = (br & 0xFF0000); - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al0) >> 8)) & 0xFF); -// m_stencil[xstart] = p; - } - } - catch (Exception e) { - } - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - iz+=izadd; - ia+=iaadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - zleft+=zleftadd; - aleft+=aleftadd; - } - } - - /** - * Plain 24-bit texture - */ - private void drawsegment_texture24(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - float iuf = iuadd; - float ivf = ivadd; - - boolean tint = (m_fill & 0xFFFFFF) != 0xFFFFFF; - int rtint = (m_fill >> 16) & 0xff; - int gtint = (m_fill >> 8) & 0xff; - int btint = m_fill & 0xFF; - - int ypixel = ytop/SCREEN_WIDTH;//ACCTEX - int lastRowStart = m_texture.length - TEX_WIDTH - 2;//If we're past this index, we can't shift down a row w/o throwing an exception - // int exCount = 0;//counter for exceptions caught - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; //bring this local since it will be accessed often - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - - //Interpolation length of 16 tends to look good except at a small angle; 8 looks okay then, except for the - //above issue. When viewing close to flat, as high as 32 is often acceptable. Could add dynamic interpolation - //settings based on triangle angle - currently we just pick a value and leave it (by default I have the - //power set at 3, so every 8 pixels a true coordinate is calculated, which seems a decent compromise). - - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion gave us garbage, revert to normal rendering (something is degenerate) - } - } - - - while (ytop < ybottom) {//scanline loop - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0){ xstart = 0; } - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH){ xend = SCREEN_WIDTH; } - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - float iz = izadd * xdiff + zleft; - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - //off by one (half, I guess) hack, w/o it the first rows are outside the texture - maybe a mistake somewhere? - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az;//OPT - some of this could be brought out of the y-loop since - b = screenx*bx+screeny*by+screenz*bz;//xpixel and ypixel just increment by the same numbers each iteration. - c = screenx*cx+screeny*cy+screenz*cz;//Probably not a big bottleneck, though. - } - - //Figure out whether triangle is going further into the screen or not as we move along scanline - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - - //Set up linear interpolation between calculated texture points - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - //float fdeltaU = 0; float fdeltaV = 0;//vars for floating point interpolating version of algorithm - //float fiu = 0; float fiv = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - - //Bugfix (done): it's a Really Bad Thing to interpolate along a scanline when the triangle goes deeper into the screen, - //because if the angle is severe enough the last control point for interpolation may cross the vanishing - //point. This leads to some pretty nasty artifacts, and ideally we should scan from right to left if the - //triangle is better served that way, or (what we do now) precompute the offset that we'll need so that we end up - //with a control point exactly at the furthest edge of the triangle. - - if (accurateMode&&goingIn){ - //IMPORTANT!!! Results are horrid without this hack! - //If polygon goes into the screen along scan line, we want to match the control point to the furthest point drawn - //since the control points are less meaningful the closer you are to the vanishing point. - //We'll do this by making the first control point lie before the start of the scanline (safe since it's closer to us) - - int rightOffset = (xend-xstart-1)%linearInterpLength; //"off by one" hack...probably means there's a small bug somewhere - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - - //Take step to control point to the left of start pixel - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - - //Now step to right control point - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - - //Get deltas for interpolation - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - //Otherwise the left edge is further, and we pin the first control point to it - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ; xstart < xend; xstart++ ) {//pixel loop - keep trim, can execute thousands of times per frame - //boolean drawBlack = false; //used to display control points - if(accurateMode){ - /* //Non-interpolating algorithm - slowest version, calculates exact coordinate for each pixel, - //and casts from float->int - float oneoverc = 65536.0f/c; //a bit faster to pre-divide for next two steps - iu = (int)(a*oneoverc); - iv = (int)(b*oneoverc); - a += newax; - b += newbx; - c += newcx; - */ - - //Float while calculating, int while interpolating - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - //drawBlack = true; - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; //ints are used for interpolation, not actual computation - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ //race through using linear interpolation if we're not at a control point - iu += deltaU; - iv += deltaV; - } - interpCounter++; - - /* //Floating point interpolating version - slower than int thanks to casts during interpolation steps - if (interpCounter == 0) { - interpCounter = linearInterpLength; - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; - oldfv = fv; - fu = (a*oneoverc); - fv = (b*oneoverc); - //oldu = u; oldv = v; - fiu = oldfu; - fiv = oldfv; - fdeltaU = (fu-oldfu)/linearInterpLength; - fdeltaV = (fv-oldfv)/linearInterpLength; - } - else{ - fiu += fdeltaU; - fiv += fdeltaV; - } - interpCounter--; - iu = (int)(fiu); iv = (int)(fiv);*/ - - } - - // try-catch just in case pixel offset is out of range - try{ - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - m_zbuffer[xstart] = iz; - if (m_bilinear) { - //We could (should?) add bounds checking on iu and iv here (keep in mind the 16 bit shift!). - //This would also be the place to add looping texture mode (bounds check == clamped). - //For looping/clamped textures, we'd also need to change PGraphics.textureVertex() to remove - //the texture range check there (it constrains normalized texture coordinates from 0->1). - - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - //if(ofs < 0) { ofs += TEX_WIDTH; } - //if(ofs > m_texture.length-2) {ofs -= TEX_WIDTH; } - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; //quick hack to thwart exceptions - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - int red = up + (((dn-up) * ivi) >> 7); - if (tint) red = ((red * rtint) >> 8) & 0xFF0000; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - int grn = up + (((dn-up) * ivi) >> 7); - if (tint) grn = ((grn * gtint) >> 8) & 0xFF00; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - int blu = up + (((dn-up) * ivi) >> 7); - if (tint) blu = ((blu * btint) >> 8) & 0xFF; - - //m_pixels[xstart] = (red & 0xFF0000) | (grn & 0xFF00) | (blu & 0xFF); - m_pixels[xstart] = 0xFF000000 | - (red & 0xFF0000) | (grn & 0xFF00) | (blu & 0xFF); - - } else { - m_pixels[xstart] = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - } -// m_stencil[xstart] = p; - } - } catch (Exception e) {/*exCount++;*/} - iz+=izadd; - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - } - ypixel++; //accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - zleft+=zleftadd; - uleft+=uleftadd; - vleft+=vleftadd; - } - //if (exCount>0) System.out.println(exCount+" exceptions in this segment"); - } - - - /** - * Alpha 24-bit texture - */ - private void drawsegment_texture24_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - boolean tint = (m_fill & 0xFFFFFF) != 0xFFFFFF; - int rtint = (m_fill >> 16) & 0xff; - int gtint = (m_fill >> 8) & 0xff; - int btint = m_fill & 0xFF; - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - // get alpha - int al = ia >> 16; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - int red = up + (((dn-up) * ivi) >> 7); - if (tint) red = ((red * rtint) >> 8) & 0xFF0000; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - int grn = up + (((dn-up) * ivi) >> 7); - if (tint) grn = ((grn * gtint) >> 8) & 0xFF00; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - int blu = up + (((dn-up) * ivi) >> 7); - if (tint) blu = ((blu * btint) >> 8) & 0xFF; - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - - } else { - int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - int grn = red & 0xFF00; - int blu = red & 0xFF; - red&=0xFF0000; - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - - xpixel++; // accurate mode - if (!accurateMode){ - iu += iuadd; - iv += ivadd; - } - ia+=iaadd; - iz+=izadd; - } - ypixel++; // accurate mode - - ytop+=SCREEN_WIDTH; - - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - zleft+=zleftadd; - aleft+=aleftadd; - } - } - - /** - * Plain 32-bit texutre - */ - private void drawsegment_texture32(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop*=SCREEN_WIDTH; - ybottom*=SCREEN_WIDTH; -// int p = m_index; - - boolean tint = m_fill != 0xFFFFFFFF; - int rtint = (m_fill >> 16) & 0xff; - int gtint = (m_fill >> 8) & 0xff; - int btint = m_fill & 0xFF; - - float iuf = iuadd; - float ivf = ivadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - // try-catch just in case pixel offset it out of range - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - int red = up + (((dn-up) * ivi) >> 7); - if (tint) red = ((red * rtint) >> 8) & 0xFF0000; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - int grn = up + (((dn-up) * ivi) >> 7); - if (tint) grn = ((grn * gtint) >> 8) & 0xFF00; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - int blu = up + (((dn-up) * ivi) >> 7); - if (tint) blu = ((blu * btint) >> 8) & 0xFF; - - // alpha - pix0>>>=24; - pix2>>>=24; - up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7); - dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7); - int al = up + (((dn-up) * ivi) >> 7); - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } else { - int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - int al = red >>> 24; - int grn = red & 0xFF00; - int blu = red & 0xFF; - red&=0xFF0000; - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - iz+=izadd; - } - ypixel++;//accurate mode - - ytop+=SCREEN_WIDTH; - - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - zleft+=zleftadd; - aleft+=aleftadd; - } - - - } - - /** - * Alpha 32-bit texutre - */ - private void drawsegment_texture32_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - boolean tint = (m_fill & 0xFFFFFF) != 0xFFFFFF; - int rtint = (m_fill >> 16) & 0xff; - int gtint = (m_fill >> 8) & 0xff; - int btint = m_fill & 0xFF; - - float iuf = iuadd; - float ivf = ivadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - - float xdiff = (xstart + PIXEL_CENTER) - xleft; - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - // try-catch just in case pixel offset it out of range - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - // get alpha - int al = ia >> 16; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - int red = up + (((dn-up) * ivi) >> 7); - if (tint) red = ((red * rtint) >> 8) & 0xFF0000; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - int grn = up + (((dn-up) * ivi) >> 7); - if (tint) grn = ((grn * gtint) >> 8) & 0xFF00; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - int blu = up + (((dn-up) * ivi) >> 7); - if (tint) blu = ((blu * btint) >> 8) & 0xFF; - - // alpha - pix0>>>=24; - pix2>>>=24; - up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7); - dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7); - al = al * (up + (((dn-up) * ivi) >> 7)) >> 8; - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } else { - int red = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - al = al * (red >>> 24) >> 8; - int grn = red & 0xFF00; - int blu = red & 0xFF; - red&=0xFF0000; - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ia+=iaadd; - iz+=izadd; - } - ypixel++;//accurate mode - - ytop+=SCREEN_WIDTH; - - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - zleft+=zleftadd; - aleft+=aleftadd; - } - - - } - - - /** - * Gouraud blended with 8-bit alpha texture - */ - private void drawsegment_gouraud_texture8(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - try - { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - int al0; - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = iu & 0xFFFF; - al0 = m_texture[ofs] & 0xFF; - int al1 = m_texture[ofs + 1] & 0xFF; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int al2 = m_texture[ofs] & 0xFF; - int al3 = m_texture[ofs + 1] & 0xFF; - al0 = al0 + (((al1-al0) * iui) >> 16); - al2 = al2 + (((al3-al2) * iui) >> 16); - al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16); - } else { - al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF; - } - - // get RGB colors - int red = ir & 0xFF0000; - int grn = (ig >> 8) & 0xFF00; - int blu = (ib >> 16); - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al0) >> 8)) & 0xFF); - - // write stencil -// m_stencil[xstart] = p; - } - } - catch (Exception e) { - - } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - iz+=izadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - zleft+=zleftadd; - } - } - - - /** - * Texture multiplied with gouraud - */ - private void drawsegment_gouraud_texture8_alpha(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - // Accurate texture mode added - comments stripped from dupe code, - // see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode) { - // see if the precomputation goes well, if so finish the setup - if (precomputeAccurateTexturing()) { - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - // if the matrix inversion screwed up, - // revert to normal rendering (something is degenerate) - accurateMode = false; - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - int al0; - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = iu & 0xFFFF; - al0 = m_texture[ofs] & 0xFF; - int al1 = m_texture[ofs + 1] & 0xFF; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int al2 = m_texture[ofs] & 0xFF; - int al3 = m_texture[ofs + 1] & 0xFF; - al0 = al0 + (((al1-al0) * iui) >> 16); - al2 = al2 + (((al3-al2) * iui) >> 16); - al0 = al0 + (((al2-al0) * (iv & 0xFFFF)) >> 16); - } else { - al0 = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)] & 0xFF; - } - al0 = (al0 * (ia >> 16)) >> 8; - - // get RGB colors - int red = ir & 0xFF0000; - int grn = (ig >> 8) & 0xFF00; - int blu = (ib >> 16); - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al0) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al0) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al0) >> 8)) & 0xFF); - - // write stencil -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - ia+=iaadd; - iz+=izadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - aleft+=aleftadd; - zleft+=zleftadd; - } - } - - - /** - * Texture multiplied with gouraud - */ - private void drawsegment_gouraud_texture24(float leftadd, - float rghtadd, - int ytop, - int ybottom) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - m_zbuffer[xstart] = iz; - - int red; - int grn; - int blu; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - red = up + (((dn-up) * ivi) >> 7); - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - grn = up + (((dn-up) * ivi) >> 7); - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - blu = up + (((dn-up) * ivi) >> 7); - } else { - // get texture pixel color - blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - red = (blu & 0xFF0000); - grn = (blu & 0xFF00); - blu = blu & 0xFF; - } - - // - int r = (ir >> 16); - int g = (ig >> 16); - // oops, namespace collision with accurate - // texture vector b...sorry [ewjordan] - int bb2 = (ib >> 16); - - m_pixels[xstart] = 0xFF000000 | - ((((red * r) & 0xFF000000) | ((grn * g) & 0xFF0000) | (blu * bb2)) >> 8); -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - iz+=izadd; - } - ypixel++;//accurate mode - - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - zleft+=zleftadd; - } - } - - - /** - * Gouraud*texture blended with interpolating alpha - */ - private void drawsegment_gouraud_texture24_alpha - ( - float leftadd, - float rghtadd, - int ytop, - int ybottom - ) { - - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ;xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - // get texture pixel color - try - { - //if (iz < m_zbuffer[xstart]) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { // [fry 041114] - //m_zbuffer[xstart] = iz; - - // blend - int al = ia >> 16; - - int red; - int grn; - int blu; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - red = (up + (((dn-up) * ivi) >> 7)) >> 16; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - grn = (up + (((dn-up) * ivi) >> 7)) >> 8; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - blu = up + (((dn-up) * ivi) >> 7); - } else { - blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - red = (blu & 0xFF0000) >> 16; // 0 - 255 - grn = (blu & 0xFF00) >> 8; // 0 - 255 - blu = (blu & 0xFF); // 0 - 255 - } - - // multiply with gouraud color - red = (red * ir) >>> 8; // 0x00FF???? - grn = (grn * ig) >>> 16; // 0x0000FF?? - blu = (blu * ib) >>> 24; // 0x000000FF - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - - // - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); -// m_stencil[xstart] = p; - } - } - catch (Exception e) { - } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - ia+=iaadd; - iz+=izadd; - } - - ypixel++;//accurate mode - - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - aleft+=aleftadd; - zleft+=zleftadd; - } - } - - - /** - * Gouraud*texture blended with interpolating alpha - */ - private void drawsegment_gouraud_texture32 - ( - float leftadd, - float rghtadd, - int ytop, - int ybottom - ) { - - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop*=SCREEN_WIDTH; - ybottom*=SCREEN_WIDTH; - //int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - - for ( ; xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - try { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { - //m_zbuffer[xstart] = iz; - - int red; - int grn; - int blu; - int al; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - red = (up + (((dn-up) * ivi) >> 7)) >> 16; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - grn = (up + (((dn-up) * ivi) >> 7)) >> 8; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - blu = up + (((dn-up) * ivi) >> 7); - - // alpha - pix0>>>=24; - pix2>>>=24; - up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7); - dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7); - al = up + (((dn-up) * ivi) >> 7); - } else { - // get texture pixel color - blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - al = (blu >>> 24); - red = (blu & 0xFF0000) >> 16; - grn = (blu & 0xFF00) >> 8; - blu = blu & 0xFF; - } - - // multiply with gouraud color - red = (red * ir) >>> 8; // 0x00FF???? - grn = (grn * ig) >>> 16; // 0x0000FF?? - blu = (blu * ib) >>> 24; // 0x000000FF - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - - // - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); - } - } catch (Exception e) { } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - iz+=izadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - zleft+=zleftadd; - } - } - - - /** - * Gouraud*texture blended with interpolating alpha - */ - private void drawsegment_gouraud_texture32_alpha - ( - float leftadd, - float rghtadd, - int ytop, - int ybottom - ) { - //Accurate texture mode added - comments stripped from dupe code, see drawsegment_texture24() for details - int ypixel = ytop; - int lastRowStart = m_texture.length - TEX_WIDTH - 2; - boolean accurateMode = parent.hints[ENABLE_ACCURATE_TEXTURES]; - float screenx = 0; float screeny = 0; float screenz = 0; - float a = 0; float b = 0; float c = 0; - int linearInterpPower = TEX_INTERP_POWER; - int linearInterpLength = 1 << linearInterpPower; - if (accurateMode){ - if(precomputeAccurateTexturing()){ //see if the precomputation goes well, if so finish the setup - newax *= linearInterpLength; - newbx *= linearInterpLength; - newcx *= linearInterpLength; - screenz = nearPlaneDepth; - firstSegment = false; - } else{ - accurateMode = false; //if the matrix inversion screwed up, revert to normal rendering (something is degenerate) - } - } - - ytop *= SCREEN_WIDTH; - ybottom *= SCREEN_WIDTH; -// int p = m_index; - - float iuf = iuadd; - float ivf = ivadd; - float irf = iradd; - float igf = igadd; - float ibf = ibadd; - float iaf = iaadd; - - while (ytop < ybottom) { - int xstart = (int) (xleft + PIXEL_CENTER); - if (xstart < 0) - xstart = 0; - - int xpixel = xstart;//accurate mode - - int xend = (int) (xrght + PIXEL_CENTER); - if (xend > SCREEN_WIDTH) - xend = SCREEN_WIDTH; - float xdiff = (xstart + PIXEL_CENTER) - xleft; - - int iu = (int) (iuf * xdiff + uleft); - int iv = (int) (ivf * xdiff + vleft); - int ir = (int) (irf * xdiff + rleft); - int ig = (int) (igf * xdiff + gleft); - int ib = (int) (ibf * xdiff + bleft); - int ia = (int) (iaf * xdiff + aleft); - float iz = izadd * xdiff + zleft; - - xstart+=ytop; - xend+=ytop; - if (accurateMode){ - screenx = xmult*(xpixel+.5f-(SCREEN_WIDTH/2.0f)); - screeny = ymult*(ypixel+.5f-(SCREEN_HEIGHT/2.0f)); - a = screenx*ax+screeny*ay+screenz*az; - b = screenx*bx+screeny*by+screenz*bz; - c = screenx*cx+screeny*cy+screenz*cz; - } - boolean goingIn = ( (newcx > 0) == (c > 0) )?false:true; - int interpCounter = 0; - int deltaU = 0; int deltaV = 0; - float fu = 0; float fv = 0; - float oldfu = 0; float oldfv = 0; - - if (accurateMode&&goingIn){ - int rightOffset = (xend-xstart-1)%linearInterpLength; - int leftOffset = linearInterpLength-rightOffset; - float rightOffset2 = rightOffset / ((float)linearInterpLength); - float leftOffset2 = leftOffset / ((float)linearInterpLength); - interpCounter = leftOffset; - float ao = a-leftOffset2*newax; - float bo = b-leftOffset2*newbx; - float co = c-leftOffset2*newcx; - float oneoverc = 65536.0f/co; - oldfu = (ao*oneoverc); oldfv = (bo*oneoverc); - a += rightOffset2*newax; - b += rightOffset2*newbx; - c += rightOffset2*newcx; - oneoverc = 65536.0f/c; - fu = a*oneoverc; fv = b*oneoverc; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - iu = ( (int)oldfu )+(leftOffset-1)*deltaU; iv = ( (int)oldfv )+(leftOffset-1)*deltaV; //another "off-by-one" hack - } else{ - float preoneoverc = 65536.0f/c; - fu = (a*preoneoverc); - fv = (b*preoneoverc); - } - - for ( ;xstart < xend; xstart++ ) { - if(accurateMode){ - if (interpCounter == linearInterpLength) interpCounter = 0; - if (interpCounter == 0){ - a += newax; - b += newbx; - c += newcx; - float oneoverc = 65536.0f/c; - oldfu = fu; oldfv = fv; - fu = (a*oneoverc); fv = (b*oneoverc); - iu = (int)oldfu; iv = (int)oldfv; - deltaU = ((int)(fu - oldfu)) >> linearInterpPower; - deltaV = ((int)(fv - oldfv)) >> linearInterpPower; - } else{ - iu += deltaU; - iv += deltaV; - } - interpCounter++; - } - - // get texture pixel color - try { - //if (iz < m_zbuffer[xstart]) { - if (noDepthTest || (iz <= m_zbuffer[xstart])) { // [fry 041114] - //m_zbuffer[xstart] = iz; - - // blend - int al = ia >> 16; - - int red; - int grn; - int blu; - - if (m_bilinear) { - int ofs = (iv >> 16) * TEX_WIDTH + (iu >> 16); - int iui = (iu & 0xFFFF) >> 9; - int ivi = (iv & 0xFFFF) >> 9; - - // get texture pixels - int pix0 = m_texture[ofs]; - int pix1 = m_texture[ofs + 1]; - if (ofs < lastRowStart) ofs+=TEX_WIDTH; - int pix2 = m_texture[ofs]; - int pix3 = m_texture[ofs + 1]; - - // red - int red0 = (pix0 & 0xFF0000); - int red2 = (pix2 & 0xFF0000); - int up = red0 + ((((pix1 & 0xFF0000) - red0) * iui) >> 7); - int dn = red2 + ((((pix3 & 0xFF0000) - red2) * iui) >> 7); - red = (up + (((dn-up) * ivi) >> 7)) >> 16; - - // grn - red0 = (pix0 & 0xFF00); - red2 = (pix2 & 0xFF00); - up = red0 + ((((pix1 & 0xFF00) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF00) - red2) * iui) >> 7); - grn = (up + (((dn-up) * ivi) >> 7)) >> 8; - - // blu - red0 = (pix0 & 0xFF); - red2 = (pix2 & 0xFF); - up = red0 + ((((pix1 & 0xFF) - red0) * iui) >> 7); - dn = red2 + ((((pix3 & 0xFF) - red2) * iui) >> 7); - blu = up + (((dn-up) * ivi) >> 7); - - // alpha - pix0>>>=24; - pix2>>>=24; - up = pix0 + ((((pix1 >>> 24) - pix0) * iui) >> 7); - dn = pix2 + ((((pix3 >>> 24) - pix2) * iui) >> 7); - al = al * (up + (((dn-up) * ivi) >> 7)) >> 8; - } else { - blu = m_texture[(iv >> 16) * TEX_WIDTH + (iu >> 16)]; - al = al * (blu >>> 24) >> 8; - red = (blu & 0xFF0000) >> 16; // 0 - 255 - grn = (blu & 0xFF00) >> 8; // 0 - 255 - blu = (blu & 0xFF); // 0 - 255 - } - - // multiply with gouraud color - red = (red * ir) >>> 8; // 0x00FF???? - grn = (grn * ig) >>> 16; // 0x0000FF?? - blu = (blu * ib) >>> 24; // 0x000000FF - - // get buffer pixels - int bb = m_pixels[xstart]; - int br = (bb & 0xFF0000); // 0x00FF0000 - int bg = (bb & 0xFF00); // 0x0000FF00 - bb = (bb & 0xFF); // 0x000000FF - - // - m_pixels[xstart] = 0xFF000000 | - ((br + (((red - br) * al) >> 8)) & 0xFF0000) | - ((bg + (((grn - bg) * al) >> 8)) & 0xFF00) | - ((bb + (((blu - bb) * al) >> 8)) & 0xFF); -// m_stencil[xstart] = p; - } - } catch (Exception e) { } - - // - xpixel++;//accurate mode - if (!accurateMode){ - iu+=iuadd; - iv+=ivadd; - } - ir+=iradd; - ig+=igadd; - ib+=ibadd; - ia+=iaadd; - iz+=izadd; - } - ypixel++;//accurate mode - ytop+=SCREEN_WIDTH; - xleft+=leftadd; - xrght+=rghtadd; - uleft+=uleftadd; - vleft+=vleftadd; - rleft+=rleftadd; - gleft+=gleftadd; - bleft+=bleftadd; - aleft+=aleftadd; - zleft+=zleftadd; - } - } -}