问题
I'm writing a program that is supposed to draw 3D parametric shapes in webgl. The code I have currently seems to work (mostly) for a sphere, but when I switch out the equations used to find x, y, and z, for a torus, only the top half of the torus is being rendered (in the x-y plane). All of the parametric equations I have (for a sphere, a torus, and a cylinder) work when just the 2d canvas context is used without any webgl; however, when webgl is used, there seems to be a problem. In addition the problem with only rendering half of the torus, the equation used to render the cylinder doesn't render anything.
What could be causing only half of the torus to be rendered? The code for rendering the parametric shapes is below:
var latitudeBands = 30;
var longitudeBands = 30;
var radius = 0.5;
var vertexPositionData = [];
var normalData = [];
var textureCoordData = [];
var indexData = [];
for (var latNumber = 0; latNumber <= latitudeBands; latNumber++)
{ var theta = latNumber * Math.PI / latitudeBands;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
for (var longNumber = 0; longNumber <= longitudeBands; longNumber++) {
var phi = longNumber * 2 * Math.PI / longitudeBands;
var sinPhi = Math.sin(phi);
var cosPhi = Math.cos(phi);
//Equation used for sphere
//var x = Math.cos(phi) * Math.cos(theta);
//var y = Math.cos(phi) * Math.sin(theta);
//var z = Math.sin(phi);
//Equation used for torus
var x = (1 + radius * Math.cos(phi)) * Math.cos(theta);
var y = (1 + radius * Math.cos(phi)) * Math.sin(theta);
var z = radius * Math.sin(phi);
//Equation used for cylinder
//var x = Math.cos(theta);
//var y = Math.sin(theta);
//var z = 2 * latNumber - 1;
var u = 1 - (longNumber / longitudeBands);
var v = 1 - (latNumber / latitudeBands);
normalData.push(x);
normalData.push(y);
normalData.push(z);
textureCoordData.push(u);
textureCoordData.push(v);
vertexPositionData.push(radius * x);
vertexPositionData.push(radius * y);
vertexPositionData.push(radius * z)
}
}
for (var latNumber = 0; latNumber < latitudeBands; latNumber++) {
for (var longNumber = 0; longNumber < longitudeBands; longNumber++) {
var first = (latNumber * (longitudeBands + 1)) + longNumber;
var second = first + longitudeBands + 1;
indexData.push(first);
indexData.push(second);
indexData.push(first + 1);
indexData.push(second);
indexData.push(second + 1);
indexData.push(first + 1);
}
}
moonVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, moonVertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), gl.STATIC_DRAW);
moonVertexPositionBuffer.itemSize = 3;
moonVertexPositionBuffer.numItems = vertexPositionData.length / 3;
moonVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, moonVertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);
moonVertexIndexBuffer.itemSize = 1;
moonVertexIndexBuffer.numItems = indexData.length;
回答1:
Your elevation angle range for a sphere is only PI (from pole to pole), but the range is 2*PI for a torus; Thus
theta = latNumber * Math.PI / latitudeBands
should be
theta = latNumber * 2 * Math.PI / latitudeBands
See WebGL Torus Example.
回答2:
Honestly for these type of problems the most likely error arise from the geometry generation code. I suggest consult the excellent THREE.js source code to check for discrepancies. Toros generation code here.
You can find code for other geometry generation here should you need them in the future.
来源:https://stackoverflow.com/questions/33860167/issue-when-rendering-a-torus-in-webgl