在webgl中旋转旋转轴

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

因此,我不确定我的问题是更多的编程问题,更多的纯数学问题,还是两者兼而有之。

简短版:我在webgl中有一个旋转的球体,但是它并没有按照我想要的方式旋转。我think我想要的是围绕一个轴旋转球体,然后围绕第二个轴旋转那个轴

因此,我下载并调整了一些javascript webgl代码,这些代码可呈现二十面体,并且可以在合成旋转组中单独或同时使其沿x,y或z轴旋转。我对它的工作方式有所了解。

我还读过(such as here),任何欧拉角旋转组实际上只是产生一些新的净单旋转轴。这意味着仅使用这三个轴的旋转就无法获得想要的动画。

因此,我认为我需要的是一种新的旋转类型,它可以旋转旋转轴本身。但是我不知道如何将其应用于矩阵变换。

    将作为单独的转换实施吗?

  • 是否包含在y轴旋转的几何形状中?
  • 通过绕x轴旋转
  • camera
  • 会更容易实现吗?我应该将其交叉发布到数学堆栈交换中以获取纯数学的帮助吗?
  • 无论是高级概念建议还是详细的代码建议,我都会为您提供帮助。

    下面是我当前正在使用的代码段。它绕y轴旋转,我希望该旋转轴绕x轴旋转。但这与仅同时绕x和y轴进行旋转组不同-只是产生了y = x线的单个复合旋转轴。

    var App = (function () { function App(canvas) { this._canvas = canvas; this._ctx = canvas.getContext('webgl'); this._ctx.viewport(0, 0, canvas.width, canvas.height); this._canvas.setAttribute('width', this._canvas.clientWidth.toString()); this._canvas.setAttribute('height', this._canvas.clientHeight.toString()); this._config = { DrawMode: this._ctx.TRIANGLES, Quality: 3, ZoomLevel: -4, Rotation: { X: 0.0000, Y: 0.0100, Z: 0.0000 } }; } App.prototype._setData = function () { var ctx = this._ctx; var icosahedron = new Icosahedron3D(this._config.Quality); this._vertices = icosahedron.Points.reduce(function (a, b, i) { return i === 1 ? [a.x, a.y, a.z, b.x, b.y, b.z] : a.concat([b.x, b.y, b.z]); }); this._indices = icosahedron.TriangleIndices; this._colors = this._generateColors(this._vertices); var vertex_buffer = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, vertex_buffer); ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(this._vertices), ctx.STATIC_DRAW); var color_buffer = ctx.createBuffer(); ctx.bindBuffer(ctx.ARRAY_BUFFER, color_buffer); ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(this._colors), ctx.STATIC_DRAW); var index_buffer = ctx.createBuffer(); ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, index_buffer); ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(this._indices), ctx.STATIC_DRAW); return { vertex: vertex_buffer, color: color_buffer, index: index_buffer }; }; App.prototype._generateColors = function (vertices) { var colors = []; for (var i = 0; i < vertices.length; i += 3) { var cvalue = 0; var testvalue = 0; if (vertices[i] >= 0) testvalue++; if (vertices[i+1] >= 0) testvalue++; if (vertices[i+2] >= 0) testvalue++; else testvalue = 0; if (testvalue > 0) cvalue = 1; colors.push(cvalue); colors.push(cvalue); colors.push(cvalue); } return colors; } App.prototype._animate = function (proj_matrix, view_matrix, mov_matrix) { var _this = this; var ctx = this._ctx; var rotThetas = this._config.Rotation; var time_old = 0; var zoomLevel_old = 0; var execAnimation = function (time) { var dt = time - time_old; time_old = time; for (var axis in rotThetas) { var theta = rotThetas[axis]; if (theta > 0.0 || theta < 0.0) { Matrix[("Rotate" + axis)](mov_matrix, dt * theta); } } if (Math.abs(_this._config.ZoomLevel - zoomLevel_old) >= 0.01) { view_matrix[14] = view_matrix[14] + (zoomLevel_old * -1) + _this._config.ZoomLevel; zoomLevel_old = _this._config.ZoomLevel; } ctx.enable(ctx.DEPTH_TEST); ctx.depthFunc(ctx.LEQUAL); ctx.clearDepth(1.0); ctx.viewport(0.0, 0.0, _this._canvas.width, _this._canvas.height); ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT); ctx.uniformMatrix4fv(_this._shader.Pmatrix, false, proj_matrix); ctx.uniformMatrix4fv(_this._shader.Vmatrix, false, view_matrix); ctx.uniformMatrix4fv(_this._shader.Mmatrix, false, mov_matrix); ctx.drawElements(_this._config.DrawMode, _this._indices.length, ctx.UNSIGNED_SHORT, 0); window.requestAnimationFrame(execAnimation); }; execAnimation(0); }; App.prototype.Draw = function () { var buffers = this._setData(); this._shader = App.UseQuarternionShaderProgram(this._ctx, buffers.vertex, buffers.color); var proj_matrix = new Float32Array(Matrix.GetProjection(40, this._canvas.width / this._canvas.height, 1, 100)); var view_matrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); var mov_matrix = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); this._animate(proj_matrix, view_matrix, mov_matrix); }; App.UseQuarternionVertShader = function (context) { var vertCode = "\n\t\t\tattribute vec3 position;\n\t\t\tattribute highp vec3 aVertexNormal;\n\t\t\t\n\t\t\tuniform mat4 Pmatrix;\n\t\t\tuniform mat4 Vmatrix;\n\t\t\tuniform mat4 Mmatrix;\n\n\t\t\tattribute vec4 color;\n\t\t\tvarying lowp vec4 vColor;\n\n\t\t\tvarying vec3 vLightWeighting;\n\t\t\t\n\t\t\tuniform vec3 uAmbientColor;\n\t\t\tuniform vec3 uPointLightingLocation;\n\t\t\tuniform vec3 uPointLightingColor;\n\n\t\t\tvoid main(void) {\n\t\t\t\tvec4 mvPosition = Mmatrix * vec4(position, 1.);\n\t\t\t\tgl_Position = Pmatrix*Vmatrix*mvPosition;\n\t\t\t\tgl_PointSize = 4.0;\n\t\t\t\tvColor = color;\n\n\t\t\t\tvec3 lightDirection = normalize(uPointLightingLocation - mvPosition.xyz);\n\t\t\t\tvec3 transformedNormal = vec3(Vmatrix) * aVertexNormal;\n\t\t\t\tfloat directionalLightWeighting = max(dot(transformedNormal, lightDirection), 0.0);\n\t\t\t\tvLightWeighting = uAmbientColor + uPointLightingColor * directionalLightWeighting;\n\t\t\t}"; var vertShader = context.createShader(context.VERTEX_SHADER); context.shaderSource(vertShader, vertCode); context.compileShader(vertShader); return vertShader; }; App.UseVariableFragShader = function (context) { var fragCode = "\n\t\t\tprecision mediump float;\n\t\t\tvarying lowp vec4 vColor;\n\t\t\tvarying vec3 vLightWeighting;\n\t\t\tvoid main(void) {\n\t\t\t\tgl_FragColor = vec4(vColor.rgb, 1.);\n\t\t\t}"; var fragShader = context.createShader(context.FRAGMENT_SHADER); context.shaderSource(fragShader, fragCode); context.compileShader(fragShader); return fragShader; }; App.UseQuarternionShaderProgram = function (ctx, vertex_buffer, color_buffer) { var vertShader = App.UseQuarternionVertShader(ctx); var fragShader = App.UseVariableFragShader(ctx); var shaderProgram = ctx.createProgram(); ctx.attachShader(shaderProgram, vertShader); ctx.attachShader(shaderProgram, fragShader); ctx.linkProgram(shaderProgram); var Pmatrix = ctx.getUniformLocation(shaderProgram, "Pmatrix"); var Vmatrix = ctx.getUniformLocation(shaderProgram, "Vmatrix"); var Mmatrix = ctx.getUniformLocation(shaderProgram, "Mmatrix"); ctx.bindBuffer(ctx.ARRAY_BUFFER, vertex_buffer); var position = ctx.getAttribLocation(shaderProgram, "position"); ctx.vertexAttribPointer(position, 3, ctx.FLOAT, false, 0, 0); ctx.enableVertexAttribArray(position); ctx.bindBuffer(ctx.ARRAY_BUFFER, color_buffer); var color = ctx.getAttribLocation(shaderProgram, "color"); ctx.vertexAttribPointer(color, 3, ctx.FLOAT, false, 0, 0); ctx.enableVertexAttribArray(color); ctx.useProgram(shaderProgram); var ambientColor = ctx.getUniformLocation(shaderProgram, "uAmbientColor"); var pointLightingLocation = ctx.getUniformLocation(shaderProgram, "uPointLightingLocation"); var pointLightingColor = ctx.getUniformLocation(shaderProgram, "uPointLightingColor"); ctx.uniform3f(ambientColor, 0.2, 0.2, 0.2); ctx.uniform3f(pointLightingLocation, 0.0, 0.0, -20.0); ctx.uniform3f(pointLightingColor, 0.8, 0.8, 0.8); return { Pmatrix: Pmatrix, Vmatrix: Vmatrix, Mmatrix: Mmatrix, ShaderProgram: shaderProgram }; }; return App; })(); var Matrix = (function () { function Matrix() { } Matrix.GetProjection = function (angle, a, zMin, zMax) { var ang = Math.tan((angle * .5) * Math.PI / 180); return [ 0.5 / ang, 0, 0, 0, 0, 0.5 * a / ang, 0, 0, 0, 0, -(zMax + zMin) / (zMax - zMin), -1, 0, 0, (-2 * zMax * zMin) / (zMax - zMin), 0 ]; }; Matrix.RotateX = function (m, angle) { var c = Math.cos(angle); var s = Math.sin(angle); var mv1 = m[1], mv5 = m[5], mv9 = m[9]; m[1] = m[1] * c - m[2] * s; m[5] = m[5] * c - m[6] * s; m[9] = m[9] * c - m[10] * s; m[2] = m[2] * c + mv1 * s; m[6] = m[6] * c + mv5 * s; m[10] = m[10] * c + mv9 * s; }; Matrix.RotateY = function (m, angle) { var c = Math.cos(angle); var s = Math.sin(angle); var mv0 = m[0], mv4 = m[4], mv8 = m[8]; m[0] = c * m[0] + s * m[2]; m[4] = c * m[4] + s * m[6]; m[8] = c * m[8] + s * m[10]; m[2] = c * m[2] - s * mv0; m[6] = c * m[6] - s * mv4; m[10] = c * m[10] - s * mv8; }; Matrix.RotateZ = function (m, angle) { var c = Math.cos(angle); var s = Math.sin(angle); var mv0 = m[0], mv4 = m[4], mv8 = m[8]; m[0] = c * m[0] - s * m[1]; m[4] = c * m[4] - s * m[5]; m[8] = c * m[8] - s * m[9]; m[1] = c * m[1] + s * mv0; m[5] = c * m[5] + s * mv4; m[9] = c * m[9] + s * mv8; }; Matrix.Translate = function (a, b, c) { var d = b[0], e = b[1], s = b[2]; if (!c || a == c) { a[12] = a[0] * d + a[4] * e + a[8] * s + a[12]; a[13] = a[1] * d + a[5] * e + a[9] * s + a[13]; a[14] = a[2] * d + a[6] * e + a[10] * s + a[14]; a[15] = a[3] * d + a[7] * e + a[11] * s + a[15]; return a; } var g = a[0], f = a[1], h = a[2], i = a[3], j = a[4], k = a[5], l = a[6], o = a[7], m = a[8], n = a[9], p = a[10], r = a[11]; c[0] = g; c[1] = f; c[2] = h; c[3] = i; c[4] = j; c[5] = k; c[6] = l; c[7] = o; c[8] = m; c[9] = n; c[10] = p; c[11] = r; c[12] = g * d + j * e + m * s + a[12]; c[13] = f * d + k * e + n * s + a[13]; c[14] = h * d + l * e + p * s + a[14]; c[15] = i * d + o * e + r * s + a[15]; return c; }; ; return Matrix; })(); var Icosahedron3D = (function () { function Icosahedron3D(quality) { this._quality = quality; this._calculateGeometry(); } Icosahedron3D.prototype._calculateGeometry = function () { this.Points = []; this.TriangleIndices = []; this._middlePointIndexCache = {}; this._index = 0; var t = (1.0 + Math.sqrt(5.0)) / 2.0; this._addVertex(-1, t, 0); this._addVertex(1, t, 0); this._addVertex(-1, -t, 0); this._addVertex(1, -t, 0); this._addVertex(0, -1, t); this._addVertex(0, 1, t); this._addVertex(0, -1, -t); this._addVertex(0, 1, -t); this._addVertex(t, 0, -1); this._addVertex(t, 0, 1); this._addVertex(-t, 0, -1); this._addVertex(-t, 0, 1); this._addFace(0, 11, 5); this._addFace(0, 5, 1); this._addFace(0, 1, 7); this._addFace(0, 7, 10); this._addFace(0, 10, 11); this._addFace(1, 5, 9); this._addFace(5, 11, 4); this._addFace(11, 10, 2); this._addFace(10, 7, 6); this._addFace(7, 1, 8); this._addFace(3, 9, 4); this._addFace(3, 4, 2); this._addFace(3, 2, 6); this._addFace(3, 6, 8); this._addFace(3, 8, 9); this._addFace(4, 9, 5); this._addFace(2, 4, 11); this._addFace(6, 2, 10); this._addFace(8, 6, 7); this._addFace(9, 8, 1); this._refineVertices(); }; Icosahedron3D.prototype._addVertex = function (x, y, z) { var length = Math.sqrt(x * x + y * y + z * z); this.Points.push({ x: x / length, y: y / length, z: z / length }); return this._index++; }; Icosahedron3D.prototype._addFace = function (x, y, z) { this.TriangleIndices.push(x); this.TriangleIndices.push(y); this.TriangleIndices.push(z); }; Icosahedron3D.prototype._refineVertices = function () { for (var i = 0; i < this._quality; i++) { var faceCount = this.TriangleIndices.length; for (var face = 0; face < faceCount; face += 3) { var x1 = this.TriangleIndices[face]; var y1 = this.TriangleIndices[face + 1]; var z1 = this.TriangleIndices[face + 2]; var x2 = this._getMiddlePoint(x1, y1); var y2 = this._getMiddlePoint(y1, z1); var z2 = this._getMiddlePoint(z1, x1); this._addFace(x1, x2, z2); this._addFace(y1, y2, x2); this._addFace(z1, z2, y2); this._addFace(x2, y2, z2); } } }; Icosahedron3D.prototype._getMiddlePoint = function (p1, p2) { var firstIsSmaller = p1 < p2; var smallerIndex = firstIsSmaller ? p1 : p2; var greaterIndex = firstIsSmaller ? p2 : p1; var key = (smallerIndex << 32) + greaterIndex; var p = this._middlePointIndexCache[key]; if (p !== undefined) p; var point1 = this.Points[p1]; var point2 = this.Points[p2]; var middle = { x: (point1.x + point2.x) / 2.0, y: (point1.y + point2.y) / 2.0, z: (point1.z + point2.z) / 2.0, }; var i = this._addVertex(middle.x, middle.y, middle.z); this._middlePointIndexCache[key] = i; return i; }; return Icosahedron3D; })(); (function () { var app = new App(document.getElementById('canvas')); app.Draw(); })();
    <body style="background-color: rgb(55,55,55);">
    <canvas id="canvas" style="position: absolute;top:0;left:0;width:100%;height:100%;" />
    </body>
    因此,我不确定我的问题是更多的编程问题,更多的纯数学问题还是两者均是。简短版:我在webgl中有一个旋转的球体,但它的旋转方式不是我...
  • javascript matrix webgl
    1个回答
    0
    投票
    因此,最简单的解决方案似乎是移动视图而不是对象的概念。
    © www.soinside.com 2019 - 2024. All rights reserved.