在Java中查找顶点法线的代码?

时间:2011-02-13 10:30:12

标签: java android objective-c opengl-es

我在此source中使用此代码:

#import <Foundation/Foundation.h>
#import "OpenGLCommon.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSMutableString *result = [NSMutableString string];

    static const Vertex3D vertices[]= {
        {0, -0.525731, 0.850651},             // vertices[0]
        {0.850651, 0, 0.525731},              // vertices[1]
        {0.850651, 0, -0.525731},             // vertices[2]
        {-0.850651, 0, -0.525731},            // vertices[3]
        {-0.850651, 0, 0.525731},             // vertices[4]
        {-0.525731, 0.850651, 0},             // vertices[5]
        {0.525731, 0.850651, 0},              // vertices[6]
        {0.525731, -0.850651, 0},             // vertices[7]
        {-0.525731, -0.850651, 0},            // vertices[8]
        {0, -0.525731, -0.850651},            // vertices[9]
        {0, 0.525731, -0.850651},             // vertices[10]
        {0, 0.525731, 0.850651}               // vertices[11]
    };

    static const GLubyte icosahedronFaces[] = {
        1, 2, 6,
        1, 7, 2,
        3, 4, 5,
        4, 3, 8,
        6, 5, 11,
        5, 6, 10,
        9, 10, 2,
        10, 9, 3,
        7, 8, 9,
        8, 7, 0,
        11, 0, 1,
        0, 11, 4,
        6, 2, 10,
        1, 6, 11,
        3, 5, 10,
        5, 4, 11,
        2, 7, 9,
        7, 1, 0,
        3, 9, 8,
        4, 8, 0,
    };

    Vector3D *surfaceNormals = calloc(20, sizeof(Vector3D));

    // Calculate the surface normal for each triangle

    for (int i = 0; i < 20; i++)
    {
        Vertex3D vertex1 = vertices[icosahedronFaces[(i*3)]];
        Vertex3D vertex2 = vertices[icosahedronFaces[(i*3)+1]];
        Vertex3D vertex3 = vertices[icosahedronFaces[(i*3)+2]];
        Triangle3D triangle = Triangle3DMake(vertex1, vertex2, vertex3);
        Vector3D surfaceNormal = Triangle3DCalculateSurfaceNormal(triangle);
        Vector3DNormalize(&surfaceNormal);
        surfaceNormals[i] = surfaceNormal;
    }

    Vertex3D *normals = calloc(12, sizeof(Vertex3D));
    [result appendString:@"static const Vector3D normals[] = {\n"];
    for (int i = 0; i < 12; i++)
    {
        int faceCount = 0;
        for (int j = 0; j < 20; j++)
        {
            BOOL contains = NO;
            for (int k = 0; k < 3; k++)
            {
                if (icosahedronFaces[(j * 3) + k] == i)
                    contains = YES;
            }
            if (contains)
            {
                faceCount++;
                normals[i] = Vector3DAdd(normals[i], surfaceNormals[j]);
            }
        }

        normals[i].x /= (GLfloat)faceCount;
        normals[i].y /= (GLfloat)faceCount;
        normals[i].z /= (GLfloat)faceCount;
        [result appendFormat:@"\t{%f, %f, %f},\n", normals[i].x, normals[i].y, normals[i].z];
    }
    [result appendString:@"};\n"];
    NSLog(result);
    [pool drain];
    return 0;
}

有人可以指点我做与上面相同的Java代码吗?我还需要对其进行修改,使其不仅适用于isohadron,而且适用于任何具有相关索引数组的顶点数组。

1 个答案:

答案 0 :(得分:5)

这适用于任何基于三角形的网格。

for(int i = 0; i < indices.Length; i += 3)
{
   Vector3 v0 = vertices[indicies[i]].Position;
   Vector3 v1 = vertices[indicies[i+1]].Position;
   Vector3 v2 = vertices[indicies[i+2]].Position;

   Vector3 normal = Vector3.Normalize(Vector3.Cross(v2 - v0, v1 - v0));

   vertices[indicies[i]].Normal += normal;
   vertices[indicies[i+1]].Normal += normal;
   vertices[indicies[i+2]].Normal += normal;
}
for(int i = 0; i < vertices.Length; i++)
{
   vertices[i].Normal = Vector3.Normalize(vertices[i].Normal);
}

这是一个精简版的Vector3结构

public struct Vector3
{
   float X, Y, Z;

   public Vector3(float x, float y, float z)
   {
      X = x; Y = y; Z = z;
   }

   public static Vector3 Cross(Vector3 v1, Vector3 v2)
   {
      Vector3 result;
      result.X = (v1.Y * v2.Z) - (v1.Z * v2.Y);
      result.Y = (v1.Z * v2.X) - (v1.X * v2.Z);
      result.Z = (v1.X * v2.Y) - (v1.Y * v2.X);
      return result;
   }
   public static Vector3 Normalize(Vector3 v1)
   {
       float length = v1.X * v1.X + v1.Y * v1.Y + v1.Z * v1.Z;
       length = Math.Sqrt(length);
       v1.X /= length; v1.Y /= length; v1.Z /= length;
   }
}

我希望有所帮助。