예제 #1
0
  private int getMiddle(int v1, Point2D p1, int v2, Point2D p2) {
    String key = "" + Math.min(v1, v2) + "_" + Math.max(v1, v2);
    if (map.get(key) != null) {
      return map.get(key);
    }

    texCoord1.add(p1.add(p2).multiply(0.5f));

    map.put(key, index.get());
    return index.getAndIncrement();
  }
예제 #2
0
  private TriangleMesh createTetrahedra(float height, int level) {

    TriangleMesh m0 = null;
    if (level > 0) {
      m0 = createTetrahedra(height, level - 1);
    }

    if (level == 0) {
      a = new Affine();
      float hw = height;
      if (center.get() != null) {
        a = a.createConcatenation(new Translate(center.get().x, center.get().y, center.get().z));
      }
      final float[] baseVertices =
          new float[] {
            0f,
            0f,
            0.612372f * hw,
            -0.288675f * hw,
            -0.5f * hw,
            -0.204124f * hw,
            -0.288675f * hw,
            0.5f * hw,
            -0.204124f * hw,
            0.57735f * hw,
            0f,
            -0.204124f * hw
          };

      final float[] baseTexCoords =
          new float[] {
            0f, 0f,
            0.5f, 0.866025f,
            1f, 0f,
            1f, 1.73205f,
            1.5f, 0.866025f,
            2f, 0f
          };

      final int[] baseTexture =
          new int[] {
            0, 2, 1,
            3, 1, 4,
            2, 4, 1,
            4, 2, 5
          };

      final List<Integer> baseFaces = Arrays.asList(1, 2, 3, 2, 1, 0, 3, 0, 1, 0, 3, 2);

      for (int i = 0; i < baseVertices.length / 3; i++) {
        Point3D ta =
            transform(baseVertices[3 * i], baseVertices[3 * i + 1], baseVertices[3 * i + 2]);
        baseVertices[3 * i] = ta.x;
        baseVertices[3 * i + 1] = ta.y;
        baseVertices[3 * i + 2] = ta.z;
      }
      points0 = baseVertices;
      numVertices = baseVertices.length / 3;

      texCoord0 = baseTexCoords;
      numTexCoords = baseTexCoords.length / 2;

      faces0 =
          IntStreams.range(0, baseFaces.size() / 3)
              .mapToObj(
                  i ->
                      IntStreams.of(
                          baseFaces.get(3 * i),
                          baseTexture[3 * i],
                          baseFaces.get(3 * i + 1),
                          baseTexture[3 * i + 1],
                          baseFaces.get(3 * i + 2),
                          baseTexture[3 * i + 2]))
              .flatMapToInt(i -> i)
              .toArray();
      numFaces = baseFaces.size() / 3;
    } else if (m0 != null) {
      points0 = new float[numVertices * m0.getPointElementSize()];
      m0.getPoints().toArray(points0);
    }

    List<Point3D> points1 =
        IntStreams.range(0, numVertices)
            .mapToObj(i -> new Point3D(points0[3 * i], points0[3 * i + 1], points0[3 * i + 2]))
            .collect(Collectors.toList());

    if (level > 0 && m0 != null) {
      texCoord0 = new float[numTexCoords * m0.getTexCoordElementSize()];
      m0.getTexCoords().toArray(texCoord0);
    }

    texCoord1 =
        IntStreams.range(0, numTexCoords)
            .mapToObj(i -> new Point2D(texCoord0[2 * i], texCoord0[2 * i + 1]))
            .collect(Collectors.toList());

    if (level > 0 && m0 != null) {
      faces0 = new int[numFaces * m0.getFaceElementSize()];
      m0.getFaces().toArray(faces0);
    }

    List<Face3> faces1 =
        IntStreams.range(0, numFaces)
            .mapToObj(i -> new Face3(faces0[6 * i], faces0[6 * i + 2], faces0[6 * i + 4]))
            .collect(Collectors.toList());

    index.set(points1.size());
    map.clear();
    listVertices.clear();
    listFaces.clear();
    listVertices.addAll(points1);

    Iterables.forEach(
        faces1,
        face -> {
          int v1 = face.p0;
          int v2 = face.p1;
          int v3 = face.p2;
          if (level > 0) {
            int a = getMiddle(v1, points1.get(v1), v2, points1.get(v2));
            int b = getMiddle(v2, points1.get(v2), v3, points1.get(v3));
            int c = getMiddle(v3, points1.get(v3), v1, points1.get(v1));

            listFaces.add(new Face3(v1, a, c));
            listFaces.add(new Face3(v2, b, a));
            listFaces.add(new Face3(v3, c, b));
            listFaces.add(new Face3(a, b, c));
          } else {
            listFaces.add(new Face3(v1, v2, v3));
          }
        });
    map.clear();
    numVertices = listVertices.size();
    numFaces = listFaces.size();

    List<Face3> textures1;
    if (level == 0) {
      textures1 =
          IntStreams.range(0, faces0.length / 6)
              .mapToObj(i -> new Face3(faces0[6 * i + 1], faces0[6 * i + 3], faces0[6 * i + 5]))
              .collect(Collectors.toList());
    } else {
      textures1 = stream(listTextures).map(t -> t).collect(Collectors.toList());
    }

    index.set(texCoord1.size());
    listTextures.clear();
    Iterables.forEach(
        textures1,
        face -> {
          int v1 = face.p0;
          int v2 = face.p1;
          int v3 = face.p2;
          if (level > 0) {
            int a = getMiddle(v1, texCoord1.get(v1), v2, texCoord1.get(v2));
            int b = getMiddle(v2, texCoord1.get(v2), v3, texCoord1.get(v3));
            int c = getMiddle(v3, texCoord1.get(v3), v1, texCoord1.get(v1));

            listTextures.add(new Face3(v1, a, c));
            listTextures.add(new Face3(v2, b, a));
            listTextures.add(new Face3(v3, c, b));
            listTextures.add(new Face3(a, b, c));
          } else {
            listTextures.add(new Face3(v1, v2, v3));
          }
        });
    map.clear();

    texCoord0 =
        stream(texCoord1)
            .flatMapToDouble(p -> DoubleStreams.of(p.getX(), p.getY()))
            .collect(
                () -> new FloatCollector(texCoord1.size() * 2),
                FloatCollector::add,
                FloatCollector::join)
            .toArray();
    numTexCoords = texCoord0.length / 2;
    textureCoords = texCoord0;
    if (level == getLevel()) {
      areaMesh.setWidth(2f * height);
      areaMesh.setHeight(height * Math.sqrt(3));

      // 1<<j -> bitset, 00100. Otherwise: 000111 will mean they are shared
      smoothingGroups =
          IntStreams.range(0, listFaces.size())
              .map(i -> 1 << (i / (listFaces.size() / 4)))
              .toArray();
      // smoothing groups based on 3DViewer -> same result
      //            float[] normals=new float[]{1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1};
      //            int[] newFaces = IntStreams.range(0, listFaces.size())
      //                        .mapToObj(i->IntStream.of((int)listFaces.get(i).x,
      // (int)listFaces.get(i).x,
      //                                (int)listFaces.get(i).y, (int)listFaces.get(i).y,
      //                                (int)listFaces.get(i).z, (int)listFaces.get(i).z))
      //                        .flatMapToInt(i->i).toArray();
      //            int[] newFaceNormals = IntStreams.range(0,listFaces.size()).mapToObj(i->{
      //                int j=(i/(listFaces.size()/6));
      //                return IntStream.of(j,j,j);
      //            }).flatMapToInt(i->i).toArray();
      //            smoothingGroups=SmoothingGroups.calcSmoothGroups(new TriangleMesh(), newFaces,
      // newFaceNormals, normals);
    }
    return createMesh();
  }