Каталог статей
Меню сайта


Форма входа


Категории раздела
Мои статьи [1]
Пользовательские статьи [0]
Здесь вы можете размещать свои статьи ;)


Поиск


Друзья сайта


Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0


Приветствую Вас, Гость · RSS 19-Апр-2024, 16:14
Главная » Статьи » Мои статьи

Работа с surface в памяти Blitz3D :)
Для эффективной и максимально быстрой работы с вершинами и треугольниками, операции над ними можно производить непосредственно в памяти из внешних библиотек, не прибегая к встроенным командам блица.

В качестве примера напишем функцию для преобразования всех вершин выбранного сурфейса в глобальную систему координат произвольной Entity, в качастве среды разработки возьмём MSVC++ 6.0.

Для начала нам нужно получить адрес сурфейса(сетки), где хранятся Vertex Buffer и Index Buffer(треугольники).

SurfHandle = GetSurface(model, 1 ) ;хендл(адрес) сурфейса.

(прим. Структуру сурфейса можно посмотреть здесь: http://blitz.pp.ru/forum/showthread.php?s=&threadid=203 )

Vertex Buffer лежит по смещению (SurfHandle + 28байт), Index Buffer - (SurfHandle + 44байта).

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


typedef struct _BBVERTEX
{
float x,y,z;
float nx,ny,nz;
char a,r,g,b;
float u0,v0;
float u1,v1;
char i1,i2,i3,i4;
float w1,w2,w3,w4;

} BBVERTEX, *LPBBVERTEX;

Точно также можно сделать и для треугольников:



typedef struct _BBTRIANGE
{
unsigned short a,b,c;

} BBTRIANGE, *LPBBTRIANGE;

(прим. Треугольник - это последовательность 3-х индексов в IndexBuffer соответственно)

Для получения положения Entity (поворот, размер, позиция), воспользуемся её матрицей трансформации.
Глобальная матрица хранится по смещению (SurfHandle + 216байт), таже матрица, но с учётом Tween(если используется), хранится по адресу (SurfHandle + 516байт).

(прим. В спецификации DirectX используются матрицы размерностью 4х4, но для пространственных преобразований достаточно матрицы 3х4, она и хранится в структуре Entity в блице)

Получение матрицы:



float EMatrix11= *(Entity+44);
float EMatrix12= *(Entity+45);
float EMatrix13= *(Entity+46);

float EMatrix21= *(Entity+47);
float EMatrix22= *(Entity+48);
float EMatrix23= *(Entity+49);

float EMatrix31= *(Entity+50);
float EMatrix32= *(Entity+51);
float EMatrix33= *(Entity+52);

float EMatrix41= *(Entity+53);
float EMatrix42= *(Entity+54);
float EMatrix43= *(Entity+55);

(прим. В С++ значение смещения для указателей учитывается в соответствии с их типом, например, если используется тип Float(4байта), то смещение на 40 байт будет указано как +10)

Для преобразования координат вершины, нужно перемножить их на матрицу:



//координаты исходной сетки.
x=SrcVertexBuffer[vertex].x;
y=SrcVertexBuffer[vertex].y;
z=SrcVertexBuffer[vertex].z;

//преобразованные координаты.
DestVertexBuffer [vertex].x = EMatrix11*x + EMatrix21*y + EMatrix31*z + EMatrix41;
DestVertexBuffer [vertex].y = EMatrix12*x + EMatrix22*y + EMatrix32*z + EMatrix42;
DestVertexBuffer [vertex].z = EMatrix13*x + EMatrix23*y + EMatrix33*z + EMatrix43;

Количество вершин можно получить так:

int VertexCount = ( *(surfaceSrc+8) - *(surfaceSrc+7) )/64;
(прим. 64 - количество байт на одну вершину)

Цикл перебора вершин будет выглядеть так:



for (int vertex = 0; vertex {
x=SrcVertexBuffer[vertex].x;
y=SrcVertexBuffer[vertex].y;
z=SrcVertexBuffer[vertex].z;

DestVertexBuffer [vertex].x = EMatrix11*x + EMatrix21*y + EMatrix31*z + EMatrix41;
DestVertexBuffer [vertex].y = EMatrix12*x + EMatrix22*y + EMatrix32*z + EMatrix42;
DestVertexBuffer [vertex].z = EMatrix13*x + EMatrix23*y + EMatrix33*z + EMatrix43;
}

Таким образом Мы можем вертеть сетку в соответствии с позицией любой Entity smile

(Прим. При изменении координат вершин мы изменяем размер всей сетки, но блиц проверяет её видимость по старому размеру, поэтому корректнее также изменять и параметры ограничивающего бокса(Bounding Box) - см. структуру меша)

Полный код функции:



BBDECL void TransformSurfaceToMatrix( unsigned int *surfaceSrc, unsigned int *surfaceDest, float *Entity )

{
LPBBVERTEX SrcVertexBuffer, DestVertexBuffer ;

float x,y,z;

float EMatrix11= *(Entity+44);
float EMatrix12= *(Entity+45);
float EMatrix13= *(Entity+46);

float EMatrix21= *(Entity+47);
float EMatrix22= *(Entity+48);
float EMatrix23= *(Entity+49);

float EMatrix31= *(Entity+50);
float EMatrix32= *(Entity+51);
float EMatrix33= *(Entity+52);

float EMatrix41= *(Entity+53);
float EMatrix42= *(Entity+54);
float EMatrix43= *(Entity+55);

SrcVertexBuffer = (struct _BBVERTEX *)*(surfaceSrc +7); //Адрес начала вершинного буфера исходной сетки
DestVertexBuffer = (struct _BBVERTEX *)*(surfaceDest+7); //Адрес начала вершинного буфера трансформируемой сетки

*(surfaceDest+16)=0; //Обнуление этого флага означает изменение вертекс буфера, после чего он будет передан видеокарте

int VertexCount = ( *(surfaceSrc+8) - *(surfaceSrc+7) )/64; //Количество вершин в сетке

for (int vertex = 0; vertex {
x=SrcVertexBuffer[vertex].x;
y=SrcVertexBuffer[vertex].y;
z=SrcVertexBuffer[vertex].z;

// Здесь мы производим перемножение координат вершины исходной сетки на матрицу и запись результата в изменяемую сетку
DestVertexBuffer [vertex].x = EMatrix11*x + EMatrix12*y + EMatrix13*z + EMatrix41;
DestVertexBuffer [vertex].y = EMatrix21*x + EMatrix22*y + EMatrix23*z + EMatrix42;
DestVertexBuffer [vertex].z = EMatrix31*x + EMatrix32*y + EMatrix33*z + EMatrix43;
}

}

Пример использования в Blitz3D:



Graphics3D 640,480,32,2

SetBuffer BackBuffer()

camera=CreateCamera()
PositionEntity camera,0,10,-30

light=CreateLight(1)
RotateEntity light,50,80,0

Entity1=CreateCube();
PositionEntity Entity1,15,10,0
ScaleEntity Entity1,5,5,5

SurfaceSrc = GetSurface(Entity1, 1)
Vcount = CountVertices(SurfaceSrc)

Entity2=CopyMesh(Entity1)
EntityColor Entity2,255,0,0
PositionEntity Entity2,-30,0,0

SurfaceDest = GetSurface(Entity2, 1)

While Not KeyHit(1)

TurnEntity Entity1, 1, 1, 0

RenderWorld()

If KeyDown(57)
Text 5,5, "Don't ransformate"
Else
Text 5,5, "Transformating SurfaceSrc(Red color)"
TransformSurfaceToMatrix SurfaceSrc, SurfaceDest, Entity1
EndIf

Flip 1
Wend
End


Пример к статье можно найти здесь: http://andreyman.ucoz.ru/VertexSample.rar

Категория: Мои статьи | Добавил: ANDREYman (04-Ноя-2006) | Автор: Андрей
Просмотров: 5096 | Комментарии: 5 | Рейтинг: 5.0/1
Всего комментариев: 3
3 Igrok  
0
хорошая статейка, таких бы побольше

2 Timon  
0
то-что надо! побольше бы таких статей! спасибо!

1 Reltek  
0
Хиловато

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]