在webgl中绘制圆环

问题描述 投票:0回答:1

我正在尝试使用webgl渲染圆环。我正在使用第三方库,这使此过程更容易:我只需要声明各个顶点,其法线和索引。 3个索引的每个元组绘制一个三角形,并且顶点必须遵循右手定则。

到目前为止,这是我所拥有的:

 this.vertices = [];
        this.indices = [];
        this.normals = [];
        this.texCoords = [];

        let slices_angle = 0;
        let loops_angle = 0;
        let slices_delta = (2 * Math.PI) / this.slices;
        let loops_delta = (2 * Math.PI) / this.loops;
        let abc = 0;

        while (slices_angle < 2 * Math.PI + slices_delta) {
            let cos_slices = Math.cos(slices_angle);
            let sin_slices = Math.sin(slices_angle);
            let cos_loops = Math.cos(loops_angle);
            let sin_loops = Math.sin(loops_angle);

            while (loops_angle < 2 * Math.PI + loops_delta) {
                //   x=(R+r·cos(v))cos(w)
                //   y=(R+r·cos(v))sin(w)
                //             z=r.sin(v)

                let x = (this.outerRad + this.inner_rad * cos_slices) * cos_loops;
                let y = (this.outerRad + this.inner_rad * cos_slices) * sin_loops;
                let z = this.inner_rad * sin_slices;

                this.vertices.push(x, y, z);
                this.normals.push(x, y, z);

                // this.texCoords.push(j / this.slices);
                // this.texCoords.push(i / this.stacks);

                loops_angle += loops_delta;
            }

            slices_angle += slices_delta;
        }

        for (var i = 0; i < this.loops; i++) {
            let v1 = i * (this.slices + 1);
            let v2 = v1 + this.slices + 1;

            for (var j = 0; j < this.slices; j++) {

                this.indices.push(v1);
                this.indices.push(v2);
                this.indices.push(v1 + 1);

                this.indices.push(v1 + 1);
                this.indices.push(v2);
                this.indices.push(v2 + 1);

                v1++;
                v2++;
            }
        }

我在此网站的帮助下声明了顶点的坐标,但是索引存在问题。

example

3d webgl
1个回答
0
投票

乍一看,代码没有多大意义。您有一个内部和外部循环

在内部循环中,此代码计算一个顶点

           let x = (this.outerRad + this.inner_rad * cos_slices) * cos_loops;
           let y = (this.outerRad + this.inner_rad * cos_slices) * sin_loops;
           let z = this.inner_rad * sin_slices;

           this.vertices.push(x, y, z);
           this.normals.push(x, y, z);

但是这些计算在内环内什么都没有改变

然后您的索引将每个切片作为(循环+1)个顶点,所以我认为代码中的循环是向后的。

如果是我,而不是基于我将基于循环和切片循环的角度循环

for (slice = 0; slice < this.slices; ++slice) {
  for (loop = 0; loop < this.loops; ++loop) {
    ...

所以这是另一个版本

const o = {
  slices: 8,
  loops: 20,
  inner_rad: 0.5,
  outerRad: 2,
  makeVerts() {
    this.vertices = [];
    this.indices = [];
    this.normals = [];
    this.texCoords = [];

    for (let slice = 0; slice <= this.slices; ++slice) {
      const v = slice / this.slices;
      const slice_angle = v * 2 * Math.PI;
      const cos_slices = Math.cos(slice_angle);
      const sin_slices = Math.sin(slice_angle);
      const slice_rad = this.outerRad + this.inner_rad * cos_slices;

      for (let loop = 0; loop <= this.loops; ++loop) {
        //   x=(R+r·cos(v))cos(w)
        //   y=(R+r·cos(v))sin(w)
        //             z=r.sin(v)
        const u = loop / this.loops;
        const loop_angle = u * 2 * Math.PI;
        const cos_loops = Math.cos(loop_angle);
        const sin_loops = Math.sin(loop_angle);

        const x = slice_rad * cos_loops;
        const y = slice_rad * sin_loops;
        const z = this.inner_rad * sin_slices;

        this.vertices.push(x, y, z);
        this.normals.push(
           cos_loops * sin_slices, 
           sin_loops * sin_slices, 
           cos_slices);

        this.texCoords.push(u);
        this.texCoords.push(v);
      }
    }
    
    
    // 0  1  2  3  4  5
    // 6  7  8  9  10 11
    // 12 13 14 15 16 17

    const vertsPerSlice = this.loops + 1;
    for (let i = 0; i < this.slices; ++i) {
      let v1 = i * vertsPerSlice;
      let v2 = v1 + vertsPerSlice;

      for (let j = 0; j < this.loops; ++j) {

        this.indices.push(v1);
        this.indices.push(v1 + 1);
        this.indices.push(v2);

        this.indices.push(v2);
        this.indices.push(v1 + 1);
        this.indices.push(v2 + 1);

        v1 += 1;
        v2 += 1;
      }
    }
    //this.indices = undefined;
  },
};
o.makeVerts();

// -------------- ignore below this line -------------

const gl = document.querySelector('canvas').getContext('webgl');
const m4 = twgl.m4;

const vs = `
attribute vec4 position;
attribute vec3 normal;
attribute vec2 texcoord;
uniform mat4 u_matrix;
varying vec3 v_normal;
void main() {
  gl_Position = u_matrix * position;
  v_normal = normal; // just for testing
  //v_normal = vec3(texcoord, 0);  // comment in to see texcoords
  gl_PointSize = 3.0;
}
`;

const fs = `
precision highp float;
varying vec3 v_normal;
void main() {
  gl_FragColor = vec4(v_normal * 0.5 + 0.5, 1);
}
`;

const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
  position: o.vertices,
  normal: o.normals,
  texcoord: o.texCoords,
  indices: o.indices,
});
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
gl.useProgram(programInfo.program);
function render(time) {
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);
  let mat = m4.perspective(
    45 * Math.PI / 180,  // fov
    2,    // aspect
    0.1,  // near
    100,  // far
  );
  mat = m4.translate(mat, [0, 0, -7]);
  mat = m4.rotateY(mat, time * 0.001);
  mat = m4.rotateX(mat, time * 0.0005);
  twgl.setUniforms(programInfo, { u_matrix: mat });
  twgl.drawBufferInfo(gl, bufferInfo);
  //twgl.drawBufferInfo(gl, bufferInfo, gl.POINTS);
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.