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

com.jme3.scene.shape.Dome Maven / Gradle / Ivy

There is a newer version: 3.7.0-stable
Show newest version
/*
 * Copyright (c) 2009-2021 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
// $Id: Dome.java 4131 2009-03-19 20:15:28Z blaine.dev $
package com.jme3.scene.shape;

import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.util.BufferUtils;
import com.jme3.util.TempVars;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

/**
 * A hemisphere.
 *
 * @author Peter Andersson
 * @author Joshua Slack (Original sphere code that was adapted)
 * @version $Revision: 4131 $, $Date: 2009-03-19 16:15:28 -0400 (Thu, 19 Mar 2009) $
 */
public class Dome extends Mesh {

    private int planes;
    private int radialSamples;
    /** The radius of the dome */
    private float radius;
    /** The center of the dome */
    private Vector3f center;
    private boolean insideView = true;

    /**
     * Serialization only. Do not use.
     */
    protected Dome() {
    }

    /**
     * Constructs a dome for use as a SkyDome. The SkyDome is centered at the origin
     * and only visible from the inside.
     * @param planes
     *            The number of planes along the Z-axis. Must be >= 2.
     *            Influences how round the arch of the dome is.
     * @param radialSamples
     *            The number of samples along the radial.
     *            Influences how round the base of the dome is.
     * @param radius
     *            Radius of the dome.
     * @see #Dome(com.jme3.math.Vector3f, int, int, float)
     */
    public Dome(int planes, int radialSamples, float radius) {
        this(new Vector3f(0, 0, 0), planes, radialSamples, radius);
    }

    /**
     * Constructs a dome visible from the inside, e.g. for use as a SkyDome.
     * All geometry data buffers are updated automatically. 
* For a cone, set planes=2. For a pyramid, set radialSamples=4 and planes=2. * Increasing planes and radialSamples increase the quality of the dome. * * @param center * Center of the dome. * @param planes * The number of planes along the Z-axis. Must be >= 2. * Influences how round the arch of the dome is. * @param radialSamples * The number of samples along the radial. * Influences how round the base of the dome is. * @param radius * The radius of the dome. */ public Dome(Vector3f center, int planes, int radialSamples, float radius) { super(); updateGeometry(center, planes, radialSamples, radius, true); } /** * Constructs a dome. Use this constructor for half-sphere, pyramids, or cones. * All geometry data buffers are updated automatically.
* For a cone, set planes=2. For a pyramid, set radialSamples=4 and planes=2. * Setting higher values for planes and radialSamples increases * the quality of the half-sphere. * * @param center * Center of the dome. * @param planes * The number of planes along the Z-axis. Must be >= 2. * Influences how round the arch of the dome is. * @param radialSamples * The number of samples along the radial. * Influences how round the base of the dome is. * @param radius * The radius of the dome. * @param insideView * If true, the dome is only visible from the inside, like a SkyDome. * If false, the dome is only visible from the outside. */ public Dome(Vector3f center, int planes, int radialSamples, float radius, boolean insideView) { super(); updateGeometry(center, planes, radialSamples, radius, insideView); } public Vector3f getCenter() { return center; } /** * Get the number of planar segments along the z-axis of the dome. * * @return the count */ public int getPlanes() { return planes; } /** * Get the number of samples radially around the main axis of the dome. * * @return the count */ public int getRadialSamples() { return radialSamples; } /** * Get the radius of the dome. * * @return the radius (in mesh units) */ public float getRadius() { return radius; } /** * Are the triangles connected in such a way as to present a view out from the dome or not. * * @return true if visible from inside, false if visible from outside */ public boolean isInsideView() { return insideView; } /** * Rebuilds the dome with a new set of parameters. * * @param center the new center of the dome. * @param planes the number of planes along the Z-axis. * @param radialSamples the new number of radial samples of the dome. * @param radius the new radius of the dome. * @param insideView should the dome be set up to be viewed from the inside looking out. */ public void updateGeometry(Vector3f center, int planes, int radialSamples, float radius, boolean insideView) { this.insideView = insideView; this.center = center != null ? center : new Vector3f(0, 0, 0); this.planes = planes; this.radialSamples = radialSamples; this.radius = radius; int vertCount = ((planes - 1) * (radialSamples + 1)) + 1; // Allocate vertices, allocating one extra in each radial to get the // correct texture coordinates // setVertexCount(); // setVertexBuffer(createVector3Buffer(getVertexCount())); // allocate normals // setNormalBuffer(createVector3Buffer(getVertexCount())); // allocate texture coordinates // getTextureCoords().set(0, new TexCoords(createVector2Buffer(getVertexCount()))); FloatBuffer vb = BufferUtils.createVector3Buffer(vertCount); FloatBuffer nb = BufferUtils.createVector3Buffer(vertCount); FloatBuffer tb = BufferUtils.createVector2Buffer(vertCount); setBuffer(Type.Position, 3, vb); setBuffer(Type.Normal, 3, nb); setBuffer(Type.TexCoord, 2, tb); // generate geometry float fInvRS = 1.0f / radialSamples; float fYFactor = 1.0f / (planes - 1); // Generate points on the unit circle to be used in computing the mesh // points on a dome slice. float[] afSin = new float[(radialSamples)]; float[] afCos = new float[(radialSamples)]; for (int iR = 0; iR < radialSamples; iR++) { float fAngle = FastMath.TWO_PI * fInvRS * iR; afCos[iR] = FastMath.cos(fAngle); afSin[iR] = FastMath.sin(fAngle); } TempVars vars = TempVars.get(); Vector3f tempVc = vars.vect3; Vector3f tempVb = vars.vect2; Vector3f tempVa = vars.vect1; // generate the dome itself int i = 0; for (int iY = 0; iY < (planes - 1); iY++, i++) { float fYFraction = fYFactor * iY; // in (0,1) float fY = radius * fYFraction; // compute center of slice Vector3f kSliceCenter = tempVb.set(center); kSliceCenter.y += fY; // compute radius of slice float fSliceRadius = FastMath.sqrt(FastMath.abs(radius * radius - fY * fY)); // compute slice vertices Vector3f kNormal; int iSave = i; for (int iR = 0; iR < radialSamples; iR++, i++) { float fRadialFraction = iR * fInvRS; // in [0,1) Vector3f kRadial = tempVc.set(afCos[iR], 0, afSin[iR]); kRadial.mult(fSliceRadius, tempVa); vb.put(kSliceCenter.x + tempVa.x).put( kSliceCenter.y + tempVa.y).put( kSliceCenter.z + tempVa.z); BufferUtils.populateFromBuffer(tempVa, vb, i); kNormal = tempVa.subtractLocal(center); kNormal.normalizeLocal(); if (!insideView) { nb.put(kNormal.x).put(kNormal.y).put(kNormal.z); } else { nb.put(-kNormal.x).put(-kNormal.y).put(-kNormal.z); } tb.put(fRadialFraction).put(fYFraction); } BufferUtils.copyInternalVector3(vb, iSave, i); BufferUtils.copyInternalVector3(nb, iSave, i); tb.put(1.0f).put(fYFraction); } vars.release(); // pole vb.put(this.center.x).put(this.center.y + radius).put(this.center.z); nb.put(0).put(insideView ? -1 : 1).put(0); tb.put(0.5f).put(1.0f); // allocate connectivity int triCount = (planes - 2) * radialSamples * 2 + radialSamples; ShortBuffer ib = BufferUtils.createShortBuffer(3 * triCount); setBuffer(Type.Index, 3, ib); // generate connectivity int index = 0; // Generate only for middle planes for (int plane = 1; plane < (planes - 1); plane++) { int bottomPlaneStart = ((plane - 1) * (radialSamples + 1)); int topPlaneStart = (plane * (radialSamples + 1)); for (int sample = 0; sample < radialSamples; sample++, index += 6) { if (insideView) { ib.put((short) (bottomPlaneStart + sample)); ib.put((short) (bottomPlaneStart + sample + 1)); ib.put((short) (topPlaneStart + sample)); ib.put((short) (bottomPlaneStart + sample + 1)); ib.put((short) (topPlaneStart + sample + 1)); ib.put((short) (topPlaneStart + sample)); } else { ib.put((short) (bottomPlaneStart + sample)); ib.put((short) (topPlaneStart + sample)); ib.put((short) (bottomPlaneStart + sample + 1)); ib.put((short) (bottomPlaneStart + sample + 1)); ib.put((short) (topPlaneStart + sample)); ib.put((short) (topPlaneStart + sample + 1)); } } } // pole triangles int bottomPlaneStart = (planes - 2) * (radialSamples + 1); for (int samples = 0; samples < radialSamples; samples++, index += 3) { if (insideView) { ib.put((short) (bottomPlaneStart + samples)); ib.put((short) (bottomPlaneStart + samples + 1)); ib.put((short) (vertCount - 1)); } else { ib.put((short) (bottomPlaneStart + samples)); ib.put((short) (vertCount - 1)); ib.put((short) (bottomPlaneStart + samples + 1)); } } updateBound(); } @Override public void read(JmeImporter importer) throws IOException { super.read(importer); InputCapsule capsule = importer.getCapsule(this); planes = capsule.readInt("planes", 0); radialSamples = capsule.readInt("radialSamples", 0); radius = capsule.readFloat("radius", 0); center = (Vector3f) capsule.readSavable("center", Vector3f.ZERO.clone()); } @Override public void write(JmeExporter e) throws IOException { super.write(e); OutputCapsule capsule = e.getCapsule(this); capsule.write(planes, "planes", 0); capsule.write(radialSamples, "radialSamples", 0); capsule.write(radius, "radius", 0); capsule.write(center, "center", Vector3f.ZERO); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy