/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.graphics.RE.software; import static java.lang.System.arraycopy; import static jpcsp.graphics.RE.software.PixelColor.getColor; import static jpcsp.util.Utilities.normalize3; import static jpcsp.util.Utilities.round; import static jpcsp.util.Utilities.vectorMult33; import static jpcsp.util.Utilities.vectorMult34; /** * @author gid15 * */ public final class PixelState { public int materialAmbient; public int materialDiffuse; public int materialSpecular; public boolean hasNormal; private boolean computedV; private boolean computedN; private boolean computedNormalizedN; private boolean computedVe; private boolean computedNe; private boolean computedNormalizedNe; private final float[] V = new float[] { 0.f, 0.f, 0.f, 1.f }; private final float[] Ve = new float[3]; private final float[] N = new float[] { 0.f, 0.f, 1.f }; private final float[] normalizedN = new float[] { 0.f, 0.f, 1.f }; private final float[] Ne = new float[] { 0.f, 0.f, 1.f }; private final float[] normalizedNe = new float[] { 0.f, 0.f, 1.f }; public float v1x, v1y, v1z; public float v2x, v2y, v2z; public float v3x, v3y, v3z; public float n1x, n1y, n1z; public float n2x, n2y, n2z; public float n3x, n3y, n3z; public int c1a, c1b, c1g, c1r; public int c2a, c2b, c2g, c2r; public int c3a, c3b, c3g, c3r, c3; public final float[] textureMatrix = new float[16]; public final float[] modelViewMatrix = new float[16]; public final float[] modelViewProjectionMatrix = new float[16]; public final float[] normalMatrix = new float[16]; private int numberPixels; public float triangleWeight1; public float triangleWeight2; public float triangleWeight3; protected void copy(PixelState from) { materialAmbient = from.materialAmbient; materialDiffuse = from.materialDiffuse; materialSpecular = from.materialSpecular; hasNormal = from.hasNormal; v1x = from.v1x; v1y = from.v1y; v1z = from.v1z; v2x = from.v2x; v2y = from.v2y; v2z = from.v2z; v3x = from.v3x; v3y = from.v3y; v3z = from.v3z; n1x = from.n1x; n1y = from.n1y; n1z = from.n1z; n2x = from.n2x; n2y = from.n2y; n2z = from.n2z; n3x = from.n3x; n3y = from.n3y; n3z = from.n3z; c1a = from.c1a; c1b = from.c1b; c1g = from.c1g; c1r = from.c1r; c2a = from.c2a; c2b = from.c2b; c2g = from.c2g; c2r = from.c2r; c3a = from.c3a; c3b = from.c3b; c3g = from.c3g; c3r = from.c3r; c3 = from.c3; arraycopy(from.textureMatrix, 0, textureMatrix, 0, textureMatrix.length); arraycopy(from.modelViewMatrix, 0, modelViewMatrix, 0, modelViewMatrix.length); arraycopy(from.modelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, modelViewProjectionMatrix.length); if (hasNormal) { arraycopy(from.normalMatrix, 0, normalMatrix, 0, normalMatrix.length); } } public float getTriangleWeightedValue(float value1, float value2, float value3) { return triangleWeight1 * value1 + triangleWeight2 * value2 + triangleWeight3 * value3; } public int getTriangleWeightedValue(int value1, int value2, int value3) { return round(triangleWeight1 * value1 + triangleWeight2 * value2 + triangleWeight3 * value3); } public int getTriangleColorWeightedValue() { int a = getTriangleWeightedValue(c1a, c2a, c3a); int b = getTriangleWeightedValue(c1b, c2b, c3b); int g = getTriangleWeightedValue(c1g, c2g, c3g); int r = getTriangleWeightedValue(c1r, c2r, c3r); return getColor(a, b, g, r); } public boolean isInsideTriangle() { final float limit = -1e-5f; // The limit should be 0.0f. Allowing small rounding errors. return triangleWeight1 >= limit && triangleWeight2 >= limit && triangleWeight3 >= limit; } public void newPixel2D() { numberPixels++; } public void newPixel3D() { newPixel2D(); computedV = false; computedN = false; computedNormalizedN = false; computedVe = false; computedNe = false; computedNormalizedNe = false; } public void reset() { numberPixels = 0; } public int getNumberPixels() { return numberPixels; } private void computeV() { if (!computedV) { V[0] = getTriangleWeightedValue(v1x, v2x, v3x); V[1] = getTriangleWeightedValue(v1y, v2y, v3y); V[2] = getTriangleWeightedValue(v1z, v2z, v3z); computedV = true; } } public float[] getV() { computeV(); return V; } public void getV(float[] V) { computeV(); V[0] = this.V[0]; V[1] = this.V[1]; V[2] = this.V[2]; } private void computeN() { if (!computedN && hasNormal) { N[0] = getTriangleWeightedValue(n1x, n2x, n3x); N[1] = getTriangleWeightedValue(n1y, n2y, n3y); N[2] = getTriangleWeightedValue(n1z, n2z, n3z); computedN = true; } } public float[] getN() { computeN(); return N; } public void getN(float[] N) { computeN(); N[0] = this.N[0]; N[1] = this.N[1]; N[2] = this.N[2]; } private void computeNormalizedN() { if (!computedNormalizedN && hasNormal) { computeN(); normalize3(normalizedN, N); computedNormalizedN = true; } } public float[] getNormalizedN() { computeNormalizedN(); return normalizedN; } public void getNormalizedN(float[] normalizedN) { computeNormalizedN(); normalizedN[0] = this.normalizedN[0]; normalizedN[1] = this.normalizedN[1]; normalizedN[2] = this.normalizedN[2]; } private void computeVe() { if (!computedVe) { computeV(); vectorMult34(Ve, modelViewMatrix, V); computedVe = true; } } public void getVe(float[] Ve) { computeVe(); Ve[0] = this.Ve[0]; Ve[1] = this.Ve[1]; Ve[2] = this.Ve[2]; } private void computeNe() { if (!computedNe && hasNormal) { computeN(); vectorMult33(Ne, normalMatrix, N); computedNe = true; } } public void getNe(float[] Ne) { computeNe(); Ne[0] = this.Ne[0]; Ne[1] = this.Ne[1]; Ne[2] = this.Ne[2]; } private void computeNormalizedNe() { if (!computedNormalizedNe && hasNormal) { computeNe(); normalize3(normalizedNe, Ne); computedNormalizedNe = true; } } public void getNormalizedNe(float[] normalizedNe) { computeNormalizedNe(); normalizedNe[0] = this.normalizedNe[0]; normalizedNe[1] = this.normalizedNe[1]; normalizedNe[2] = this.normalizedNe[2]; } }