Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Вниз

Анализ поверхности   Найти похожие ветки 

 
Toxic   (2005-03-20 15:14) [0]

Здравствуйте.
Кратко: есть поверхность, есть точка с известными X и Z координатами. Необходимо рассчитать высоту (Y-координату) точки над поверхностью.
Проще говоря, при перемещении точки она должна скользить ПО ПОВЕРХНОСТИ, а  не над или под ней.
Подробнее:
Поверхность состоит из одномерного массива Vertexes
type TVertex = record
    X, Y, Z : real;
end;

и одномерного массива Quads
type TQuad = record
    A, B, C, D : integer;
end;

для разложения поверхности на элементы (квадраты).
Естественно, известны все координаты всех точек и какая точка какому квадрату принадлежит. Итак, уважаемые мастера, прошу поделиться опытом/знаниями/соображениями/идеями в области определения координат :)


 
XProger ©   (2005-03-20 15:25) [1]

1) Делай треугольниками
2) находи треугольник на позиции X Z
3) составляй уравнение плоскости треугольника
4) подставляй в него X Z и выражай Y


 
Toxic   (2005-03-20 18:54) [2]

//Делай треугольниками
Сам базовый элемент не столь важен. Сделал и трианглами.
//Находи триангл на позиции X Z
Тоже нашел
//Составляй уравнение плоскости триангла
Здесь нужна помощь знатока -  я с математикой дружен, но не настолько.


 
Asteroid ©   (2005-03-20 19:48) [3]

> Toxic   (20.03.05 18:54) [2]
> Составляй уравнение плоскости триангла

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

Я так понял, треугольники получаются прямоугольные? Если да, то все довольно просто...


 
Asteroid ©   (2005-03-20 19:48) [4]

> Toxic   (20.03.05 18:54) [2]
> Составляй уравнение плоскости триангла

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

Я так понял, треугольники получаются прямоугольные? Если да, то все довольно просто...


 
Asteroid ©   (2005-03-20 19:49) [5]

(прошу прощения за дубль)


 
XProger ©   (2005-03-20 21:43) [6]

Имеем 3 вершины треугольника: v1, v2, v3
И уравнение плоскости: A*x + B*y + C*z + D = 0
Вектор N(A, B, C) - нормаль к полигону, вычисляется путём нехитрых действий называемых векторным умножением.

w1.X := v2.X - v1.X;
w1.Y := v2.Y - v1.Y;
w1.Z := v2.Z - v1.Z;

w2.X := v3.X - v2.X;
w2.Y := v3.Y - v2.Y;
w2.Z := v3.Z - v2.Z;

A := w2.Y * w1.Z - w2.Z * w1.Y;
B := w2.Z * w1.X - w2.X * w1.Z;
C := w2.X * w1.Y - w2.Y * w1.X;

Затем нормализуем полученную нормаль

len := sqrt(A*A + B*B + C*C)
A := A/len
B := B/len
C := C/len

Далее, псле того как нашли нормаль, подаставляем её в уравнение, а также вместо x y z указываем координаты одной из врешин полигона (не важно какой)

Отседа выражаем

D = -(A*v1.X + B*v1.Y + C*v1.Z)

Всё! Теперь осталось подставить твои X Z и выразить

Y := - (D + C*Z + A*X)/B

Заметь, что для вертикальных полигонов (которых я надеюсь у тебя нет) этот метод не подходит.


 
Toxic   (2005-03-20 21:44) [7]

У меня есть оба варианта реализации поверхности - по трианглам и по квадам.
А треугольники прямоугольные.
//Если да, то все довольно просто...
Поделись, пожалуйста!


 
Toxic   (2005-03-20 21:52) [8]

Вот спасибо, XProger, выручил! :)


 
Toxic   (2005-03-25 14:19) [9]

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

function TSurface.GetHeightAtPosition(Vector : TVector): real;
var D : real;
   Triangle : integer;
begin
Triangle := IndexTriangle(Vector);
D := -(FNormals[Triangle].X * FVertex[FFaces[Triangle].A].X + FNormals[Triangle].Y * FVertices[FFaces[Triangle].A].Y + FNormals[Triangle].Z * FVertices[FFaces[Triangle].A].Z);
Result := -(D + FNormals[Triangle].Z * FVertices[FFaces[Triangle].A].Z + FNormals[Triangle].X * FVertices[FFaces[Triangle].A].X) / FNormals[Triangle].Y;
end;
Такая вот громоздкая функция определения высоты...

А вот функция IndexTriangle, которую позаимствовал с сишного кода:
function TSurface.IndexTriangle(Vector : TVector): integer;
const
 MATCH_FACTOR : real = 0.9999;    // Used to cover up the error in floating point
var
 Angle : real;            // Initialize the angle
 vA, vB, vC : TVector;            // Create temp vectors
 i : integer;

function GetAngleBetweenVectors(V1, V2 : TVector) : real;
var DotProduct : real;
   Magnitude : real;
   Angle : real;
begin
DotProduct := VectorDotProduct(V1, V2);
Magnitude := VectorMagnitude(V1) * VectorMagnitude(V2);
Angle := arccos(DotProduct / Magnitude);
Result := Angle;
end;

begin
 Angle := 0.0;

 for i := 0 to FFacesCount - 1 do    // Go in a circle to each vertex and get the angle between
 begin
     vA := VectorSub(VertexAsVector(FVertices[FFaces[i].A]), Vector);  // Subtract the intersection point from the current vertex
     vB := VectorSub(VertexAsVector(FVertices[FFaces[i].B]), Vector);  // Subtract the point from the next vertex
     vC := VectorSub(VertexAsVector(FVertices[FFaces[i].C]), Vector);  // Subtract the point from the next vertex
     Angle := Angle + GetAngleBetweenVectors(vA, vB);  // Find the angle between the 2 vectors and add them all up as we go along
     Angle := Angle + GetAngleBetweenVectors(vB, vC);
     Angle := Angle + GetAngleBetweenVectors(vC, vA);
   if(Angle >= (MATCH_FACTOR * (2.0 * PI)) ) then  // If the angle is greater than 2 PI, (360 degrees)
    begin
     result := i;              // The point is inside of the polygon
     exit;
   end;
  end;

 result := 0;                // If you get here, it obviously wasn"t inside the polygon, so Return FALSE

end;

А функции VectorMagnitude и VectorDotProduct такие:
function VectorMagnitude(Vec : TVector) : real;
begin
Result := sqrt(Vec.X * Vec.X + Vec.Y * Vec.Y + Vec.Z * Vec.Z);
end;

function VectorDotProduct(Vec1, Vec2: TVector): Single;
begin
Result := Vec1.X * Vec2.X + Vec1.Y * Vec2.Y + Vec1.Z * Vec2.Z;
end;

Вот и весь код. Где и в чем ошибка - в упор не вижу. Объясните бестолковому, пожалуйста!


 
Toxic   (2005-03-25 14:22) [10]

P.S.: нормали к треугольникам рассчитаны заранее.


 
XProger ©   (2005-03-25 18:00) [11]

Всё! Теперь осталось подставить твои X Z и выразить
Y := - (D + C*Z + A*X)/B

Я имел ввиду координаты игрока X и Z а не вершины полигона! :)


with FNormals[Triangle] do
Result := -(D + Z * Vector.Z + X * Vector.X)/Y;

Вот так заработает

И по поводу поиска полигона под ногами...
Я конечно понимаю что сегоднашние программисты не стремятся искать красивые решения, но всё же хочу дать тебе подсказку: у тебя Height map - сетка - матрица ты знаешь координаты X и Z соответственно путём нехитрых махинаций ты найдёшь полигон под копытами в FFacesCount*N раз быстрее чем тем методом который ты содрал из сишного кода.
И вот пример. есть экран 640х480 разделён он на 20х30 клеточек? нумерующикся слева-направо сверху-вниз. Следовательно размер каждой клеточки 32х16 пикселей. Вопрос: Как определить номер клетки в которой находится точка M (в экранной системе координат)? Ответ: M.Y div 16 * 40 * M.X div 32
А у тебя тут треугольники, что совсем незначительно усложнит задачу.

P.S.
А потом народ спрашивает "А почему у меня низкий FPS?". Так что не доводи до этого... ;)


 
XProger ©   (2005-03-25 18:03) [12]

Ответ: (M.Y div 16) * 20 + (M.X div 32)
:)


 
Toxic   (2005-03-26 17:39) [13]

Ндя... Признаюсь - невнимателен (: Спасибо, что поправил.
А решения красивые искать стремлюсь (: Хотя и не от желания - энцатьлетней давности P-233 без гипертрединга, с никаким кэшем... так что волей-неволей приходится сокращаться... иначе никак (:



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.036 c
4-1114869698
psa247
2005-04-30 18:01
2005.06.29
Изменения реестра


1-1117982090
Cijgan
2005-06-05 18:34
2005.06.29
предусмотреть ввод данных в Edit


3-1116421131
Nadya
2005-05-18 16:58
2005.06.29
данные из InterBase


1-1117703923
Rentgen
2005-06-02 13:18
2005.06.29
Massiv[ALL]:=99;


4-1114710007
MUHAMOR
2005-04-28 21:40
2005.06.29
Разные винды - разный результат





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский