forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   Как найти UV координаты новой точки на триангле. (http://forum.boolean.name/showthread.php?t=13872)

CRASHER 11.12.2010 04:49

Как найти UV координаты новой точки на триангле.
 
Значит, задача была поставленна в таком виде.

Есть три вершины, образующие треугольную грань, для каждой из которых известны её 3d коорлинаты и UV координаты текстуры.
Есть вершина внутри грани(лежит в её плоскости ) с известными 3d координатами.
КАК найти, какие будут у этой вершины UV?

Код:

                    B
                    .
                    / \
                  /  \
                  /    \
                /  .D  \
                /        \
              .-----------.
            A              C

Решено было так.

Код:

Vector3 A = new Vector3(1, 0, 0);        Vector2 Auv = new Vector2(0, 0);
Vector3 B = new Vector3(10f, 4f, 4f);    Vector2 Buv = new Vector2(1, 0);
Vector3 C = new Vector3(0, 6f, 13f);    Vector2 Cuv = new Vector2(0.5f, 1);
Vector3 D = new Vector3(4, 3, 5);
Vector3 N = Vector3.Normalize(Vector3.Cross(B - A, C - A));
float AreaABC = Vector3.Dot(N, Vector3.Cross(B - A, C - A));
float AreaPBC = Vector3.Dot(N, Vector3.Cross(B - D, C - D));
float AreaPCA = Vector3.Dot(N, Vector3.Cross(C - D, A - D));
float b = AreaPCA / AreaABC;float a = AreaPBC / AreaABC;
float c = 1.0f - a - b;
Vector2 Duv = a * Auv + b * Buv + c * Cuv;

Внимание вопрос. Что сдесь вообще происходит?)
Понял что решение идет через барицентрические координаты.
Впринцепе можно это представить в формате кода блитза, тогда я сам все пойму ;)

Morganolla 11.12.2010 14:31

Ответ: Как найти UV координаты новой точки на триангле.
 
Для стороннего наблюдателя - это абракадабра, так как нет хедеров описывающих типы данных и методы вектор2,3 и т.д.
Или ты думаешь, что все здесь гении типа джимона и кнайтмара?
Откуда ты всю эту хрень выдернул, чувак?

impersonalis 11.12.2010 14:44

Ответ: Как найти UV координаты новой точки на триангле.
 
а чо тут непонятного:
Vector3 -трёхмерный вектор
Vector2 -двумерный
Normalize - нормализация
Cross - векторное умножение
Dot - скалярное

Morganolla 11.12.2010 14:48

Ответ: Как найти UV координаты новой точки на триангле.
 
Ты уверен что "Cross - векторное умножение" ?

CRASHER 11.12.2010 16:14

Ответ: Как найти UV координаты новой точки на триангле.
 
Эммм, так я не понял это можно разшифровать?)
Как это на блитзе бы выглядело?

falcon 11.12.2010 17:21

Ответ: Как найти UV координаты новой точки на триангле.
 
Morganolla если не быть параноиком то по поводу ф-ций сомнений быть не может...

CRASHER 11.12.2010 18:08

Ответ: Как найти UV координаты новой точки на триангле.
 
impersonalis, объясни пжалст про Vector2 и Vector3. Как это в блитз записать можно? И функцию нормализ я тоже не понимаю.

falcon 12.12.2010 00:25

Ответ: Как найти UV координаты новой точки на триангле.
 
тут vector это структуры..
в блице так:

Код:

Type vector2
      Field x#,y#;
End Type

ну с vector3 аналогию провести надеюсь сообразишь.
нормализация - приведение вектора к единичной длине.
соответственно именно это ф-ция и делает.

CRASHER 12.12.2010 07:23

Ответ: Как найти UV координаты новой точки на триангле.
 
Если кто то понял как код работает, пжалст объясните как мне найти эти векторы ? Я так понял Vector3 это Nx,Ny,Nz, а Vector2 это UV верно?

Venom2 12.12.2010 10:42

Ответ: Как найти UV координаты новой точки на триангле.
 
Вложений: 1
Цитата:

Сообщение от CRASHER (Сообщение 171681)
Если кто то понял как код работает, пжалст объясните как мне найти эти векторы ? Я так понял Vector3 это Nx,Ny,Nz, а Vector2 это UV верно?

Код:

; вычитание векторов
Function Sub3(Dst#[3], Src1#[3], Src2#[3])
        Dst[0] = Src1[0] - Src2[0]
        Dst[1] = Src1[1] - Src2[1]
        Dst[2] = Src1[2] - Src2[2]
End Function

; векторное произведение векторов
; по сути получается перпендикуляр к плоскости образующейся исходными двумя векторами
Function Cross3(Dst#[3], Src1#[3], Src2#[3])
        Dst[0] = Src1[1] * Src2[2] - Src1[2] * Src2[1]
        Dst[1] = Src1[2] * Src2[0] - Src1[0] * Src2[2]
        Dst[2] = Src1[0] * Src2[1] - Src1[1] * Src2[0]
End Function

; скалярное произведение векторов
; в результате получается косинус угла между исходными векторами
Function Dot3#(Src1#[3], Src2#[3])
        Return Src1[0] * Src2[0] + Src1[1] * Src2[1] + Src1[2] * Src2[2]
End Function

; нормализация вектора, приведение его к единичной длине
; просто делим элементы вектора на длину
Function Normalize3(Dst#[3], Src#[3])
        Local Dot# = Dot3(Src, Src)
        If Dot > 0.001 Then
                Dot = 1.0 / Sqr(Dot)
                Dst[0] = Src[0] * Dot
                Dst[1] = Src[1] * Dot
                Dst[2] = Src[2] * Dot
        Else
                Dst[0] = 0
                Dst[1] = 0
                Dst[2] = 0
        End If
End Function

; инициализация
Function Vector3(Dst#[3], x#, y#, z#)
        Dst[0] = x
        Dst[1] = y
        Dst[2] = z
End Function

; инициализация
Function Vector2(Dst#[2], x#, y#)
        Dst[0] = x
        Dst[1] = y
End Function

Function ComputeUV(A#[3], Auv#[2], B#[3], Buv#[2], C#[3], Cuv#[2], D#[3], Duv#[2])

        Local T1#[3], T2#[3], T3#[3], N#[3]
        Local r1#, r2#, r3#

        ; получаем два ребра AB и AC
        Sub3(T1, B, A)
        Sub3(T2, C, A)

        ; берем перпендикуляр к плоскости треугольника, образованого его ребрами
        Cross3(N, T1, T2)

        ; нормализуем чтобы получить вектор нормали
        Normalize3(N, N)

        ; получаем ребра DB, DC
        Sub3(T1, B, D)
        Sub3(T2, C, D)

        ; перпендикуляр к образуемой плоскости
        Cross3(T3, T1, T2)

        ; косинус угла между ним и нормалью
        r1 = Dot3(N, T3)

        ; получаем ребра DC, DA
        Sub3(T1, C, D)
        Sub3(T2, A, D)
       
        ; перпендикуляр к образуемой плоскости
        Cross3(T3, T1, T2)

        ; косинус угла между ним и нормалью
        r2 = Dot3(N, T3)

        ; косинус третьего угла (сумма всех косинусов углов равна единице)
        r3 = 1.0 - AreaPBC - AreaPCA

        ; используем косинусы для определения долей от каждой вершины
        Duv[0] = Auv[0] * r1 + Buv[0] * r2 + Cuv[0] * r3
        Duv[1] = Auv[1] * r1 + Buv[1] * r2 + Cuv[1] * r3

End Function

Local A#[3], Auv#[2]
Local B#[3], Buv#[2]
Local C#[3], Cuv#[2]
Local D#[3], Duv#[2]


Vector3(A, -1,  0,  0)
Vector2(Auv,  0.0,  0.0)

Vector3(B,  0,  1,  0)
Vector2(Buv,  1.0,  0.0)

Vector3(C,  1,  0,  0)
Vector2(Cuv,  1.0,  1.0)

Vector3(D, 0, 0.5, 0)

ComputeUV(A, Auv, B, Buv, C, Cuv, D, Duv)

Print(Str(Duv[0]))
Print(Str(Duv[1]))

WaitKey()


End

Работает корректно, судя по рисунку

ЗЫ
Лучше юзать массивы, вместо типа, т.к. доступ к ним чуток быстрее, к тому же не надо задумываться об управлении памятью (хотя по хорошему выделять память для таких вычислений извращение, лучше вынести всю математику в длл)

Venom2 12.12.2010 11:42

Ответ: Как найти UV координаты новой точки на триангле.
 
Ох шыт, очепятка там была в нормализации вектора, забыл квадратный корень.

CRASHER 12.12.2010 12:47

Ответ: Как найти UV координаты новой точки на триангле.
 
Цитата:

Сообщение от Venom2 (Сообщение 171693)
Ох шыт, очепятка там была в нормализации вектора, забыл квадратный корень.

Вот вот, а я и думаю что то у меня не выходит :)
Можешь написать строку которую нужно за менить и строку которой нужно заменить?

Venom2 12.12.2010 13:17

Ответ: Как найти UV координаты новой точки на триангле.
 
Цитата:

Сообщение от CRASHER (Сообщение 171700)
Вот вот, а я и думаю что то у меня не выходит :)
Можешь написать строку которую нужно за менить и строку которой нужно заменить?

в Function Normalize3 было
Код:

Dot = 1.0 / Dot
а надо
Код:

Dot = 1.0 / Sqr(Dot)
скалярное умножение вектора на себя дает фактически квадрат длины, потому корень нужен


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

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot