/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2011 Andreas Maschke
This 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 software 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 software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.transform;
import org.jwildfire.image.SimpleImage;
import org.jwildfire.transform.Mesh3DTransformer.Faces;
import org.jwildfire.transform.Mesh3DTransformer.Light;
public class Simple3DRenderer extends Mesh3DRenderer {
@Override
public void renderImage(Mesh3D pMesh3D, Mesh3DTransformer pMesh3DTransformer, SimpleImage pImg) {
init(pMesh3D, pMesh3DTransformer, pImg);
viewz = 1.0;
for (int i = 0; i < f3Count; i++) {
int p1 = p31[i];
int p2 = p32[i];
int p3 = p33[i];
fZSortArray[i] = 0.0 - (z[p1] + z[p2] + z[p3]) * 0.33;
fInd[i] = i;
}
heapSortFloat1(fZSortArray, fInd, f3Count);
for (int i = 0; i < f3Count; i++) {
int p1 = p31[fInd[i]];
int p2 = p32[fInd[i]];
int p3 = p33[fInd[i]];
double x1 = cx + x[p1];
double y1 = cy + y[p1];
double z1 = z[p1];
double x2 = cx + x[p2];
double y2 = cy + y[p2];
double z2 = z[p2];
double x3 = cx + x[p3];
double y3 = cy + y[p3];
double z3 = z[p3];
lux = (int) (x1 + 0.5);
luy = (int) (y1 + 0.5);
luz = (int) (z1 + 0.5);
rux = (int) (x2 + 0.5);
ruy = (int) (y2 + 0.5);
ruz = (int) (z2 + 0.5);
rbx = (int) (x3 + 0.5);
rby = (int) (y3 + 0.5);
rbz = (int) (z3 + 0.5);
double vax = x2 - x1;
double vay = y2 - y1;
double vaz = z2 - z1;
double vbx = x3 - x1;
double vby = y3 - y1;
double vbz = z3 - z1;
nfx = vay * vbz - vaz * vby;
nfy = vaz * vbx - vax * vbz;
nfz = vax * vby - vay * vbx;
rr = Math.sqrt(nfx * nfx + nfy * nfy + nfz * nfz);
if (Math.abs(rr) <= PZERO) {
nfx = nfy = 0.0;
nfz = -1.0;
}
else {
nfx = 0.0 - nfx / rr;
nfy = 0.0 - nfy / rr;
nfz = 0.0 - nfz / rr;
}
if (faces == Faces.MIRRORED) {
nfx = 0.0 - nfx;
nfy = 0.0 - nfy;
nfz = 0.0 - nfz;
}
reflectViewVector();
cosa = 0.0 - nfz;
if ((faces == Faces.DOUBLE) && (cosa >= 0.0)) {
nfx = 0.0 - nfx;
nfy = 0.0 - nfy;
nfz = 0.0 - nfz;
reflectViewVector();
cosa = 0.0 - nfz;
}
if (cosa < 0.0) {
if (u != null) {
int px = (int) (u[p1] * texture.getImageWidth() + 0.5);
int py = (int) (v[p1] * texture.getImageHeight() + 0.5);
toolPixel.setARGBValue(texture.getARGBValueIgnoreBounds(px, py));
}
else {
toolPixel.setARGBValue(coloro[fInd[i]]);
}
r = toolPixel.r;
g = toolPixel.g;
b = toolPixel.b;
/* fill the transformed rectangle */
/* create the edges */
/* 1->2 */
if (p1 < p2) {
n12 = bresenham3D(lux, luy, luz, rux, ruy, ruz, x12, y12, z12);
}
else {
n12 = bresenham3D(rux, ruy, ruz, lux, luy, luz, x12, y12, z12);
}
/* 2->3 */
if (p2 < p3) {
n23 = bresenham3D(rux, ruy, ruz, rbx, rby, rbz, x23, y23, z23);
}
else {
n23 = bresenham3D(rbx, rby, rbz, rux, ruy, ruz, x23, y23, z23);
}
/* 3->1 */
if (p3 < p1) {
n41 = bresenham3D(rbx, rby, rbz, lux, luy, luz, x41, y41, z41);
}
else {
n41 = bresenham3D(lux, luy, luz, rbx, rby, rbz, x41, y41, z41);
}
/* create the bounding box */
int xmin, xmax;
xmin = xmax = lux;
if (rux < xmin)
xmin = rux;
else if (rux > xmax)
xmax = rux;
if (rbx < xmin)
xmin = rbx;
else if (rbx > xmax)
xmax = rbx;
int ymin, ymax;
ymin = ymax = luy;
if (ruy < ymin)
ymin = ruy;
else if (ruy > ymax)
ymax = ruy;
if (rby < ymin)
ymin = rby;
else if (rby > ymax)
ymax = rby;
/* fill the area */
for (k = ymin; k <= ymax; k++) {
if ((k >= 0) && (k < height)) {
rFill3();
double zs;
int zz = zMin;
if (min != max)
zs = (double) (zMax - zMin) / (double) (max - min);
else
zs = 0.0;
for (int l = min; l <= max; l++) {
if ((l >= 0) && (l < width)) {
if (doLight != Light.OFF) {
addLight((double) l, (double) k, zz);
}
else {
pr = r;
pg = g;
pb = b;
}
pImg.setRGB(l, k, pr, pg, pb);
}
zz += zs;
}
}
} /* k loop */
} /* cosa */
}/* loop */
}
}