public void orthogonalLineFit(FloatBuffer points) { if (points == null) { return; } points.rewind(); // compute average of points int length = points.remaining() / 3; BufferUtils.populateFromBuffer(origin, points, 0); for (int i = 1; i < length; i++) { BufferUtils.populateFromBuffer(compVec1, points, i); origin.addLocal(compVec1); } origin.multLocal(1f / (float) length); // compute sums of products float sumXX = 0.0f, sumXY = 0.0f, sumXZ = 0.0f; float sumYY = 0.0f, sumYZ = 0.0f, sumZZ = 0.0f; points.rewind(); for (int i = 0; i < length; i++) { BufferUtils.populateFromBuffer(compVec1, points, i); compVec1.subtract(origin, compVec2); sumXX += compVec2.x * compVec2.x; sumXY += compVec2.x * compVec2.y; sumXZ += compVec2.x * compVec2.z; sumYY += compVec2.y * compVec2.y; sumYZ += compVec2.y * compVec2.z; sumZZ += compVec2.z * compVec2.z; } // find the smallest eigen vector for the direction vector compMat1.m00 = sumYY + sumZZ; compMat1.m01 = -sumXY; compMat1.m02 = -sumXZ; compMat1.m10 = -sumXY; compMat1.m11 = sumXX + sumZZ; compMat1.m12 = -sumYZ; compMat1.m20 = -sumXZ; compMat1.m21 = -sumYZ; compMat1.m22 = sumXX + sumYY; compEigen1.calculateEigen(compMat1); direction = compEigen1.getEigenVector(0); }
/** * <code>tessellate</code> generates the <code>BezierMesh</code> vertices from the supplied patch * and detail level. This method is called when patch is set, and therefore, should normally have * to be called. However, if patch is changed externally, and you wish to update the mesh, a call * to <code>tessellate</code> is appropriate. */ public void tessellate() { if (patch == null) { return; } int u = 0, v; float py, px, pyold; int detailLevel = patch.getDetailLevel(); Vector3f[] temp = new Vector3f[4]; Vector3f[] last = new Vector3f[detailLevel + 1]; temp[0] = patch.getAnchor(0, 3); temp[1] = patch.getAnchor(1, 3); temp[2] = patch.getAnchor(2, 3); temp[3] = patch.getAnchor(3, 3); for (v = 0; v <= detailLevel; v++) { px = ((float) v) / ((float) detailLevel); last[v] = calcBerstein(px, temp); } u = 1; setVertexCount(((detailLevel * 2) + 2) * detailLevel); setVertexBuffer(BufferUtils.createVector3Buffer(getVertexCount())); setTextureCoords(new TexCoords(BufferUtils.createFloatBuffer(getVertexCount() * 2), 2), 0); setNormalBuffer(BufferUtils.createVector3Buffer(getVertexCount())); setTriangleQuantity(detailLevel * detailLevel * 6); setIndexBuffer(BufferUtils.createIntBuffer(getTriangleCount() * 3)); getVertexBuffer().clear(); FloatBuffer src = getTextureCoords().get(0).coords; src.clear(); for (u = 1; u <= detailLevel; u++) { py = ((float) u) / ((float) detailLevel); pyold = (u - 1.0f) / (detailLevel); temp[0] = calcBerstein(py, patch.getAnchors()[0]); temp[1] = calcBerstein(py, patch.getAnchors()[1]); temp[2] = calcBerstein(py, patch.getAnchors()[2]); temp[3] = calcBerstein(py, patch.getAnchors()[3]); for (v = 0; v <= detailLevel; v++) { px = ((float) v) / ((float) detailLevel); src.put(pyold).put(px); getVertexBuffer().put(last[v].x).put(last[v].y).put(last[v].z); last[v] = calcBerstein(px, temp); src.put(py).put(px); getVertexBuffer().put(last[v].x).put(last[v].y).put(last[v].z); } } int index = -1; for (int i = 0; i < getTriangleCount(); i = i + 6) { index++; if (i > 0 && i % (detailLevel * 6) == 0) { index += 1; } getIndexBuffer().put(2 * index); getIndexBuffer().put((2 * index) + 1); getIndexBuffer().put((2 * index) + 2); getIndexBuffer().put((2 * index) + 3); getIndexBuffer().put((2 * index) + 2); getIndexBuffer().put((2 * index) + 1); } setNormalBuffer(BufferUtils.createVector3Buffer(getVertexCount())); Vector3f oppositePoint = new Vector3f(); Vector3f adjacentPoint = new Vector3f(); Vector3f rootPoint = new Vector3f(); Vector3f tempNorm = new Vector3f(); int adj = 0, opp = 0, normalIndex = 0; for (int i = 0; i < detailLevel; i++) { for (int j = 0; j < (detailLevel * 2) + 2; j++) { BufferUtils.populateFromBuffer(rootPoint, getVertexBuffer(), normalIndex); if (j % 2 == 0) { if (i == 0) { if (j < (detailLevel * 2)) { // right cross up adj = normalIndex + 1; opp = normalIndex + 2; } else { // down cross right adj = normalIndex - 1; opp = normalIndex + 1; } } else { int ind = normalIndex - (detailLevel * 2 + 1); getNormalBuffer().rewind(); tempNorm.x = getNormalBuffer().get(ind * 3); tempNorm.y = getNormalBuffer().get(ind * 3 + 1); tempNorm.z = getNormalBuffer().get(ind * 3 + 2); tempNorm.normalizeLocal(); BufferUtils.setInBuffer(tempNorm, getNormalBuffer(), normalIndex); normalIndex++; continue; } } else { if (j < (detailLevel * 2) + 1) { // up cross left adj = normalIndex + 2; opp = normalIndex - 1; } else { // left cross down adj = normalIndex - 1; opp = normalIndex - 2; } } BufferUtils.populateFromBuffer(adjacentPoint, getVertexBuffer(), adj); BufferUtils.populateFromBuffer(oppositePoint, getVertexBuffer(), opp); tempNorm .set(adjacentPoint) .subtractLocal(rootPoint) .crossLocal(oppositePoint.subtractLocal(rootPoint)) .normalizeLocal(); BufferUtils.setInBuffer(tempNorm, getNormalBuffer(), normalIndex); normalIndex++; } } }