Я рисую сферу с помощью OpenGL.Эта программа может рисовать сферу, когда "SLIED = STACK".Но это не работает, когда "SLIED не равен STACK".Я могу быть ошибкой «индексный массив».
Я хочу использовать VBO и DMA (динамическая память allocate.use flat array).Но если у вас есть еще одна хорошая идея, научите меня.
//#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib,"glew32.lib")
#include <gl/glew.h>
#include <math.h>
#include <GL/freeglut/freeglut.h>
#define WIDTH 640
#define HEIGHT 480
#define M_PI 3.14159265358979323846
float angle=0.0f;
//functions----------------------------------------------//
void Shere_dma(double radius, int nSlice, int nStack);
void setSphereData(double radius, int nSlice, int nStack);
void DrawSphereVBO(void);
//-------------------------------------------------------//
//variabless---------------------------------------------//
int SLICE=0;
int STACK=0;
GLuint SVboId[3];
GLfloat* Svertex;//Vertex
GLfloat* Snormal;//Normal
GLfloat* Scolor; //Color
GLuint* indices_top; //TOP indices
GLuint* indices_bottom; //BOTTOM indies
GLuint* indices_side; //SIDE indices
//-------------------------------------------------------//
//Memory Allocate
void Shere_dma(double radius, int nSlice, int nStack){
Svertex = new GLfloat[(nSlice+1)*(nStack+1)*3];
Snormal = new GLfloat[(nSlice+1)*(nStack+1)*3];
Scolor = new GLfloat[(nSlice+1)*(nStack+1)*3];
indices_top = new GLuint[(nSlice+1)*(nStack+1)*3];
indices_bottom = new GLuint[(nSlice+1)*(nStack+1)*3];
indices_side = new GLuint[(nSlice+1)*(nStack+1)*4];
}
//inputData
void setSphereData(double radius, int nSlice, int nStack){
double phi; //Azimuth
double theta; //long
int coordinates=0;
int Slice_current_point_no=0;
int Slice_next_point_no=0;
const int x = 0;
const int y = 1;
const int z = 2;
const int p1 = 0;
const int p2 = 1;
const int p3 = 2;
const int p4 = 3;
//Vertex
for(int i = 0;i <= nSlice;i++)
{
phi = 2.0 * M_PI * (double)i / (double)nSlice;
for(int j = 0;j <= nStack;j++)
{
theta = M_PI * (double)j / (double)nStack;
Svertex[coordinates+x] = (float)(radius * sin(theta) * cos(phi)); //x
Svertex[coordinates+y] = (float)(radius * sin(theta) * sin(phi)); //y
Svertex[coordinates+z] = (float)(radius * cos(theta)); //z
Snormal[coordinates+x] = (float)(radius * sin(theta) * cos(phi)); //x
Snormal[coordinates+y] = (float)(radius * sin(theta) * sin(phi)); //y
Snormal[coordinates+z] = (float)(radius * cos(theta)); //z
Scolor[coordinates+x] = 1.0; //x
Scolor[coordinates+y] = 0.0; //y
Scolor[coordinates+z] = 0.0; //z
coordinates += 3;
}
}
//TOP
coordinates = 0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice;
for(int i = 0; i < nSlice; i++){
indices_top[coordinates+p1] = Slice_current_point_no;
indices_top[coordinates+p2] = indices_top[coordinates]+1;
indices_top[coordinates+p3] = Slice_next_point_no+2;
coordinates+=3;
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//BOTTOM
coordinates =0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice;
for(int i = 0; i < nSlice; i++){
indices_bottom[coordinates+p1] = Slice_current_point_no+(nStack-1);
indices_bottom[coordinates+p2] = indices_bottom[coordinates]+1;
indices_bottom[coordinates+p3] = Slice_next_point_no+(nStack);
coordinates+=3;
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//↓May be wrong ********************************************************************************//
//SIDE
coordinates=0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice+1;
for(int i=0; i < nSlice;i++){
for(int j=1; j < nStack-1; j++){
indices_side[coordinates+p1] = Slice_current_point_no+j;
indices_side[coordinates+p2] = indices_side[coordinates]+1;
indices_side[coordinates+p3] = Slice_next_point_no+(j+1);
indices_side[coordinates+p4] = Slice_next_point_no+j;
coordinates+=4;
}
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//↑May be wrong ********************************************************************************//
glGenBuffers(3,&SVboId[0]);
//Vertex
glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Svertex,GL_DYNAMIC_DRAW);
//Normal
glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Snormal,GL_DYNAMIC_DRAW);
//Color
glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Scolor,GL_STREAM_DRAW);
}
//Draw
void DrawSphereVBO(void)
{
int point=0;
//Enable
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//Vertex
glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
//Normal
glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
glNormalPointer(GL_FLOAT, 0, 0);
//Color
glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
glColorPointer(3,GL_FLOAT, 0, 0);
//---------------------------------Draw---------------------------------------------------//
//TOP
for(int i=0; i<SLICE;i++){
glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_top+i*3);
point+=3;
}
//BOTTOM
point=0;
for(int i=0; i<SLICE;i++){
glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_bottom+i*3);
point+=3;
}
//↓May be wrong ********************************************************************************//
//SIDE
point=0;
for(int i=0; i< (SLICE*(STACK-2));i++){
glDrawRangeElements(GL_QUADS, point, point+3, 4, GL_UNSIGNED_INT, indices_side+i*4);
point+=4;
}
//↑May be wrong ********************************************************************************//
//---------------------------------Draw---------------------------------------------------//
//Disable
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,WIDTH,HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5.0, 5.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angle,0.0f,1.0f,0.0f);
DrawSphereVBO();
glutSwapBuffers();
}
void idle(void)
{
glutPostRedisplay();
angle+=0.2f;
}
void Init(){
glewInit();
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
SLICE = 5;
STACK = 5;
Shere_dma(1,SLICE,STACK); //MemoryAllocate
setSphereData(1,SLICE,STACK); //InputData
}
int main(int argc, char *argv[])
{
glutInitWindowPosition(100, 100);
glutInitWindowSize(WIDTH, HEIGHT);
glutInit(&argc, argv);
glutCreateWindow("VBO");
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutDisplayFunc(display);
glutIdleFunc(idle);
Init();
glutMainLoop();
return 0;
}
Я ссылаюсь на этот код.
void drawSphere(double radius, int nSlice, int nStack)
{
int i, j;
double phi; //
double theta; //long
float p[31][31][3]; //Vertex
float *p1,*p2,*p3,*p4;
if(nSlice > 30) nSlice = 30;
if(nStack > 30) nStack = 30;
//Vertex
for(i = 0;i <= nSlice;i++)
{
phi = 2.0 * M_PI * (double)i / (double)nSlice;
for(j = 0;j <= nStack;j++)
{
theta = M_PI * (double)j / (double)nStack;
p[i][j][0] = (float)(radius * sin(theta) * cos(phi));//x
p[i][j][1] = (float)(radius * sin(theta) * sin(phi));//y
p[i][j][2] = (float)(radius * cos(theta)); //z
}
}
//Top(j=0)
for(i = 0;i < nSlice; i++)
{
p1 = p[i][0]; p2 = p[i][1];
p3 = p[i+1][1];
glBegin(GL_TRIANGLES);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glEnd();
}
//Bottom
j=nStack-1;
for(i = 0;i < nSlice; i++)
{
p1 = p[i][j]; p2 = p[i][j+1];
p3 = p[i+1][j];
glBegin(GL_TRIANGLES);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glEnd();
}
for(i = 0;i < nSlice;i++){
for(j = 1;j < nStack-1; j++)
{
p1 = p[i][j]; p2 = p[i][j+1];
p3 = p[i+1][j+1]; p4 = p[i+1][j];
glBegin(GL_QUADS);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glNormal3fv(p4); glVertex3fv(p4);
glEnd();
}
}
}