Jump to content
  • Advertisement
Sign in to follow this  
sandy_bence

Rendering a sphere using Triangle strips

This topic is 4667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How do I go about rendering a sphere using triangle strips and sphereical coordinates? I understand the following code will draw a sphere but I want to use a triangle strip and put the coordinates into a vertice array. for (float i=0; i<=360; i+=360/detail_latitude) for (float j=-90; j<=90; j+=180/detail_longitude) { Vertex.x = cos(i)*Radius *cos(j); Vertex.y = sin(i)*Radius *cos(j); Vertex.z = sin(j)*radius; } I want to call the render sphere function: glBegin(GL_TRIANGLE_STRIP); for (int i=0; i < number_of_vertices; i++) glVertex3f(vertices.x, vertices.y, vertices.z); glEnd(); Any Suggestions?

Share this post


Link to post
Share on other sites
Advertisement
You need to wind the vertices into the correct order for a triangle strip. So you have to think of them as


1-----3
|\ |
| \ |
| \ |
| \ |
0-----2


and apply the texture coordinates accordingly

Share this post


Link to post
Share on other sites
I can draw a dome using this:


int n =0;
for (phi=0; phi <= 90 - delta_phi; phi += (int)delta_phi) {
for (theta=0; theta <= 360 - delta_theta; theta += (int)delta_theta) {
vertices[n].x = radius_x * sinf(phi*deg2rad) * cosf(deg2rad*theta);
vertices[n].y = radius_y * sinf(phi*deg2rad) * sinf(deg2rad*theta);
vertices[n].z = radius_z * cosf(phi*deg2rad);
n++;

vertices[n].x = radius_x * sinf((phi+delta_phi)*deg2rad) * cosf(theta*deg2rad);
vertices[n].y = radius_y * sinf((phi+delta_phi)*deg2rad) * sinf(theta*deg2rad);
vertices[n].z = radius_z * cosf((phi+delta_phi)*deg2rad);
n++;

vertices[n].x = radius_x * sinf(deg2rad*phi) * cosf(deg2rad*(theta+delta_theta));
vertices[n].y = radius_y * sinf(deg2rad*phi) * sinf(deg2rad*(theta+delta_theta));
vertices[n].z = radius_z * cosf(deg2rad*phi);
n++;

if (phi > -90 && phi < 90) {
vertices[n].x = radius_x * sinf((phi+delta_phi)*deg2rad) * cosf(deg2rad*(theta+delta_theta));
vertices[n].y = radius_y * sinf((phi+delta_phi)*deg2rad) * sinf(deg2rad*(theta+delta_theta));
vertices[n].z = radius_z * cosf((phi+delta_phi)*deg2rad);
n++;
}
}
}



however I am unsure how to convert this to a completesphere. I have tried:

for (phi=0; phi <= 180 - delta_phi; phi += (int)delta_phi)

but this draws two sphere's over each other. Both going the other direction...!

Thanks in advance, anyone?

Share this post


Link to post
Share on other sites
u wanna draw it with a single strip?
if so then u will need to use degenerate triangles (seacrh for what they are) ie
-start at bottom of sphere
-draw a strip around the sphere until u hit the first 2 vertices then repeat one of them 2 or 3 times (work it out on paper)
-move the tri strip up and repeat

Share this post


Link to post
Share on other sites
You don't have to use degenerate triangles to render a sphere in a single strip. You can also use the orange-peel method. Here's some old code to demonstrate (SpiralSphere - it's indexed, but it shouldn't be too difficult to adapt it to non-indexed):
#include <cmath>
#include <vector>
#include <gl/glut.h>

const float PI = 3.14159265358979323846f;

#pragma pack(1)
template <typename TYPE>
class GeometryVector
{

public:

GeometryVector(const TYPE x_ = TYPE(), const TYPE y_ = TYPE(), const TYPE z_ = TYPE());

const TYPE x;
const TYPE y;
const TYPE z;

};
#pragma pack()

template <typename TYPE>
GeometryVector<TYPE>::GeometryVector(const TYPE x_, const TYPE y_, const TYPE z_)
:
x(x_),
y(y_),
z(z_)
{
}

class StackedSphere
{

public:

StackedSphere(const float radius = 1.0f, const unsigned int stacks = 8, const unsigned int slices = 16);
void render() const;

private:

std::vector<GeometryVector<float> > geometryData_;
std::vector<unsigned short> indexData_;

};

StackedSphere::StackedSphere(const float radius, const unsigned int stacks, const unsigned int slices)
{
for (unsigned int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
{
for (unsigned int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
{
float theta = stackNumber * PI / stacks;
float phi = sliceNumber * 2 * PI / slices;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));
}
}
for (unsigned int stackNumber = 0; stackNumber < stacks; ++stackNumber)
{
for (unsigned int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
{
indexData_.push_back((stackNumber * slices) + (sliceNumber % slices));
indexData_.push_back(((stackNumber + 1) * slices) + (sliceNumber % slices));
}
}
}

void StackedSphere::render() const
{
glVertexPointer(3, GL_FLOAT, 0, &geometryData_[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLE_STRIP, indexData_.size(), GL_UNSIGNED_SHORT, &indexData_[0]);
}

class SpiralSphere
{

public:

SpiralSphere(const float radius = 1.0f, const unsigned int loops = 8, const unsigned int segmentsPerLoop = 16);
void render() const;

private:

std::vector<GeometryVector<float> > geometryData_;
std::vector<unsigned short> indexData_;

};

SpiralSphere::SpiralSphere(const float radius, const unsigned int loops, const unsigned int segmentsPerLoop)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
float theta = 0;
float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));

}
for (unsigned int loopNumber = 0; loopNumber <= loops; ++loopNumber)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
float theta = (loopNumber * PI / loops) + ((PI * loopSegmentNumber) / (segmentsPerLoop * loops));
if (loopNumber == loops)
{
theta = PI;
}
float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));

}
}
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
indexData_.push_back(loopSegmentNumber);
indexData_.push_back(segmentsPerLoop + loopSegmentNumber);
}
for (unsigned int loopNumber = 0; loopNumber < loops; ++loopNumber)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
indexData_.push_back(((loopNumber + 1) * segmentsPerLoop) + loopSegmentNumber);
indexData_.push_back(((loopNumber + 2) * segmentsPerLoop) + loopSegmentNumber);
}
}
}

void SpiralSphere::render() const
{
glVertexPointer(3, GL_FLOAT, 0, &geometryData_[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLE_STRIP, indexData_.size(), GL_UNSIGNED_SHORT, &indexData_[0]);
}

StackedSphere sphere1(4, 8, 16);
SpiralSphere sphere2(4, 8, 16);
int r = 0;

void reshape(int width, int height){
if (height == 0)
{
height = 1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -25);
glPushMatrix();
glTranslatef(-5, 0, 0);
glRotatef(r, 0, 1, 0);
sphere1.render();
glPopMatrix();
glPushMatrix();
glTranslatef(5, 0, 0);
glRotatef(r, 0, 1, 0);
sphere2.render();
glPopMatrix();
glutSwapBuffers();
r++;
}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(512,512);
glutCreateWindow("Sphere Test");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);
glutMainLoop();
return 0;
}

Enigma

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!