All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jmol.g3d.CylinderRenderer Maven / Gradle / Ivy

There is a newer version: 14.31.10
Show newest version
/* $RCSfile$
 * $Author: hansonr $
 * $Date: 2017-02-12 13:55:04 -0600 (Sun, 12 Feb 2017) $
 * $Revision: 21428 $
 *
 * Copyright (C) 2003-2006  Miguel, Jmol Development, www.jmol.org
 *
 * Contact: [email protected]
 *
 *  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.jmol.g3d;

import javajs.util.AU;
import javajs.util.P3;
import javajs.util.P3i;

import org.jmol.util.GData;
import org.jmol.util.Shader;

/**
 *

* Draws shaded cylinders in 3D. *

*

* Cylinders are used to draw bonds. *

* * @author Miguel, [email protected] */ class CylinderRenderer { private final Graphics3D g3d; private final LineRenderer line3d; private final Shader shader; CylinderRenderer(Graphics3D g3d) { this.g3d = g3d; line3d = g3d.line3d; shader = g3d.shader; } private short colixA, colixB; private int[] shadesA; private int[] shadesB; private int xA, yA, zA; private int dxB, dyB, dzB; private float xAf, yAf, zAf; private float dxBf, dyBf, dzBf; private boolean tEvenDiameter; //private int evenCorrection; private int diameter; private byte endcaps; private boolean endCapHidden; private int xEndcap, yEndcap, zEndcap; private int argbEndcap; private short colixEndcap; private int endcapShadeIndex; private float radius, radius2, cosTheta, cosPhi, sinPhi; private boolean clipped; private int rasterCount; private float[][] xyztRaster = new float[][] {new float[32], new float[32], new float[32], new float[32] }; private int[][] xyzfRaster = new int[][] {new int[32], new int[32], new int[32], new int[32]}; void renderOld(short colixA, short colixB, int screen, byte endcaps, int diameter, int xa, int ya, int za, int xb, int yb, int zb) { //0 for colixA or colixB means ignore for this pass int r = diameter / 2 + 1; //System.out.println("Cyl " + xa + " " + ya + " " + za + " " + xb + " " + yb + " " + zb + " " ); Graphics3D g = this.g3d; int codeMinA = g.clipCode3(xa - r, ya - r, za - r); int codeMaxA = g.clipCode3(xa + r, ya + r, za + r); int codeMinB = g.clipCode3(xb - r, yb - r, zb - r); int codeMaxB = g.clipCode3(xb + r, yb + r, zb + r); //all bits 0 --> no clipping int c = (codeMinA | codeMaxA | codeMinB | codeMaxB); clipped = (c != 0); //any two bits same in all cases --> fully clipped if (c == -1 || (codeMinA & codeMaxB & codeMaxA & codeMinB) != 0) return; // fully clipped; dxB = xb - xa; dyB = yb - ya; dzB = zb - za; if (diameter <= 1) { line3d.plotLineDeltaOld(g.getColorArgbOrGray(colixA), g .getColorArgbOrGray(colixB), xa, ya, za, dxB, dyB, dzB, clipped); return; } boolean drawBackside = (screen == 0 && (clipped || endcaps == GData.ENDCAPS_FLAT || endcaps == GData.ENDCAPS_NONE)); this.diameter = diameter; this.xA = xa; this.yA = ya; this.zA = za; this.endcaps = endcaps; shadesA = g.getShades(this.colixA = colixA); shadesB = g.getShades(this.colixB = colixB); calcArgbEndcap(true, false); // generate base ellipse calcCosSin(dxB, dyB, dzB); calcPoints(3, false); interpolate(0, 1, xyzfRaster, xyztRaster); interpolate(1, 2, xyzfRaster, xyztRaster); int[][] xyzf = xyzfRaster; if (endcaps == GData.ENDCAPS_FLAT) renderFlatEndcap(true, false, xyzf); g.setZMargin(5); int width = g.width; int[] zbuf = g.zbuf; int[] xr = xyzf[0]; int[] yr = xyzf[1]; int[] zr = xyzf[2]; int[] fr = xyzf[3]; Pixelator p = g.pixel; for (int i = rasterCount; --i >= 0;) { int fpz = fr[i] >> (8); int fpzBack = fpz >> 1; int x = xr[i]; int y = yr[i]; int z = zr[i]; if (endCapHidden && argbEndcap != 0) { if (clipped) { g.plotPixelClippedArgb(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelClippedArgb(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } else { g.plotPixelUnclipped(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelUnclipped(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } } line3d.plotLineDeltaAOld(shadesA, shadesB, screen, fpz, xA + x, yA + y, zA - z, dxB, dyB, dzB, clipped); if (drawBackside) { line3d.plotLineDeltaOld(shadesA[fpzBack], shadesB[fpzBack], xA - x, yA - y, zA + z, dxB, dyB, dzB,clipped); } } g.setZMargin(0); if (endcaps == GData.ENDCAPS_SPHERICAL) renderSphericalEndcaps(); } private P3 ptA0, ptB0; void renderBitsFloat(short colixA, short colixB, int screen, byte endcaps, int diameter, P3 ptA, P3 ptB) { Graphics3D g = this.g3d; // checked already // if (diameter == 0 || diameter == 1) { // line3d.plotLineBits(g.getColorArgbOrGray(colixA), g.getColorArgbOrGray(colixB), ptA, ptB); // return; // } if (ptA0 == null) { ptA0 = new P3(); ptB0 = new P3(); } ptA0.setT(ptA); // dipole cross, cartoonRockets, draw mesh nofill or width = -1 // oops -- problem here if diameter < 0 is that we may have already clipped it! int r = diameter / 2 + 1; int ixA = Math.round(ptA.x); int iyA = Math.round(ptA.y); int izA = Math.round(ptA.z); int ixB = Math.round(ptB.x); int iyB = Math.round(ptB.y); int izB = Math.round(ptB.z); int codeMinA = g.clipCode3(ixA - r, iyA - r, izA - r); int codeMaxA = g.clipCode3(ixA + r, iyA + r, izA + r); int codeMinB = g.clipCode3(ixB - r, iyB - r, izB - r); int codeMaxB = g.clipCode3(ixB + r, iyB + r, izB + r); //all bits 0 --> no clipping int c = (codeMinA | codeMaxA | codeMinB | codeMaxB); //any two bits same in all cases --> fully clipped clipped = (c != 0); //any two bits same in all cases --> fully clipped if (c == -1 || (codeMinA & codeMaxB & codeMaxA & codeMinB) != 0) return; dxBf = ptB.x - ptA.x; dyBf = ptB.y - ptA.y; dzBf = ptB.z - ptA.z; if (diameter > 0) { this.diameter = diameter; this.xAf = ptA.x; this.yAf = ptA.y; this.zAf = ptA.z; } boolean drawBackside = (screen == 0 && (clipped || endcaps == GData.ENDCAPS_FLAT || endcaps == GData.ENDCAPS_NONE)); this.xA = (int) xAf; this.yA = (int) yAf; this.zA = (int) zAf; this.dxB = (int) dxBf; this.dyB = (int) dyBf; this.dzB = (int) dzBf; this.shadesA = g.getShades(this.colixA = colixA); this.shadesB = g.getShades(this.colixB = colixB); this.endcaps = endcaps; calcArgbEndcap(true, true); int[][] xyzf = xyzfRaster; if (diameter > 0) generateBaseEllipsePrecisely(false); if (endcaps == GData.ENDCAPS_FLAT) renderFlatEndcap(true, true, xyzf); line3d.setLineBits(dxBf, dyBf); g.setZMargin(5); Pixelator p = g.pixel; int width = g.width; int[] zbuf = g.zbuf; int[] xr = xyzf[0]; int[] yr = xyzf[1]; int[] zr = xyzf[2]; int[] fr = xyzf[3]; for (int i = rasterCount; --i >= 0;) { int fpz = fr[i] >> (8); int fpzBack = fpz >> 1; int x = xr[i]; int y = yr[i]; int z = zr[i]; if (endCapHidden && argbEndcap != 0) { if (clipped) { g.plotPixelClippedArgb(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelClippedArgb(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } else { g.plotPixelUnclipped(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelUnclipped(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } } ptA0.set(xA + x, yA + y, zA - z); ptB0.setT(ptA0); ptB0.x += dxB; ptB0.y += dyB; ptB0.z += dzB; line3d.plotLineDeltaABitsFloat(shadesA, shadesB, fpz, ptA0, ptB0, screen, clipped); if (drawBackside) { ptA0.set(xA - x, yA - y, zA + z); ptB0.setT(ptA0); ptB0.x += dxB; ptB0.y += dyB; ptB0.z += dzB; line3d.plotLineDeltaABitsFloat(shadesA, shadesB, fpzBack, ptA0, ptB0, screen, clipped); } } g.setZMargin(0); if (endcaps == GData.ENDCAPS_SPHERICAL) renderSphericalEndcaps(); this.xAf += dxBf; this.yAf += dyBf; this.zAf += dzBf; } private P3i ptA0i = new P3i(); private P3i ptB0i = new P3i(); void renderBits(short colixA, short colixB, int screen, byte endcaps, int diameter, P3i ptA, P3i ptB) { Graphics3D g = this.g3d; if (diameter == 0 || diameter == 1) { line3d.plotLineBits(g.getColorArgbOrGray(colixA), g.getColorArgbOrGray(colixB), ptA, ptB, 0, 0, false); return; } ptA0i.setT(ptA); // dipole cross, cartoonRockets, draw mesh nofill or width = -1 // oops -- problem here if diameter < 0 is that we may have already clipped it! int r = diameter / 2 + 1; int ixA = ptA.x; int iyA = ptA.y; int izA = ptA.z; int ixB = ptB.x; int iyB = ptB.y; int izB = ptB.z; int codeMinA = g.clipCode3(ixA - r, iyA - r, izA - r); int codeMaxA = g.clipCode3(ixA + r, iyA + r, izA + r); int codeMinB = g.clipCode3(ixB - r, iyB - r, izB - r); int codeMaxB = g.clipCode3(ixB + r, iyB + r, izB + r); //all bits 0 --> no clipping int c = (codeMinA | codeMaxA | codeMinB | codeMaxB); //any two bits same in all cases --> fully clipped clipped = (c != 0); //any two bits same in all cases --> fully clipped if (c == -1 || (codeMinA & codeMaxB & codeMaxA & codeMinB) != 0) return; dxBf = ptB.x - ptA.x; dyBf = ptB.y - ptA.y; dzBf = ptB.z - ptA.z; if (diameter > 0) { this.diameter = diameter; xAf = ptA.x; yAf = ptA.y; zAf = ptA.z; } boolean drawBackside = (screen == 0 && (clipped || endcaps == GData.ENDCAPS_FLAT || endcaps == GData.ENDCAPS_NONE)); xA = (int) xAf; yA = (int) yAf; zA = (int) zAf; dxB = (int) dxBf; dyB = (int) dyBf; dzB = (int) dzBf; shadesA = g.getShades(this.colixA = colixA); shadesB = g.getShades(this.colixB = colixB); this.endcaps = endcaps; calcArgbEndcap(true, true); int[][] xyzf = xyzfRaster; if (diameter > 0) generateBaseEllipsePrecisely(false); if (endcaps == GData.ENDCAPS_FLAT) renderFlatEndcap(true, true, xyzf); line3d.setLineBits(dxBf, dyBf); g.setZMargin(5); Pixelator p = g.pixel; int width = g.width; int[] zbuf = g.zbuf; int[] xr = xyzf[0]; int[] yr = xyzf[1]; int[] zr = xyzf[2]; int[] fr = xyzf[3]; for (int i = rasterCount; --i >= 0;) { int fpz = fr[i] >> (8); int fpzBack = fpz >> 1; int x = xr[i]; int y = yr[i]; int z = zr[i]; if (endCapHidden && argbEndcap != 0) { if (clipped) { g.plotPixelClippedArgb(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelClippedArgb(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } else { g.plotPixelUnclipped(argbEndcap, xEndcap + x, yEndcap + y, zEndcap - z - 1, width, zbuf, p); g.plotPixelUnclipped(argbEndcap, xEndcap - x, yEndcap - y, zEndcap + z - 1, width, zbuf, p); } } ptA0i.set(xA + x, yA + y, zA - z); ptB0i.setT(ptA0i); ptB0i.x += dxB; ptB0i.y += dyB; ptB0i.z += dzB; line3d.plotLineDeltaABitsInt(shadesA, shadesB, fpz, ptA0i, ptB0i, screen, clipped); if (drawBackside) { ptA0i.set(xA - x, yA - y, zA + z); ptB0i.setT(ptA0i); ptB0i.x += dxB; ptB0i.y += dyB; ptB0i.z += dzB; line3d.plotLineDeltaABitsInt(shadesA, shadesB, fpzBack, ptA0i, ptB0i, screen, clipped); } } g.setZMargin(0); if (endcaps == GData.ENDCAPS_SPHERICAL) renderSphericalEndcaps(); this.xAf += dxBf; this.yAf += dyBf; this.zAf += dzBf; } private float xTip, yTip, zTip; void renderConeOld(short colix, byte endcap, int diameter, float xa, float ya, float za, float xtip, float ytip, float ztip, boolean doFill, boolean isBarb) { dxBf = (xtip) - (xAf = xa); dyBf = (ytip) - (yAf = ya); dzBf = (ztip) - (zAf = za); xA = (int) Math.floor(xAf); yA = (int) Math.floor(yAf); zA = (int) Math.floor(zAf); dxB = (int) Math.floor(dxBf); dyB = (int) Math.floor(dyBf); dzB = (int) Math.floor(dzBf); xTip = xtip; yTip = ytip; zTip = ztip; shadesA = g3d.getShades(colixA = colix); int shadeIndexTip = shader.getShadeIndex(dxB, dyB, -dzB); Graphics3D g3d = this.g3d; Pixelator p = g3d.pixel; int width = g3d.width; int[] zbuf = g3d.zbuf; g3d.plotPixelClippedArgb(shadesA[shadeIndexTip], (int) xtip, (int) ytip, (int) ztip, width, zbuf, p); this.diameter = diameter; if (diameter <= 1) { if (diameter == 1) line3d.plotLineDeltaOld(colixA, colixA, xA, yA, zA, dxB, dyB, dzB, clipped); return; } this.endcaps = endcap; calcArgbEndcap(false, true); generateBaseEllipsePrecisely(isBarb); if (!isBarb && endcaps == GData.ENDCAPS_FLAT) renderFlatEndcap(false, true, xyzfRaster); g3d.setZMargin(5); float[] xr = xyztRaster[0]; float[] yr = xyztRaster[1]; float[] zr = xyztRaster[2]; int[] fr = xyzfRaster[3]; int[] sA = shadesA; boolean doOpen = (endCapHidden && argbEndcap != 0); for (int i = rasterCount; --i >= 0;) { float x = xr[i]; float y = yr[i]; float z = zr[i]; int fpz = fr[i] >> (8); float xUp = xAf + x, yUp = yAf + y, zUp = zAf - z; float xDn = xAf - x, yDn = yAf - y, zDn = zAf + z; int argb = sA[0]; if (doOpen) { g3d.plotPixelClippedArgb(argbEndcap, (int) xUp, (int) yUp, (int) zUp, width, zbuf, p); g3d.plotPixelClippedArgb(argbEndcap, (int) xDn, (int) yDn, (int) zDn, width, zbuf, p); } if (argb != 0) { line3d.plotLineDeltaAOld(sA, sA, 0, fpz, (int) xUp, (int) yUp, (int) zUp, (int) Math.ceil(xTip - xUp), (int) Math.ceil(yTip - yUp), (int) Math.ceil(zTip - zUp), true); if (doFill) { //rockets, not arrows line3d.plotLineDeltaAOld(sA, sA, 0, fpz, (int) xUp, (int) yUp + 1, (int) zUp, (int) Math.ceil(xTip - xUp), (int) Math.ceil(yTip - yUp) + 1, (int) Math.ceil(zTip - zUp), true); line3d.plotLineDeltaAOld(sA, sA, 0, fpz, (int) xUp + 1, (int) yUp, (int) zUp, (int) Math.ceil(xTip - xUp) + 1, (int) Math.ceil(yTip - yUp), (int) Math.ceil(zTip - zUp), true); } if (!isBarb && !(endcaps != GData.ENDCAPS_FLAT && dzB > 0)) { line3d.plotLineDeltaOld(argb, argb, (int) xDn, (int) yDn, (int) zDn, (int) Math.ceil(xTip - xDn), (int) Math .ceil(yTip - yDn), (int) Math.ceil(zTip - zDn), true); } } } g3d.setZMargin(0); } private void generateBaseEllipsePrecisely(boolean isBarb) { calcCosSin(dxBf, dyBf, dzBf); calcPoints(isBarb ? 2 : 3, true); interpolatePrecisely(0, 1, xyzfRaster, xyztRaster); if (!isBarb) interpolatePrecisely(1, 2, xyzfRaster, xyztRaster); for (int i = 3; --i >= 0;) for (int j = rasterCount; --j >= 0;) xyzfRaster[i][j] = (int) Math.floor(xyztRaster[i][j]); } private void calcPoints(int count, boolean isPrecise) { calcRotatedPoint(0f, 0, isPrecise, xyzfRaster, xyztRaster); calcRotatedPoint(0.5f, 1, isPrecise, xyzfRaster, xyztRaster); if ((rasterCount = count) == 3) calcRotatedPoint(1f, 2, isPrecise, xyzfRaster, xyztRaster); } private void calcCosSin(float dx, float dy, float dz) { float mag2d2 = dx * dx + dy * dy; if (mag2d2 == 0) { cosTheta = 1; cosPhi = 1; sinPhi = 0; } else { float mag2d = (float) Math.sqrt(mag2d2); float mag3d = (float) Math.sqrt(mag2d2 + dz * dz); cosTheta = dz / mag3d; cosPhi = dx / mag2d; sinPhi = dy / mag2d; } } private void calcRotatedPoint(float t, int i, boolean isPrecision, int[][] xyzf, float[][] xyzt) { xyzt[3][i] = t; double tPI = t * Math.PI; double xT = Math.sin(tPI) * cosTheta; double yT = Math.cos(tPI); double xR = radius * (xT * cosPhi - yT * sinPhi); double yR = radius * (xT * sinPhi + yT * cosPhi); double z2 = radius2 - (xR * xR + yR * yR); double zR = (z2 > 0 ? Math.sqrt(z2) : 0); if (isPrecision) { xyzt[0][i] = (float) xR; xyzt[1][i] = (float) yR; xyzt[2][i] = (float) zR; } else if (tEvenDiameter) { xyzf[0][i] = (int) (xR - 0.5); xyzf[1][i] = (int) (yR - 0.5); xyzf[2][i] = (int) (zR + 0.5); } else { xyzf[0][i] = (int) (xR); xyzf[1][i] = (int) (yR); xyzf[2][i] = (int) (zR + 0.5); } xyzf[3][i] = shader.getShadeFp8((float) xR, (float) yR, (float) zR); } private int allocRaster(boolean isPrecision, int[][] xyzf, float[][] xyzt) { if (rasterCount >= xyzf[0].length) while (rasterCount >= xyzf[0].length) { for (int i = 4; --i >= 0;) xyzf[i] = AU.doubleLengthI(xyzf[i]); xyzt[3] = AU.doubleLengthF(xyzt[3]); } if (isPrecision) while (rasterCount >= xyzt[0].length) { for (int i = 3; --i >= 0;) xyzt[i] = AU.doubleLengthF(xyzt[i]); } return rasterCount++; } private void interpolate(int iLower, int iUpper, int[][] xyzf, float[][] xyzt) { int[] x = xyzf[0]; int[] y = xyzf[1]; int dx = x[iUpper] - x[iLower]; if (dx < 0) dx = -dx; int dy = y[iUpper] - y[iLower]; if (dy < 0) dy = -dy; if ((dx + dy) <= 1) return; int iMid = allocRaster(false, xyzf, xyzt); x = xyzf[0]; y = xyzf[1]; int[] f = xyzf[3]; float tLower = xyzt[3][iLower]; float tUpper = xyzt[3][iUpper]; for (int j = 4; --j >= 0;) { float tMid = (tLower + tUpper) / 2; calcRotatedPoint(tMid, iMid, false, xyzf, xyzt); if ((x[iMid] == x[iLower]) && (y[iMid] == y[iLower])) { f[iLower] = (f[iLower] + f[iMid]) >>> 1; tLower = tMid; } else if ((x[iMid] == x[iUpper]) && (y[iMid] == y[iUpper])) { f[iUpper] = (f[iUpper] + f[iMid]) >>> 1; tUpper = tMid; } else { interpolate(iLower, iMid, xyzf, xyzt); interpolate(iMid, iUpper, xyzf, xyzt); return; } } x[iMid] = x[iLower]; y[iMid] = y[iUpper]; } private void interpolatePrecisely(int iLower, int iUpper, int[][] xyzf, float[][] xyzt) { float[] x = xyzt[0]; float[] y = xyzt[1]; int dx = (int) Math.floor(x[iUpper]) - (int) Math.floor(x[iLower]); if (dx < 0) dx = -dx; float dy = (int) Math.floor(y[iUpper]) - (int) Math.floor(y[iLower]); if (dy < 0) dy = -dy; if ((dx + dy) <= 1) return; float[] t = xyzt[3]; float tLower = t[iLower]; float tUpper = t[iUpper]; int iMid = allocRaster(true, xyzf, xyzt); x = xyzt[0]; y = xyzt[1]; t = xyzt[3]; int[] f = xyzf[3]; for (int j = 4; --j >= 0;) { float tMid = (tLower + tUpper) / 2; calcRotatedPoint(tMid, iMid, true, xyzf, xyzt); if (((int) Math.floor(x[iMid]) == (int) Math .floor(x[iLower])) && ((int) Math.floor(y[iMid]) == (int) Math .floor(y[iLower]))) { f[iLower] = (f[iLower] + f[iMid]) >>> 1; tLower = tMid; } else if (((int) Math.floor(x[iMid]) == (int) Math .floor(x[iUpper])) && ((int) Math.floor(y[iMid]) == (int) Math .floor(y[iUpper]))) { f[iUpper] = (f[iUpper] + f[iMid]) >>> 1; tUpper = tMid; } else { interpolatePrecisely(iLower, iMid, xyzf, xyzt); interpolatePrecisely(iMid, iUpper, xyzf, xyzt); return; } } x[iMid] = x[iLower]; y[iMid] = y[iUpper]; } private void renderFlatEndcap(boolean isCylinder, boolean isPrecise, int[][] xyzf) { int xT, yT, zT; if (isPrecise) { if (dzBf == 0 || !g3d.setC(colixEndcap)) return; float xTf = xAf; float yTf = yAf; float zTf = zAf; if (isCylinder && dzBf < 0) { xTf += dxBf; yTf += dyBf; zTf += dzBf; } xT = (int) xTf; yT = (int) yTf; zT = (int) zTf; } else { if (dzB == 0 || !g3d.setC(colixEndcap)) return; xT = xA; yT = yA; zT = zA; if (isCylinder && dzB < 0) { xT += dxB; yT += dyB; zT += dzB; } } int yMin = xyzf[1][0]; int yMax = xyzf[1][0]; int zXMin = 0, zXMax = 0; // findMinMaxY int[] xr = xyzf[0]; int[] yr = xyzf[1]; int[] zr = xyzf[2]; for (int i = rasterCount; --i > 0;) { int y = yr[i]; if (y < yMin) yMin = y; else if (y > yMax) yMax = y; else { y = -y; if (y < yMin) yMin = y; else if (y > yMax) yMax = y; } } for (int y = yMin; y <= yMax; ++y) { // findMinMaxX int xMin = Integer.MAX_VALUE; int xMax = Integer.MIN_VALUE; for (int i = rasterCount; --i >= 0;) { if (yr[i] == y) { int x = xr[i]; if (x < xMin) { xMin = x; zXMin = zr[i]; } if (x > xMax) { xMax = x; zXMax = zr[i]; } } if (yr[i] == -y) { // 0 will run through here too int x = -xr[i]; if (x < xMin) { xMin = x; zXMin = -zr[i]; } if (x > xMax) { xMax = x; zXMax = -zr[i]; } } } int count = xMax - xMin + 1; g3d.setColorNoisy(endcapShadeIndex); g3d.plotPixelsClippedRaster(count, xT + xMin, yT + y, zT - zXMin - 1, zT - zXMax - 1, null, null); } } private void renderSphericalEndcaps() { if (colixA != 0 && g3d.setC(colixA)) g3d.fillSphereXYZ(diameter, xA, yA, zA + 1); if (colixB != 0 && g3d.setC(colixB)) g3d.fillSphereXYZ(diameter, xA + dxB, yA + dyB, zA + dzB + 1); } private void calcArgbEndcap(boolean tCylinder, boolean isFloat) { tEvenDiameter = ((diameter & 1) == 0); radius = diameter / 2.0f; radius2 = radius * radius; endCapHidden = false; float dzf = (isFloat ? dzBf : (float) dzB); if (endcaps == GData.ENDCAPS_SPHERICAL || dzf == 0) return; xEndcap = xA; yEndcap = yA; zEndcap = zA; int[] shadesEndcap; float dxf = (isFloat ? dxBf : (float) dxB); float dyf = (isFloat ? dyBf : (float) dyB); if (dzf >= 0 || !tCylinder) { endcapShadeIndex = shader.getShadeIndex(-dxf, -dyf, dzf); colixEndcap = colixA; shadesEndcap = shadesA; } else { endcapShadeIndex = shader.getShadeIndex(dxf, dyf, -dzf); colixEndcap = colixB; shadesEndcap = shadesB; xEndcap += dxB; yEndcap += dyB; zEndcap += dzB; } // limit specular glare on endcap if (endcapShadeIndex > Shader.SHADE_INDEX_NOISY_LIMIT) endcapShadeIndex = Shader.SHADE_INDEX_NOISY_LIMIT; argbEndcap = shadesEndcap[endcapShadeIndex]; endCapHidden = (endcaps == GData.ENDCAPS_HIDDEN); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy