Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Отражённый луч (http://www.flasher.ru/forum/showthread.php?t=149746)

semenyakinVS 31.01.2011 01:05

Отражённый луч
 
Вложений: 1
Пишу трассировщик лучей.

Есть ядро, есть хороший математический аппарат, но возникла совершенно неожиданная и ужасно раздражающая проблема. Нужно посчитать угол отражённого луча...

Думал - фигня, за пять минут решу. Ан нет! Забыл, что углы бывают отрицательные. Начал рассматривать все случаи и понял, что дело принимает нехороший оборот. Чтобы всё отражалось без глюков надо учитывать восемь случаев: зеркало имеет положительный угол, отрицательный, и четыре варианта для луча (выше зеркала, ниже его и для каждого угол положительный, или отрицательный)! Хуже всего, что надо смотреть расположение точки относительно отрезка. А это – векторное произведение! Два умножения и разница.

Короче, плохо. Что делать, подскажете, а?

Примечания:
1. Зеркало задано отрезком (на картинке зелёное). Его угол измеряется от -90 градусов до 90. Причина этого - сортированость вершин по X.
2. Угол луч измеряется от -180 градусов до 180. Обычный atan2.

Wolsh 31.01.2011 01:44

http://habrahabr.ru/blogs/algorithm/105882/

semenyakinVS 31.01.2011 21:56

Я это читал. Собственно, сам вешал эту ссылку в ответ на чей-то пост тут.

Мой алгоритм лучше работает с углами. И, кстати, если бы был на хабре, поспорил бы с человеком, написавшим пост. Дело в том, что его способом требуется считать три векторных произведения. Это шесть умножений. И плюс суммы и разницы - опять-таки, векторов. Долго.

Один косинус считать будет быстрее! Синус полчим по основному тождеству. Итого: косинус, умножение и разница.

Я проверил. Такое должно считаться быстрее.

Добавлено через 55 минут
Вот только с углом проблема...

i.o. 31.01.2011 23:57

Не нужно преувеличивать:
Код AS3:

public class Vector2
{
        ............
 
        public function mirror( mirrorVec:Vector2 ):void
        {
                var v:Vector2 = new Vector2( mirrorVec.y, -mirrorVec.x );
                v.normalize();
 
                var m:Number = -2.0 * (this.x * v.x + this.y * v.y);
 
                this.x += m * v.x;
                this.y += m * v.y;
        }
 
        ............
}

Причем эту часть можно еще и неплохо оптимизировать...
Если mirrorVec будет единичным, а он должен быть единичным исходя из задачи, то все сведется к паре действий:
Код AS3:

        public function mirror( mirrorVec:Vector2 ):void
        {
                var m:Number = -2.0 * (this.x * mirrorVec.y - this.y * mirrorVec.x);
 
                this.x += m * mirrorVec.y;
                this.y -= m * mirrorVec.x;
        }

Не мудрите с углами — синусы и косинусы в разы тяжелее умножений и сложений :)

semenyakinVS 01.02.2011 02:11

i.o., спасибо за код. Но...

Цитата:

Не мудрите с углами — синусы и косинусы в разы тяжелее умножений и сложений
В пять раз. Я проверял. А в последнем приведённом коде шесть умножений, а ещё разницы и суммы. Понимаю, у меня тоже будут разницы углов...

Но проблема в том, что зеркало не нормализировано.

Добавлено через 1 час 16 минут
И, кстати, что такое -2.0 ?

Добавлено через 1 час 38 минут
Глянул на сайте (ссылка чего-то побилась, а источник уже не помню). Понял, откуда формула.

Да, верно. Способ мне нравится. Он универсальный.

В 2Д-случае всё-таки косинус рулит, но для 3Д - только вектора. Иначе запарюсь всё считать.
Буду думать.

Добавлено через 70 часов 46 минут
Что ж... Написал я алгоритм.

Во-первых, вот этот код:

Код AS1/AS2:

var m:Number = -2.0 * (this.x * mirrorVec.y - this.y * mirrorVec.x);
this.x += m * mirrorVec.y;
this.y -= m * mirrorVec.x;

Не будет работать. Там нету нормали, значит он уже не правильный. Погарячился, извините. Не заметил, что вы вшили нормализацию в расчёт новых координат.
Правильность проверю.

Во-вторых, подумал я, и решли, что с углом работать всё-таки логичнее. По нескольким причинам:

1. Для оптики естественнее работа с углами. Они там везде фигурируют.
2. Расчёт одного косинуса и синуса будет быстрее, чем действия, необходимые для векторного решения. И, если подумать, его можно перенести на 3D.
3. Задавать луч точкой и углом логичнее, чем двумя точками. Заодно орт считать удобнее.

Короче, буду опять мучить себя поисками углового решения...

Код того, что есть пока (не работает, но можно составить общее впечатление по кол-ву действий):

Код AS3:

var mul:Number = updateRay.Norm.X*updateRay.Norm.Y+updateRay.DeltaX*updateRay.DeltaY;
 
var newX:Number = updateRay.End.X+updateRay.DeltaX-updateRay.Norm.X*2*mul;
var newY:Number = updateRay.End.Y+updateRay.DeltaY-updateRay.Norm.Y*2*mul;
 
res.push(new Ray2d(updateRay.End, Math.atan2(newY,newX)));

(Информацию брал здесь: Хорошая статья по трассировке)


Часовой пояс GMT +4, время: 04:11.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.