Шаг 83.
Основы компьютерной графики.
Примеры изображения трехмерных объектов. Шар. Удаление невидимых точек

    На этом шаге мы рассмотрим алгоритм удаления таких точек.

    Для изображения поверхности шара с удалением невидимых точек в аксонометрической проекции можно воспользоваться таким свойством: видимыми являются точки с неотрицательным значением координаты Z в системе видовых координат. При этом центр видовых координат (X, Y, Z) совпадает с центром шара, плоскость X0Y является плоскостью проецирования, а ось Z направлена на камеру (наблюдателя). На рисунке 1 приведен простейший вариант показа поверхности шара с удалением невидимых точек меридианов и параллелей.


Рис.1. Удалены невидимые точки

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

    В заключение этого шага приведем текст программы, которая строит вращающийся шар (рисунок 1).

.   .   .   .
void MerOrPar(HDC hdc,int cxw,int cyw,double R, double alf, double bt, BOOL mer);
void DrawMyEh(HDC hdc, double alf, double bt, int cxw, int cyw);
void RotXYZ(double *X, double *Y, double *Z, 
    double x, double y, double z, double a, double b);

void DrawStudyExample(HWND hWnd)
{
  HDC hdc, hdcWin;
  RECT rc;
  HBITMAP hBitMap;
  HCURSOR hCurOld;

  hCurOld=SetCursor(LoadCursor(NULL,IDC_WAIT));
  GetClientRect(hWnd,&rc);
  hdcWin=GetDC(hWnd);
  hdc=CreateCompatibleDC(hdcWin);
  hBitMap=CreateCompatibleBitmap(hdcWin, rc.right, rc. bottom);
  SelectObject(hdc, hBitMap);
  PatBlt(hdc, 0,0,rc.right,rc.bottom, WHITENESS);
  for(int alf=0;alf<=720;alf++)
  {
    DrawMyEh(hdc,alf,45,rc.right,rc.bottom);
    BitBlt(hdcWin,0,0,rc.right,rc.bottom, hdc,0,0,SRCCOPY);
  }
  DeleteDC(hdc);
  DeleteObject(hBitMap);
  ReleaseDC(hWnd,hdcWin);
  SetCursor(hCurOld);
}

void MerOrPar(HDC hdc,int cxw,int cyw,double R, double alf, double bt, BOOL mer)
{
 int i,j, st_i,end_i, st_j,end_j;
 BOOL st;
 double x,y,z,X,Y,Z,B,L,rad;
 double *ai,*aj;
 rad=M_PI/180.0;
 alf*=rad;
 bt*=rad;
 if(mer)
  {
    st_i=0;
    end_i=360;
    st_j=-90;
    end_j=90;
    ai=&L;
    aj=&B;
  }
 else
  {
    st_i=-80;
    end_i=80;
    st_j=0;
    end_j=360;
    ai=&B;
    aj=&L;
  }
  for (i=st_i;i<end_i;i+=10)
 {
    st=FALSE;
    *ai=(double)i*rad;
    for(j=st_j;j<=end_j;j+=10)
	{
	 *aj=(double)j *rad;
	 x=R*cos(B)*sin(L);
	 y=R*cos(B)*cos(L);
	 z=R*sin(B);
	 RotXYZ(&X,&Y,&Z,x,y,z,alf,bt);
	 if(st)
	 {
	  if(Z<0) st=FALSE;
	  else LineTo(hdc,X+cxw/2,Y+cyw/2);
	 }
	 else
	 {
	  if(Z>=0)
	  {
                    st=TRUE;
                    MoveToEx(hdc, X+cxw/2,Y+cyw/2,NULL);
	  }
	 }
	}
 }
}

void DrawMyEh(HDC hdc, double alf, double bt, int cxw, int cyw)
{
  int R;
  if(cxw<=cyw)
	  R=cxw/2-10;
  else R=cyw/2-10;

  Ellipse(hdc, cxw/2-R,cyw/2-R,cxw/2+R,cyw/2+R);
  MerOrPar(hdc, cxw,cyw,R,alf,bt,TRUE);
  MerOrPar(hdc, cxw,cyw,R,alf,bt,FALSE);
}

void RotXYZ(double *X, double *Y, double *Z, double x, double y, double z, 
        double adouble, double b)
{
  *X=x*cos(a)-y*sin(a);
  *Y=x*sin(a)*cos(b)+y*cos(a)*cos(b)-z*sin(b);
  *Z=x*sin(a)*sin(b)+y*cos(a)*sin(b)+z*cos(b);
}
Полный текст программы можно взять здесь.

    На следующем шаге мы рассмотрим многогранник с закрашиванием граней.




Предыдущий шаг Содержание Следующий шаг