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(); }
/** * 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() { // 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 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); }
/**