📄 arch.java
字号:
//
// CLASS
// Arch - generalized arch
//
// DESCRIPTION
// This class builds a generalized arch where incoming parameters
// specify the angle range in theta (around the equator of a sphere),
// the angle range in phi (north-south), the number of subdivisions
// in theta and phi, and optionally radii and outer-to-inner wall
// thickness variations as phi varies from its starting value to
// its ending value. If the thicknesses are 0.0, then only an outer
// surface is created.
//
// Using this class, you can create spheres with or without inner
// surfaces, hemisphers, quarter spheres, and arches stretched or
// compressed vertically.
//
// This is probably not as general as it could be, but it was enough
// for the purposes at hand.
//
// SEE ALSO
// ModernFire
//
// AUTHOR
// David R. Nadeau / San Diego Supercomputer Center
//
//
package Java3DApplet;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Arch
extends Group
{
// The shape
private Shape3D arch = null;
// Construct an arch
public Arch( )
{
// Default to a sphere
this( 0.0, Math.PI/2.0, 9, 0.0, Math.PI, 17,
1.0, 1.0, 0.0, 0.0, new Appearance( ) );
}
public Arch( Appearance app )
{
// Default to a sphere
this( 0.0, Math.PI/2.0, 9, 0.0, Math.PI, 17,
1.0, 1.0, 0.0, 0.0, app );
}
public Arch( double startPhi, double endPhi, int nPhi,
double startTheta, double endTheta, int nTheta, Appearance app )
{
// Default to constant radius, no thickness
this( startPhi, endPhi, nPhi, startTheta, endTheta, nTheta,
1.0, 1.0, 0.0, 0.0, app );
}
public Arch( double startPhi, double endPhi, int nPhi,
double startTheta, double endTheta, int nTheta,
double startPhiRadius, double endPhiRadius,
double startPhiThickness, double endPhiThickness,
Appearance app )
{
double theta, phi, radius, radius2, thickness;
double x, y, z;
double[] xyz = new double[3];
float[] norm = new float[3];
float[] tex = new float[3];
// Compute some values for our looping
double deltaTheta = (endTheta - startTheta) / (double)(nTheta-1);
double deltaPhi = (endPhi - startPhi) / (double)(nPhi-1);
double deltaTexX = 1.0 / (double)(nTheta-1);
double deltaTexY = 1.0 / (double)(nPhi-1);
double deltaPhiRadius = (endPhiRadius - startPhiRadius) /
(double)(nPhi-1);
double deltaPhiThickness = (endPhiThickness - startPhiThickness) /
(double)(nPhi-1);
boolean doThickness = true;
if ( startPhiThickness == 0.0 && endPhiThickness == 0.0 )
doThickness = false;
// Create geometry
int vertexCount = nTheta * nPhi;
if ( doThickness )
vertexCount *= 2;
int indexCount = (nTheta-1) * (nPhi-1) * 4; // Outer surface
if ( doThickness )
{
indexCount *= 2; // plus inner surface
indexCount += (nPhi-1) * 4 * 2; // plus left & right edges
}
IndexedQuadArray polys = new IndexedQuadArray(
vertexCount,
GeometryArray.COORDINATES |
GeometryArray.NORMALS |
GeometryArray.TEXTURE_COORDINATE_2,
indexCount );
//
// Compute coordinates, normals, and texture coordinates
//
theta = startTheta;
tex[0] = 0.0f;
int index = 0;
for ( int i = 0; i < nTheta; i++ )
{
phi = startPhi;
radius = startPhiRadius;
thickness = startPhiThickness;
tex[1] = 0.0f;
for ( int j = 0; j < nPhi; j++ )
{
norm[0] = (float)(Math.cos( phi ) * Math.cos( theta ));
norm[1] = (float)(Math.sin( phi ));
norm[2] = (float)(-Math.cos( phi ) * Math.sin( theta ));
xyz[0] = radius * norm[0];
xyz[1] = radius * norm[1];
xyz[2] = radius * norm[2];
polys.setCoordinate( index, xyz );
polys.setNormal( index, norm );
polys.setTextureCoordinate( index, tex );
index++;
if ( doThickness )
{
radius2 = radius - thickness;
xyz[0] = radius2 * norm[0];
xyz[1] = radius2 * norm[1];
xyz[2] = radius2 * norm[2];
norm[0] *= -1.0f;
norm[1] *= -1.0f;
norm[2] *= -1.0f;
polys.setCoordinate( index, xyz );
polys.setNormal( index, norm );
polys.setTextureCoordinate( index, tex );
index++;
}
phi += deltaPhi;
radius += deltaPhiRadius;
thickness += deltaPhiThickness;
tex[1] += deltaTexY;
}
theta += deltaTheta;
tex[0] += deltaTexX;
}
//
// Compute coordinate indexes
// (also used as normal and texture indexes)
//
index = 0;
int phiRow = nPhi;
int phiCol = 1;
if ( doThickness )
{
phiRow += nPhi;
phiCol += 1;
}
int[] indices = new int[indexCount];
// Outer surface
int n;
for ( int i = 0; i < nTheta-1; i++ )
{
for ( int j = 0; j < nPhi-1; j++ )
{
n = i*phiRow + j*phiCol;
indices[index+0] = n;
indices[index+1] = n+phiRow;
indices[index+2] = n+phiRow+phiCol;
indices[index+3] = n+phiCol;
index += 4;
}
}
// Inner surface
if ( doThickness )
{
for ( int i = 0; i < nTheta-1; i++ )
{
for ( int j = 0; j < nPhi-1; j++ )
{
n = i*phiRow + j*phiCol;
indices[index+0] = n+1;
indices[index+1] = n+phiCol+1;
indices[index+2] = n+phiRow+phiCol+1;
indices[index+3] = n+phiRow+1;
index += 4;
}
}
}
// Edges
if ( doThickness )
{
for ( int j = 0; j < nPhi-1; j++ )
{
n = j*phiCol;
indices[index+0] = n;
indices[index+1] = n+phiCol;
indices[index+2] = n+phiCol+1;
indices[index+3] = n+1;
index += 4;
}
for ( int j = 0; j < nPhi-1; j++ )
{
n = (nTheta-1)*phiRow + j*phiCol;
indices[index+0] = n;
indices[index+1] = n+1;
indices[index+2] = n+phiCol+1;
indices[index+3] = n+phiCol;
index += 4;
}
}
polys.setCoordinateIndices( 0, indices );
polys.setNormalIndices( 0, indices );
polys.setTextureCoordinateIndices( 0, indices );
//
// Build a shape
//
arch = new Shape3D( );
arch.setCapability( Shape3D.ALLOW_APPEARANCE_WRITE );
arch.setGeometry( polys );
arch.setAppearance( app );
addChild( arch );
}
public void setAppearance( Appearance app )
{
if ( arch != null )
arch.setAppearance( app );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -