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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Z-буфер, Срочно нужна помощь! 
:(
    Опции темы
tolyadzyuba
Дата 25.5.2009, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Выручайте! Я сделал прогу, которая рисует проволочную модель выпуклого многограника. Но теперь мне надо удалить невидимые грани, используя алгоритм Z буфера. По этой теме перечитал несколько статей, и как я понял в этом алгоритме необходимо проходить по всем пикселям экрана. И я не понимаю, как по ним пройтись всем, если у меня тока ребра многограника.  Короче, кто знает про Z буфер, объясните, плиз, как мне отсканировать грани многограника, если у меня только координаты вершин извесны.
PM MAIL   Вверх
xvr
Дата 26.5.2009, 11:19 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



А нафига это было писать статьёй?
Для проволочной модели z буфер не поможет - через проволоки все прекрасно видно  smile 
Для удаления невидимых граней нужно рендерить именно грани (а не ребра). Каждая грань отображается на плоскость вывода (точнее окно). z буфер покрывает эту плоскость. При рендеринге грани образуется массив (2х мерный) точек, соотвествующий образу исходной грани. Каждая точка так же содержит исходную z координату, которая и сравнивается с тем, что лежит в этом месте в z буфере

PM MAIL   Вверх
math64
Дата 26.5.2009, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



Поскольку рисуются только рёбра, можно пройтись по всем граням и по всем рёбрам и определить какие рёбра закрываются гранями и определить множество рёбер не закрытых гранями и потом рисовать оставшиеся рёбра. Грань может закрывать часть ребра, но для выпуклого многогранника в итоге либо ребро видно целиком, либо не видно вовсе. С отдельными пискелями ничего делать не надо.
PM   Вверх
tolyadzyuba
Дата 26.5.2009, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ну тогда объясните мне, дураку, как из координат вершин сделать грани, чтобы потом их просканировать???
PM MAIL   Вверх
math64
Дата 26.5.2009, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



Многоранник должен быть представлен как множество вершин, множество рёбер и множество граней.
Если есть только вершины, можно восстановить рёбра и грани, но из-за ошибок огругления восстановленные грани будут треугольными и появятся дополнительные рёбра.
Ребро определяется двумя вершинами. Ребро имеет формулу:
Код

x = x0 + (x1-x0)*t;
y = y0 + (y1-y0)*t;
z = z0 + (z1-z0)*t;
0 <= t <= 1

Грань - минимум по трём вершинам, плоскость грани имеет формулу
Код

 a*x+b*y+c*z+d = 0

Для точек внутри многогранника и для вершин не приндлежащих грани знаки коэффициентов выбираются так, что
Код

 a*x+b*y+c*z+d > 0


PM   Вверх
math64
Дата 27.5.2009, 07:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



Вектор (a,b,c) перпендикулярен плоскости грани и направлен внутрь многогранника.
Если мы проектируем на плоскость (x,y), то грани у которых c >= 0 не видны. Соответственно, нужно рисовать только рёбра видимых граней.
PM   Вверх
tolyadzyuba
Дата 28.5.2009, 08:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Это я знаю, это для выпуклых тока. Делал так. Мне надо z-буфер теперь сделать. 
PM MAIL   Вверх
math64
Дата 28.5.2009, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

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



C z-буфером - как писал xvr. Не определяешь какие грани видны, а какие нет, а рисуешь все попиксельно. Для каждого пискеля вычисляешь координату z согласно формуле a*x+b*y+c*z+d = 0. Если новая z больше старой, рисуешь соответствуюший пискель и устанавливаешь новый z, иначе пропускаешь
Код

class Screen {
int width, int height;
Color* pixels;
double* zbuf;
public:
  Screen(int w, int h) : width(w), height(h), pixels(new Color[w*h]), zbuf(new double(w*h)) {
    for(int i=0; i < w*h; i++) {
       pixel[i] = Color::Black;
       zbuf[i] = -1E99;
    }
  }
  void putpixel(int x, int y, double z, Color c) {
    if (x < 0 || y < 0 || x >= width || y >= height)
      return;
    int off = x + y*width;
    if (z >= zbuf[off]) {
      zbuf[off] = z;
      pixels[off] = c;
    }
  }
}

PM   Вверх
tolyadzyuba
Дата 28.5.2009, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ага, спасибо огромное, на выходных буду пробовать вставить это все в программу. А то щас пока других проблем в учебе хватает!))
PM MAIL   Вверх
tolyadzyuba
Дата 30.5.2009, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Ну, помогайте опять! Посмотрите пожалуйста код мой, не могу найти, почему отображаются не правильно фигуры... Ребра не там, где надо....

Управление загрузкой фигур клавишами. Загрузка из файла, дам в конце текст файла kyb.txt. Чтобы его загрузить надо нажать Л.

Код

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <allegro.h>
#define W 1024
#define H 768

int type();
int knopki();
void povorot_x(double);
void povorot_y(double);
void povorot_z(double);
void povorot();
int x(int);
int y(int);
int z(int);
void vivesti_fig();
void zbuf(int,int);
void peremeshenie(int,int,int);
void razmer(double,double,double);
int invisible(int);
int fill(int);
void matrix(double B[4][4]);
void chistka();
void f_x3(),f_y3(),f_z3();

int fl_x=0,fl_y=0,fl_z=0;
int x3=0,y3=0,z3=0;
int fl_catch=0;
int type_fig;
int gr[100];
int n;
int f=0;
int X=0,Y=0,Z=0;
float fig[100][3];
char *file[100];
int Zbuf[786432];
int zi[786432];
double A[4][4]={
            1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            0,0,0,1};
  int red=makecol24(40,0,0);

BITMAP *bmp,*start;
PALETTE pal;

int type(){
  int i,j;
  FILE *in;
  in=fopen(*file,"r");
  fscanf(in,"%d",&n);
  for(j=0;j<3;j++)
  {
  for(i=0;i<n;i++)
      {
      fscanf(in,"%f",&fig[i][j]);   
      }  
  }     
      i=0;
      do
      {
         fscanf(in,"%d",&gr[i]);
         i++;
      }while(gr[i-1]!=-2)    ; 
  fclose(in);
  return n;
}

int knopki(){
    do{
    blit(start,bmp,0,0,886,0,1024,768);
    if (((mouse_x>897)&&(mouse_x<1012)&&(mouse_y>37)&&(mouse_y<112)&&(mouse_b&1))or(key[KEY_K])){clear_bitmap(bmp); *file="kyb.txt"; type(); fl_catch=1;}
    if (((mouse_x>897)&&(mouse_x<1012)&&(mouse_y>150)&&(mouse_y<224)&&(mouse_b&1))or(key[KEY_O])){clear_bitmap(bmp); *file="okt.txt"; type(); fl_catch=1;}
    if (((mouse_x>897)&&(mouse_x<1012)&&(mouse_y>262)&&(mouse_y<337)&&(mouse_b&1))or(key[KEY_T])){clear_bitmap(bmp); *file="tet.txt"; type(); fl_catch=1;}
    if (((mouse_x>897)&&(mouse_x<1012)&&(mouse_y>375)&&(mouse_y<449)&&(mouse_b&1))or(key[KEY_D])){clear_bitmap(bmp); *file="dod.txt"; type(); fl_catch=1;}
    if (((mouse_x>897)&&(mouse_x<1012)&&(mouse_y>487)&&(mouse_y<562)&&(mouse_b&1))or(key[KEY_I])){clear_bitmap(bmp); *file="iko.txt"; type(); fl_catch=1;}
    if (key[KEY_ESC]) return 1;
    blit(bmp,screen,0,0,0,0,W,H);
    }while(fl_catch==0);
    return 0;
}

int x(int p){
    return ((int)(fig[p][0]*A[0][0]+fig[p][1]*A[1][0]+fig[p][2]*A[2][0]+A[3][0]+W/2));
}

int y(int p){
    return ((int)(fig[p][0]*A[0][1]+fig[p][1]*A[1][1]+fig[p][2]*A[2][1]+A[3][1]+H/2));
}

int z(int p){
    return ((int)(fig[p][0]*A[0][2]+fig[p][1]*A[1][2]+fig[p][2]*A[2][2]+A[3][2]));
}

void vivesti_fig(){
    rectfill(bmp,0,0,W,H,0);
    int i=0,j=0,xp,yp,xp_1,yp_1,xp_2,yp_2,tmp=0;
    int h=0;
    for(i=0;i<786432;i++)Zbuf[i]=10000;
    i=0;
    do{
            if (gr[i]==-2){break;}
            if (gr[i]==-1)
            {
                i=i++;j=i;
                
                fl_x=(x(gr[i+2])+x(gr[i]))/2;
                fl_y=(y(gr[i+2])+y(gr[i]))/2;
                if(y(gr[i])!=y(gr[i+2]))
                fl_z=z(gr[i+2])+(z(gr[i])-z(gr[i+2]))*(fl_y-y(gr[i+2]))/(y(gr[i])-y(gr[i+2]));
                else
                    fl_z=z(gr[i+2])+(z(gr[i])-z(gr[i+2]))*(fl_x-x(gr[i+2]))/(x(gr[i])-x(gr[i+2]));
            }else
            if(gr[i+1]==-1)
            {
                zbuf(gr[i],gr[j]);
                i=i++;
            }    
            else 
            {
                zbuf(gr[i],gr[i+1]);
                i++;
            }
    }while(gr[i+1]!=-2);
           for(i=0;i<H;i++)
           for(j=0;j<W;j++)
           {
               if (Zbuf[i*W+j]<10000) putpixel(bmp, j, i, 100);
           }  
    i=0;
    do{
            if (gr[i+1]==-2){break;}
            if (gr[i]==-1){j=i+1;if(Zbuf[y(gr[j])*W+x(gr[j])]==z(gr[j]))h=1;else h=0;}
            else {
                xp=x(gr[i]);
                yp=y(gr[i]);
                       if (gr[i+1]==-1){
                           xp_1=x(gr[j]);
                           yp_1=y(gr[j]);
                           if (h) {line(bmp,xp,yp,xp_1,yp_1,red);}
                       }
                       else {
                           xp_1=x(gr[i+1]);
                           yp_1=y(gr[i+1]);
                           if (h) {line(bmp,xp,yp,xp_1,yp_1,red);}
                       }
            }
        i++;
    }while(gr[i]!=-2);
}

void zbuf(int t1,int t2)
{   
    int t=0,y1=y(t1),y2=y(t2),y3=fl_y;
    int xa=0,xb=0,za=0,zb=0,yi=0,xi=0,i=0;
    int x1=x(t1),x2=x(t2),x3=fl_x;
    int z1=z(t1),z2=z(t2),z3=fl_z;
    for(i=0;i<786432;i++)zi[i]=10000;
    do{
    if(y1>y2)
    {
        t=y1;y1=y2;y2=t;
        t=x1;x1=x2;x2=t;
        t=z1;z1=z2;z2=t;
    }    
    if(y2>y3)
    {
        t=y2;y2=y3;y3=t;
        t=x2;x2=x3;x3=t;
        t=z2;z2=z3;z3=t;
    }    
    }while(y1>y2 or y2>y3);
    if (y3 == y1)
    {
    do{
    if(x1>x2)
    {
        t=x1;x1=x2;x2=t;
        t=z1;z1=z2;z2=t;
    }    
    if(x2>x3)
    {
        t=x2;x2=x3;x3=t;
        t=z2;z2=z3;z3=t;
    }    
    }while(x1>x2 or x2>x3);
    xa=x1;xb=x3;za=z1;zb=z3;
    if(xa==xb)
    {
           zi[y1*W+xa]=za;
           if(Zbuf[y1*W+xa]>zi[y1*W+xa])Zbuf[y1*W+xa]=zi[y1*W+xa]; 
    }else
        for(xi=xa;xi<=xb;xi++)
    {
           zi[y1*W+xi]=za+(zb-za)*(xi-xa)/(xb-xa);
           if(Zbuf[y1*W+xi]>zi[y1*W+xi])Zbuf[y1*W+xi]=zi[y1*W+xi];  
    }
    }    
    else{
    for (yi = y1; yi <= y3; yi++) {
        xa = x1 + (yi - y1) * (x3 - x1) / (y3 - y1);
        za=z1+(z3-z1)*(yi-y1)/(y3-y1);
        
    if (yi < y2){
        xb = x1 + (yi - y1) * (x2 - x1) / (y2 - y1);
        zb=z1+(z2-z1)*(yi-y1)/(y2-y1);}
    else {
    if (y3 == y2)
        {xb = x2;
        zb=z2;}
    else
        xb = x2 + (yi - y2) * (x3 - x2) / (y3 - y2);
        zb=z2+(z3-z2)*(yi-y1)/(y3-y1);
    }
    if(xa>xb){t=xa;xa=xb;xb=t;}
    if(xa==xb)
    {
           zi[yi*W+xa]=za;
           if(Zbuf[yi*W+xa]>zi[yi*W+xa])Zbuf[yi*W+xa]=zi[yi*W+xa];  
    }
    else
    for(xi=xa;xi<=xb;xi++)
        {
           zi[yi*W+xi]=za+(zb-za)*(xi-xa)/(xb-xa);
           if(Zbuf[yi*W+xi]>zi[yi*W+xi])Zbuf[yi*W+xi]=zi[yi*W+xi];  
        }
    }
    }    
}       

void matrix(double B[4][4]){
    double C[4][4];
    int i,j,k;
    for (i=0; i<4; i++){
        for (k=0; k<4; k++){
                C[i][k]=0;
                for (j=0; j<4; j++){
                    C[i][k]+=A[i][j]*B[j][k];
                }
        }
    }
    for (i=0; i<4; i++){
        for (k=0; k<4; k++){
            A[i][k]=C[i][k];
        }
    }        
}

void peremeshenie(int dx, int dy, int dz){
    double B[4][4]={
            1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            dx,dy,dz,1};
    matrix(B);
}

void razmer(double mx, double my, double mz){
    X=A[3][0];
    Y=A[3][1];
    Z=A[3][2];
    peremeshenie(-X,-Y,-Z);
    double B[4][4]={
            mx,0,0,0,
            0,my,0,0,
            0,0,mz,0,
            0,0,0,1};
    matrix(B);
    peremeshenie(X,Y,Z);
}

void povorot_x(double ygol){
    X=A[3][0];
    Y=A[3][1];
    Z=A[3][2];
    peremeshenie(-X,-Y,-Z);
    double B[4][4]={
            1,0,0,0,
            0,cos(ygol),sin(ygol),0,
            0,-sin(ygol),cos(ygol),0,
            0,0,0,1};
    matrix(B);
    peremeshenie(X,Y,Z);
}

void povorot_y(double ygol){
    X=A[3][0];
    Y=A[3][1];
    Z=A[3][2];
    peremeshenie(-X,-Y,-Z);
    double B[4][4]={
            cos(ygol),0,sin(ygol),0,
            0,1,0,0,
            -sin(ygol),0,cos(ygol),0,
            0,0,0,1};
    matrix(B);
    peremeshenie(X,Y,Z);
}

void povorot_z(double ygol){
    X=A[3][0];
    Y=A[3][1];
    Z=A[3][2];
    peremeshenie(-X,-Y,-Z);
    double B[4][4]={
            cos(ygol),sin(ygol),0,0,
            -sin(ygol),cos(ygol),0,0,
            0,0,1,0,
            0,0,0,1};
    matrix(B);
    peremeshenie(X,Y,Z);
}

int invisible(int p){
    double c=(y(gr[p+1])-y(gr[p]))*(x(gr[p+2])-x(gr[p]))-(y(gr[p+2])-y(gr[p]))*(x(gr[p+1])-x(gr[p]));
    if (c>=0) return 1;
    if (c<0) return 0;
}

using namespace std;

int main(int argc, char *argv[])
{
  allegro_init();
  install_keyboard();
  install_mouse();
  install_timer();
  bmp=create_bitmap(W,H);
  set_gfx_mode(GFX_AUTODETECT,W,H,0,0);
  set_color_depth(24);
  show_mouse(bmp);
  start=load_bitmap("start.bmp",pal);
  type_fig=-1;
  do{
      if (knopki()==1){return 0;}
  show_mouse(NULL);
  do{
      if (n!=-1){vivesti_fig();}
                if (key[KEY_LEFT]){peremeshenie(-2,0,0);}
                if (key[KEY_RIGHT]){peremeshenie(2,0,0);}
                if (key[KEY_UP]){peremeshenie(0,-2,0);}
                if (key[KEY_DOWN]){peremeshenie(0,2,0);}
                if (key[KEY_HOME]){peremeshenie(0,0,-2);}
                if (key[KEY_END]){peremeshenie(0,0,2);}
                if (key[KEY_1]){razmer(0.990,0.990,0.990);}
                if (key[KEY_2]){razmer(1.010,1.010,1.010);}
                if (key[KEY_X]){povorot_x(3.14/100);}
                if (key[KEY_Y]){povorot_y(3.14/100);}
                if (key[KEY_Z]){povorot_z(3.14/100);}
                if (key[KEY_A]){f=1;}
                if (f==1) {povorot_x(3.14/800); povorot_y(3.14/550); povorot_z(3.14/400);}
                if (key[KEY_S]){f=0;}

  blit(bmp,screen,0,0,0,0,W,H);
  
  if (key[KEY_ESC]) return 0;
  }while(!key[KEY_P]);
  fl_catch=0;
  clear_bitmap(bmp);
  show_mouse(bmp);
  }while(!key[KEY_ESC]);
  allegro_exit();
  return 0;
}
END_OF_MAIN();


kyb.txt:

Код

8
-100 -100 100 100 -100 -100 100 100
100 -100 -100 100 100 -100 -100 100
100 100 100 100 -100 -100 -100 -100
-1 0 1 2 3 -1 7 6 5 4 -1 3 2 6 7 -1 0 4 5 1 -1 1 5 6 2 -1 0 3 7 4 -1 
-2

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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