Модераторы: Rickert
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> создание куба вращающегося 
:(
    Опции темы
AVRUDOI
Дата 22.9.2007, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 29.8.2007

Репутация: нет
Всего: нет



Здраствуйте. Есть желание написать программу вращающегося куба по оси Y. Сам немогу. Нехвотает знаний если у каго есть желание помочь? Хочу написать на Делфи 7.

Это сообщение отредактировал(а) AVRUDOI - 22.9.2007, 12:59
PM MAIL   Вверх
Чупакабро
Дата 24.9.2007, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



А кубег какой должен быть: проволочный, со сплошной закраской, с текстурой?
И как вы его хотите рисовать: с помощью методов tcanvas или Directx или OpenGL?
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
AVRUDOI
Дата 27.9.2007, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 29.8.2007

Репутация: нет
Всего: нет



Скорея всего с помощью методов tconves. Мне больше по душе этот метод. Он позволяет прочуствовать на линиях и точка красоту 3D. А потом хоть квейк пиши.smile текстура ненужна пока. Просто куб с ребрами.

Это сообщение отредактировал(а) AVRUDOI - 27.9.2007, 12:09
PM MAIL   Вверх
Чупакабро
Дата 27.9.2007, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



Значит так, выкладываю код.
Нужно создать форму с таймером и весь код модуля unit1 заменить на нижеследующий.
Сейчас нет времени писать подробные комментарии, это я наверное на выходных сделаю, но про некоторые особенности напишу сейчас.
Прграмма рисует вращающийся куб, режим закраски можно менять клавишей "пробел".
Прграмма поддерживает отрисовку и анимацию произвольных полигональных объектов стандартными средствами Delphi (без использования DirectX и OpenGL). Можно изменять позицию объектов и камеры.
Не успел реализовать отсечение невидимых треугольников, z-buffer, направленные источники света. Возможно добавлю позднее.
Программа получилась большая, т.к. претендует на универсальность, а не только на отрисовку конкретно вращающегося куба.

Собственно код:

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Math, ExtCtrls;  //uses math

type

  TMatrix=record
    _11,_12,_13,_14,_21,_22,_23,_24,_31,_32,_33,_34,_41,_42,_43,_44:single;
  end;
  T3Matrix=record
    _11,_12,_13,_21,_22,_23,_31,_32,_33:single
  end;

  TPoint3d=record
    x,y,z:single;
  end;

  TTriangle=array[1..3] of TPoint3d;

  TMesh=class
    triangles:array of TTriangle;
    cx,cy,cz:single;
    procedure rotate(rx,ry,rz:single);
    procedure move(dx,dy,dz:single);
  end;

  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
  public
    { Public declarations }
    HW:single;
    fov:single;
    pview:tpoint3d;
    pviewto:tpoint3d;
    fillmode:byte;//0-solid,1-wireframe,2-point
    cullmode:byte;//0-iao iona?aiey,1-?eno?ony ii ?n,2-?eno?ony i?ioea ?n
    backBitmap:tbitmap;
    clbckgr:tcolor;
    curcl:tcolor;
    curbrcl:tcolor;
    function projection(tr3d:TTriangle; clwidth,clheight:integer):TTriangle;
    procedure setrotatexmatrix(var m:TMatrix; angle:single);
    procedure setrotateymatrix(var m:TMatrix; angle:single);
    procedure setrotatezmatrix(var m:TMatrix; angle:single);
    procedure settranslatematrix(var m:TMatrix; x,y,z:single);
    procedure render;
    procedure drawtriangle(t:TTriangle);
    procedure addcube;
  end;

var
  Form1: TForm1;
  cube:tmesh;

implementation

{$R *.dfm}
function GetVecLength(x,y,z:single):single;
begin
  GetVecLength:=sqrt(sqr(x)+sqr(y)+sqr(z));
end;

function norm(p1,p2,p3:TPoint3d):TPoint3d;
var
  v1,v2:tpoint3d;
begin
  v1.x:=p2.x-p1.x;
  v1.y:=p2.y-p1.y;
  v1.z:=p2.z-p1.z;
  v2.x:=p3.x-p1.x;
  v2.y:=p3.y-p1.y;
  v2.z:=p3.z-p1.z;
  norm.x:=v1.y*v2.z-v1.z*v2.y;
  norm.y:=-v1.x*v2.z+v1.z*v2.x;
  norm.z:=v1.x*v2.y-v1.y*v2.x;
end;

{function det(_11,_12,_13,_21,_22,_23,_31,_32,_33:single):single;
begin
  det:=_11*(_22*_33-_32*_23)-_12*(_21*_33-_31*_23)+_13*(_21*_32-_31*_22);
end;}

function matrixmul(m1,m2:TMatrix):TMatrix;
begin
  matrixmul._11:=m1._11*m2._11+m1._12*m2._21+m1._13*m2._31+m1._14*m2._41;
  matrixmul._12:=m1._11*m2._12+m1._12*m2._22+m1._13*m2._32+m1._14*m2._42;
  matrixmul._13:=m1._11*m2._13+m1._12*m2._23+m1._13*m2._33+m1._14*m2._43;
  matrixmul._14:=m1._11*m2._14+m1._12*m2._24+m1._13*m2._34+m1._14*m2._44;

  matrixmul._21:=m1._21*m2._11+m1._22*m2._21+m1._23*m2._31+m1._24*m2._41;
  matrixmul._22:=m1._21*m2._12+m1._22*m2._22+m1._23*m2._32+m1._24*m2._42;
  matrixmul._23:=m1._21*m2._13+m1._22*m2._23+m1._23*m2._33+m1._24*m2._43;
  matrixmul._24:=m1._21*m2._14+m1._22*m2._24+m1._23*m2._34+m1._24*m2._44;

  matrixmul._31:=m1._31*m2._11+m1._32*m2._21+m1._33*m2._31+m1._34*m2._41;
  matrixmul._32:=m1._31*m2._12+m1._32*m2._22+m1._33*m2._32+m1._34*m2._42;
  matrixmul._33:=m1._31*m2._13+m1._32*m2._23+m1._33*m2._33+m1._34*m2._43;
  matrixmul._34:=m1._31*m2._14+m1._32*m2._24+m1._33*m2._34+m1._34*m2._44;

  matrixmul._41:=m1._41*m2._11+m1._42*m2._21+m1._43*m2._31+m1._44*m2._41;
  matrixmul._42:=m1._41*m2._12+m1._42*m2._22+m1._43*m2._32+m1._44*m2._42;
  matrixmul._43:=m1._41*m2._13+m1._42*m2._23+m1._43*m2._33+m1._44*m2._43;
  matrixmul._44:=m1._41*m2._14+m1._42*m2._24+m1._43*m2._34+m1._44*m2._44;
end;

procedure TMesh.rotate(rx,ry,rz:single);
var
  i,j:integer;
  rvec:tpoint3d;
  length:single;
  ax,ay,az:single;
  dc,dx,dy,dz:T3Matrix;
  dx1,dy1,dz1:single;
begin
  for i:=0 to high(triangles) do
  begin
    for j:=1 to 3 do
    begin

        rvec.x:=(triangles[i][j].x-cx);
        rvec.y:=(triangles[i][j].y-cy);
        rvec.z:=(triangles[i][j].z-cz);

        if rx<>0 then
        begin
          length:=GetVecLength(0,triangles[i][j].y-cy,triangles[i][j].z-cz);
          if length<>0 then
          begin
            if rvec.y>=0 then
            begin
              dx1:=arccos((rvec.z)/length) ;
            end
            else begin
              dx1:=-arccos((rvec.z)/length) ;
            end;
          end
          else begin
            dx1:=0;
          end;
          triangles[i][j].y:=cy+length*sin(rx+dx1);
          triangles[i][j].z:=cz+length*cos(rx+dx1);
          rvec.x:=(triangles[i][j].x-cx);
          rvec.y:=(triangles[i][j].y-cy);
          rvec.z:=(triangles[i][j].z-cz);
        end;

        if ry<>0 then
        begin
          length:=GetVecLength(triangles[i][j].x-cx,0,triangles[i][j].z-cz);
          if length<>0 then
          begin
            if rvec.z>=0 then
            begin
              dy1:=arccos(rvec.x/length) ;
            end
            else begin
              dy1:=-arccos(rvec.x/length) ;
            end;
          end
          else begin
            dy1:=0;
          end;
          triangles[i][j].x:=cx+length*cos(ry+dy1);
          triangles[i][j].z:=cz+length*sin(ry+dy1);
          rvec.x:=(triangles[i][j].x-cx);
          rvec.y:=(triangles[i][j].y-cy);
          rvec.z:=(triangles[i][j].z-cz);
        end;

        if rz<>0 then
        begin
          length:=GetVecLength(triangles[i][j].x-cx,triangles[i][j].y-cy,0);
          if length<>0 then
          begin
            if rvec.x>=0 then
            begin
              dz1:=arccos((rvec.y)/length) ;
            end
            else begin
              dz1:=-arccos((rvec.y)/length) ;
            end;
          end
          else begin
            dz1:=0;
          end;
          triangles[i][j].x:=cx+length*sin(rz+dz1);
          triangles[i][j].y:=cy+length*cos(rz+dz1);
        end;


    end;
  end;
end;

procedure TMesh.move(dx,dy,dz:single);
var
  i,j:integer;

begin
  for i:=0 to high(triangles) do
  begin
    for j:=1 to 3 do
    begin
      triangles[i][j].x:=triangles[i][j].x+dx;
      triangles[i][j].y:=triangles[i][j].y+dy;
      triangles[i][j].z:=triangles[i][j].z+dz;
    end;
  end;
end;

function TForm1.projection(tr3d:TTriangle; clwidth,clheight:integer):TTriangle;
var
  i:integer;
  xc,yc,zc,xc1,yc1,zc1,lc,l:single;//aaeoi? eaia?u
  crx,cry,crz:single;
  mtx,mty,mtz,mts,beeline:tmatrix;
  vect:tpoint3d;
  x,y,z:single;
  halfWidth,halfHeight:integer;
  tx,ty:single;
begin
  halfwidth:=clwidth div 2;
  halfheight:=clheight div 2;
  lc:=GetVeclength(pviewto.x-pview.x,pviewto.y-pview.y,pviewto.z-pview.z);
  if lc=0 then exit;
  xc:=(pviewto.x-pview.x)/lc;
  yc:=(pviewto.y-pview.y)/lc;
  zc:=(pviewto.z-pview.z)/lc;

  l:=GetVeclength(0,pviewto.y-pview.y,pviewto.z-pview.z);
  if l<>0 then
  begin
    yc1:=(pviewto.y-pview.y)/l;
    zc1:=(pviewto.z-pview.z)/l;
    if zc1<=0  then  crx:=-arcsin(yc1) else crx:=arcsin(yc1);
  end
  else crx:=0;


  l:=GetVeclength(pviewto.x-pview.x,0,pviewto.z-pview.z);
  if l<>0 then
  begin
    xc1:=(pviewto.x-pview.x)/l;
    zc1:=(pviewto.z-pview.z)/l;
    if xc1>=0  then  cry:=arccos(zc1) else cry:=-arccos(zc1);
  end
  else cry:=0;

  {l:=GetVeclength(pviewto.x-pview.x,pviewto.y-pview.y,0);
  if l<>0 then
  begin
    xc1:=(pviewto.x-pview.x)/l;
    yc1:=(pviewto.y-pview.y)/l;
    if yc1>=0  then  crz:=arccos(xc1) else crz:=-arccos(xc1);
  end
  else crz:=0; }

  setrotatexmatrix(mtx,-crx);
  setrotateymatrix(mty,-cry);
  {setrotatezmatrix(mtz,-crz); }
  mts:=matrixmul(mtx,mty);
  {mts:=matrixmul(mts,mtz);}
  settranslatematrix(beeline,-pview.x,-pview.y,-pview.z);
  mts:=matrixmul(beeline,mts);

  for i:=1 to 3 do
  begin
    x:=tr3d[i].x;
    y:=tr3d[i].y;
    z:=tr3d[i].z{-pview.z};
    vect.x:=x*mts._11+y*mts._21+z*mts._31+mts._41;
    vect.y:=x*mts._12+y*mts._22+z*mts._32-mts._42;
    vect.z:=x*mts._13+y*mts._23+z*mts._33+mts._43;
    x:=vect.x;
    y:=vect.y;
    z:=vect.z;
    x:=x/(2*(z+0.5/tan(fov/2))*tan(fov/2));
    y:=y/(2*(z+0.5/tan(fov/2))*tan(fov/2));
    projection[i].x:=x*clwidth*hw+halfWidth;
    projection[i].y:=y*clheight+halfHeight;
  end;
end;

procedure tform1.setrotatexmatrix(var m:TMatrix; angle:single);
begin
  m._11:=1;
  m._12:=0;
  m._13:=0;
  m._14:=0;
  m._21:=0;
  m._22:=cos(angle);
  m._23:=sin(angle);
  m._24:=0;
  m._31:=0;
  m._32:=-sin(angle);
  m._33:=cos(angle);
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;

procedure tform1.setrotateymatrix(var m:TMatrix; angle:single);
begin
  m._11:=cos(angle);
  m._12:=0;
  m._13:=-sin(angle);
  m._14:=0;
  m._21:=0;
  m._22:=1;
  m._23:=0;
  m._24:=0;
  m._31:=sin(angle);
  m._32:=0;
  m._33:=cos(angle);
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;


procedure tform1.setrotatezmatrix(var m:TMatrix; angle:single);
begin
  m._11:=cos(angle);
  m._12:=sin(angle);
  m._13:=0;
  m._14:=0;
  m._21:=-sin(angle);
  m._22:=cos(angle);
  m._23:=0;
  m._24:=0;
  m._31:=0;
  m._32:=0;
  m._33:=1;
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;

procedure tform1.settranslatematrix(var m:TMatrix; x,y,z:single);
begin
  m._11:=1;
  m._12:=0;
  m._13:=0;
  m._14:=0;
  m._21:=0;
  m._22:=1;
  m._23:=0;
  m._24:=0;
  m._31:=0;
  m._32:=0;
  m._33:=1;
  m._34:=0;
  m._41:=x;
  m._42:=y;
  m._43:=z;
  m._44:=1;
end;

procedure tform1.addcube;
begin
  cube:=tmesh.Create;
  cube.cx:=0;
  cube.cy:=0;
  cube.cz:=0;
  setlength(cube.triangles,12);

  cube.triangles[0][1].x:=-0.5;
  cube.triangles[0][1].y:=-0.5;
  cube.triangles[0][1].z:=0.5;
  cube.triangles[0][2].x:=-0.5;
  cube.triangles[0][2].y:=0.5;
  cube.triangles[0][2].z:=0.5;
  cube.triangles[0][3].x:=0.5;
  cube.triangles[0][3].y:=0.5;
  cube.triangles[0][3].z:=0.5;

  cube.triangles[1][1].x:=-0.5;
  cube.triangles[1][1].y:=-0.5;
  cube.triangles[1][1].z:=0.5;
  cube.triangles[1][2].x:=0.5;
  cube.triangles[1][2].y:=0.5;
  cube.triangles[1][2].z:=0.5;
  cube.triangles[1][3].x:=0.5;
  cube.triangles[1][3].y:=-0.5;
  cube.triangles[1][3].z:=0.5;

  cube.triangles[2][1].x:=0.5;
  cube.triangles[2][1].y:=-0.5;
  cube.triangles[2][1].z:=-0.5;
  cube.triangles[2][2].x:=0.5;
  cube.triangles[2][2].y:=0.5;
  cube.triangles[2][2].z:=-0.5;
  cube.triangles[2][3].x:=-0.5;
  cube.triangles[2][3].y:=0.5;
  cube.triangles[2][3].z:=-0.5;

  cube.triangles[3][1].x:=0.5;
  cube.triangles[3][1].y:=-0.5;
  cube.triangles[3][1].z:=-0.5;
  cube.triangles[3][2].x:=-0.5;
  cube.triangles[3][2].y:=0.5;
  cube.triangles[3][2].z:=-0.5;
  cube.triangles[3][3].x:=-0.5;
  cube.triangles[3][3].y:=-0.5;
  cube.triangles[3][3].z:=-0.5;

  cube.triangles[4][1].x:=0.5;
  cube.triangles[4][1].y:=-0.5;
  cube.triangles[4][1].z:=-0.5;
  cube.triangles[4][2].x:=0.5;
  cube.triangles[4][2].y:=0.5;
  cube.triangles[4][2].z:=-0.5;
  cube.triangles[4][3].x:=0.5;
  cube.triangles[4][3].y:=0.5;
  cube.triangles[4][3].z:=0.5;

  cube.triangles[5][1].x:=0.5;
  cube.triangles[5][1].y:=-0.5;
  cube.triangles[5][1].z:=-0.5;
  cube.triangles[5][2].x:=0.5;
  cube.triangles[5][2].y:=0.5;
  cube.triangles[5][2].z:=0.5;
  cube.triangles[5][3].x:=0.5;
  cube.triangles[5][3].y:=-0.5;
  cube.triangles[5][3].z:=0.5;

  cube.triangles[6][1].x:=-0.5;
  cube.triangles[6][1].y:=-0.5;
  cube.triangles[6][1].z:=0.5;
  cube.triangles[6][2].x:=-0.5;
  cube.triangles[6][2].y:=0.5;
  cube.triangles[6][2].z:=0.5;
  cube.triangles[6][3].x:=-0.5;
  cube.triangles[6][3].y:=0.5;
  cube.triangles[6][3].z:=-0.5;

  cube.triangles[7][1].x:=-0.5;
  cube.triangles[7][1].y:=-0.5;
  cube.triangles[7][1].z:=0.5;
  cube.triangles[7][2].x:=-0.5;
  cube.triangles[7][2].y:=0.5;
  cube.triangles[7][2].z:=-0.5;
  cube.triangles[7][3].x:=-0.5;
  cube.triangles[7][3].y:=-0.5;
  cube.triangles[7][3].z:=-0.5;

  cube.triangles[8][1].x:=-0.5;
  cube.triangles[8][1].y:=0.5;
  cube.triangles[8][1].z:=-0.5;
  cube.triangles[8][2].x:=-0.5;
  cube.triangles[8][2].y:=0.5;
  cube.triangles[8][2].z:=0.5;
  cube.triangles[8][3].x:=0.5;
  cube.triangles[8][3].y:=0.5;
  cube.triangles[8][3].z:=0.5;

  cube.triangles[9][1].x:=-0.5;
  cube.triangles[9][1].y:=0.5;
  cube.triangles[9][1].z:=-0.5;
  cube.triangles[9][2].x:=0.5;
  cube.triangles[9][2].y:=0.5;
  cube.triangles[9][2].z:=0.5;
  cube.triangles[9][3].x:=0.5;
  cube.triangles[9][3].y:=0.5;
  cube.triangles[9][3].z:=-0.5;

  cube.triangles[10][1].x:=0.5;
  cube.triangles[10][1].y:=-0.5;
  cube.triangles[10][1].z:=-0.5;
  cube.triangles[10][2].x:=0.5;
  cube.triangles[10][2].y:=-0.5;
  cube.triangles[10][2].z:=0.5;
  cube.triangles[10][3].x:=-0.5;
  cube.triangles[10][3].y:=-0.5;
  cube.triangles[10][3].z:=0.5;

  cube.triangles[11][1].x:=0.5;
  cube.triangles[11][1].y:=-0.5;
  cube.triangles[11][1].z:=-0.5;
  cube.triangles[11][2].x:=-0.5;
  cube.triangles[11][2].y:=-0.5;
  cube.triangles[11][2].z:=0.5;
  cube.triangles[11][3].x:=-0.5;
  cube.triangles[11][3].y:=-0.5;
  cube.triangles[11][3].z:=-0.5;
  
end;

procedure tform1.drawtriangle(t:TTriangle);
var
  v1,v2:tpoint3d;
  pp:array of tpoint;
begin
  v1.x:=pviewto.x-pview.x;
  v1.y:=pviewto.y-pview.y;
  v1.z:=pviewto.z-pview.z;
  v2:=norm(t[1],t[2],t[3]);
  case cullmode of
    0:begin
    end;
    1:begin
      if v1.x*v2.x+v1.y*v2.y+v1.z*v2.z<0 then
      begin
        exit;
      end;
    end;
    2:begin
    end;
  end;
  case fillmode of
    0:begin
      t:=projection(t,form1.ClientWidth,form1.ClientHeight);
      setlength(pp,3);
      pp[0].X:=round(t[1].x);
      pp[0].Y:=round(t[1].y);
      pp[1].X:=round(t[2].x);
      pp[1].Y:=round(t[2].y);
      pp[2].X:=round(t[3].x);
      pp[2].Y:=round(t[3].y);
      backbitmap.Canvas.Brush.Color:=curbrcl;
      backbitmap.Canvas.pen.color:=curbrcl;
      backbitmap.Canvas.Polygon(pp);
      {backbitmap.Canvas.MoveTo(round(t[1].x),round(t[1].y));
      backbitmap.Canvas.LineTo(round(t[2].x),round(t[2].y));
      backbitmap.Canvas.LineTo(round(t[3].x),round(t[3].y));
      backbitmap.Canvas.LineTo(round(t[1].x),round(t[1].y)); }
    end;
    1:begin
      t:=projection(t,form1.ClientWidth,form1.ClientHeight);
      backbitmap.Canvas.pen.color:=curcl;
      backbitmap.Canvas.MoveTo(round(t[1].x),round(t[1].y));
      backbitmap.Canvas.LineTo(round(t[2].x),round(t[2].y));
      backbitmap.Canvas.LineTo(round(t[3].x),round(t[3].y));
      backbitmap.Canvas.LineTo(round(t[1].x),round(t[1].y));
    end;
    2:begin
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  backbitmap:=tbitmap.Create;
  backbitmap.Width:=screen.Width;
  backbitmap.Height:=screen.height;
  fillmode:=1;
  curbrcl:=clyellow;
  cullmode:=0;
  curcl:=clgray;
  pview.x:=0;
  pview.y:=0.5;
  pview.z:=4;
  pviewto.x:=0;
  pviewto.y:=0;
  pviewto.z:=0;
  addcube;
  fov:=1;
  hw:=clientheight/clientwidth;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  render;
  cube.rotate(0,0.1,0);
end;

procedure tform1.render;
var
  rect:trect;
  i:integer;
begin
  hw:=clientheight/clientwidth;
  setrect(rect,0,0,clientwidth,clientheight);
  backbitmap.Canvas.Brush.Color:=clbckgr;
  backbitmap.Canvas.FillRect(rect);
  if cube<>nil then
  begin
    for i:=0 to high(cube.triangles) do
    begin
      drawtriangle(cube.triangles[i]);
    end;
  end;
  form1.Canvas.CopyRect(rect,backbitmap.Canvas,rect);
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if key=' ' then
  begin
    if fillmode=0 then fillmode:=1 else fillmode:=0;
  end;
end;

end.


ЗЫ Практической ценности пример ИМХО не представляет, лучше изучать dx или opengl.
ЗЗЫ Создание вращающегося куба и написание серьезного 3d приложения (игры) это две ОГРОМНЫЕ разницы.
ЗЗЗЫ А может это вам в школе по предмету "Информатика" задали?smile Тогда нечего и огород городить. Там все гораздо проще.

Это сообщение отредактировал(а) Чупакабро - 27.9.2007, 20:57
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
Rickert
Дата 28.9.2007, 07:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ситхи не пройдут!
****


Профиль
Группа: Комодератор
Сообщений: 3356
Регистрация: 11.7.2006
Где: Лакрима

Репутация: 6
Всего: 52



Канвас красивее OGL & D3D  smile 
Мда...
И вообще, тема должна быть в Дельфи, в таком случае.
[...уходит ворча...]


--------------------
Ни что не внушает сна крепче, чем день приисполненный трудов!
PM MAIL WWW Skype GTalk   Вверх
fse
Дата 28.9.2007, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 28.9.2007
Где: г. Рязань

Репутация: нет
Всего: 1



Всем привет!
AVRUDOI, похвально стремление докопаться до сути 3д, правда на канвасе мало кто что рисует трёхмерного;)
Предложу и свой вариант кода.
Чупакабро написал, видимо, рабочий код, но для новичка в этом деле сложный. По крайней мере разбираться можно долгоsmile


Код

type
  TPoint3D = record
    X, Y, Z: Float;
    {$IFDEF USEPOINTDATA}
    Data: TUserData;
    {$ENDIF}
  end;

  TAngles = TPoint3D;
...

//Процедура поворота точки на 3 угла относительно начала координат в последовательности поворотов OX>OY>OZ:
function PointRotate(Angles: TAngles; Pt: TPoint3D): TPoint3D; overload;
begin
  Result:=PointRotateOX(Angles.X, Pt);
  Result:=PointRotateOY(Angles.Y, Result);
  Result:=PointRotateOZ(Angles.Z, Result);
end;

//Отдельные повороты:

function PointRotateOX(Angle: Float; Pt: TPoint3D): TPoint3D;
begin
  Angle:=DegToRad(Angle);
  Result.X:=Pt.X;
  Result.Y:=Pt.Y*Cos(Angle)-Pt.Z*Sin(Angle);
  Result.Z:=Pt.Y*Sin(Angle)+Pt.Z*Cos(Angle);
end;

function PointRotateOY(Angle: Float; Pt: TPoint3D): TPoint3D;
begin
  Angle:=DegToRad(Angle);
  Result.X:=Pt.X*Cos(Angle)+Pt.Z*Sin(Angle);
  Result.Z:=Pt.Z*Cos(Angle)-Pt.X*Sin(Angle);
  Result.Y:=Pt.Y;
end;

function PointRotateOZ(Angle: Float; Pt: TPoint3D): TPoint3D;
begin
  Angle:=DegToRad(Angle);
  Result.X:=Pt.X*Cos(Angle)-Pt.Y*Sin(Angle);
  Result.Y:=Pt.X*Sin(Angle)+Pt.Y*Cos(Angle);
  Result.Z:=Pt.Z;
end;


Вся дальнейшая работа сводится к повороту на нужные углы соответствующих вершин куба. И рисовать грани между соответствующими в кубе точками.

Могу посоветовать:

Если пересчитывается много точек, то создай таблицу sin(ox, oy, oz) и cos(ox, oy, oz), а не вычисляй их постоянно.

А реально, эти формулы получаются как раз из перемножения матриц поворота на вектор, то, что сделано у Чупакабро.
Это касательно поворотов.
Перспективу можно строить при помощи косоугольных систем координат.
Если с заливкой рисовать, то после поворотов всех точек нужно делать тест глубины (грубо говоря, сортировка точек по удалённости от проекционной плоскости).

Советую почитать:
Аналитическая геометрия (вышка)
Компьютерная графика (статьи в инете)

Удачи;)
PM MAIL   Вверх
Чупакабро
Дата 28.9.2007, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



Цитата(fse @  28.9.2007,  12:21 Найти цитируемый пост)
Чупакабро написал, видимо, рабочий код, но для новичка в этом деле сложный

А вы пробовали запускать? (заискивающе улыбается)
Цитата(fse @  28.9.2007,  12:21 Найти цитируемый пост)
рабочий код, но для новичка в этом деле сложный. По крайней мере разбираться можно долго

Дык я скоро комментарии подготовлю. Хотя ведь и не факт, что человеку реально нужно разобраться.
Я сам-то там половину методом научного тыка написал, например, нужно ли перемножать матрицу сдвига на матрицу поворота или в обратном порядке, чтобы получить нормальную картинку.
Ну а вообще вращающийся куб иногда рисуют даже в школе на информатике, хотя к 3d это имеет весьма отдаленное отношение.
Зато код получается простой, это да.
Да, кстати... fse, у вас получается, что куб вращается вокруг начала координат. В принципе, автору темы наверно это и нужно, но если реализовывать поворот вокруг произвольной оси, то код усложняется. То же самое с перспективой. Это как раз-таки задачка посложнее, чем само по себе вращение куба. А если сюда же добавить эмуляцию пиксельных шейдеров... smile

Цитата(Rickert @  28.9.2007,  07:41 Найти цитируемый пост)
И вообще, тема должна быть в Дельфи, в таком случае.

Нет нет. Все правильно это именно программирование графики, а перевести все это на C, например, дело недолгое, т.к. здесь одна математика.


Это сообщение отредактировал(а) Чупакабро - 28.9.2007, 18:29
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
fse
Дата 29.9.2007, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 28.9.2007
Где: г. Рязань

Репутация: нет
Всего: 1



Чупакабро, оно так всё, если делать по науке - то конечно, матрицы. Хотя на уровне формул тоже нужно понимать.
Цитата

если реализовывать поворот вокруг произвольной оси, то код усложняется

Не согласен, вот как будет выглядеть процедура поворота...

Как было

Код

function PointRotate(Angles: TAngles; Pt: TPoint3D): TPoint3D; overload;
begin
  Result:=PointRotateOX(Angles.X, Pt);
  Result:=PointRotateOY(Angles.Y, Result);
  Result:=PointRotateOZ(Angles.Z, Result);
end;


Как стало

Код

function PointRotate(Angles: TAngles; Pt: TPoint3D; RotCenter: TPoint3D): TPoint3D; overload;
begin
  Pt.X := Pt.X - RotCenter.X;
  Pt.Y := Pt.Y - RotCenter.Y;
  Pt.Z := Pt.Z - RotCenter.Z;

  Result:=PointRotateOX(Angles.X, Pt);
  Result:=PointRotateOY(Angles.Y, Result);
  Result:=PointRotateOZ(Angles.Z, Result);

  Result.X := Result.X + RotCenter.X;
  Result.Y := Result.Y + RotCenter.Y;
  Result.Z := Result.Z + RotCenter.Z;
end;


Т.е. мы просто перевели точку к другому началу координат простым перемещением, повернули точку вокруг нового начала координат, потом переместили обратно!smile

На самом деле, в тех задачах, что сейчас у меня, удобно работать именно не с матрицами, а с формулами, поэтому я пишу именно так.
При этом, вместо матрицы смещения используется просто суммирование координат. Масштабирование: умножение координат на коэффициенты.
При таком подходе существенно возрастает скорость, т.к. мы отходим от не столь быстрой операции умножения матриц.

Цитата

То же самое с перспективой


Опять же, спорный вопрос ;)

Перспектива - это просто перенос вектора в косоугольную систему координат.
Если есть оси ox, oy, oz (единичные вектора) в новой косоугольной СК; x, y, z - координаты вектора; их нужно перевести в эту новую СК. При этом нужно просто найти проекции вектора каждую ось новой СК. Эти проекции численно будут являться координатами в перспективе. Находится тремя операциями скалярного произведения, что весьма быстроsmile

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

"добавить эмуляцию пиксельных шейдеров" - ууух, я и словей таких не знаю smile

Цитата

перемножать матрицу сдвига на матрицу поворота или в обратном порядке


Хм, а это всё зависет от нужного нам результата ;)
PM MAIL   Вверх
Чупакабро
Дата 29.9.2007, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



Цитата(fse @  29.9.2007,  12:12 Найти цитируемый пост)
Т.е. мы просто перевели точку к другому началу координат простым перемещением, повернули точку вокруг нового начала координат, потом переместили обратно!

Дык. Это я и имел в виду под усложнением кода) У вас получилось на 6 строчек больше smile

Цитата(fse @  29.9.2007,  12:12 Найти цитируемый пост)
"добавить эмуляцию пиксельных шейдеров" - ууух, я и словей таких не знаю 

Ну, может я не так выразился. Имелось в виду выполнение операций над пикселями (как растерезация, так и всякие эффекты) центральным процессором, а не GPU.

--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
AVRUDOI
Дата 18.10.2007, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 29.8.2007

Репутация: нет
Всего: нет



Цитата(Чупакабро @ 27.9.2007,  16:09)
Значит так, выкладываю код.
Нужно создать форму с таймером и весь код модуля unit1 заменить на нижеследующий.
Сейчас нет времени писать подробные комментарии, это я наверное на выходных сделаю, но про некоторые особенности напишу сейчас.
Прграмма рисует вращающийся куб, режим закраски можно менять клавишей "пробел".
Прграмма поддерживает отрисовку и анимацию произвольных полигональных объектов стандартными средствами Delphi (без использования DirectX и OpenGL). Можно изменять позицию объектов и камеры.
Не успел реализовать отсечение невидимых треугольников, z-buffer, направленные источники света. Возможно добавлю позднее.
Программа получилась большая, т.к. претендует на универсальность, а не только на отрисовку конкретно вращающегося куба.

Собственно код:

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Math, ExtCtrls;  //uses math

type

  TMatrix=record
    _11,_12,_13,_14,_21,_22,_23,_24,_31,_32,_33,_34,_41,_42,_43,_44:single;
  end;
  T3Matrix=record
    _11,_12,_13,_21,_22,_23,_31,_32,_33:single
  end;

  TPoint3d=record
    x,y,z:single;
  end;

  TTriangle=array[1..3] of TPoint3d;

  TMesh=class
    triangles:array of TTriangle;
    cx,cy,cz:single;
    procedure rotate(rx,ry,rz:single);
    procedure move(dx,dy,dz:single);
  end;

  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
  private
    { Private declarations }
  public
    { Public declarations }
    HW:single;
    fov:single;
    pview:tpoint3d;
    pviewto:tpoint3d;
    fillmode:byte;//0-solid,1-wireframe,2-point
    cullmode:byte;//0-iao iona?aiey,1-?eno?ony ii ?n,2-?eno?ony i?ioea ?n
    backBitmap:tbitmap;
    clbckgr:tcolor;
    curcl:tcolor;
    curbrcl:tcolor;
    function projection(tr3d:TTriangle; clwidth,clheight:integer):TTriangle;
    procedure setrotatexmatrix(var m:TMatrix; angle:single);
    procedure setrotateymatrix(var m:TMatrix; angle:single);
    procedure setrotatezmatrix(var m:TMatrix; angle:single);
    procedure settranslatematrix(var m:TMatrix; x,y,z:single);
    procedure render;
    procedure drawtriangle(t:TTriangle);
    procedure addcube;
  end;

var
  Form1: TForm1;
  cube:tmesh;

implementation

{$R *.dfm}
function GetVecLength(x,y,z:single):single;
begin
  GetVecLength:=sqrt(sqr(x)+sqr(y)+sqr(z));
end;

function norm(p1,p2,p3:TPoint3d):TPoint3d;
var
  v1,v2:tpoint3d;
begin
  v1.x:=p2.x-p1.x;
  v1.y:=p2.y-p1.y;
  v1.z:=p2.z-p1.z;
  v2.x:=p3.x-p1.x;
  v2.y:=p3.y-p1.y;
  v2.z:=p3.z-p1.z;
  norm.x:=v1.y*v2.z-v1.z*v2.y;
  norm.y:=-v1.x*v2.z+v1.z*v2.x;
  norm.z:=v1.x*v2.y-v1.y*v2.x;
end;

{function det(_11,_12,_13,_21,_22,_23,_31,_32,_33:single):single;
begin
  det:=_11*(_22*_33-_32*_23)-_12*(_21*_33-_31*_23)+_13*(_21*_32-_31*_22);
end;}

function matrixmul(m1,m2:TMatrix):TMatrix;
begin
  matrixmul._11:=m1._11*m2._11+m1._12*m2._21+m1._13*m2._31+m1._14*m2._41;
  matrixmul._12:=m1._11*m2._12+m1._12*m2._22+m1._13*m2._32+m1._14*m2._42;
  matrixmul._13:=m1._11*m2._13+m1._12*m2._23+m1._13*m2._33+m1._14*m2._43;
  matrixmul._14:=m1._11*m2._14+m1._12*m2._24+m1._13*m2._34+m1._14*m2._44;

  matrixmul._21:=m1._21*m2._11+m1._22*m2._21+m1._23*m2._31+m1._24*m2._41;
  matrixmul._22:=m1._21*m2._12+m1._22*m2._22+m1._23*m2._32+m1._24*m2._42;
  matrixmul._23:=m1._21*m2._13+m1._22*m2._23+m1._23*m2._33+m1._24*m2._43;
  matrixmul._24:=m1._21*m2._14+m1._22*m2._24+m1._23*m2._34+m1._24*m2._44;

  matrixmul._31:=m1._31*m2._11+m1._32*m2._21+m1._33*m2._31+m1._34*m2._41;
  matrixmul._32:=m1._31*m2._12+m1._32*m2._22+m1._33*m2._32+m1._34*m2._42;
  matrixmul._33:=m1._31*m2._13+m1._32*m2._23+m1._33*m2._33+m1._34*m2._43;
  matrixmul._34:=m1._31*m2._14+m1._32*m2._24+m1._33*m2._34+m1._34*m2._44;

  matrixmul._41:=m1._41*m2._11+m1._42*m2._21+m1._43*m2._31+m1._44*m2._41;
  matrixmul._42:=m1._41*m2._12+m1._42*m2._22+m1._43*m2._32+m1._44*m2._42;
  matrixmul._43:=m1._41*m2._13+m1._42*m2._23+m1._43*m2._33+m1._44*m2._43;
  matrixmul._44:=m1._41*m2._14+m1._42*m2._24+m1._43*m2._34+m1._44*m2._44;
end;

procedure TMesh.rotate(rx,ry,rz:single);
var
  i,j:integer;
  rvec:tpoint3d;
  length:single;
  ax,ay,az:single;
  dc,dx,dy,dz:T3Matrix;
  dx1,dy1,dz1:single;
begin
  for i:=0 to high(triangles) do
  begin
    for j:=1 to 3 do
    begin

        rvec.x:=(triangles[i][j].x-cx);
        rvec.y:=(triangles[i][j].y-cy);
        rvec.z:=(triangles[i][j].z-cz);

        if rx<>0 then
        begin
          length:=GetVecLength(0,triangles[i][j].y-cy,triangles[i][j].z-cz);
          if length<>0 then
          begin
            if rvec.y>=0 then
            begin
              dx1:=arccos((rvec.z)/length) ;
            end
            else begin
              dx1:=-arccos((rvec.z)/length) ;
            end;
          end
          else begin
            dx1:=0;
          end;
          triangles[i][j].y:=cy+length*sin(rx+dx1);
          triangles[i][j].z:=cz+length*cos(rx+dx1);
          rvec.x:=(triangles[i][j].x-cx);
          rvec.y:=(triangles[i][j].y-cy);
          rvec.z:=(triangles[i][j].z-cz);
        end;

        if ry<>0 then
        begin
          length:=GetVecLength(triangles[i][j].x-cx,0,triangles[i][j].z-cz);
          if length<>0 then
          begin
            if rvec.z>=0 then
            begin
              dy1:=arccos(rvec.x/length) ;
            end
            else begin
              dy1:=-arccos(rvec.x/length) ;
            end;
          end
          else begin
            dy1:=0;
          end;
          triangles[i][j].x:=cx+length*cos(ry+dy1);
          triangles[i][j].z:=cz+length*sin(ry+dy1);
          rvec.x:=(triangles[i][j].x-cx);
          rvec.y:=(triangles[i][j].y-cy);
          rvec.z:=(triangles[i][j].z-cz);
        end;

        if rz<>0 then
        begin
          length:=GetVecLength(triangles[i][j].x-cx,triangles[i][j].y-cy,0);
          if length<>0 then
          begin
            if rvec.x>=0 then
            begin
              dz1:=arccos((rvec.y)/length) ;
            end
            else begin
              dz1:=-arccos((rvec.y)/length) ;
            end;
          end
          else begin
            dz1:=0;
          end;
          triangles[i][j].x:=cx+length*sin(rz+dz1);
          triangles[i][j].y:=cy+length*cos(rz+dz1);
        end;


    end;
  end;
end;

procedure TMesh.move(dx,dy,dz:single);
var
  i,j:integer;

begin
  for i:=0 to high(triangles) do
  begin
    for j:=1 to 3 do
    begin
      triangles[i][j].x:=triangles[i][j].x+dx;
      triangles[i][j].y:=triangles[i][j].y+dy;
      triangles[i][j].z:=triangles[i][j].z+dz;
    end;
  end;
end;

function TForm1.projection(tr3d:TTriangle; clwidth,clheight:integer):TTriangle;
var
  i:integer;
  xc,yc,zc,xc1,yc1,zc1,lc,l:single;//aaeoi? eaia?u
  crx,cry,crz:single;
  mtx,mty,mtz,mts,beeline:tmatrix;
  vect:tpoint3d;
  x,y,z:single;
  halfWidth,halfHeight:integer;
  tx,ty:single;
begin
  halfwidth:=clwidth div 2;
  halfheight:=clheight div 2;
  lc:=GetVeclength(pviewto.x-pview.x,pviewto.y-pview.y,pviewto.z-pview.z);
  if lc=0 then exit;
  xc:=(pviewto.x-pview.x)/lc;
  yc:=(pviewto.y-pview.y)/lc;
  zc:=(pviewto.z-pview.z)/lc;

  l:=GetVeclength(0,pviewto.y-pview.y,pviewto.z-pview.z);
  if l<>0 then
  begin
    yc1:=(pviewto.y-pview.y)/l;
    zc1:=(pviewto.z-pview.z)/l;
    if zc1<=0  then  crx:=-arcsin(yc1) else crx:=arcsin(yc1);
  end
  else crx:=0;


  l:=GetVeclength(pviewto.x-pview.x,0,pviewto.z-pview.z);
  if l<>0 then
  begin
    xc1:=(pviewto.x-pview.x)/l;
    zc1:=(pviewto.z-pview.z)/l;
    if xc1>=0  then  cry:=arccos(zc1) else cry:=-arccos(zc1);
  end
  else cry:=0;

  {l:=GetVeclength(pviewto.x-pview.x,pviewto.y-pview.y,0);
  if l<>0 then
  begin
    xc1:=(pviewto.x-pview.x)/l;
    yc1:=(pviewto.y-pview.y)/l;
    if yc1>=0  then  crz:=arccos(xc1) else crz:=-arccos(xc1);
  end
  else crz:=0; }

  setrotatexmatrix(mtx,-crx);
  setrotateymatrix(mty,-cry);
  {setrotatezmatrix(mtz,-crz); }
  mts:=matrixmul(mtx,mty);
  {mts:=matrixmul(mts,mtz);}
  settranslatematrix(beeline,-pview.x,-pview.y,-pview.z);
  mts:=matrixmul(beeline,mts);

  for i:=1 to 3 do
  begin
    x:=tr3d[i].x;
    y:=tr3d[i].y;
    z:=tr3d[i].z{-pview.z};
    vect.x:=x*mts._11+y*mts._21+z*mts._31+mts._41;
    vect.y:=x*mts._12+y*mts._22+z*mts._32-mts._42;
    vect.z:=x*mts._13+y*mts._23+z*mts._33+mts._43;
    x:=vect.x;
    y:=vect.y;
    z:=vect.z;
    x:=x/(2*(z+0.5/tan(fov/2))*tan(fov/2));
    y:=y/(2*(z+0.5/tan(fov/2))*tan(fov/2));
    projection[i].x:=x*clwidth*hw+halfWidth;
    projection[i].y:=y*clheight+halfHeight;
  end;
end;

procedure tform1.setrotatexmatrix(var m:TMatrix; angle:single);
begin
  m._11:=1;
  m._12:=0;
  m._13:=0;
  m._14:=0;
  m._21:=0;
  m._22:=cos(angle);
  m._23:=sin(angle);
  m._24:=0;
  m._31:=0;
  m._32:=-sin(angle);
  m._33:=cos(angle);
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;

procedure tform1.setrotateymatrix(var m:TMatrix; angle:single);
begin
  m._11:=cos(angle);
  m._12:=0;
  m._13:=-sin(angle);
  m._14:=0;
  m._21:=0;
  m._22:=1;
  m._23:=0;
  m._24:=0;
  m._31:=sin(angle);
  m._32:=0;
  m._33:=cos(angle);
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;


procedure tform1.setrotatezmatrix(var m:TMatrix; angle:single);
begin
  m._11:=cos(angle);
  m._12:=sin(angle);
  m._13:=0;
  m._14:=0;
  m._21:=-sin(angle);
  m._22:=cos(angle);
  m._23:=0;
  m._24:=0;
  m._31:=0;
  m._32:=0;
  m._33:=1;
  m._34:=0;
  m._41:=0;
  m._42:=0;
  m._43:=0;
  m._44:=1;
end;

procedure tform1.settranslatematrix(var m:TMatrix; x,y,z:single);
begin
  m._11:=1;
  m._12:=0;
  m._13:=0;
  m._14:=0;
  m._21:=0;
  m._22:=1;
  m._23:=0;
  m._24:=0;
  m._31:=0;
  m._32:=0;
  m._33:=1;
  m._34:=0;
  m._41:=x;
  m._42:=y;
  m._43:=z;
  m._44:=1;
end;

procedure tform1.addcube;
begin
  cube:=tmesh.Create;
  cube.cx:=0;
  cube.cy:=0;
  cube.cz:=0;
  setlength(cube.triangles,12);

  cube.triangles[0][1].x:=-0.5;
  cube.triangles[0][1].y:=-0.5;
  cube.triangles[0][1].z:=0.5;
  cube.triangles[0][2].x:=-0.5;
  cube.triangles[0][2].y:=0.5;
  cube.triangles[0][2].z:=0.5;
  cube.triangles[0][3].x:=0.5;
  cube.triangles[0][3].y:=0.5;
  cube.triangles[0][3].z:=0.5;

  cube.triangles[1][1].x:=-0.5;
  cube.triangles[1][1].y:=-0.5;
  cube.triangles[1][1].z:=0.5;
  cube.triangles[1][2].x:=0.5;
  cube.triangles[1][2].y:=0.5;
  cube.triangles[1][2].z:=0.5;
  cube.triangles[1][3].x:=0.5;
  cube.triangles[1][3].y:=-0.5;
  cube.triangles[1][3].z:=0.5;

  cube.triangles[2][1].x:=0.5;
  cube.triangles[2][1].y:=-0.5;
  cube.triangles[2][1].z:=-0.5;
  cube.triangles[2][2].x:=0.5;
  cube.triangles[2][2].y:=0.5;
  cube.triangles[2][2].z:=-0.5;
  cube.triangles[2][3].x:=-0.5;
  cube.triangles[2][3].y:=0.5;
  cube.triangles[2][3].z:=-0.5;

  cube.triangles[3][1].x:=0.5;
  cube.triangles[3][1].y:=-0.5;
  cube.triangles[3][1].z:=-0.5;
  cube.triangles[3][2].x:=-0.5;
  cube.triangles[3][2].y:=0.5;
  cube.triangles[3][2].z:=-0.5;
  cube.triangles[3][3].x:=-0.5;
  cube.triangles[3][3].y:=-0.5;
  cube.triangles[3][3].z:=-0.5;

  cube.triangles[4][1].x:=0.5;
  cube.triangles[4][1].y:=-0.5;
  cube.triangles[4][1].z:=-0.5;
  cube.triangles[4][2].x:=0.5;
  cube.triangles[4][2].y:=0.5;
  cube.triangles[4][2].z:=-0.5;
  cube.triangles[4][3].x:=0.5;
  cube.triangles[4][3].y:=0.5;
  cube.triangles[4][3].z:=0.5;

  cube.triangles[5][1].x:=0.5;
  cube.triangles[5][1].y:=-0.5;
  cube.triangles[5][1].z:=-0.5;
  cube.triangles[5][2].x:=0.5;
  cube.triangles[5][2].y:=0.5;
  cube.triangles[5][2].z:=0.5;
  cube.triangles[5][3].x:=0.5;
  cube.triangles[5][3].y:=-0.5;
  cube.triangles[5][3].z:=0.5;

  cube.triangles[6][1].x:=-0.5;
  cube.triangles[6][1].y:=-0.5;
  cube.triangles[6][1].z:=0.5;
  cube.triangles[6][2].x:=-0.5;
  cube.triangles[6][2].y:=0.5;
  cube.triangles[6][2].z:=0.5;
  cube.triangles[6][3].x:=-0.5;
  cube.triangles[6][3].y:=0.5;
  cube.triangles[6][3].z:=-0.5;

  cube.triangles[7][1].x:=-0.5;
  cube.triangles[7][1].y:=-0.5;
  cube.triangles[7][1].z:=0.5;
  cube.triangles[7][2].x:=-0.5;
  cube.triangles[7][2].y:=0.5;
  cube.triangles[7][2].z:=-0.5;
  cube.triangles[7][3].x:=-0.5;
  cube.triangles[7][3].y:=-0.5;
  cube.triangles[7][3].z:=-0.5;

  cube.triangles[8][1].x:=-0.5;
  cube.triangles[8][1].y:=0.5;
  cube.triangles[8][1].z:=-0.5;
  cube.triangles[8][2].x:=-0.5;
  cube.triangles[8][2].y:=0.5;
  cube.triangles[8][2].z:=0.5;
  cube.triangles[8][3].x:=0.5;
  cube.triangles[8][3].y:=0.5;
  cube.triangles[8][3].z:=0.5;

  cube.triangles[9][1].x:=-0.5;
  cube.triangles[9][1].y:=0.5;
  cube.triangles[9][1].z:=-0.5;
  cube.triangles[9][2].x:=0.5;
  cube.triangles[9][2].y:=0.5;
  cube.triangles[9][2].z:=0.5;
  cube.triangles[9][3].x:=0.5;
  cube.triangles[9][3].y:=0.5;
  cube.triangles[9][3].z:=-0.5;

  cube.triangles[10][1].x:=0.5;
  cube.triangles[10][1].y:=-0.5;
  cube.triangles[10][1].z:=-0.5;
  cube.triangles[10][2].x:=0.5;
  cube.triangles[10][2].y:=-0.5;
  cube.triangles[10][2].z:=0.5;
  cube.triangles[10][3].x:=-0.5;
  cube.triangles[10][3].y:=-0.5;
  cube.triangles[10][3].z:=0.5;

  cube.triangles[11][1].x:=0.5;
  cube.triangles[11][1].y:=-0.5;
  cube.triangles[11][1].z:=-0.5;
  cube.triangles[11][2].x:=-0.5;
  cube.triangles[11][2].y:=-0.5;
  cube.triangles[11][2].z:=0.5;
  cube.triangles[11][3].x:=-0.5;
  cube.triangles[11][3].y:=-0.5;
  cube.triangles[11][3].z:=-0.5;
  
end;

procedure tform1.drawtriangle(t:TTriangle);
var
  v1,v2:tpoint3d;
  pp:array of tpoint;
begin
  v1.x:=pviewto.x-pview.x;
  v1.y:=pviewto.y-pview.y;
  v1.z:=pviewto.z-pview.z;
  v2:=norm(t[1],t[2],t[3]);
  case cullmode of
    0:begin
    end;
    1:begin
      if v1.x*v2.x+v1.y*v2.y+v1.z*v2.z<0 then
      begin
        exit;
      end;
    end;
    2:begin
    end;
  end;
  case fillmode of
    0:begin
      t:=projection(t,form1.ClientWidth,form1.ClientHeight);
      setlength(pp,3);
      pp[0].X:=round(t[1].x);
      pp[0].Y:=round(t[1].y);
      pp[1].X:=round(t[2].x);
      pp[1].Y:=round(t[2].y);
      pp[2].X:=round(t[3].x);
      pp[2].Y:=round(t[3].y);
      backbitmap.Canvas.Brush.Color:=curbrcl;
      backbitmap.Canvas.pen.color:=curbrcl;
      backbitmap.Canvas.Polygon(pp);
      {backbitmap.Canvas.MoveTo(round(t[1].x),round(t[1].y));
      backbitmap.Canvas.LineTo(round(t[2].x),round(t[2].y));
      backbitmap.Canvas.LineTo(round(t[3].x),round(t[3].y));
      backbitmap.Canvas.LineTo(round(t[1].x),round(t[1].y)); }
    end;
    1:begin
      t:=projection(t,form1.ClientWidth,form1.ClientHeight);
      backbitmap.Canvas.pen.color:=curcl;
      backbitmap.Canvas.MoveTo(round(t[1].x),round(t[1].y));
      backbitmap.Canvas.LineTo(round(t[2].x),round(t[2].y));
      backbitmap.Canvas.LineTo(round(t[3].x),round(t[3].y));
      backbitmap.Canvas.LineTo(round(t[1].x),round(t[1].y));
    end;
    2:begin
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  backbitmap:=tbitmap.Create;
  backbitmap.Width:=screen.Width;
  backbitmap.Height:=screen.height;
  fillmode:=1;
  curbrcl:=clyellow;
  cullmode:=0;
  curcl:=clgray;
  pview.x:=0;
  pview.y:=0.5;
  pview.z:=4;
  pviewto.x:=0;
  pviewto.y:=0;
  pviewto.z:=0;
  addcube;
  fov:=1;
  hw:=clientheight/clientwidth;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  render;
  cube.rotate(0,0.1,0);
end;

procedure tform1.render;
var
  rect:trect;
  i:integer;
begin
  hw:=clientheight/clientwidth;
  setrect(rect,0,0,clientwidth,clientheight);
  backbitmap.Canvas.Brush.Color:=clbckgr;
  backbitmap.Canvas.FillRect(rect);
  if cube<>nil then
  begin
    for i:=0 to high(cube.triangles) do
    begin
      drawtriangle(cube.triangles[i]);
    end;
  end;
  form1.Canvas.CopyRect(rect,backbitmap.Canvas,rect);
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if key=' ' then
  begin
    if fillmode=0 then fillmode:=1 else fillmode:=0;
  end;
end;

end.


ЗЫ Практической ценности пример ИМХО не представляет, лучше изучать dx или opengl.
ЗЗЫ Создание вращающегося куба и написание серьезного 3d приложения (игры) это две ОГРОМНЫЕ разницы.
ЗЗЗЫ А может это вам в школе по предмету "Информатика" задали?smile Тогда нечего и огород городить. Там все гораздо проще.

Здраствуйте. Поидеи все вроде номально. НО вот пробелемма что код нехочет работать с Делфи 7. Пробемма соостоит в том что происхотит  перегрузка памети т.е. код выходит за пределы выделенной помети. Пока не могу понять где. Увожаемая "Чупокабра" немогли бы подсказать где может произойти перегрузка. smile 
PM MAIL   Вверх
Чупакабро
Дата 21.10.2008, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 27.2.2007

Репутация: 2
Всего: 4



Цитата(AVRUDOI @  18.10.2007,  14:54 Найти цитируемый пост)
Увожаемая "Чупокабра

Сильно сказано!
Не понял: что значит "код твыходит за пределы выделенной памяти"?
А в других версиях Delphi работает?
У меня в седьмой все нормально...
--------------------
Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 00459B8B in module 'Project1.exe'. Read of address 0000019C'. Process stopped. Use Step or Run to continue.
PM MAIL   Вверх
fse
Дата 21.10.2008, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 28.9.2007
Где: г. Рязань

Репутация: нет
Всего: 1



Всем привет!

Чупакабро, код запустил, симпотично smile)
Правда сложные многоугольники без теста глубины чудить будут ужасно. Я когда-то даже поддержал в проекте GDI-3Д своего загрузку моделей из максовских файлов и произвольное освещение. Как положено, цвет считался по проекции на вектор нормали полигона! Без теста глубины получилось плачевно smile)) А тест глубины - довольно сложный алгоритм, так что DOOM4 не получился smile

А у AVRUDOI пологаю что знаю в чём проблема!
По шагам, что делать в D7:
- Создаёшь новый проект
- Копипастишь напрямую
- Ctrl-F9
Она спросит "удалить ли описанный Timer1", говоришь да
Помещаешь его на форму
Создаёшь из среды для таймера OnTimer
Для формы OnCreate и OnKeyPress.

И тогда всё заработает. Иначе программа обращается к объектам backbitmap и cube, которые не создаются, т.к. не вызывается OnCreate. И тогда аксес невалялся  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование игр, графики и искуственного интеллекта"
Rickert

НА ЗЛОБУ ДНЯ: Дорогие посетители, прошу обратить внимание что новые темы касающиеся новых вопросов создаются кнопкой "Новая тема" а не "Ответить"! Любые оффтопиковые вопросы, заданные в текущих тематических темах будут удалены а их авторы, при рецедиве, забанены.

  • Литературу, связанную с программированием графики, обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы связанные с программированием графики и мультимедии на языках С++ и Delphi
  • Вопросы по реализации алгоритмов рассматриваются здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rickert.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование игр, графики и искусственного интеллекта | Следующая тема »


 




[ Время генерации скрипта: 0.1086 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.