1 | package pl.vorg.mowa.core.graphics;
|
---|
2 |
|
---|
3 | import com.framsticks.net.client3D.Log;
|
---|
4 |
|
---|
5 | /**
|
---|
6 | * A set of helper metods useful with 3d objects.
|
---|
7 | *
|
---|
8 | * @author vorg
|
---|
9 | */
|
---|
10 | public 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 | }
|
---|