2012-05-23 7 views
1

을 libgdx :이 클래스를 사용하여 그릴 때병합은 OpenGL을 메쉬 나는 여러 메시를 병합하려면 다음 코드를 사용하고

import java.util.ArrayList; 
import java.util.Arrays; 

import org.obsgolem.crystalia.gfx.Renderer; 

import com.badlogic.gdx.graphics.Mesh; 
import com.badlogic.gdx.graphics.VertexAttribute; 
import com.badlogic.gdx.graphics.VertexAttributes.Usage; 
import com.badlogic.gdx.math.Vector3; 
import com.badlogic.gdx.utils.Array; 
import java.util.*; 

public class MeshBatch 
{ 

    private final static VertexAttribute[] attributeConfig = new VertexAttribute[]{ 
     new VertexAttribute(Usage.Position, 3, "a_position"), 
     new VertexAttribute(Usage.ColorPacked, 4, "a_color"), 
     new VertexAttribute(Usage.Normal, 3, "a_normal")}; 
    private final static int VERTEX_SIZE = 3 + 1 + 3; 

    private Mesh m; 
    private List<Float> vertices = new ArrayList<Float>(); 
    private List<Short> indices = new ArrayList<Short>(); 

    public void addMesh(float[] vert, short[] ind) 
    { 
     int offset = (vertices.size()/VERTEX_SIZE); 

     //You have to throw an exception when you get over the limit of short indices 
     if (offset + vert.length/VERTEX_SIZE > Short.MAX_VALUE) { 
      throw new RuntimeException("blablabla"); 
     } 

     for (short i : addOffset(ind, offset)) { 
      indices.add(i); 
     } 

     for (float v : vert) { 
      vertices.add(v); 
     } 
    } 

    public short[] addOffset(short[] ind, int offset) 
    { 
     short[] indarr = new short[ind.length]; 
     for (int i = 0; i < ind.length; ++i) { 
      //Do you really need this check? You are the only one using this code 
      //so make sure that you never provide a null value. If you really want to have a chekc throw an exception instead 
      short value = ind[i];//ind[i] == null ? 0 : ind[i]; 
      indarr[i] = (short) (value + offset); 
     } 
     return indarr; 
    } 


    public void end() 
    { 
     m = new Mesh(false, vertices.size(), indices.size(), attributeConfig); 
     m.setVertices(Renderer.makeFloatArray(vertices)); 
     m.setIndices(Renderer.makeShortArray(indices)); 
    } 

    public void render() 
    { 
     Renderer.getInstance().render(m); 
    } 
} 

그러나 나는 조명 이상한 효과를 얻을. 이 메시로 빛은 다른 모든 물체에 비해 밝아지며 렌더링 된 이미지는 평평하게 보입니다. 정상적인 방법 (각 물체에 대한 분리 메쉬)을 사용하면 멋진 부드러운 라이팅을 얻을 수 있습니다.

병합 된 메쉬 :
Merged mesh lighting

병합 된 메쉬없이 : 여기가했다 두 스크린 샷입니다
Smooth per pixel lighting without merged mesh

무엇이 문제를 일으키는 지, 그리고 어떻게 다른 메쉬의 조명에 영향을 줄 수? 내 꼭지점은 올바른 형식으로 전송됩니다 (정점의 경우 3 개, 색상의 경우 1 개, 법선의 경우 3 개). 제 색인도 잘 작동합니다. 메쉬가 실제로 렌더링 될 때만 문제가 발생합니다. 그것이 없으면 조명이 완벽하게 작동합니다. 문제는 법선과 관련이 있다고 생각하지만 문제가 무엇인지 알 수는 없습니다.

편집 : 문제가 해결 된 것 같습니다. 타일을 별도의 메쉬에서 메쉬 배치로 바꿨을 때 조명 자체가 고정되었습니다. 어떻게 이런 일이 일어날 수 있겠습니까?

+0

나는 libgdx에 대해 아무 생각이 없다, 그래서 나는 대답하고 싶지 않아요. 그러나 도움이되는 몇 가지 : (1) 평면 음영은 얼굴의 모든 법선이 같은 방향을 가리키고 있음을 의미합니다. 그러니 그들을 인쇄 해보고 그런 경우인지 확인하십시오. (2) 빛으로부터의 거리를 계산할 때 문제가 될 수도있다. 어쩌면 모든 법선이 같은 방향으로 향하게 될지도 모르지만 모든 꼭지점에 대해 같은 거리가되도록 빛의 거리를 계산하고있는 것입니다. 어떤 조명 모델을 사용하는지 모르겠으므로 더 도움이되지 못합니다. – Max

+0

@Max 픽셀 당 조명을 사용하고 있습니다. 각 메쉬는 큐브입니다. 큐브면이 한 방향을 가리키는 법선이 아닌가? – jbills

+0

유용하다고 말할만한 정보가 충분하지 않습니다. 하나의 float를 사용한다고 주장하면 Color에 대한 VertexAttribute에 '4'를 보내면 이상하지만,이 클래스가 무엇을하는지 전혀 모르겠다. – Tim

답변

0

이이 question의 애 스커을 위해 잘 작동하는 것 같다 :

public static Mesh mergeMeshes(AbstractList<Mesh> meshes, AbstractList<Matrix4> transformations) 
{ 
    if(meshes.size() == 0) return null; 

    int vertexArrayTotalSize = 0; 
    int indexArrayTotalSize = 0; 

    VertexAttributes va = meshes.get(0).getVertexAttributes(); 
    int vaA[] = new int [va.size()]; 
    for(int i=0; i<va.size(); i++) 
    { 
     vaA[i] = va.get(i).usage; 
    } 

    for(int i=0; i<meshes.size(); i++) 
    { 
     Mesh mesh = meshes.get(i); 
     if(mesh.getVertexAttributes().size() != va.size()) 
     { 
      meshes.set(i, copyMesh(mesh, true, false, vaA)); 
     } 

     vertexArrayTotalSize += mesh.getNumVertices() * mesh.getVertexSize()/4; 
     indexArrayTotalSize += mesh.getNumIndices(); 
    } 

    final float vertices[] = new float[vertexArrayTotalSize]; 
    final short indices[] = new short[indexArrayTotalSize]; 

    int indexOffset = 0; 
    int vertexOffset = 0; 
    int vertexSizeOffset = 0; 
    int vertexSize = 0; 

    for(int i=0; i<meshes.size(); i++) 
    { 
     Mesh mesh = meshes.get(i); 

     int numIndices = mesh.getNumIndices(); 
     int numVertices = mesh.getNumVertices(); 
     vertexSize = mesh.getVertexSize()/4; 
     int baseSize = numVertices * vertexSize; 
     VertexAttribute posAttr = mesh.getVertexAttribute(Usage.Position); 
     int offset = posAttr.offset/4; 
     int numComponents = posAttr.numComponents; 

     { //uzupelnianie tablicy indeksow 
      mesh.getIndices(indices, indexOffset); 
      for(int c = indexOffset; c < (indexOffset + numIndices); c++) 
      { 
       indices[c] += vertexOffset; 
      } 
      indexOffset += numIndices; 
     } 

     mesh.getVertices(0, baseSize, vertices, vertexSizeOffset); 
     Mesh.transform(transformations.get(i), vertices, vertexSize, offset, numComponents, vertexOffset, numVertices); 
     vertexOffset += numVertices; 
     vertexSizeOffset += baseSize; 
    } 

    Mesh result = new Mesh(true, vertexOffset, indices.length, meshes.get(0).getVertexAttributes()); 
    result.setVertices(vertices); 
    result.setIndices(indices); 
    return result; 
} 

    public static Mesh copyMesh(Mesh meshToCopy, boolean isStatic, boolean removeDuplicates, final int[] usage) { 
    // TODO move this to a copy constructor? 
    // TODO duplicate the buffers without double copying the data if possible. 
    // TODO perhaps move this code to JNI if it turns out being too slow. 
    final int vertexSize = meshToCopy.getVertexSize()/4; 
    int numVertices = meshToCopy.getNumVertices(); 
    float[] vertices = new float[numVertices * vertexSize]; 
    meshToCopy.getVertices(0, vertices.length, vertices); 
    short[] checks = null; 
    VertexAttribute[] attrs = null; 
    int newVertexSize = 0; 
    if (usage != null) { 
     int size = 0; 
     int as = 0; 
     for (int i = 0; i < usage.length; i++) 
      if (meshToCopy.getVertexAttribute(usage[i]) != null) { 
       size += meshToCopy.getVertexAttribute(usage[i]).numComponents; 
       as++; 
      } 
     if (size > 0) { 
      attrs = new VertexAttribute[as]; 
      checks = new short[size]; 
      int idx = -1; 
      int ai = -1; 
      for (int i = 0; i < usage.length; i++) { 
       VertexAttribute a = meshToCopy.getVertexAttribute(usage[i]); 
       if (a == null) 
        continue; 
       for (int j = 0; j < a.numComponents; j++) 
        checks[++idx] = (short)(a.offset/4 + j); 
       attrs[++ai] = new VertexAttribute(a.usage, a.numComponents, a.alias); 
       newVertexSize += a.numComponents; 
      } 
     } 
    } 
    if (checks == null) { 
     checks = new short[vertexSize]; 
     for (short i = 0; i < vertexSize; i++) 
      checks[i] = i; 
     newVertexSize = vertexSize; 
    } 

    int numIndices = meshToCopy.getNumIndices(); 
    short[] indices = null; 
    if (numIndices > 0) { 
     indices = new short[numIndices]; 
     meshToCopy.getIndices(indices); 
     if (removeDuplicates || newVertexSize != vertexSize) { 
      float[] tmp = new float[vertices.length]; 
      int size = 0; 
      for (int i = 0; i < numIndices; i++) { 
       final int idx1 = indices[i] * vertexSize; 
       short newIndex = -1; 
       if (removeDuplicates) { 
        for (short j = 0; j < size && newIndex < 0; j++) { 
         final int idx2 = j*newVertexSize; 
         boolean found = true; 
         for (int k = 0; k < checks.length && found; k++) { 
          if (tmp[idx2+k] != vertices[idx1+checks[k]]) 
           found = false; 
         } 
         if (found) 
          newIndex = j; 
        } 
       } 
       if (newIndex > 0) 
        indices[i] = newIndex; 
       else { 
        final int idx = size * newVertexSize; 
        for (int j = 0; j < checks.length; j++) 
         tmp[idx+j] = vertices[idx1+checks[j]]; 
        indices[i] = (short)size; 
        size++; 
       } 
      } 
      vertices = tmp; 
      numVertices = size; 
     } 
    } 

    Mesh result; 
    if (attrs == null) 
     result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, meshToCopy.getVertexAttributes()); 
    else 
     result = new Mesh(isStatic, numVertices, indices == null ? 0 : indices.length, attrs); 
    result.setVertices(vertices, 0, numVertices * newVertexSize); 
    result.setIndices(indices); 
    return result; 
} 
관련 문제