Подумать только

logoas CogITas

Сомневаться - Трудиться - Любить

× Error from canvas.getContext(): Maybe your browser or hardware (GPU) does not appear to support WebGL. The Canvas for WebGL below will be empty.
Mouse и Num Lock

Выход где-то рядом!

Строим 3D проекты – Шаг 11

Лопатой не собьешь
Лопатой не собьешь

 

   К данному шагу наша программа получила интерфейс (ссылка на программу). Очевидна нехватка информации о том, на какие углы повернут объект в данный момент. Также желательно придать объекту форму, по которой будет в любой момент понятно, где перед и верх фигуры. Сместим фигуру в центр координат, заменим текстуру, и получим такой результат (ссылка на обновленную программу):

Обновляем модель
Обновляем модель

 

   Рассмотрим процесс внесения этих изменений.

 

   Контроль кнопками

   По аналогии с управлением скоростью, введем кнопки и ползунок для управления углом поворота. Например, для поворота относительно оси Х:

	<input class='handonbutton' type='submit' id='clXangleDownID11pr' value='&nbsp;-&nbsp;' onclick='clXangleDown11pr()'>
	Angle-x:
	<span id="x-angle-label11pr">0.000</span>
	<input class='handonbutton' type='submit' id='clXangleUpID11pr' value='+' onclick='clXangleUp11pr()'>
	<input type='range' step='1.0' id='x-angle-range11pr' name='x-angle-range11pr' value='0.000' min='-360.000' max='360.000'/>

   Максимальный угол поворота в каждую сторону – 360 градусов; точность поворота – 1 градус.

   Пропишем новые функции для увеличеня/уменьшения угла, перемещения ползунка:

//--X angle--------------------------------------------------------------------------------
$(document).ready(function()
{
    $("#x-angle-range11pr").change(function()
	{
        var range = $(this);
		var value = parseFloat(range.val());
		var angleXoutRad = -(value*PI/180);

		angleX11pr = angleXoutRad;
		$("#x-angle-label11pr").html(value);
    });
});	

function clXangleDown11pr()
{
	var angleXoutDegr = -(angleX11pr*180/PI).toFixed(0) - 1;
	outAngleX(angleXoutDegr)
}

function clXangleUp11pr()
{
	var angleXoutDegr = -(angleX11pr*180/PI).toFixed(0) + 1;
	outAngleX(angleXoutDegr);

}  

function outAngleX(angleXoutDegr)
{
	//Keep in [-2pi,2pi].
	if(angleXoutDegr > 360)
		angleXoutDegr = -359;
	if(angleXoutDegr < -359)
		angleXoutDegr = 360;	

	var angleXoutRad = -(angleXoutDegr*PI/180);
	angleX11pr = angleXoutRad;

	$("#x-angle-label11pr").html(angleXoutDegr);
	document.getElementById("x-angle-range11pr").value = angleXoutDegr;
}

   В выражении

angleXoutRad = -(value*PI/180);

(var PI=3.141592653589793238462643383;)

мы преобразуем значение в градусах (используемые нами в интерфейсе) в радианы (используемые нами в вычислении модели). Знак минус введен для изменения направления вращения. И еще, мы следим, чтобы угол не вырастал больше 360 градусов.

   Задаем в файле обработчиков кнопок еще одну функцию, которая будет обновлять значение угла в интерфейсе при автоматическом вращении, либо при вращении мышью:

//Common out.
function OutToLabelAndRange()
{
	//X
	if(document.getElementById( "clXbackID11pr" ).value == " | | " ||
	   document.getElementById( "clXforwID11pr" ).value == " | | " ||
	   capture11pr
	  )
	{
		//Keep in [-2pi,2pi].
		if(angleX11pr > 2*Math.PI)                    //360
			angleX11pr = -2*Math.PI;   //-359
		if(angleX11pr < -2*Math.PI )//+ 1*Math.PI/180)   //-359
			angleX11pr = 2*Math.PI;                         //360

		var angleXoutDegr = -(angleX11pr*180/PI).toFixed(0);
		$( "#x-angle-label11pr" ).html(angleXoutDegr);
		document.getElementById( "x-angle-range11pr" ).value = angleXoutDegr;
	}	

//Y
…
//Z
…
}

   Здесь мы наоборот, преобразуем радианы в градусы.

   Также значительно изменится функция сброса настроек в начальные:

function SetInitialSettings11pr()
{
	StopRotation();
	SetEqualSpeeds11pr();

	angleX11pr = initXrotView;

	var angleXoutDegr = -(angleX11pr*180/PI).toFixed(0);
	$("#x-angle-label11pr").html(angleXoutDegr);
	document.getElementById("x-angle-range11pr").value = angleXoutDegr;		

//Y
	…
//Z
…
}

   Теперь начальные углы поворота сцены хранятся в новых глобальных переменных:

		//Start angles in Rad.
		var initXrotView = 0.50;
		var initYrotView =-0.70;
		var initZrotView = 0.00;

   Приготовления закончены, теперь – изменяем главный алгоритм в функции setupWebGL11pr ():

	//Initial scene rotation.
		//Set position of cam.
		mat4.translate(mvMatrix11pr, [0.0, 0.0, -4.0]);		//Zoom.

		//Zoom view.
		mat4.scale(mvMatrix11pr, [zoom11pr, zoom11pr, zoom11pr]);

		if(startProg)
		{
			startProg = !startProg;
			SetInitialSettings11pr();
		}

	//Plus scene rotation this frame.
		mat4.rotate(mvMatrix11pr, angleX11pr, [1.0, 0.0, 0.0]);
		mat4.rotate(mvMatrix11pr, angleY11pr, [0.0, 1.0, 0.0]);
		mat4.rotate(mvMatrix11pr, angleZ11pr, [0.0, 0.0, 1.0]);
		//mat4.rotate(mvMatrix11pr, angle11pr, [0.0, 1.0, 0.0]);
		if( !paused11pr )
		{
			angleX11pr += ASDirectionX11pr * ASspeedX11pr;
			angleY11pr += ASDirectionY11pr * ASspeedY11pr;
			angleZ11pr += ASDirectionZ11pr * ASspeedZ11pr;

			//Out to label and range if auto-rotation.
			OutToLabelAndRange();
		}

 

   Изменение формы и места объекта

   Теперь, к самому интересному. Призму можно преобразовать в похожий на самолет объект смещением некоторых точек, как на схеме ниже:

Трансформация призмы в стелс
Трансформация призмы в стелс

 

   Положение такого объекта в пространстве легче определять визуально, то есть, видно, где у него нос, крылья, днище.

   Сразу после задания начальных точек призмы, сместим их:

	//Move object into center of coords.
	for(var i=0; i<triangleVerticesOriginal.length; i+=3)
	{
		triangleVerticesOriginal[i]   -= 1;
		triangleVerticesOriginal[i+1] -= 1;
		triangleVerticesOriginal[i+2] += 1;
	}

	//Make air plane, moving points of prism.
		var j; //Num of vertice.
		var i; //Num of coord X of vertice j.

		//Forward.
		j = 1; i = j*3;
		triangleVerticesOriginal[i+2] += 3;

		//Right wing.
		j = 6; i = j*3;
		triangleVerticesOriginal[i]   -= 2;
		triangleVerticesOriginal[i+1] += 1;

		//Left wing.
		j = 8; i = j*3;
		triangleVerticesOriginal[i]   += 2;
		triangleVerticesOriginal[i+1] += 1;	

		//Roof.
		j = 5; i = j*3;
		triangleVerticesOriginal[i+1] -= 0.5;
		triangleVerticesOriginal[i+2] -= 1;
		j = 11; i = j*3;
		triangleVerticesOriginal[i+1] -= 0.5;
		triangleVerticesOriginal[i+2] -= 1.5;

		//Back.
		j = 7; i = j*3;
		triangleVerticesOriginal[i+2] -= 1;
		j = 9; i = j*3;
		triangleVerticesOriginal[i+2] -= 1;
		j = 10; i = j*3;
		triangleVerticesOriginal[i+2] -= 1;
Результат трансформации
Результат трансформации

 

   Для симметрии днища мы меняем треугольники на 0-7-1 и 0-6-7. А также добавим треугольник 1-0-2.

	VertexIndices =
	[
	…

/*
		//For prism.
		0,6,1,		//tr17
		1,6,7,		//tr18
		1,7,2,		//tr19
		2,7,8,		//tr20
*/
		//For airplane.
		1,0,2,
		0,6,7,
		2,7,8,
		0,7,2,
	];

   Вуаля! Остается только задать другие текстуры.

 

   Контроль мышью

   Управление мышью пока не изменится, только добавим вывод результатов вращений:

	 $("#my-canvas11pr").mousemove(function(e)
	{
		if(capture11pr)
		{
                        …
                       //Out nums.
			OutToLabelAndRange();
		}
	});

 

   Тесты

   Напоследок, рассмотрим проблему, которую теперь можно легко смоделироавать в нашей программе – шарнирный замок. Изначально, еще до начальных поворотов, наш объект повернут носом вдоль оси Z:

Начальное направление осей
Начальное направление осей

 

   Если мы повернем модель, например, относительно оси Y на 90 градусов, то ось Z совпадет с начальной осью X. Теперь вращение вокруг осей X и Z совпадает, и если мы запустим по ним вращение в разные стороны, то объект будет неподвижен, хотя углы поворота будут меняться:

Демонстрация шарнирного замка
Демонстрация шарнирного замка

 

   Решение для данной проблемы давно найдено, и скоро мы его применим.

Попадание в шарнирный замок
Попадание в шарнирный замок

 

4-е измерение для избегания замка
4-е измерение для избегания замка

 


Оцените, насколько статья оказалась полезной!

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (62 баллов, 13 оценок)
Loading...

<< Предыдущий шаг

Все статьи


Комментарии к “Выход где-то рядом!”

  • Testosteron говорит:

    Ну здорово, что сайт поднят 🙂

    Ответить
  • Оставить комментарий для Testosteron Отменить

    Ваш email не будет отображаться. Обязательные поля помечены *

    (Чтобы установить аватар, необходимо зарегистрировать свой e-mail на gravatar.com. Как это сделать, написано в статье http://cogitas.ru/robots-avatar-icon-wordpress.html)