/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is based on code from idx3dIII * Copyright 1999, 2000 Peter Walser * http://www.idx3d.ch/idx3d/idx3d.html * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME 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. * * JAME 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 JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.core.media.g3d; public class FastRasterizer extends Rasterizer { private Texture material_texture; private int material_transparency; private int material_reflectivity; private int material_color; private int[] texture_pixels; private int texture_width_mask; private int texture_height_mask; private int texture_wsize; private int triangle_id; private int[] pixels; private int[] zbuffer; private int[] idbuffer; private int[][] diffuse; private int[][] specular; private Vertex v; private Vertex p1; private Vertex p2; private Vertex p3; private int center_x; private int center_y; private int x1; private int x2; private int x3; private int x4; private int y1; private int y2; private int y3; private int z4; private int z1; private int z2; private int z3; private int nx1; private int nx2; private int nx3; private int nx4; private int ny1; private int ny2; private int ny3; private int ny4; private int tx1; private int tx2; private int tx3; private int tx4; private int ty1; private int ty2; private int ty3; private int ty4; private int dx; private int dy; private int dz; private int dnx; private int dny; private int dtx; private int dty; private int dxL; private int dxR; private int dzBase; private int dnxBase; private int dnyBase; private int dtxBase; private int dtyBase; private int xL; private int xR; private int xMax; private int xBase; private int zBase; private int nxBase; private int nyBase; private int txBase; private int tyBase; private int x; private int y; private int z; private int nx; private int ny; private int tx; private int ty; private int cnx; private int cny; private int cnz; private int offset; private int lutid; private int lutz; private int j; private int t; private int c; private int s; private int w; private int h; public FastRasterizer() { } @Override protected void render_triangle(final Triangle triangle, final Material material) { material_transparency = material.transparency; material_reflectivity = material.reflectivity; material_texture = material.texture; material_color = material.color; if (material_texture != null) { texture_pixels = material_texture.pixels; texture_width_mask = material_texture.width - 1; texture_height_mask = material_texture.height - 1; texture_wsize = material_texture.wsize; } triangle_id = triangle.id; pixels = pipeline.pixels; zbuffer = pipeline.zbuffer; idbuffer = pipeline.idbuffer; center_x = pipeline.center_x; center_y = pipeline.center_y; w = pipeline.w; h = pipeline.h; p1 = triangle.p1; p2 = triangle.p2; p3 = triangle.p3; if (p1.py > p2.py) { v = p1; p1 = p2; p2 = v; } if (p2.py > p3.py) { v = p2; p2 = p3; p3 = v; } if (p1.py > p2.py) { v = p1; p1 = p2; p2 = v; } x1 = p1.px + center_x; x2 = p2.px + center_x; x3 = p3.px + center_x; y1 = p1.py + center_y; y2 = p2.py + center_y; y3 = p3.py + center_y; if (y3 < 0) { return; } if (y1 >= h) { return; } if (y1 == y3) { return; } z1 = p1.pz; z2 = p2.pz; z3 = p3.pz; if ((z1 < 6553) || (z2 < 6553) || (z3 < 6553)) { return; } nx1 = p1.nx; nx2 = p2.nx; nx3 = p3.nx; ny1 = p1.ny; ny2 = p2.ny; ny3 = p3.ny; tx1 = p1.tx; tx2 = p2.tx; tx3 = p3.tx; ty1 = p1.ty; ty2 = p2.ty; ty3 = p3.ty; cnx = triangle.nx; cny = triangle.ny; cnz = triangle.nz; if (triangle.cosine > 0) { nx1 = 254 - nx1; ny1 = 254 - ny1; nx2 = 254 - nx2; ny2 = 254 - ny2; nx3 = 254 - nx3; ny3 = 254 - ny3; cnx = 254 - cnx; cny = 254 - cny; cnz = -cnz; } diffuse = pipeline.diffuse; specular = pipeline.specular; if (cnz > 0) { lutz = 0; } else { lutz = 1; } x1 <<= 8; x2 <<= 8; x3 <<= 8; nx1 <<= 8; nx2 <<= 8; nx3 <<= 8; ny1 <<= 8; ny2 <<= 8; ny3 <<= 8; tx1 <<= 8; tx2 <<= 8; tx3 <<= 8; ty1 <<= 8; ty2 <<= 8; ty3 <<= 8; x4 = x1 + (((x3 - x1) * (y2 - y1)) / (y3 - y1)); z4 = z1 + (((z3 - z1) * (y2 - y1)) / (y3 - y1)); nx4 = nx1 + (((nx3 - nx1) * (y2 - y1)) / (y3 - y1)); ny4 = ny1 + (((ny3 - ny1) * (y2 - y1)) / (y3 - y1)); tx4 = tx1 + (((tx3 - tx1) * (y2 - y1)) / (y3 - y1)); ty4 = ty1 + (((ty3 - ty1) * (y2 - y1)) / (y3 - y1)); x1 <<= 8; x2 <<= 8; x3 <<= 8; x4 <<= 8; nx1 <<= 8; nx2 <<= 8; nx3 <<= 8; nx4 <<= 8; ny1 <<= 8; ny2 <<= 8; ny3 <<= 8; ny4 <<= 8; tx1 <<= 8; tx2 <<= 8; tx3 <<= 8; tx4 <<= 8; ty1 <<= 8; ty2 <<= 8; ty3 <<= 8; ty4 <<= 8; dx = (x4 - x2) >> 16; if (dx == 0) { return; } dz = (z4 - z2) / dx; dnx = (nx4 - nx2) / dx; dny = (ny4 - ny2) / dx; dtx = (tx4 - tx2) / dx; dty = (ty4 - ty2) / dx; dxL = 0; dxR = 0; dzBase = 0; dnxBase = 0; dnyBase = 0; dtxBase = 0; dtyBase = 0; if (dx < 0) { t = x2; x2 = x4; x4 = t; t = z2; z2 = z4; z4 = t; t = nx2; nx2 = nx4; nx4 = t; t = ny2; ny2 = ny4; ny4 = t; t = tx2; tx2 = tx4; tx4 = t; t = ty2; ty2 = ty4; ty4 = t; } if (y2 >= 0) { dy = y2 - y1; if (dy != 0) { dxL = (x2 - x1) / dy; dxR = (x4 - x1) / dy; dzBase = (z2 - z1) / dy; dnxBase = (nx2 - nx1) / dy; dnyBase = (ny2 - ny1) / dy; dtxBase = (tx2 - tx1) / dy; dtyBase = (ty2 - ty1) / dy; } xMax = x1; xBase = x1; zBase = z1; nxBase = nx1; nyBase = ny1; txBase = tx1; tyBase = ty1; if (y1 < 0) { xMax -= (y1 * dxR); xBase -= (y1 * dxL); zBase -= (y1 * dzBase); nxBase -= (y1 * dnxBase); nyBase -= (y1 * dnyBase); txBase -= (y1 * dtxBase); tyBase -= (y1 * dtyBase); y1 = 0; } offset = y1 * w; y2 = (y2 < h) ? y2 : h; for (y = y1; y < y2; y++) { xL = xBase >> 16; xR = xMax >> 16; z = zBase; nx = nxBase; ny = nyBase; tx = txBase; ty = tyBase; if (xL < 0) { z -= (xL * dz); nx -= (xL * dnx); ny -= (xL * dny); tx -= (xL * dtx); ty -= (xL * dty); xL = 0; } xR = (xR < w) ? xR : w; render_line(xL, xR); offset += w; xMax += dxR; xBase += dxL; zBase += dzBase; nxBase += dnxBase; nyBase += dnyBase; txBase += dtxBase; tyBase += dtyBase; } } if (y2 < h) { dy = y3 - y2; if (dy != 0) { dxL = (x3 - x2) / dy; dxR = (x3 - x4) / dy; dzBase = (z3 - z2) / dy; dnxBase = (nx3 - nx2) / dy; dnyBase = (ny3 - ny2) / dy; dtxBase = (tx3 - tx2) / dy; dtyBase = (ty3 - ty2) / dy; } xMax = x4; xBase = x2; zBase = z2; nxBase = nx2; nyBase = ny2; txBase = tx2; tyBase = ty2; if (y2 < 0) { xMax -= (y2 * dxR); xBase -= (y2 * dxL); zBase -= (y2 * dzBase); nxBase -= (y2 * dnxBase); nyBase -= (y2 * dnyBase); txBase -= (y2 * dtxBase); tyBase -= (y2 * dtyBase); y2 = 0; } offset = y2 * w; y3 = (y3 < h) ? y3 : h; for (y = y2; y < y3; y++) { xL = xBase >> 16; xR = xMax >> 16; z = zBase; nx = nxBase; ny = nyBase; tx = txBase; ty = tyBase; if (xL < 0) { z -= (xL * dz); nx -= (xL * dnx); ny -= (xL * dny); tx -= (xL * dtx); ty -= (xL * dty); xL = 0; } xR = (xR < w) ? xR : w; render_line(xL, xR); offset += w; xMax += dxR; xBase += dxL; zBase += dzBase; nxBase += dnxBase; nyBase += dnyBase; txBase += dtxBase; tyBase += dtyBase; } } } private void render_line(final int xL, final int xR) { if (pipeline.flat_shading) { if (pipeline.texture_mapping && (material_texture != null)) { render_lineFSTM(xL, xR); } else { render_lineFS(xL, xR); } } else { if (pipeline.texture_mapping && (material_texture != null)) { render_lineGSTM(xL, xR); } else { render_lineGS(xL, xR); } } } private void render_lineFSTM(final int xL, final int xR) { for (x = xL; x < xR; x++) { j = x + offset; if (z < zbuffer[j]) { c = texture_pixels[((tx >> 16) & texture_width_mask) + (((ty >> 16) & texture_height_mask) << texture_wsize)]; lutid = (cnx & 255) + ((cny & 255) << 8); c = Color.mul(c, diffuse[lutz][lutid]); c = Color.mix(c, pixels[j], material_transparency); s = Color.scale(specular[lutz][lutid], material_reflectivity); c = Color.add(c, s); zbuffer[j] = z; pixels[j] = c; idbuffer[j] = triangle_id; } z += dz; tx += dtx; ty += dty; } } private void render_lineFS(final int xL, final int xR) { for (x = xL; x < xR; x++) { j = x + offset; if (z < zbuffer[j]) { c = material_color; lutid = (cnx & 255) + ((cny & 255) << 8); c = Color.mul(c, diffuse[lutz][lutid]); c = Color.mix(c, pixels[j], material_transparency); s = Color.scale(specular[lutz][lutid], material_reflectivity); c = Color.add(c, s); zbuffer[j] = z; pixels[j] = c; idbuffer[j] = triangle_id; } z += dz; } } private void render_lineGSTM(final int xL, final int xR) { for (x = xL; x < xR; x++) { j = x + offset; if (z < zbuffer[j]) { c = texture_pixels[((tx >> 16) & texture_width_mask) + (((ty >> 16) & texture_height_mask) << texture_wsize)]; lutid = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8); c = Color.mul(c, diffuse[lutz][lutid]); c = Color.mix(c, pixels[j], material_transparency); s = Color.scale(specular[lutz][lutid], material_reflectivity); c = Color.add(c, s); zbuffer[j] = z; pixels[j] = c; idbuffer[j] = triangle_id; } z += dz; nx += dnx; ny += dny; tx += dtx; ty += dty; } } private void render_lineGS(final int xL, final int xR) { for (x = xL; x < xR; x++) { j = x + offset; if (z < zbuffer[j]) { c = material_color; lutid = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8); c = Color.mul(c, diffuse[lutz][lutid]); c = Color.mix(c, pixels[j], material_transparency); s = Color.scale(specular[lutz][lutid], material_reflectivity); c = Color.add(c, s); zbuffer[j] = z; pixels[j] = c; idbuffer[j] = triangle_id; } z += dz; nx += dnx; ny += dny; } } }