Параллелепипед
Чтобы построить параллелепипед с центром в начале координат, необходимо в первую очередь определить это самое начало. Все просто - делим длину, ширину и высоту параллелепипеда пополам и перемещаем полученную точку в точку с координатами (0,0,0). Затем последовательно строим каждую грань по четырем вершинам, для первой вершины рассчитываем нормаль как векторное произведение двух ребер параллелограмма, исходящих из этой вершины. Функция построения параллелограмма (код для наглядности не оптимизирован):
; #########################################################################
SolidBox PROC ListNumber:DWORD,Leng:DWORD,Wid:DWORD,Hei:DWORD
LOCAL nLn:DWORD,nWd:DWORD,nHg:DWORD
LOCAL pLn:DWORD,pWd:DWORD,pHg:DWORD
fld [Leng]
fdiv [dva]
fst [pLn]
fld [pLn]
fchs
fst [nLn]
fld [Wid]
fdiv [dva]
fst [pWd]
fld [pWd]
fchs
fst [nWd]
fld [Hei]
fdiv [dva]
fst [pHg]
fld [pHg]
fchs
fst [nHg]
invoke glNewList,ListNumber,GL_COMPILE_AND_EXECUTE
invoke glEnable,GL_COLOR_MATERIAL
invoke glBegin,GL_QUADS
invoke Normals,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR nHg
invoke Normals,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR pHg,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR nHg
invoke Normals,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR pHg
invoke Normals,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR pHg
invoke Normals,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR nHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR nHg
invoke Normals,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR pHg,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR nWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR nLn,DWORD PTR pWd,DWORD PTR pHg
invoke glVertex3f,DWORD PTR pLn,DWORD PTR pWd,DWORD PTR pHg
invoke glEnd
invoke glEndList
ret
SolidBox ENDP
; #########################################################################
Прототип функции:
SolidBox PROTO :DWORD,:DWORD,:DWORD,:DWORD
Функция для нормалей (расчет векторного произведения), нормаль к вершине строится непосредственно в самой функции:
; #########################################################################
Normals PROC x0:DWORD,y0:DWORD,z0:DWORD,\
x1:DWORD,y1:DWORD,z1:DWORD,\
x2:DWORD,y2:DWORD,z2:DWORD
LOCAL xn:DWORD,yn:DWORD,zn:DWORD
LOCAL xi1:DWORD,yi1:DWORD,zi1:DWORD,xi2:DWORD,yi2:DWORD,zi2:DWORD
fld[x1]
fsub[x0]
fst[xi1]
finit
fld[y1]
fsub[y0]
fst[yi1]
finit
fld[z1]
fsub[z0]
fst[zi1]
finit
fld[x2]
fsub[x0]
fst[xi2]
finit
fld[y2]
fsub[y0]
fst[yi2]
finit
fld[z2]
fsub[z0]
fst[zi2]
finit
invoke Determinant,zi1,yi1,zi2,yi2,ADDR xn
invoke Determinant,xi1,zi1,xi2,zi2,ADDR yn
invoke Determinant,yi1,xi1,yi2,xi2,ADDR zn
invoke glNormal3f,DWORD PTR xn,DWORD PTR yn,DWORD PTR zn
ret
Normals ENDP
; #########################################################################
Прототип функции:
Normals PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
Вспомогательная функция - вычисление определителя второго порядка:
; #########################################################################
Determinant PROC x1:DWORD,y1:DWORD,x2:DWORD,y2:DWORD,Number:DWORD
LOCAL tmpval:DWORD
finit
fld[x2]
fmul[y1]
fst[tmpval]
fld[x1]
fmul[y2]
fsub[tmpval]
mov eax,Number
fst DWORD PTR [eax]
ret
Determinant ENDP
; #########################################################################
Прототип функции:
Determinant PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
Текстурные координаты, если необходимо, можно добавить в функцию SolidBox одновременно с определением координат вершин. Константа, необходимая для работы функций, объявлена в примере как глобальная (может быть и локальная) и типа float (но можно и integer, но тогда нужно немного изменить функции, заменив деление типа float на целочисленное):
dva dd 2.0
Пример программы, использующей эти функции: