• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed WebGL zapobieganie zwiększaniu szybkości obrotu

VPS Starter Arubacloud
0 głosów
227 wizyt
pytanie zadane 30 stycznia 2017 w JavaScript przez Mjollnir951 Użytkownik (770 p.)
zamknięte 7 lutego 2017 przez Mjollnir951

Witam! 
Mam pewien problem z moim skryptem WebGL. 
Przy klikaniu przycisku 'Uruchom' obiekt za każdym razem zyskuje na prędkości. Chciałbym, żeby prędkość obrotu była stała, bez względu na to ile razy przycisk zostanie wciśnięty. Proszę o pomoc w tym temacie ;) 

 

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Grafika komputerowa - WebGL</title>
   <link rel="stylesheet" href="CSS/style.css">
   <script src="JS/matrix.js"></script>
   <script src="JS/main.js"></script>
</head>
<body>
	<div>
		<form class="rotationCheckboxes">
			<input type="checkbox" id="rotateX"> Rotacja X&nbsp;&nbsp;&nbsp;
			<input type="checkbox" id="rotateY"> Rotacja Y&nbsp;&nbsp;&nbsp;
			<input type="checkbox" id="rotateZ"> Rotacja Z
		</form>
		<canvas id="glcanvas" width="500" height="300">Brak wsparcia dla elementu HTML canvas.</canvas>
		<br />
		<input type="button" value="Uruchom" onclick="runWebGL()"/>
		<input type="button" value="Zamknij" onclick="self.close()"/> 
   </div>
</body>
</html>
var gl_canvas;
var gl_ctx;

var _triangleVertexBuffer;
var _triangleFacesBuffer;
var _position;
var _color;
var _PosMatrix;
var _MovMatrix;
var _ViewMatrix;
var _matrixProjection;
var _matrixMovement;
var _matrixView;

var rotationSpeed = 0.001;
var zoomRatio = -6;

var X, Y, Z;

function runWebGL () {
   getRotation();
   gl_canvas = document.getElementById("glcanvas");
   gl_ctx = gl_getContext(gl_canvas);
   gl_initShaders();
   gl_initBuffers();
   gl_setMatrix();
   gl_draw();
}

function getRotation() {
   X = document.getElementById('rotateX').checked;
   Y = document.getElementById('rotateY').checked;
   Z = document.getElementById('rotateZ').checked;
}

// ==================================================================== //

function gl_getContext (canvas) {
   try {
      var ctx = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      ctx.viewportWidth = canvas.width;
      ctx.viewportHeight = canvas.height;
   } catch (e) {}

   if (!ctx) {
      document.write('Unable to initialize WebGL. Your browser may not support it.')
   }
   return ctx;
}

// ==================================================================== //

// Declare the shaders. They are pieces of code compiled by WebGL and
// executed on the graphics device. They are written in GLSL.
function gl_initShaders () {
   // position of the point - 0. is Z and 1. is W
   // PosMatrix is uniform variable - its value is constant while rendering an object
   // MovMatrix is the movement matrix of the triangle
   // gl_position -> we move position with MovMatrix before projecting it
   var vertexShader = "\n\
      attribute vec3 position;\n\
      uniform mat4 PosMatrix;\n\
      uniform mat4 MovMatrix;\n\
      uniform mat4 ViewMatrix; \n\
      attribute vec3 color;\n\
      varying vec3 vColor;\n\
      void main(void) {\n\
         gl_Position = PosMatrix * ViewMatrix * MovMatrix * vec4(position, 1.);\n\
         vColor = color;\n\
      }";

   // set black color
   var fragmentShader = "\n\
      precision mediump float;\n\
      varying vec3 vColor;\n\
      void main(void) {\n\
         gl_FragColor = vec4(vColor, 1.);\n\
      }";

   // this function is used to compile a shader
   var getShader = function(source, type, typeString) {
      var shader = gl_ctx.createShader(type);
      gl_ctx.shaderSource(shader, source);
      gl_ctx.compileShader(shader);

      if (!gl_ctx.getShaderParameter(shader, gl_ctx.COMPILE_STATUS)) {
         alert('error in' + typeString);
         return false;
      }
      return shader;
   };

   // Compile the vertex and fragment shaders
   var shader_vertex = getShader(vertexShader, gl_ctx.VERTEX_SHADER, "VERTEX");
   var shader_fragment = getShader(fragmentShader, gl_ctx.FRAGMENT_SHADER, "FRAGMENT");


   // Create the Shader program.
   // Shader program is a combination of a vertex and fragment shaders.
   var SHADER_PROGRAM = gl_ctx.createProgram();
   gl_ctx.attachShader(SHADER_PROGRAM, shader_vertex);
   gl_ctx.attachShader(SHADER_PROGRAM, shader_fragment);


   // Linking of the shader program to the WebGL context - gl_ctx,
   // in order to match the shader variables to javascript variables
   gl_ctx.linkProgram(SHADER_PROGRAM);

   // Link PosMatrix\MovMatrix\ViewMatrix GLSL variables to
   // _PosMatrix\_MovMatrix\_ViewMatrix javascript variables
   // Uniforms do not need to be enabled like attributes
   _PosMatrix = gl_ctx.getUniformLocation(SHADER_PROGRAM, "PosMatrix");
   _MovMatrix = gl_ctx.getUniformLocation(SHADER_PROGRAM, "MovMatrix");
   _ViewMatrix = gl_ctx.getUniformLocation(SHADER_PROGRAM, "ViewMatrix");

   // position GLSL variable links to _position variable
   _position = gl_ctx.getAttribLocation(SHADER_PROGRAM, "position");    // *******
   // color GLSL variable links to _color variable
   _color = gl_ctx.getAttribLocation(SHADER_PROGRAM, "color");
   // enable GLSL attributes variables
   gl_ctx.enableVertexAttribArray(_position);
   gl_ctx.enableVertexAttribArray(_color);
   // linking is over - tells WebGL context to use SHADER_PROGRAM for rendering.
   gl_ctx.useProgram(SHADER_PROGRAM);
}

// ==================================================================== //

function gl_initBuffers () {
   // Point coordinates array of the triangle
//   var triangleVertices = [
//      -1, -1, 0,    // bottom left
//       0, 0, 1,      // submit color: blue
//       1, -1, 0,    // bottom right
//       1, 1, 1,      // submit color: white
//       1, 1, 0,     // top right
//       1, 0, 0       // submit color: red
//   ];
   var triangleVertices = [
    1,0,2,    // wierzchołek #1
    0, 0, 0,       // kolor: czarny
    1,0,0,      // wierzchołek #2
    2, 0, 0,       // kolor: czerwony
    -1,0,1,       // wierzchołek #3
    1, 1, 0,       // kolor: zółty
    0,2,0,       // wierzchołek #4
    0, 1, 0      // kolor: niebieski
];


   // Building Vertex Buffer Object - WebGL vertex array
   _triangleVertexBuffer = gl_ctx.createBuffer();                // *******
   gl_ctx.bindBuffer(gl_ctx.ARRAY_BUFFER, _triangleVertexBuffer);
   gl_ctx.bufferData(gl_ctx.ARRAY_BUFFER, new Float32Array(triangleVertices), gl_ctx.STATIC_DRAW);


   // Triangle faces array
   // var triangleFaces = [0, 1, 2];
   var triangleFaces = [
   0, 1, 2,       // pobierz 1, 2 i 3 wierzchołek z tablicy triangleVertices
   0, 1, 3,
   1, 2, 3,
   0, 2, 3
];

   _triangleFacesBuffer = gl_ctx.createBuffer();                     // *******
   gl_ctx.bindBuffer(gl_ctx.ELEMENT_ARRAY_BUFFER, _triangleFacesBuffer);
   gl_ctx.bufferData(gl_ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(triangleFaces), gl_ctx.STATIC_DRAW);
}

// ==================================================================== //

function gl_setMatrix () {
   _matrixProjection = MATRIX.getProjection(40, gl_canvas.width/gl_canvas.height, 1, 100);
   _matrixMovement = MATRIX.getIdentityMatrix();
   _matrixView = MATRIX.getIdentityMatrix();

   MATRIX.translateZ(_matrixView, zoomRatio);
}

// ==================================================================== //

function gl_draw() {
   // set the color to transparent
   gl_ctx.clearColor(0.0, 0.0, 0.0, 0.0);
   // enable Depth buffer test and set depth buffer comparison function
   gl_ctx.enable(gl_ctx.DEPTH_TEST);
   gl_ctx.depthFunc(gl_ctx.LEQUAL);

   // set the clear value for the depth buffer to 1
   gl_ctx.clearDepth(1.0);

    var timeOld = 0;
	var dAngle = 0;
	
   var animate = function (time) {
       dAngle = rotationSpeed * (time - timeOld);
		
      if (X) {
         MATRIX.rotateX(_matrixMovement, dAngle);
      }
      if (Y) {
         MATRIX.rotateY(_matrixMovement, dAngle);
      }
      if (Z) {
         MATRIX.rotateZ(_matrixMovement, dAngle);
      }

      timeOld = time;

      // set the drawing area on the canvas and clear it
      gl_ctx.viewport(0.0, 0.0, gl_canvas.width, gl_canvas.height);
      gl_ctx.clear(gl_ctx.COLOR_BUFFER_BIT | gl_ctx.DEPTH_BUFFER_BIT);

      // set projection matrix. _matrixProjection is not set yet.
      // It is a javascript array of 1 dimension with 16 floats
      gl_ctx.uniformMatrix4fv(_PosMatrix, false, _matrixProjection);
      gl_ctx.uniformMatrix4fv(_MovMatrix, false, _matrixMovement);
      gl_ctx.uniformMatrix4fv(_ViewMatrix, false, _matrixView);
      // drawing is here - use these points for next drawing
      // gl_ctx.vertexAttribPointer(variable, dimension, type, normalize, total vertex size in bytes, offset)
      gl_ctx.vertexAttribPointer(_position, 3, gl_ctx.FLOAT, false, 4*6, 0);
      gl_ctx.vertexAttribPointer(_color, 3, gl_ctx.FLOAT, false, 4*4, 0);

      gl_ctx.bindBuffer(gl_ctx.ARRAY_BUFFER, _triangleVertexBuffer);
      gl_ctx.bindBuffer(gl_ctx.ELEMENT_ARRAY_BUFFER, _triangleFacesBuffer);

      // draw the triangle
      //gl_ctx.drawElements(gl_ctx.TRIANGLES, 3, gl_ctx.UNSIGNED_SHORT, 0);

      // draw cube
      gl_ctx.drawElements(gl_ctx.TRIANGLES, 12, gl_ctx.UNSIGNED_SHORT, 0);

      // drawing is finished - show the render
      gl_ctx.flush();
      // redraws the scene as soon as ready
      window.requestAnimationFrame(animate);
   };

   // launch animate for the first time
	   animate(timeOld);

}

 

komentarz zamknięcia: Problem rozwiązany we własnym zakresie

2 odpowiedzi

0 głosów
odpowiedź 30 stycznia 2017 przez ShiroUmizake Nałogowiec (46,300 p.)
Stwórz zmieną isActiveObject ustaw wstępnie na false, jeśli obiekt zostanie kliknięty. Zmień wartość na true. Stwórz warunek sprawdzający to na starcie tej funkcji, jak to jest prawda wyjdż z funkcji.

(Metoda dobra, ale nienajlepsza)

Notka: Naucz się używać własnych obiektów w JS. Bo ten teraz kod, nie wygląda za ładnie.
komentarz 30 stycznia 2017 przez Mjollnir951 Użytkownik (770 p.)
function runWebGL () {
   getRotation();
   gl_canvas = document.getElementById("glcanvas");
   gl_ctx = gl_getContext(gl_canvas);
   gl_initShaders();
   gl_initBuffers();
   gl_setMatrix();
   gl_draw();
   isObjectActive = true;
}

Plus

   var animate = function (time) {
       dAngle = rotationSpeed * (time - timeOld);
		
		if(isObjectActive)
		{
			return;
		}

Jeśli o takie rozwiązanie chodziło, niestety teraz wydaje się w ogóle nie wykonywać rotacji. Zakładam, że jest wykonywana tylko jedna rotacja - o bardzo mały kąt. Przy próbie wykonania następnej następuje return. 
Co do jakości kodu to jak najbardziej mam tego świadomość ale dopiero wkraczam w JS'a. Częściej jednak zajmuję się backendem w aplikacjach .Netowych 

komentarz 30 stycznia 2017 przez ShiroUmizake Nałogowiec (46,300 p.)

	
var animate = function (time) {
    if (!isObjectActive){
    dAngle = rotationSpeed * (time - timeOld);
   isObjectActive = true;
   return;
     } 
     else if(isObjectActive)
     {
         return dAngle;
     }

Coś takiego.

Czyli jezeli nie zostala funkcja zainicjonowana wykonaj dAngle (zakładając, że time jest zmienną dynamiczną) innym wypadku zwróć  nie zmienioną wartość dAngle. Gdzie wywołujesz animacje, wykorzystującą animate.

komentarz 30 stycznia 2017 przez bumpMind Gaduła (4,260 p.)
edycja 30 stycznia 2017 przez bumpMind
Znam ten kod, później postaram się znaleźć rozwiązanie jak do tej pory nikt nie pomoże

Edit: Źle spojrzałem na pytanie stąd ten komentarz
0 głosów
odpowiedź 7 lutego 2017 przez Mjollnir951 Użytkownik (770 p.)
Rozwiązaniem jest wywołanie metody runWebGL tylko raz, a w momencie zmiany kierunku rotacji wywołanie metody getRotation.
Jakby ktoś potrzebował większej pomocy z podobnym problemem zapraszam do kontaktu, póki co rozwiązane.

Podobne pytania

0 głosów
0 odpowiedzi 66 wizyt
pytanie zadane 18 sierpnia 2021 w JavaScript przez Qjr Nowicjusz (120 p.)
0 głosów
0 odpowiedzi 118 wizyt
pytanie zadane 19 stycznia 2019 w JavaScript przez MrxCI Dyskutant (8,260 p.)
0 głosów
1 odpowiedź 255 wizyt
pytanie zadane 4 grudnia 2018 w JavaScript przez MrxCI Dyskutant (8,260 p.)

92,453 zapytań

141,262 odpowiedzi

319,087 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...