source: java/client_3D/src/pl/vorg/mowa/core/graphics/GeometryUtils.java @ 66

Last change on this file since 66 was 66, checked in by Maciej Komosinski, 13 years ago

set 'eol-style' to 'native'

  • Property svn:eol-style set to native
File size: 8.2 KB
Line 
1package pl.vorg.mowa.core.graphics;
2
3import com.framsticks.net.client3D.Log;
4
5/**
6 * A set of helper metods useful with 3d objects.
7 *
8 * @author vorg
9 */
10public class GeometryUtils {
11        public static void generateNormals(Geometry geometry) {
12                VertexStream vertexStream = geometry.getVertexStream();
13                if (vertexStream == null) {
14                        Log.getInstance()
15                                        .log("err",
16                                                        "GeometryUtils.generateNormals err: vertex stream not found");
17                        return;
18                }
19                if (vertexStream.getAttribByName("normal") == null) {
20                        FloatVertexAttrib normalAttrib = new FloatVertexAttrib("normal");
21                        vertexStream.addAttrib(normalAttrib);
22                        float[] normals = new float[((FloatVertexAttrib) vertexStream
23                                        .getAttribByName("pos")).getBuffer().length];
24                        normalAttrib.setBuffer(normals);
25                }
26                if (geometry.getPrimitiveType() == PrimitiveType.Triangles) {
27                        genSmoothTriangleNormals(geometry.getVertexStream());
28                }
29                if (geometry.getPrimitiveType() == PrimitiveType.Quads) {
30                        genSmoothQuadNormals(geometry.getVertexStream());
31                }
32        }
33
34        private static void genSmoothTriangleNormals(VertexStream vertexStream) {
35                IndexBuffer indexBuffer = vertexStream.getIndexBuffer();
36                int[] indices = indexBuffer.getBuffer();
37                FloatVertexAttrib posAttrib = (FloatVertexAttrib) vertexStream
38                                .getAttribByName("pos");
39                float[] positions = posAttrib.getBuffer();
40                FloatVertexAttrib normalAttrib = (FloatVertexAttrib) vertexStream
41                                .getAttribByName("normal");
42                float[] normals = normalAttrib.getBuffer();
43                normalAttrib.setBuffer(normals);
44                Vec3[] faceNormalList = new Vec3[indices.length / 3];
45
46                for (int i = 0; i < indices.length; i += 3) {
47                        Vec3 a = new Vec3(positions[indices[i] * 3],
48                                        positions[indices[i] * 3 + 1],
49                                        positions[indices[i] * 3 + 2]);
50                        Vec3 b = new Vec3(positions[indices[i + 1] * 3],
51                                        positions[indices[i + 1] * 3 + 1],
52                                        positions[indices[i + 1] * 3 + 2]);
53                        Vec3 c = new Vec3(positions[indices[i + 2] * 3],
54                                        positions[indices[i + 2] * 3 + 1],
55                                        positions[indices[i + 2] * 3 + 2]);
56                        Vec3 bsa = Vec3.sub(b, a);
57                        Vec3 bsc = Vec3.sub(b, c);
58                        Vec3 n = Vec3.cross(bsc, bsa);
59                        n.normalize();
60                        faceNormalList[i / 3] = n;
61                }
62
63                // For each vertice.
64                for (int i = 0; i < positions.length; i += 3) {
65                        // Search faces containg the vertice and add a normal vector to it.
66                        float x = positions[i];
67                        float y = positions[i + 1];
68                        float z = positions[i + 2];
69                        Vec3 vertNormal = new Vec3();
70                        for (int j = 0; j < indices.length; j++) {
71                                if ((x == positions[indices[j] * 3])
72                                                && (y == positions[indices[j] * 3 + 1])
73                                                && (z == positions[indices[j] * 3 + 2])) {
74                                        vertNormal.add(faceNormalList[j / 3]);
75                                }
76                        }
77                        vertNormal.normalize();
78                        normals[i] = vertNormal.getX();
79                        normals[i + 1] = vertNormal.getY();
80                        normals[i + 2] = vertNormal.getZ();
81                }
82        }
83
84        private static void genSmoothQuadNormals(VertexStream vertexStream) {
85                IndexBuffer indexBuffer = vertexStream.getIndexBuffer();
86                int[] indices = indexBuffer.getBuffer();
87                FloatVertexAttrib posAttrib = (FloatVertexAttrib) vertexStream
88                                .getAttribByName("pos");
89                float[] positions = posAttrib.getBuffer();
90                FloatVertexAttrib normalAttrib = (FloatVertexAttrib) vertexStream
91                                .getAttribByName("normal");
92                float[] normals = new float[positions.length];
93                normalAttrib.setBuffer(normals);
94                Vec3[] faceNormalList = new Vec3[indices.length / 4];
95
96                for (int i = 0; i < indices.length; i += 4) {
97                        Vec3 a = new Vec3(positions[indices[i] * 3],
98                                        positions[indices[i] * 3 + 1],
99                                        positions[indices[i] * 3 + 2]);
100                        Vec3 b = new Vec3(positions[indices[i + 1] * 3],
101                                        positions[indices[i + 1] * 3 + 1],
102                                        positions[indices[i + 1] * 3 + 2]);
103                        Vec3 c = new Vec3(positions[indices[i + 2] * 3],
104                                        positions[indices[i + 2] * 3 + 1],
105                                        positions[indices[i + 2] * 3 + 2]);
106                        Vec3 bsa = Vec3.sub(b, a);
107                        Vec3 bsc = Vec3.sub(b, c);
108                        Vec3 n = Vec3.cross(bsc, bsa);
109                        n.normalize();
110                        faceNormalList[i / 4] = n;
111                }
112
113                // For each vertice.
114                for (int i = 0; i < positions.length; i += 3) {
115                        // Search faces containg the vertice and add a normal vector to it.
116                        float x = positions[i];
117                        float y = positions[i + 1];
118                        float z = positions[i + 2];
119                        Vec3 vertNormal = new Vec3();
120                        for (int j = 0; j < indices.length; j++) {
121                                if ((x == positions[indices[j] * 3])
122                                                && (y == positions[indices[j] * 3 + 1])
123                                                && (z == positions[indices[j] * 3 + 2])) {
124                                        vertNormal.add(faceNormalList[j / 4]);
125                                }
126                        }
127                        vertNormal.normalize();
128                        normals[i] = vertNormal.getX();
129                        normals[i + 1] = vertNormal.getY();
130                        normals[i + 2] = vertNormal.getZ();
131                }
132        }
133
134        // Isn't tested well.
135        public static void generateTangents(Geometry geometry) {
136                VertexStream vertexStream = geometry.getVertexStream();
137                if (vertexStream == null) {
138                        Log.getInstance()
139                                        .log("err",
140                                                        "GeometryUtils.generateTangents err: vertex stream not found");
141                        return;
142                }
143                if (vertexStream.getAttribByName("tangent") == null) {
144                        FloatVertexAttrib tangentAttrib = new FloatVertexAttrib("tangent");
145                        vertexStream.addAttrib(tangentAttrib);
146                        float[] tangents = new float[((FloatVertexAttrib) vertexStream
147                                        .getAttribByName("pos")).getBuffer().length];
148                        tangentAttrib.setBuffer(tangents);
149                }
150                if (vertexStream.getAttribByName("normal") == null) {
151                        FloatVertexAttrib normalAttrib = new FloatVertexAttrib("normal");
152                        vertexStream.addAttrib(normalAttrib);
153                        float[] normals = new float[((FloatVertexAttrib) vertexStream
154                                        .getAttribByName("pos")).getBuffer().length];
155                        normalAttrib.setBuffer(normals);
156                }
157                if (geometry.getPrimitiveType() == PrimitiveType.Triangles) {
158                        genTriangleTangents(geometry.getVertexStream());
159                }
160        }
161
162        private static void genTriangleTangents(VertexStream vertexStream) {
163                IndexBuffer indexBuffer = vertexStream.getIndexBuffer();
164                int[] indices = indexBuffer.getBuffer();
165                FloatVertexAttrib posAttrib = (FloatVertexAttrib) vertexStream
166                                .getAttribByName("pos");
167                float[] positions = posAttrib.getBuffer();
168                FloatVertexAttrib texCoord0Attrib = (FloatVertexAttrib) vertexStream
169                                .getAttribByName("texCoord0");
170                float[] texCoords0 = texCoord0Attrib.getBuffer();
171                FloatVertexAttrib tangentAttrib = (FloatVertexAttrib) vertexStream
172                                .getAttribByName("tangent");
173                float[] tangents = tangentAttrib.getBuffer();
174
175                for (int i = 0; i < indices.length; i += 3) {
176                        int i1 = indices[i];
177                        int i2 = indices[i + 1];
178                        int i3 = indices[i + 2];
179                        Vec3 pos1 = new Vec3(positions[i1] * 3, positions[i1 * 3 + 1],
180                                        positions[i1 * 3 + 2]);
181                        Vec3 pos2 = new Vec3(positions[i2] * 3, positions[i2 * 3 + 1],
182                                        positions[i2 * 3 + 2]);
183                        Vec3 pos3 = new Vec3(positions[i3] * 3, positions[i3 * 3 + 1],
184                                        positions[i3 * 3 + 2]);
185                        Vec2 coord1 = new Vec2(texCoords0[i1 * 2], texCoords0[i1 * 2 + 1]);
186                        Vec2 coord2 = new Vec2(texCoords0[i2 * 2], texCoords0[i2 * 2 + 1]);
187                        Vec2 coord3 = new Vec2(texCoords0[i3 * 2], texCoords0[i3 * 2 + 1]);
188                        Vec3 v0 = Vec3.sub(pos1, pos2);
189                        Vec3 v1 = Vec3.sub(pos3, pos1);
190                        Vec3 normal = Vec3.normalized(Vec3.cross(v0, v1));
191
192                        float dt0 = coord1.getT() - coord2.getT();
193                        float dt1 = coord3.getT() - coord1.getT();
194                        Vec3 tangent = Vec3.normalized(Vec3.sub(Vec3.mul(dt1, v0),
195                                        Vec3.mul(dt0, v1)));
196
197                        float ds0 = coord1.getS() - coord2.getS();
198                        float ds1 = coord3.getS() - coord1.getS();
199                        Vec3 binormal = Vec3.normalized(Vec3.sub(Vec3.mul(ds1, v0),
200                                        Vec3.mul(ds0, v1)));
201
202                        Vec3 tangentCross = Vec3.cross(tangent, binormal);
203                        if (Vec3.dot(tangentCross, normal) < 0.0f) {
204                                tangent = Vec3.neg(tangent);
205                                binormal = Vec3.neg(binormal);
206                        }
207
208                        tangents[i1 * 3] = tangents[i1 * 3] + tangent.getX();
209                        tangents[i1 * 3 + 1] = tangents[i1 * 3 + 1] + tangent.getY();
210                        tangents[i1 * 3 + 2] = tangents[i1 * 3 + 2] + tangent.getZ();
211
212                        tangents[i2 * 3] = tangents[i2 * 3] + tangent.getX();
213                        tangents[i2 * 3 + 1] = tangents[i2 * 3 + 1] + tangent.getY();
214                        tangents[i2 * 3 + 2] = tangents[i2 * 3 + 2] + tangent.getZ();
215
216                        tangents[i3 * 3] = tangents[i3 * 3] + tangent.getX();
217                        tangents[i3 * 3 + 1] = tangents[i3 * 3 + 1] + tangent.getY();
218                        tangents[i3 * 3 + 2] = tangents[i3 * 3 + 2] + tangent.getZ();
219                }
220
221                for (int j = 0; j < tangents.length; j += 3) {
222                        Vec3 tangent = new Vec3(tangents[j], tangents[j + 1],
223                                        tangents[j + 2]);
224                        tangent.normalize();
225                        tangents[j] = tangent.getX();
226                        tangents[j + 1] = tangent.getY();
227                        tangents[j + 2] = tangent.getZ();
228                }
229
230        }
231}
Note: See TracBrowser for help on using the repository browser.