Итак, это небольшая помощь тем, кто решил вступить на нелёгкий путь гейм-мэйкера =) Собственно, название статьи целиком отражает её содержимое: примеры реализации геометрических операций с векторами и матрицами. Примеры на Delphi, но переделать под С не составит труда. Итак, начнём) Для начала укажем типы для векторов(за стандартный можно взять например вектор из 4-х чисел с плавающей точкой): type TVector4f = array[0..3] of single; TVector = TVector4f; Ещё неплохо бы задать константы для единичных векторов: const NullVector: TVector = ((0),(0),(0),(0)); const Vector1 : TVector = ((1),(1),(1),(1)); const XVector1 : TVector = ((1),(0),(0),(0)); const YVector1 : TVector = ((0),(1),(0),(0)); const ZVector1 : TVector = ((0),(0),(1),(0)); Задавать вектора удобно с помощью ф-ий, вроде этой: function VectorMake(X,Y,Z: single; W: single = 1): TVector; overload; var V: TVector; begin V[0]:=X; V[1]:=Y; V[2]:=Z; V[3]:=W; VectorMake:=V; end; Очень частая операция - нахождение длины вектора(корень из суммы квадратов разности координат начала и конца вектора, но начало-то у нас в 0.0.0): function VectorLength(V: TVector): single; var a: single; begin a:=Sqr(V[0])+Sqr(V[1])+Sqr(V[2]); Result:=Sqrt(A); end; //без оптимизации) По определению - расстояние между точками(их радиус-векторами): function Distance(V1,V2: TVector): single; begin Result:=Sqrt(Sqr(V1[0]-V2[0])+Sqr(V1[1]-V2[1])+Sqr(V1[2]-V2[2])); end; Часто приходится отразить вектор относительно нуля, т.е. V[i] = -V[i]: function VectorNegate(Vector: TVector): TVector; begin Result[0]:= -Vector[0]; Result[1]:= -Vector[1]; Result[2]:= -Vector[2]; end; Простейшая "арифметика" - сложение, вычитание...: function VectorAdd(V1,V2: TVector): TVector; var V: TVector; begin V[0]:=V1[0]+V2[0]; V[1]:=V1[1]+V2[1]; V[2]:=V1[2]+V2[2]; Result:=V; end; function VectorSubtract(V1,V2: TVector): TVector; begin Result:=VectorAdd(V1,VectorNegate(V2)); end; function VectorScale(Vector: TVector; f: single): TVector; var V: TVector; begin V[0]:=Vector[0]*f; V[1]:=Vector[1]*f; V[2]:=Vector[2]*f; Result:=V; end; Скалярное произведение: function VectorDotProduct(V1,V2: TVector): single; var a: single; begin a:=(V1[0]*V2[0]+V1[1]*V2[1]+V1[2]*V2[2])/VectorLength(V1)/VectorLength(V2); Result:=a; end; И векторное: function VectorCrossProduct(V1,V2: TVector): TVector; var V: TVector; begin V[0]:=V1[1]*V2[2]-V1[2]*V2[1]; V[1]:=V1[2]*V2[0]-V1[0]*V2[2]; V[2]:=V1[0]*V2[1]-V1[1]*V2[0]; Result:=V; end; Нормализация(приведение к длине 1): function VectorNormalize(V: TVector): TVector; var L: single; begin L:=VectorLength(V); if L = 0 then begin Result:=NullVector; Exit; end; Result[0]:=V[0]/L; Result[1]:=V[1]/L; Result[2]:=V[2]/L; end;
|