Reputation:
I want to calculate the normals for an icosahedron with its origin at {0.0, 0.0, 0.0}, but I do not have any idea of how to do it!
For example, when i constructed a cube earlier, it was rather simple to get the normals, because each face of the cube was directed parallel either to the x, y or z-axis and the arrays containing the vertices and normals looked like that:
var vertices = [
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
-1.0, -1.0, -1.0, -1.0, 1.0, -1.0,
1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
-1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
-1.0, -1.0, -1.0, 1.0, -1.0, -1.0,
1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
1.0, 1.0, 1.0, 1.0, -1.0, 1.0,
-1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, -1.0
];
var normals = [
0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
0.0, 0.0, -1.0, 0.0, 0.0, -1.0,
0.0, 0.0, -1.0, 0.0, 0.0, -1.0,
0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
0.0, -1.0, 0.0, 0.0, -1.0, 0.0,
0.0, -1.0, 0.0, 0.0, -1.0, 0.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0
];
But now, working on my icosahedron, things are getting a bit more complicated...
Edit 1:
Following the instructions of the answer given, i tried to calculate the normals this way:
First I stored the vertices in a multidimensional Array like that:
var r = (1 + Math.sqrt(5)) / 2;
var triangles = [
[ [-1.0, r, 0.0], [0.0, 1.0, r], [1.0, r, 0.0] ],
[ [1.0, r, 0.0], [0.0, 1.0, -r], [-1.0, r, 0.0] ],
[ [1.0, r, 0.0], [0.0, 1.0, r], [r, 0.0, 1.0] ],
[ [1.0, r, 0.0], [r, 0.0, -1.0], [0.0, 1.0, -r] ],
[ [r, 0.0, -1.0], [1.0, r, 0.0], [r, 0.0, 1.0] ],
[ [-1.0, -r, 0.0], [1.0, -r, 0.0], [0.0, -1.0, r] ],
[ [-1.0, -r, 0.0], [0.0, -1.0, -r], [1.0, -r, 0.0] ],
[ [-1.0, -r, 0.0], [0.0, -1.0, r], [-r, 0.0, 1.0] ],
[ [-1.0, -r, 0.0], [-r, 0.0, -1.0], [0.0, -1.0, -r] ],
[ [-r, 0.0, 1.0], [-r, 0.0, -1.0], [-1.0, -r, 0.0] ],
[ [-1.0, r, 0.0], [-r, 0.0, 1.0], [0.0, 1.0, r] ],
[ [-1.0, r, 0.0], [0.0, 1.0, -r], [-r, 0.0, -1.0] ],
[ [-1.0, r, 0.0], [-r, 0.0, -1.0], [-r, 0.0, 1.0] ],
[ [1.0, -r, 0.0], [r, 0.0, 1.0], [0.0, -1.0, r] ],
[ [1.0, -r, 0.0], [0.0, -1.0, -r], [r, 0.0, -1.0] ],
[ [1.0, -r, 0.0], [r, 0.0, -1.0], [r, 0.0, 1.0] ],
[ [0.0, -1.0, -r], [-r, 0.0, -1.0], [0.0, 1.0, -r] ],
[ [0.0, -1.0, -r], [0.0, 1.0, -r], [r, 0.0, -1.0] ],
[ [0.0, 1.0, r], [-r, 0.0, 1.0], [0.0, -1.0, r] ],
[ [0.0, 1.0, r], [0.0, -1.0, r], [r, 0.0, 1.0] ]
];
Then, based on the given answer, I wrote this function to calculate the normals...
var normals = [ ];
triangles.forEach(function (triangle) {
var v1 = triangle[0],
v2 = triangle[1],
v3 = triangle[2];
var p12 = new Array(3);
p12[0] = v2[0] - v1[0];
p12[1] = v2[1] - v1[1];
p12[2] = v2[2] - v1[2];
var p23 = new Array(3);
p23[0] = v3[0] - v2[0];
p23[1] = v3[1] - v2[1];
p23[2] = v3[2] - v2[2];
var cp = new Array(3);
var x1 = p12[0],
y1 = p12[1],
z1 = p12[2];
var x2 = p23[0],
y2 = p23[1],
z2 = p23[2];
cp[0] = y1 * z2 - z1 * y2;
cp[1] = z1 * x2 - x1 * z2;
cp[2] = x1 * y2 - y1 * x2;
var x = Math.pow(cp[0], 2),
y = Math.pow(cp[1], 2),
z = Math.pow(cp[2], 2);
var len = Math.sqrt(x + y + z);
var normal = new Array(3);
normal[0] = cp[0] / len;
normal[1] = cp[1] / len;
normal[2] = cp[2] / len;
for (var i = 0; i < 3; i++) {
normals.push(normal);
}
});
...to finally unpack and use them:
var unpackedNormals = [ ];
for (var n in normals) {
unpackedNormals = unpackedNormals.concat(normals[n]);
}
var vertexNormalData = unpackedNormals;
But somehow it doesn't work like it should!
I can see the icosahedron on screen, but the lighting of the triangles on the surface seems to be completly wrong.
I ran the same program with my earlier mentioned cube-function instead of the one constructing the icosahedron, and it all works perfectly fine, so I think the error must be located within this new function to calculate the normals.
Maybe someone has an idea what I did wrong?
I'd be thankful for any help!
PS: Please excuse my bad english.
Edit 2: PROBLEM SOLVED!
I changed the order of the vectors in the triangle-array and now all of the triangles behave like they should!
I updated the triangle-array in this post too, so the snipped further up now represents the correct order, AFAIK.
Upvotes: 2
Views: 1634
Reputation: 707
If you are interested in the results only, here below is a Wavefront icosahedron.obj file I exported from Blender with triangulated vertices, textures and normals.
# Blender v2.77 (sub 0) OBJ File: 'icosahedron.blend'
# www.blender.org
mtllib icosahedron.mtl
o Icosphere
v 0.000000 -1.000000 0.000000
v 0.723600 -0.447215 0.525720
v -0.276385 -0.447215 0.850640
v -0.894425 -0.447215 0.000000
v -0.276385 -0.447215 -0.850640
v 0.723600 -0.447215 -0.525720
v 0.276385 0.447215 0.850640
v -0.723600 0.447215 0.525720
v -0.723600 0.447215 -0.525720
v 0.276385 0.447215 -0.850640
v 0.894425 0.447215 0.000000
v 0.000000 1.000000 0.000000
vt 0.6739 0.5441
vt 0.5057 0.4329
vt 0.6731 0.1917
vt 0.5162 0.7848
vt 0.8418 0.4311
vt 0.8321 0.7831
vt 0.3418 0.5689
vt 0.3321 0.2169
vt 1.0162 0.2152
vt 1.0057 0.5671
vt 1.1731 0.8083
vt 0.1731 0.8083
vt 0.1739 0.4559
vt 0.0162 0.2152
vt 0.0057 0.5671
vn 0.1876 -0.7947 0.5774
vn 0.6071 -0.7947 0.0000
vn -0.4911 -0.7947 0.3568
vn -0.4911 -0.7947 -0.3568
vn 0.1876 -0.7947 -0.5774
vn 0.9822 -0.1876 0.0000
vn 0.3035 -0.1876 0.9342
vn -0.7946 -0.1876 0.5774
vn -0.7946 -0.1876 -0.5774
vn 0.3035 -0.1876 -0.9342
vn 0.7946 0.1876 0.5774
vn -0.3035 0.1876 0.9342
vn -0.9822 0.1876 0.0000
vn -0.3035 0.1876 -0.9342
vn 0.7946 0.1876 -0.5774
vn 0.4911 0.7947 0.3568
vn -0.1876 0.7947 0.5774
vn -0.6071 0.7947 0.0000
vn -0.1876 0.7947 -0.5774
vn 0.4911 0.7947 -0.3568
usemtl None
s off
f 1/1/1 2/2/1 3/3/1
f 2/2/2 1/1/2 6/4/2
f 1/1/3 3/3/3 4/5/3
f 1/1/4 4/5/4 5/6/4
f 1/1/5 5/6/5 6/4/5
f 2/2/6 6/4/6 11/7/6
f 3/3/7 2/2/7 7/8/7
f 4/5/8 3/3/8 8/9/8
f 5/6/9 4/5/9 9/10/9
f 6/4/10 5/6/10 10/11/10
f 2/2/11 11/7/11 7/8/11
f 3/3/12 7/8/12 8/9/12
f 4/5/13 8/9/13 9/10/13
f 5/6/14 9/10/14 10/11/14
f 6/4/15 10/12/15 11/7/15
f 7/8/16 11/7/16 12/13/16
f 8/14/17 7/8/17 12/13/17
f 9/15/18 8/14/18 12/13/18
f 10/12/19 9/15/19 12/13/19
f 11/7/20 10/12/20 12/13/20
Upvotes: 2
Reputation: 451
I think what you need is "cross-product", the vector product of two vectors. The cross product will always be perpendicular to the plane defined by the two vectors.
http://en.wikipedia.org/wiki/Cross_product
For each triangle of your icosahedron you have the vectors describing the sides (for example if v1, v2 and v3 are the vectors describing your vertices, the sides are p12 = v2-v1, p23 = v3-v2 and p31 = v1-v3). Your normal will be the cross-product of two of the three vectors normalized (divided by it's modulus), for example
n123 = (p12 x p23) / (|p12 x p23|)
Useful stuff you should know:
difference of two vectors
p12 = v2 - v1 = [x2, y2, z2] - [x1, y1, z1] = [x2-x1, y2-y1, z2-z1]
modulus (length) of a vector:
|v| = |[x, y, z]| = sqrt(x^2 + y^2 + z^2)
Hope this helps.
Upvotes: 2