OpenGL obserwator

0
#include<windows.h>
#include<stdio.h>

/* Główna bibloteka OpenGL */
#include<GL/gl.h>
/* Biblioteka GLUT */
#include<GL/glut.h>
#include<math.h>

/* Deklaracje funkcji narzędziowych */
void DrawScene(void);
void DrawSceneAxes(void);
void InitOpenGL(void);
void ReshapeWindow(int width, int height);
void drawFractal(GLclampf a,GLclampf x, GLclampf y, GLfloat z,GLshort depth);
void drawTetraedr(GLclampf a, GLclampf x, GLclampf y, GLfloat z, GLclampf r, GLclampf g, GLclampf b);
void MouseFunc(int button, int state, int x, int y);
void MouseMotion(GLsizei x, GLsizei y);
/* Deklaracja globalnych zmiennych */
int x=1,y=1;
float light_pos[]={0.0,0.0,0.0};
GLfloat viewer_pos[] = { 10.0, 0.0, 0.0 };
GLfloat R = 10.0f;
GLfloat thetax = 0.0f;
GLfloat thetay = 0.0f;
GLfloat thetax1 = 0.0f;
GLfloat thetay1 = 0.0f;
GLfloat pixels2angle = 0.0;
GLint lbutton_status = 0;
GLint rbutton_status = 0;
GLint x_last_pos = 0; 
GLint y_last_pos = 0;
GLint x_delta = 0;
GLint y_delta = 0;
int mainWindow;
///////////////////////
GLshort Depth = 1.0;///
///////////////////////
struct vertex_coord {
	GLfloat x;
	GLfloat y;
	GLfloat z;
};
struct vertex_coord w1;
struct vertex_coord w2;
struct vertex_coord w3;
struct vertex_coord w4;

void mKeyboard(unsigned char c, int /*x*/,int /*y*/);
/* Funkcja main */
int main(int argc, char **argv){
	glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(1000, 690);
	glutInitWindowPosition(370,10);
    mainWindow = glutCreateWindow("ZADANIE DO DOMU :)");
	if(mainWindow == 0){
		puts("Nie mozna stworzyc okna!!!\nWyjscie z programu.\n");
		exit(-1);
	}
	glutSetWindow(mainWindow);
	InitOpenGL();
	glutDisplayFunc(DrawScene);
	glutReshapeFunc(ReshapeWindow);
	glutMouseFunc(MouseFunc);
	glutMotionFunc(MouseMotion);
	glutKeyboardFunc(mKeyboard);
	glEnable(GL_DEPTH_TEST);
	glutMainLoop();
	return(0);
}
void DrawScene(void){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	gluLookAt(viewer_pos[0],viewer_pos[1],viewer_pos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
	if(!x)
	{
		InitOpenGL();
	}
	DrawSceneAxes();
	if(lbutton_status == 1){
		if(x){
		thetax += x_delta*pixels2angle/50;
		thetay += y_delta*pixels2angle/50;
		}
		else{
		thetax1 += x_delta*pixels2angle/50;
		thetay1 += y_delta*pixels2angle/50;
		}
	}
	if(rbutton_status == 1){
		R+=(y_delta/2);
	}
	viewer_pos[0] = abs(R)*cos(thetax)*cos(thetay);
	viewer_pos[1] = abs(R)*sin(thetay);
	viewer_pos[2] = abs(R)*cos(thetay)*sin(thetax);

	light_pos[0] = R*cos(thetax1)*cos(thetay1);
	light_pos[1] = R*sin(thetay1);
	light_pos[2] = R*cos(thetay1)*sin(thetax1);

	printf("%lf %lf %lf \n",viewer_pos[0] ,viewer_pos[1] ,viewer_pos[2]  );
	//printf("[%lf %lf %lf] \n",light_pos[0] ,light_pos[1] ,light_pos[2]  );
	drawFractal(5.0f,0.0f,3.0f,0.0f,Depth);
	//DrawSierp(0,0,0,5, 4);
	glFlush();
	glutSwapBuffers();

}


void drawTetraedr(GLclampf a, GLclampf x, GLclampf y, GLfloat z, GLclampf r, GLclampf g, GLclampf b) {
	GLfloat h = (a * sqrt(3.0f))/2;
	GLfloat h1 = h/3;
	GLfloat h2 = 2*h1;
	glBegin(GL_TRIANGLE_STRIP);
		glColor3f(0, 0.9, 1); 

			w1.x=x;
			w1.y=y;
			w1.z=z;

			w2.x= x + 0.5*a;
			w2.y=y-h;
			w2.z=z-h1;
			
			w3.x=x - 0.5*a ;
			w3.y=y-h;
			w3.z=z-h1;
			
			w4.x= x;
			w4.y=y - h;
			w4.z=z + h2;
	

		glVertex3f(x, y, z);
		glVertex3f(x - 0.5*a, y-h, z-h1);
		glVertex3f(x + 0.5*a, y-h, z-h1);
		glVertex3f(x, y - h, z + h2);
		glVertex3f(x, y, z);
		glVertex3f(x - 0.5*a, y-h, z-h1);
	glEnd();
}
void drawFractal(GLclampf a,GLclampf x, GLclampf y, GLfloat z,GLshort depth){
	 if(depth == 1) {
		drawTetraedr(a, x, y, z, 1.0f , 1.0f, 1.0f);
	 } else {
		GLfloat h = (a * sqrt(3.0f))/2;
		GLfloat h1 = h/3;
		GLfloat h2 = 2*h1;
		GLfloat mh = ((0.5*a) * sqrt(3.0f))/2;
		GLfloat mh1 = mh/3;
		GLfloat mh2 = (2*mh)/3;
		drawFractal(0.5*a,x,y,z,depth-1);
		drawFractal(0.5*a,x,y-mh,z+h2-mh2,depth-1);
		drawFractal(0.5*a,x-0.25*a,y-mh,z-h1+mh1,depth-1);
		drawFractal(0.5*a,x+0.25*a,y-mh,z-h1+mh1,depth-1);
	 }
}
void MouseFunc(int button, int state, int x, int y){
	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
		x_last_pos = x;
		y_last_pos = y;
		lbutton_status = 1;
	} else {
		lbutton_status = 0;
	}
	if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
		x_last_pos = x;
		y_last_pos = y;
		rbutton_status = 1;
	} else {
		rbutton_status = 0;
	}
}
void MouseMotion(GLsizei x, GLsizei y){
	x_delta = x - x_last_pos;
	y_delta = y - y_last_pos;
	x_last_pos = x;
	y_last_pos = y;
	glutPostRedisplay();
}
void DrawSceneAxes(void)
{
	// Definiujemy nowy typ jako tablicę 3-elementową
	typedef float pt3d[3];

	// Początek i koniec osi X
	pt3d x_beg = { -10.0f, 0.0f, 0.0f };
	pt3d x_end = {  10.0f, 0.0f, 0.0f };

	// Poczatek i koniec osi Y
	pt3d y_beg = { 0.0f, -10.0f, 0.0f };
	pt3d y_end = { 0.0f,  10.0f, 0.0f };

	// Początek i koniec osi Z
	pt3d z_beg = { 0.0f, 0.0f, -10.0f };
	pt3d z_end = { 0.0f, 0.0f,  10.0f };

	// Rysujemy osie
	glBegin(GL_LINES);
		// Czerwony kolor dla osi X
		glColor3f(1.0f, 0.0f, 0.0f);
		glVertex3fv(x_beg);
		glVertex3fv(x_end);

		// Zielony kolor dla osi Y
		glColor3f(0.0f, 1.0f, 0.0f);
		glVertex3fv(y_beg);
		glVertex3fv(y_end);

		// Niebieski kolor dla osi Z
		glColor3f(0.0f, 0.0f, 1.0f);
		glVertex3fv(z_beg);
		glVertex3fv(z_end);
	glEnd();

}
void InitOpenGL(void){
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	
	// współczynniki ka =[kar,kag,ka dla światła otoczenia
	GLfloat mat_ambient[] = {1.0, 1.0, 1.0, 1.0};    
	// współczynniki kd =[kdr,kdg,kd światła rozproszonego
	GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};
	// współczynniki ks =[ksr,ksg,ks dla światła odbitego 
	GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};               
    // współczynnik n opisujący połysk powierzchni
    GLfloat mat_shininess  = {20.0};
    

	//światło 1 
	// składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
	GLfloat light_ambient1[] = {2.0, 0.0, 0.0, 1.0};
	// składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
	GLfloat light_diffuse1[] = {2.0, 0.0, 0.0, 1.0};
	// składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
	GLfloat light_specular1[] = {2.0, 0.0, 0.0, 1.0};

	
	//światło 2
	// składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
	GLfloat light_ambient2[] = {0.0, 0.1, 0.0, 1.0};
	// składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
	GLfloat light_diffuse2[] = {0.0, 2.0, 0.0, 1.0};    
	// składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
    GLfloat light_specular2[] = {0.0, 2.0, 0.0, 1.0};

  	//światło 3
	// składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
	GLfloat light_ambient3[] = {0.0, 0.0, 0.1, 1.0};
	// składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
	GLfloat light_diffuse3[] = {0.0, 0.0, 2.0, 1.0};    
	// składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
	GLfloat light_specular3[] = {0.0, 0.0, 2.0, 1.0};

  	//światło 4
	// składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
	GLfloat light_ambient4[] = {0.0, 0.1, 0.1, 1.0};
	// składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
	GLfloat light_diffuse4[] = {0.0, 1.0, 1.0, 1.0};    
	// składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
	GLfloat light_specular4[] = {0.0, 1.0, 1.0, 1.0};


	GLfloat light_position1[] = {0.0 + light_pos[0],10.0 + light_pos[1],0.0 + light_pos[2], 0.0};
	GLfloat light_position2[] = {0.0 + light_pos[0],3.0 + light_pos[1],-9.0 + light_pos[2], 0.0};
	GLfloat light_position3[] = {8.3 + light_pos[0],3.0 + light_pos[1],4.5 + light_pos[2], 0.0};
	GLfloat light_position4[] = {-7.8 +light_pos[0],4.5 + light_pos[1],4.3 + light_pos[2], 0.0};
 	// składowa stała ds dla modelu zmian oświetlenia w funkcji // odległości od źródła
    GLfloat att_constant  = {1.0};
	// składowa liniowa dl dla modelu zmian oświetlenia w funkcji // odległości od źródła
    GLfloat att_linear    = {0.05}; 
	// składowa kwadratowa dq dla modelu zmian oświetlenia w funkcji// odległości od źródła
	GLfloat att_quadratic  = {0.001};

                         
// Ustawienie parametrów materiału i źródła światła

// Ustawienie patrametrów materiału 

	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

// Ustawienie parametrów źródła

    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient1);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse1);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular1);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position1);

	glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient2);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse2);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular2);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position2);

	glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient3);
    glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse3);
    glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular3);
    glLightfv(GL_LIGHT2, GL_POSITION, light_position3);

	glLightfv(GL_LIGHT3, GL_AMBIENT, light_ambient4);
    glLightfv(GL_LIGHT3, GL_DIFFUSE, light_diffuse4);
    glLightfv(GL_LIGHT3, GL_SPECULAR, light_specular4);
    glLightfv(GL_LIGHT3, GL_POSITION, light_position4);


    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, att_quadratic);

	glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, att_quadratic);
	    
	glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, att_quadratic);
	    
	glLightf(GL_LIGHT3, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT3, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT3, GL_QUADRATIC_ATTENUATION, att_quadratic);


	// Ustawienie opcji systemu oświetlania sceny 

    glShadeModel(GL_SMOOTH); // właczenie łagodnego cieniowania
    glEnable(GL_LIGHTING);   // właczenie systemu oświetlenia sceny 
	glEnable(GL_LIGHT0);     // włączenie źródła o numerze 0
	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHT2);
	glEnable(GL_LIGHT3);

	    glEnable(GL_DEPTH_TEST); // włączenie mechanizmu z-bufora 


}


void ReshapeWindow(int width, int height){
	pixels2angle = 360.0f/(float)width;
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity();
	gluPerspective(70.0, 1.0, 1.0, 40.0);
    if(width <= height)
	glViewport(0, (height - width)/2, width, width);  
    else
	glViewport((width - height)/2, 0, height, height); 
    glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}


void mKeyboard(unsigned char c, int /*x*/,int /*y*/)
{
		switch(c)
		{
		case 45:
			if(Depth > 1)
				Depth--;
			DrawScene();
			printf("%d",Depth);
			
			break;
		case 43:
			if(Depth < 10)
			Depth++;
			DrawScene();
			printf("%d",Depth);
			break;
		case 49:
			if(x)x=0;
			else 
			x=1;DrawScene();
			break;
		case 50://?
			if(y)
			{	glEnable(GL_LIGHT0);     // włączenie źródła o numerze 0
				glEnable(GL_LIGHT1);
				glEnable(GL_LIGHT2);
				glEnable(GL_LIGHT3);
				y=0;
			}
			else 
			{
			glDisable(GL_LIGHT0);     // włączenie źródła o numerze 0
			glDisable(GL_LIGHT1);
			glDisable(GL_LIGHT2);
			glDisable(GL_LIGHT3);
			y=1;
			}
			DrawScene();
			break;
		case 27:
			printf("wyjscie z programu");
			exit(-1);	
		default:
			printf("%d - %c\n",c,c);
		}
}

Pytanie brzmi, dlaczego jak ruszam obserwatorem wzdłuż osi Y ( przy przejściu na 2gą stronę czworościanu) tworzy się nagle przeskok , i jak to naprawić ? Proszę o pomoc

0

Z tego co widze próbujesz zrobić coś a'la Arcball (http://aklimx.sppieniezno.pl/nehepl/display.php?id=48).

Przeskok związany jest albo ze zmianą położenia kamery w linijce:

gluLookAt(viewer_pos[0],viewer_pos[1],viewer_pos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
 

albo z samymi współrzędnymi wierzchołków fraktala które zmieniasz w trakcie renderingu. Chyba tylko w tych dwóch przypadkach
przekształcasz wierzchołki.
Magiczne wzory odpowiadają chyba z obrót, tak?:

 viewer_pos[0] = abs(R)*cos(thetax)*cos(thetay);
 viewer_pos[1] = abs(R)*sin(thetay);
 viewer_pos[2] = abs(R)*cos(thetay)*sin(thetax); 

Może tu leży problem. Sam je wyprowadziłeś?
Do obrotu znacznie wygodniej będzie ci użyć operacji na macierzach jak w linku powyżej.

Zamiast fraktala ustaw sobie jakiś sześcian z wierzchołkami na sztywno i zobacz co się stanie. Jeśli nadal lipa to wina kamery,
a dokładniej wspomnianych wzorów liczących jej pozycje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1