@Override public void startWalk(final Ray3 walkRay) { // store ray _walkRay.set(walkRay); // simplify access to direction final ReadOnlyVector3 direction = _walkRay.getDirection(); // Move start point to grid space final Vector3 start = _walkRay.getOrigin().subtract(_gridOrigin, null); _gridLocation[0] = (int) MathUtils.floor(start.getX() / _gridSpacing.getX()); _gridLocation[1] = (int) MathUtils.floor(start.getY() / _gridSpacing.getY()); final double invDirX = 1.0 / direction.getX(); final double invDirY = 1.0 / direction.getY(); // Check which direction on the X world axis we are moving. if (direction.getX() > BresenhamZUpGridTracer.TOLERANCE) { _distToNextXIntersection = ((_gridLocation[0] + 1) * _gridSpacing.getX() - start.getX()) * invDirX; _distBetweenXIntersections = _gridSpacing.getX() * invDirX; _stepXDirection = 1; } else if (direction.getX() < -BresenhamZUpGridTracer.TOLERANCE) { _distToNextXIntersection = (start.getX() - _gridLocation[0] * _gridSpacing.getX()) * -direction.getX(); _distBetweenXIntersections = -_gridSpacing.getX() * invDirX; _stepXDirection = -1; } else { _distToNextXIntersection = Double.MAX_VALUE; _distBetweenXIntersections = Double.MAX_VALUE; _stepXDirection = 0; } // Check which direction on the Y world axis we are moving. if (direction.getY() > BresenhamZUpGridTracer.TOLERANCE) { _distToNextYIntersection = ((_gridLocation[1] + 1) * _gridSpacing.getY() - start.getY()) * invDirY; _distBetweenYIntersections = _gridSpacing.getY() * invDirY; _stepYDirection = 1; } else if (direction.getY() < -BresenhamZUpGridTracer.TOLERANCE) { _distToNextYIntersection = (start.getY() - _gridLocation[1] * _gridSpacing.getY()) * -direction.getY(); _distBetweenYIntersections = -_gridSpacing.getY() * invDirY; _stepYDirection = -1; } else { _distToNextYIntersection = Double.MAX_VALUE; _distBetweenYIntersections = Double.MAX_VALUE; _stepYDirection = 0; } // Reset some variables _rayLocation.set(start); _totalTravel = 0.0; _stepDirection = Direction.None; }
@Override public void applyFilter(final InteractManager manager) { final SpatialState state = manager.getSpatialState(); final ReadOnlyVector3 scale = state.getTransform().getScale(); final double x = MathUtils.clamp(scale.getX(), _minScale.getX(), _maxScale.getX()); final double y = MathUtils.clamp(scale.getY(), _minScale.getY(), _maxScale.getY()); final double z = MathUtils.clamp(scale.getZ(), _minScale.getZ(), _maxScale.getZ()); state.getTransform().setScale(x, y, z); }
public void set(final double radius, final double start, final double end) { final FloatBuffer buf = getMeshData().getVertexBuffer(); buf.limit(buf.capacity()); this.getMeshData().updateVertexCount(); buf.rewind(); double arc = end - start; final int n = buf.limit() / 3; for (int i = 0; i < n; i++) { double theta = start + arc / (n - 1) * i; float x = (float) (MathUtils.cos(theta) * radius); float y = (float) (MathUtils.sin(theta) * radius); buf.put(x).put(y).put(0); } getMeshData().updateVertexCount(); }
public double eval(final double x, final double y, final double z) { double value = 0, signal = 0, weight = 1; double dx = x * _frequency, dy = y * _frequency, dz = z * _frequency; for (int i = 0; i < _octaves; i++) { signal = _source.eval(dx, dy, dz); signal = Math.abs(signal); signal = _offset - signal; // Square the signal to increase the sharpness of the ridges. signal *= signal; // The weighting from the previous octave is applied to the signal. // Larger values have higher weights, producing sharp points along the // ridges. signal *= weight; // Weight successive contributions by the previous signal. (clamp to [0, 1]) weight = MathUtils.clamp(signal * _gain, 0, 1); // Add the signal to the output value. value += signal * _spectralWeights[i]; // Next! dx *= _lacunarity; dy *= _lacunarity; dz *= _lacunarity; } return (value * 1.25) - 1.0; }
@Override protected void updateExample(final ReadOnlyTimer timer) { if (allowClicks && zoom) { if (index > COUNT - 1) { index = COUNT - 1; } else if (index < 0) { index = 0; } final int currentTile = MathUtils.floor(index); final float fract = index - currentTile; if (firstTile != currentTile - 1) { // update the textures on the tiles firstTile = MathUtils.floor(index - 1); for (int i = 0; i < views.length; i++) { if (firstTile + i >= 0 && firstTile + i < COUNT) { views[i].removeAllComponents(); views[i].add(srcs[firstTile + i]); views[i].updateMinimumSizeFromContents(); views[i].layout(); views[i].setVisible(true); } else { views[i].setVisible(false); } } } // update the positions of the tiles. final int y = (_canvas.getCanvasRenderer().getCamera().getHeight() / 2) - (hside / 2); for (int i = 0; i < views.length; i++) { final float x = (i - fract) * (wside + padding); views[i].setHudXY(Math.round(x), y); } // check for and apply movement index += timer.getTimePerFrame() * speed; } // update hud input hud.updateGeometricState(timer.getTimePerFrame()); }
public LwjglPbufferTextureRenderer( final DisplaySettings settings, final Renderer parentRenderer, final ContextCapabilities caps) { super(settings, parentRenderer, caps); int pTarget = RenderTexture.RENDER_TEXTURE_2D; if (!MathUtils.isPowerOfTwo(_width) || !MathUtils.isPowerOfTwo(_height)) { pTarget = RenderTexture.RENDER_TEXTURE_RECTANGLE; } // signature: boolean useRGB, boolean useRGBA, boolean useDepth, boolean isRectangle, int // target, int mipmaps _texture = new RenderTexture( false, true, true, pTarget == RenderTexture.RENDER_TEXTURE_RECTANGLE, pTarget, 0); setMultipleTargets(false); }
/** * Update the vertices for this particle, taking size, spin and viewer into consideration. In the * case of particle type ParticleType.GeomMesh, the original triangle normal is maintained rather * than rotating it to face the camera or parent vectors. * * @param cam Camera to use in determining viewer aspect. If null, or if parent is not set to * camera facing, parent's left and up vectors are used. */ public void updateVerts(final Camera cam) { final double orient = parent.getParticleOrientation() + values[VAL_CURRENT_SPIN]; final double currSize = values[VAL_CURRENT_SIZE]; if (type == ParticleSystem.ParticleType.GeomMesh || type == ParticleSystem.ParticleType.Point) {; // nothing to do } else if (cam != null && parent.isCameraFacing()) { final ReadOnlyVector3 camUp = cam.getUp(); final ReadOnlyVector3 camLeft = cam.getLeft(); final ReadOnlyVector3 camDir = cam.getDirection(); if (parent.isVelocityAligned()) { bbX.set(_velocity).normalizeLocal().multiplyLocal(currSize); camDir.cross(bbX, bbY).normalizeLocal().multiplyLocal(currSize); } else if (orient == 0) { bbX.set(camLeft).multiplyLocal(currSize); bbY.set(camUp).multiplyLocal(currSize); } else { final double cA = MathUtils.cos(orient) * currSize; final double sA = MathUtils.sin(orient) * currSize; bbX.set(camLeft) .multiplyLocal(cA) .addLocal(camUp.getX() * sA, camUp.getY() * sA, camUp.getZ() * sA); bbY.set(camLeft) .multiplyLocal(-sA) .addLocal(camUp.getX() * cA, camUp.getY() * cA, camUp.getZ() * cA); } } else { bbX.set(parent.getLeftVector()).multiplyLocal(0); bbY.set(parent.getUpVector()).multiplyLocal(0); } final Vector3 tempVec3 = Vector3.fetchTempInstance(); final FloatBuffer vertexBuffer = parent.getParticleGeometry().getMeshData().getVertexBuffer(); switch (type) { case Quad: { _position.subtract(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0); _position.subtract(bbX, tempVec3).addLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); _position.add(bbX, tempVec3).addLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2); _position.add(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 3); break; } case GeomMesh: { final Quaternion tempQuat = Quaternion.fetchTempInstance(); final ReadOnlyVector3 norm = triModel.getNormal(); if (orient != 0) { tempQuat.fromAngleNormalAxis(orient, norm); } for (int x = 0; x < 3; x++) { if (orient != 0) { tempQuat.apply(triModel.get(x), tempVec3); } else { tempVec3.set(triModel.get(x)); } tempVec3.multiplyLocal(currSize).addLocal(_position); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + x); } Quaternion.releaseTempInstance(tempQuat); break; } case Triangle: { _position .subtract(3 * bbX.getX(), 3 * bbX.getY(), 3 * bbX.getZ(), tempVec3) .subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0); _position.add(bbX, tempVec3).addLocal(3 * bbY.getX(), 3 * bbY.getY(), 3 * bbY.getZ()); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); _position.add(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2); break; } case Line: { _position.subtract(bbX, tempVec3); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex); _position.add(bbX, tempVec3); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); break; } case Point: { BufferUtils.setInBuffer(_position, vertexBuffer, startIndex); break; } } Vector3.releaseTempInstance(tempVec3); }
private void setGeometryData() { final FloatBuffer verts = _meshData.getVertexBuffer(); final FloatBuffer norms = _meshData.getNormalBuffer(); final FloatBuffer texs = _meshData.getTextureBuffer(0); verts.rewind(); norms.rewind(); texs.rewind(); // generate geometry final double inverseRadial = 1.0 / radialSamples; final double inverseSphere = 1.0 / sphereSamples; final double halfHeight = 0.5 * height; // Generate points on the unit circle to be used in computing the mesh // points on a cylinder slice. final double[] sin = new double[radialSamples + 1]; final double[] cos = new double[radialSamples + 1]; for (int radialCount = 0; radialCount < radialSamples; radialCount++) { final double angle = MathUtils.TWO_PI * inverseRadial * radialCount; cos[radialCount] = MathUtils.cos(angle); sin[radialCount] = MathUtils.sin(angle); } sin[radialSamples] = sin[0]; cos[radialSamples] = cos[0]; final Vector3 tempA = new Vector3(); // top point. verts.put(0).put((float) (radius + halfHeight)).put(0); norms.put(0).put(1).put(0); texs.put(1).put(1); // generating the top dome. for (int i = 0; i < sphereSamples; i++) { final double center = radius * (1 - (i + 1) * (inverseSphere)); final double lengthFraction = (center + height + radius) / (height + 2 * radius); // compute radius of slice final double fSliceRadius = Math.sqrt(Math.abs(radius * radius - center * center)); for (int j = 0; j <= radialSamples; j++) { final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]); kRadial.multiplyLocal(fSliceRadius); verts.put(kRadial.getXf()).put((float) (center + halfHeight)).put(kRadial.getZf()); kRadial.setY(center); kRadial.normalizeLocal(); norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf()); final double radialFraction = 1 - (j * inverseRadial); // in [0,1) texs.put((float) radialFraction).put((float) lengthFraction); } } // generate cylinder... but no need to add points for first and last // samples as they are already part of domes. for (int i = 1; i < axisSamples; i++) { final double center = halfHeight - (i * height / axisSamples); final double lengthFraction = (center + halfHeight + radius) / (height + 2 * radius); for (int j = 0; j <= radialSamples; j++) { final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]); kRadial.multiplyLocal(radius); verts.put(kRadial.getXf()).put((float) center).put(kRadial.getZf()); kRadial.normalizeLocal(); norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf()); final double radialFraction = 1 - (j * inverseRadial); // in [0,1) texs.put((float) radialFraction).put((float) lengthFraction); } } // generating the bottom dome. for (int i = 0; i < sphereSamples; i++) { final double center = i * (radius / sphereSamples); final double lengthFraction = (radius - center) / (height + 2 * radius); // compute radius of slice final double fSliceRadius = Math.sqrt(Math.abs(radius * radius - center * center)); for (int j = 0; j <= radialSamples; j++) { final Vector3 kRadial = tempA.set(cos[j], 0, sin[j]); kRadial.multiplyLocal(fSliceRadius); verts.put(kRadial.getXf()).put((float) (-center - halfHeight)).put(kRadial.getZf()); kRadial.setY(-center); kRadial.normalizeLocal(); norms.put(kRadial.getXf()).put(kRadial.getYf()).put(kRadial.getZf()); final double radialFraction = 1 - (j * inverseRadial); // in [0,1) texs.put((float) radialFraction).put((float) lengthFraction); } } // bottom point. verts.put(0).put((float) (-radius - halfHeight)).put(0); norms.put(0).put(-1).put(0); texs.put(0).put(0); }
/** * Find and apply the given material to the given Mesh. * * @param materialName our material name * @param mesh the mesh to apply material to. */ public void applyMaterial(final String materialName, final Mesh mesh) { if (materialName == null) { logger.warning("materialName is null"); return; } Element mat = _dataCache.getBoundMaterial(materialName); if (mat == null) { logger.warning("material not bound: " + materialName + ", trying search with id."); mat = _colladaDOMUtil.findTargetWithId(materialName); } if (mat == null || !"material".equals(mat.getName())) { logger.warning("material not found: " + materialName); return; } final String originalMaterial = mat.getAttributeValue("id"); MaterialInfo mInfo = null; if (!_dataCache.getMaterialInfoMap().containsKey(originalMaterial)) { mInfo = new MaterialInfo(); mInfo.setMaterialName(originalMaterial); _dataCache.getMaterialInfoMap().put(originalMaterial, mInfo); } _dataCache.getMeshMaterialMap().put(mesh, originalMaterial); final Element child = mat.getChild("instance_effect"); final Element effectNode = _colladaDOMUtil.findTargetWithId(child.getAttributeValue("url")); if (effectNode == null) { logger.warning( "material effect not found: " + mat.getChild("instance_material").getAttributeValue("url")); return; } if ("effect".equals(effectNode.getName())) { /* * temp cache for textures, we do not want to add textures twice (for example, transparant map might point * to diffuse texture) */ final HashMap<String, Texture> loadedTextures = new HashMap<String, Texture>(); final Element effect = effectNode; // XXX: For now, just grab the common technique: if (effect.getChild("profile_COMMON") != null) { if (mInfo != null) { mInfo.setProfile("COMMON"); } final Element technique = effect.getChild("profile_COMMON").getChild("technique"); String type = "blinn"; if (technique.getChild(type) == null) { type = "phong"; if (technique.getChild(type) == null) { type = "lambert"; if (technique.getChild(type) == null) { type = "constant"; if (technique.getChild(type) == null) { ColladaMaterialUtils.logger.warning( "COMMON material has unusuable techinque. " + child.getAttributeValue("url")); return; } } } } final Element blinnPhongLambert = technique.getChild(type); if (mInfo != null) { mInfo.setTechnique(type); } final MaterialState mState = new MaterialState(); // TODO: implement proper transparency handling Texture diffuseTexture = null; ColorRGBA transparent = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f); float transparency = 1.0f; boolean useTransparency = false; String opaqueMode = "A_ONE"; /* * place holder for current property, we import material properties in fixed order (for texture order) */ Element property = null; /* Diffuse property */ property = blinnPhongLambert.getChild("diffuse"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("color".equals(propertyValue.getName())) { final ColorRGBA color = _colladaDOMUtil.getColor(propertyValue.getText()); mState.setDiffuse(MaterialFace.FrontAndBack, color); } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { diffuseTexture = populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "diffuse"); } } /* Ambient property */ property = blinnPhongLambert.getChild("ambient"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("color".equals(propertyValue.getName())) { final ColorRGBA color = _colladaDOMUtil.getColor(propertyValue.getText()); mState.setAmbient(MaterialFace.FrontAndBack, color); } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "ambient"); } } /* Transparent property */ property = blinnPhongLambert.getChild("transparent"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("color".equals(propertyValue.getName())) { transparent = _colladaDOMUtil.getColor(propertyValue.getText()); // TODO: use this useTransparency = true; } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "transparent"); } opaqueMode = property.getAttributeValue("opaque", "A_ONE"); } /* Transparency property */ property = blinnPhongLambert.getChild("transparency"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("float".equals(propertyValue.getName())) { transparency = Float.parseFloat(propertyValue.getText().replace(",", ".")); // TODO: use this if (_flipTransparency) { transparency = 1f - transparency; } useTransparency = true; } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState( mesh, propertyValue, effect, loadedTextures, mInfo, "transparency"); } } /* Emission property */ property = blinnPhongLambert.getChild("emission"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("color".equals(propertyValue.getName())) { mState.setEmissive( MaterialFace.FrontAndBack, _colladaDOMUtil.getColor(propertyValue.getText())); } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "emissive"); } } /* Specular property */ property = blinnPhongLambert.getChild("specular"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("color".equals(propertyValue.getName())) { mState.setSpecular( MaterialFace.FrontAndBack, _colladaDOMUtil.getColor(propertyValue.getText())); } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "specular"); } } /* Shininess property */ property = blinnPhongLambert.getChild("shininess"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("float".equals(propertyValue.getName())) { float shininess = Float.parseFloat(propertyValue.getText().replace(",", ".")); if (shininess >= 0.0f && shininess <= 1.0f) { final float oldShininess = shininess; shininess *= 128; logger.finest( "Shininess - " + oldShininess + " - was in the [0,1] range. Scaling to [0, 128] - " + shininess); } else if (shininess < 0 || shininess > 128) { final float oldShininess = shininess; shininess = MathUtils.clamp(shininess, 0, 128); logger.warning( "Shininess must be between 0 and 128. Shininess " + oldShininess + " was clamped to " + shininess); } mState.setShininess(MaterialFace.FrontAndBack, shininess); } else if ("texture".equals(propertyValue.getName()) && _loadTextures) { populateTextureState(mesh, propertyValue, effect, loadedTextures, mInfo, "shininess"); } } /* Reflectivity property */ float reflectivity = 1.0f; property = blinnPhongLambert.getChild("reflectivity"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("float".equals(propertyValue.getName())) { reflectivity = Float.parseFloat(propertyValue.getText().replace(",", ".")); } } /* Reflective property. Texture only */ property = blinnPhongLambert.getChild("reflective"); if (property != null) { final Element propertyValue = (Element) property.getChildren().get(0); if ("texture".equals(propertyValue.getName()) && _loadTextures) { final Texture reflectiveTexture = populateTextureState( mesh, propertyValue, effect, loadedTextures, mInfo, "reflective"); reflectiveTexture.setEnvironmentalMapMode(Texture.EnvironmentalMapMode.SphereMap); reflectiveTexture.setApply(ApplyMode.Combine); reflectiveTexture.setCombineFuncRGB(CombinerFunctionRGB.Interpolate); // color 1 reflectiveTexture.setCombineSrc0RGB(CombinerSource.CurrentTexture); reflectiveTexture.setCombineOp0RGB(CombinerOperandRGB.SourceColor); // color 2 reflectiveTexture.setCombineSrc1RGB(CombinerSource.Previous); reflectiveTexture.setCombineOp1RGB(CombinerOperandRGB.SourceColor); // interpolate param will come from alpha of constant color reflectiveTexture.setCombineSrc2RGB(CombinerSource.Constant); reflectiveTexture.setCombineOp2RGB(CombinerOperandRGB.SourceAlpha); reflectiveTexture.setConstantColor(new ColorRGBA(1, 1, 1, reflectivity)); } } /* * An extra tag defines some materials not part of the collada standard. Since we're not able to parse * we simply extract the textures from the element (such that shaders etc can at least pick up on them) */ property = technique.getChild("extra"); if (property != null) { getTexturesFromElement(mesh, property, effect, loadedTextures, mInfo); } // XXX: There are some issues with clarity on how to use alpha blending in OpenGL FFP. // The best interpretation I have seen is that if transparent has a texture == diffuse, // Turn on alpha blending and use diffuse alpha. // check to make sure we actually need this. // testing separately for a transparency of 0.0 is to hack around erroneous exports, since // usually // there is no use in exporting something with 100% transparency. if ("A_ONE".equals(opaqueMode) && ColorRGBA.WHITE.equals(transparent) && transparency == 1.0 || transparency == 0.0) { useTransparency = false; } if (useTransparency) { if (diffuseTexture != null) { final BlendState blend = new BlendState(); blend.setBlendEnabled(true); blend.setTestEnabled(true); blend.setSourceFunction(BlendState.SourceFunction.SourceAlpha); blend.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha); mesh.setRenderState(blend); } else { final BlendState blend = new BlendState(); blend.setBlendEnabled(true); blend.setTestEnabled(true); transparent.setAlpha(transparent.getAlpha() * transparency); blend.setConstantColor(transparent); blend.setSourceFunction(BlendState.SourceFunction.ConstantAlpha); blend.setDestinationFunction(BlendState.DestinationFunction.OneMinusConstantAlpha); mesh.setRenderState(blend); } mesh.getSceneHints().setRenderBucketType(RenderBucketType.Transparent); } if (mInfo != null) { if (useTransparency) { mInfo.setUseTransparency(useTransparency); if (diffuseTexture == null) { mInfo.setTransparency(transparent.getAlpha() * transparency); } } mInfo.setMaterialState(mState); } mesh.setRenderState(mState); } } else { ColladaMaterialUtils.logger.warning( "material effect not found: " + mat.getChild("instance_material").getAttributeValue("url")); } }
private void setGeometryData() { // generate geometry final double inverseRadial = 1.0 / _radialSamples; final double inverseAxisLess = 1.0 / (_closed ? _axisSamples - 3 : _axisSamples - 1); final double inverseAxisLessTexture = 1.0 / (_axisSamples - 1); final double halfHeight = 0.5 * _height; // Generate points on the unit circle to be used in computing the mesh // points on a cylinder slice. final double[] sin = new double[_radialSamples + 1]; final double[] cos = new double[_radialSamples + 1]; for (int radialCount = 0; radialCount < _radialSamples; radialCount++) { final double angle = MathUtils.TWO_PI * inverseRadial * radialCount; cos[radialCount] = MathUtils.cos(angle); sin[radialCount] = MathUtils.sin(angle); } sin[_radialSamples] = sin[0]; cos[_radialSamples] = cos[0]; // generate the cylinder itself final Vector3 tempNormal = new Vector3(); for (int axisCount = 0, i = 0; axisCount < _axisSamples; axisCount++) { double axisFraction; double axisFractionTexture; int topBottom = 0; if (!_closed) { axisFraction = axisCount * inverseAxisLess; // in [0,1] axisFractionTexture = axisFraction; } else { if (axisCount == 0) { topBottom = -1; // bottom axisFraction = 0; axisFractionTexture = inverseAxisLessTexture; } else if (axisCount == _axisSamples - 1) { topBottom = 1; // top axisFraction = 1; axisFractionTexture = 1 - inverseAxisLessTexture; } else { axisFraction = (axisCount - 1) * inverseAxisLess; axisFractionTexture = axisCount * inverseAxisLessTexture; } } final double z = -halfHeight + _height * axisFraction; // compute center of slice final Vector3 sliceCenter = new Vector3(0, 0, z); // compute slice vertices with duplication at end point final int save = i; for (int radialCount = 0; radialCount < _radialSamples; radialCount++) { final double radialFraction = radialCount * inverseRadial; // in [0,1) tempNormal.set(cos[radialCount], sin[radialCount], 0); if (topBottom == 0) { if (!_inverted) { _meshData .getNormalBuffer() .put(tempNormal.getXf()) .put(tempNormal.getYf()) .put(tempNormal.getZf()); } else { _meshData .getNormalBuffer() .put(-tempNormal.getXf()) .put(-tempNormal.getYf()) .put(-tempNormal.getZf()); } } else { _meshData.getNormalBuffer().put(0).put(0).put(topBottom * (_inverted ? -1 : 1)); } tempNormal .multiplyLocal((_radius - _radius2) * axisFraction + _radius2) .addLocal(sliceCenter); _meshData .getVertexBuffer() .put(tempNormal.getXf()) .put(tempNormal.getYf()) .put(tempNormal.getZf()); _meshData .getTextureCoords(0) .getBuffer() .put((float) (_inverted ? 1 - radialFraction : radialFraction)) .put((float) axisFractionTexture); i++; } BufferUtils.copyInternalVector3(_meshData.getVertexBuffer(), save, i); BufferUtils.copyInternalVector3(_meshData.getNormalBuffer(), save, i); _meshData .getTextureCoords(0) .getBuffer() .put((_inverted ? 0.0f : 1.0f)) .put((float) axisFractionTexture); i++; } if (_closed) { _meshData.getVertexBuffer().put(0).put(0).put((float) -halfHeight); // bottom center _meshData.getNormalBuffer().put(0).put(0).put(-1 * (_inverted ? -1 : 1)); _meshData.getTextureCoords(0).getBuffer().put(0.5f).put(0); _meshData.getVertexBuffer().put(0).put(0).put((float) halfHeight); // top center _meshData.getNormalBuffer().put(0).put(0).put(1 * (_inverted ? -1 : 1)); _meshData.getTextureCoords(0).getBuffer().put(0.5f).put(1); } }
/**
private double calcNewJitter() { return ((MathUtils.nextRandomFloat() * 2.0f) - 1.0f) * _wanderJitter; }
// 4D simplex noise double noise(final double x, final double y, final double z, final double w) { // The skewing and unskewing factors are hairy again for the 4D case final double F4 = (Math.sqrt(5.0) - 1.0) / 4.0; final double G4 = (5.0 - Math.sqrt(5.0)) / 20.0; double n0, n1, n2, n3, n4; // Noise contributions from the five corners // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in final double s = (x + y + z + w) * F4; // Factor for 4D skewing final int i = (int) MathUtils.floor(x + s); final int j = (int) MathUtils.floor(y + s); final int k = (int) MathUtils.floor(z + s); final int l = (int) MathUtils.floor(w + s); final double t = (i + j + k + l) * G4; // Factor for 4D unskewing final double X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space final double Y0 = j - t; final double Z0 = k - t; final double W0 = l - t; final double x0 = x - X0; // The x,y,z,w distances from the cell origin final double y0 = y - Y0; final double z0 = z - Z0; final double w0 = w - W0; // For the 4D case, the simplex is a 4D shape I won't even try to describe. // To find out which of the 24 possible simplices we're in, we need to // determine the magnitude ordering of x0, y0, z0 and w0. // The method below is a good way of finding the ordering of x,y,z,w and // then find the correct traversal order for the simplex we’re in. // First, six pair-wise comparisons are performed between each possible pair // of the four coordinates, and the results are used to add up binary bits // for an integer index. final int c1 = (x0 > y0) ? 32 : 0; final int c2 = (x0 > z0) ? 16 : 0; final int c3 = (y0 > z0) ? 8 : 0; final int c4 = (x0 > w0) ? 4 : 0; final int c5 = (y0 > w0) ? 2 : 0; final int c6 = (z0 > w0) ? 1 : 0; final int c = c1 + c2 + c3 + c4 + c5 + c6; int i1, j1, k1, l1; // The integer offsets for the second simplex corner int i2, j2, k2, l2; // The integer offsets for the third simplex corner int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w // impossible. Only the 24 indices which have non-zero entries make any sense. // We use a thresholding to set the coordinates in turn from the largest magnitude. // The number 3 in the "simplex" array is at the position of the largest coordinate. i1 = simplex[c][0] >= 3 ? 1 : 0; j1 = simplex[c][1] >= 3 ? 1 : 0; k1 = simplex[c][2] >= 3 ? 1 : 0; l1 = simplex[c][3] >= 3 ? 1 : 0; // The number 2 in the "simplex" array is at the second largest coordinate. i2 = simplex[c][0] >= 2 ? 1 : 0; j2 = simplex[c][1] >= 2 ? 1 : 0; k2 = simplex[c][2] >= 2 ? 1 : 0; l2 = simplex[c][3] >= 2 ? 1 : 0; // The number 1 in the "simplex" array is at the second smallest coordinate. i3 = simplex[c][0] >= 1 ? 1 : 0; j3 = simplex[c][1] >= 1 ? 1 : 0; k3 = simplex[c][2] >= 1 ? 1 : 0; l3 = simplex[c][3] >= 1 ? 1 : 0; // The fifth corner has all coordinate offsets = 1, so no need to look that up. final double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords final double y1 = y0 - j1 + G4; final double z1 = z0 - k1 + G4; final double w1 = w0 - l1 + G4; final double x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords final double y2 = y0 - j2 + 2.0 * G4; final double z2 = z0 - k2 + 2.0 * G4; final double w2 = w0 - l2 + 2.0 * G4; final double x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords final double y3 = y0 - j3 + 3.0 * G4; final double z3 = z0 - k3 + 3.0 * G4; final double w3 = w0 - l3 + 3.0 * G4; final double x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords final double y4 = y0 - 1.0 + 4.0 * G4; final double z4 = z0 - 1.0 + 4.0 * G4; final double w4 = w0 - 1.0 + 4.0 * G4; // Work out the hashed gradient indices of the five simplex corners final int ii = i & 255; final int jj = j & 255; final int kk = k & 255; final int ll = l & 255; final int gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32; final int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32; final int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32; final int gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32; final int gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32; // Calculate the contribution from the five corners double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; if (t0 < 0) { n0 = 0.0; } else { t0 *= t0; n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0); } double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; if (t1 < 0) { n1 = 0.0; } else { t1 *= t1; n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1); } double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; if (t2 < 0) { n2 = 0.0; } else { t2 *= t2; n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2); } double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; if (t3 < 0) { n3 = 0.0; } else { t3 *= t3; n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3); } double t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; if (t4 < 0) { n4 = 0.0; } else { t4 *= t4; n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4); } // Sum up and scale the result to cover the range [-1,1] return 27.0 * (n0 + n1 + n2 + n3 + n4); }
// 3D simplex noise public static double noise(final double xin, final double yin, final double zin) { double n0, n1, n2, n3; // Noise contributions from the four corners // Skew the input space to determine which simplex cell we're in final double F3 = 1.0 / 3.0; final double s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D final int i = (int) MathUtils.floor(xin + s); final int j = (int) MathUtils.floor(yin + s); final int k = (int) MathUtils.floor(zin + s); final double G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too final double t = (i + j + k) * G3; final double X0 = i - t; // Unskew the cell origin back to (x,y,z) space final double Y0 = j - t; final double Z0 = k - t; final double x0 = xin - X0; // The x,y,z distances from the cell origin final double y0 = yin - Y0; final double z0 = zin - Z0; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. // Determine which simplex we are in. int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords if (x0 >= y0) { if (y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order } else { // x0<y0 if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } // Z Y X order else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } // Y Z X order else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // Y X Z order } // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where // c = 1/6. final double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords final double y1 = y0 - j1 + G3; final double z1 = z0 - k1 + G3; final double x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords final double y2 = y0 - j2 + 2.0 * G3; final double z2 = z0 - k2 + 2.0 * G3; final double x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords final double y3 = y0 - 1.0 + 3.0 * G3; final double z3 = z0 - 1.0 + 3.0 * G3; // Work out the hashed gradient indices of the four simplex corners final int ii = i & 255; final int jj = j & 255; final int kk = k & 255; final int gi0 = perm[ii + perm[jj + perm[kk]]] % 12; final int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12; final int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12; final int gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12; // Calculate the contribution from the four corners double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; if (t0 < 0) { n0 = 0.0; } else { t0 *= t0; n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0); } double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; if (t1 < 0) { n1 = 0.0; } else { t1 *= t1; n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1); } double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; if (t2 < 0) { n2 = 0.0; } else { t2 *= t2; n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2); } double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; if (t3 < 0) { n3 = 0.0; } else { t3 *= t3; n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3); } // Add contributions from each corner to get the final noise value. // The result is scaled to stay just inside [-1,1] return 32.0 * (n0 + n1 + n2 + n3); }
// 2D simplex noise public static double noise(final double xin, final double yin) { double n0, n1, n2; // Noise contributions from the three corners // Skew the input space to determine which simplex cell we're in final double F2 = 0.5 * (Math.sqrt(3.0) - 1.0); final double s = (xin + yin) * F2; // Hairy factor for 2D final int i = (int) MathUtils.floor(xin + s); final int j = (int) MathUtils.floor(yin + s); final double G2 = (3.0 - Math.sqrt(3.0)) / 6.0; final double t = (i + j) * G2; final double X0 = i - t; // Unskew the cell origin back to (x,y) space final double Y0 = j - t; final double x0 = xin - X0; // The x,y distances from the cell origin final double y0 = yin - Y0; // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords if (x0 > y0) { i1 = 1; j1 = 0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1) else { i1 = 0; j1 = 1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1) // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where // c = (3-sqrt(3))/6 final double x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords final double y1 = y0 - j1 + G2; final double x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords final double y2 = y0 - 1.0 + 2.0 * G2; // Work out the hashed gradient indices of the three simplex corners final int ii = i & 255; final int jj = j & 255; final int gi0 = perm[ii + perm[jj]] % 12; final int gi1 = perm[ii + i1 + perm[jj + j1]] % 12; final int gi2 = perm[ii + 1 + perm[jj + 1]] % 12; // Calculate the contribution from the three corners double t0 = 0.5 - x0 * x0 - y0 * y0; if (t0 < 0) { n0 = 0.0; } else { t0 *= t0; n0 = t0 * t0 * dot(grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient } double t1 = 0.5 - x1 * x1 - y1 * y1; if (t1 < 0) { n1 = 0.0; } else { t1 *= t1; n1 = t1 * t1 * dot(grad3[gi1], x1, y1); } double t2 = 0.5 - x2 * x2 - y2 * y2; if (t2 < 0) { n2 = 0.0; } else { t2 *= t2; n2 = t2 * t2 * dot(grad3[gi2], x2, y2); } // Add contributions from each corner to get the final noise value. // The result is scaled to return values in the interval [-1,1]. return 70.0 * (n0 + n1 + n2); }