细分icosphere不呈现正确。不正确的顶点顺序?

问题描述:

我目前正在研究分割我的icosphere,它最终看起来很疯狂(见下文)。它工作正常,如果我不细分它,所以我相信这个错误是在我的递归循环或getMiddlePoint方法(见下文)。我为什么会发生这种情况的想法是,我按照错误的顺序添加了顶点和索引。如果是这种情况,我应该添加什么顺序?有想法该怎么解决这个吗?细分icosphere不呈现正确。不正确的顶点顺序?

结果:

Here

递归循环:

for (int i = 0; i < RECURSION_LEVEL; i++) { 
      List<Vector3i> indices2 = new ArrayList<Vector3i>(); 
      for (Vector3i face : indices) { 
       int a = getMiddlePoint(face.x, face.y); 
       int b = getMiddlePoint(face.y, face.z); 
       int c = getMiddlePoint(face.z, face.x); 

       indices2.add(new Vector3i(face.x, a, c)); 
       indices2.add(new Vector3i(face.y, b, a)); 
       indices2.add(new Vector3i(face.z, c, b)); 
       indices2.add(new Vector3i(a, b, c)); 
      } 
      indices = indices2; 
     } 

getMiddlePoints方法:

private int getMiddlePoint(int p1, int p2) { 
     boolean firstIsSmaller = p1 < p2; 
     int smallerIndex = firstIsSmaller ? p1 : p2; 
     int greaterIndex = firstIsSmaller ? p2 : p1; 
     int key = (smallerIndex << 32) + greaterIndex; 

     Integer ret = middlePointIndexCache.get(key); 
     if (ret != null) { 
      return ret; 
     } 

     Vector3f point1 = vertices.get(p1); 
     Vector3f point2 = vertices.get(p2); 
     Vector3f middle = new Vector3f(
       (point1.x + point2.x)/2.0f, 
       (point1.y + point2.y)/2.0f, 
       (point1.z + point2.z)/2.0f 
       ); 

     int i = addVertex(middle); 
     middlePointIndexCache.put(key, i); 
     return i; 
    } 

所有我icosphere生成的代码: (忽略纹理他们是te的坐标。mporary防止我的渲染器崩溃)

package com.robert.game.planet; 

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import org.joml.Vector2f; 
import org.joml.Vector3f; 
import org.joml.Vector3i; 

import com.robert.engine.loader.Loader; 
import com.robert.engine.models.Mesh; 

public class BasePlanetGenerator { 

    private List<Vector3f> vertices = new ArrayList<Vector3f>(); 
    private List<Vector3f> normals = new ArrayList<Vector3f>(); 
    private List<Vector3i> indices = new ArrayList<Vector3i>(); // think of this as faces 
    private List<Vector2f> textureCoords = new ArrayList<Vector2f>(); 
    private Map<Integer, Integer> middlePointIndexCache = new HashMap<Integer, Integer>(); 

    private static final int RECURSION_LEVEL = 2; 

    private int index = 0; 

    float t = (float) ((1.0 + Math.sqrt(5.0))/2); 

    // Initial vertices 
    { 
//  vertices.add(new Vector3f(-1, t, 0)); 
//  vertices.add(new Vector3f(1, t, 0)); 
//  vertices.add(new Vector3f(-1, -t, 0)); 
//  vertices.add(new Vector3f(1, -t, 0)); 
//  
//  vertices.add(new Vector3f(0, -1, t)); 
//  vertices.add(new Vector3f(0, 1, t)); 
//  vertices.add(new Vector3f(0, -1, -t)); 
//  vertices.add(new Vector3f(0, 1, -t)); 
//  
//  vertices.add(new Vector3f(t, 0, -1)); 
//  vertices.add(new Vector3f(t, 0, 1)); 
//  vertices.add(new Vector3f(-t, 0, -1)); 
//  vertices.add(new Vector3f(-t, 0, 1)); 

     addVertex(new Vector3f(-1, t, 0)); 
     addVertex(new Vector3f(1, t, 0)); 
     addVertex(new Vector3f(-1, -t, 0)); 
     addVertex(new Vector3f(1, -t, 0)); 

     addVertex(new Vector3f(0, -1, t)); 
     addVertex(new Vector3f(0, 1, t)); 
     addVertex(new Vector3f(0, -1, -t)); 
     addVertex(new Vector3f(0, 1, -t)); 

     addVertex(new Vector3f(t, 0, -1)); 
     addVertex(new Vector3f(t, 0, 1)); 
     addVertex(new Vector3f(-t, 0, -1)); 
     addVertex(new Vector3f(-t, 0, 1)); 
    } 

    // Initial indices 
    { 
     indices.add(new Vector3i(0, 11, 5)); 
     indices.add(new Vector3i(0, 5, 1)); 
     indices.add(new Vector3i(0, 1, 7)); 
     indices.add(new Vector3i(0, 7, 10)); 
     indices.add(new Vector3i(0, 10, 11)); 

     indices.add(new Vector3i(1, 5, 9)); 
     indices.add(new Vector3i(5, 11, 4)); 
     indices.add(new Vector3i(11, 10, 2)); 
     indices.add(new Vector3i(10, 7, 6)); 
     indices.add(new Vector3i(7, 1, 8)); 

     indices.add(new Vector3i(3, 9, 4)); 
     indices.add(new Vector3i(3, 4, 2)); 
     indices.add(new Vector3i(3, 2, 6)); 
     indices.add(new Vector3i(3, 6, 8)); 
     indices.add(new Vector3i(3, 8, 9)); 

     indices.add(new Vector3i(4, 9, 5)); 
     indices.add(new Vector3i(2, 4, 11)); 
     indices.add(new Vector3i(6, 2, 10)); 
     indices.add(new Vector3i(8, 6, 7)); 
     indices.add(new Vector3i(9, 8, 1)); 

//  indices = Arrays.asList(new Integer[] { 
//    0, 11, 5, 
//    0, 5, 1, 
//    0, 1, 7, 
//    0, 7, 10, 
//    0, 10, 11, 
//    
//    1, 5, 9, 
//    5, 11, 4, 
//    11, 10, 2, 
//    10, 7, 6, 
//    7, 1, 8, 
//    
//    3, 9, 4, 
//    3, 4, 2, 
//    3, 2, 6, 
//    3, 6, 8, 
//    3, 8, 9, 
//    
//    4, 9, 5, 
//    2, 4, 11, 
//    6, 2, 10, 
//    8, 6, 7, 
//    9, 8, 1 
//  }); 
    } 

    // Inital textureCoords 
    { 
     textureCoords.add(new Vector2f(1, 1)); 
    } 

    float[] verticesArray; 
    int[] indicesArray; 
    float[] normalsArray; 
    float[] textureCoordsArray; 

    public Mesh generateBasePlanet(Loader loader) { 

     for (int i = 0; i < RECURSION_LEVEL; i++) { 
      List<Vector3i> indices2 = new ArrayList<Vector3i>(); 
      for (Vector3i face : indices) { 
       int a = getMiddlePoint(face.x, face.y); 
       int b = getMiddlePoint(face.y, face.z); 
       int c = getMiddlePoint(face.z, face.x); 

       indices2.add(new Vector3i(face.x, a, c)); 
       indices2.add(new Vector3i(face.y, b, a)); 
       indices2.add(new Vector3i(face.z, c, b)); 
       indices2.add(new Vector3i(a, b, c)); 
      } 
      indices = indices2; 
     } 

     for (int i = 0; i < vertices.size(); i ++) { 
      Vector3f normal = vertices.get(i); 
//   normal.normalize(); 
//   float length = normal.length();  
//   normals.add(new Vector3f(normal.x/length, normal.y/length, normal.z/length)); 
      normals.add(normal); 
     } 

     convertToArrays(); 

     return loader.createMesh(verticesArray, textureCoordsArray, normalsArray, indicesArray); 
    } 

    private int getMiddlePoint(int p1, int p2) { 
     boolean firstIsSmaller = p1 < p2; 
     int smallerIndex = firstIsSmaller ? p1 : p2; 
     int greaterIndex = firstIsSmaller ? p2 : p1; 
     int key = (smallerIndex << 32) + greaterIndex; 

     Integer ret = middlePointIndexCache.get(key); 
     if (ret != null) { 
      return ret; 
     } 

     Vector3f point1 = vertices.get(p1); 
     Vector3f point2 = vertices.get(p2); 
     Vector3f middle = new Vector3f(
       (point1.x + point2.x)/2.0f, 
       (point1.y + point2.y)/2.0f, 
       (point1.z + point2.z)/2.0f 
       ); 

     int i = addVertex(middle); 
     middlePointIndexCache.put(key, i); 
     return i; 
    } 

    private void convertToArrays() { 
     verticesArray = new float[vertices.size() * 3]; 
     indicesArray = new int[indices.size() * 3]; 
     normalsArray = new float[normals.size() * 3]; 
     textureCoordsArray = new float[textureCoords.size() * 2]; 

     for (int i = 0; i < vertices.size(); i ++) {   
      Vector3f vertex = vertices.get(i); 
      verticesArray[(i * 3)] = vertex.x; 
      verticesArray[(i * 3) + 1] = vertex.y; 
      verticesArray[(i * 3) + 2] = vertex.z; 
     } 

     for (int i = 0; i < indices.size(); i ++) { 
      Vector3i indice = indices.get(i); 
      indicesArray[(i * 3)] = indice.x; 
      indicesArray[(i * 3) + 1] = indice.y; 
      indicesArray[(i * 3) + 2] = indice.z; 
//   indicesArray[i] = indices.get(i); 
     } 

     for (int i = 0; i < normals.size(); i ++) { 
      Vector3f normal = normals.get(i); 
      normalsArray[(i * 3)] = normal.x; 
      normalsArray[(i * 3) + 1] = normal.y; 
      normalsArray[(i * 3) + 2] = normal.z; 
     } 

     for (int i = 0; i < textureCoords.size(); i ++) { 
      textureCoordsArray[(i * 2)] = textureCoords.get(i).x; 
      textureCoordsArray[(i * 2) + 1] = textureCoords.get(i).y; 
     } 
    } 

    private int addVertex(Vector3f vector) { 
     float length = vector.length(); 
     vertices.add(new Vector3f(vector.x/length, vector.y/length, vector.z/length)); 
     return index++; 
    } 
} 

oracle java specification明确表示:

的整数类型的值是在下列范围内的整数:
- 对于int,从-2147483648到2147483647,含

这意味着数据类型int是一个整数数据类型,大小为32位。

在功能getMiddlePoint,线

int key = (smallerIndex << 32) + greaterIndex; 

导致溢出。

将其更改为

int key = (smallerIndex << 16) + greaterIndex; 

和您的代码将适当的工作。

+0

谢谢!我不能为我的生活弄明白。 –