Showing posts with label qt. Show all posts
Showing posts with label qt. Show all posts

Wednesday, March 11, 2009

Drawing a Rosette



Building the Rosette


Above is a picture of a rosette with 40 points. To make a rosette, create a set of equidistant points around a circle and then connect every point to every other point.

Candidate Points


First, we need to compute the rosette points by making points equally spaced around a circle.

struct GLFloatPoint{GLfloat x, y;};

// Compute the candidate points, by equally
// spacing them around a circle.
GLFloatPoint* points = new GLFloatPoint[numPoints];
float angleStep = (3.14159f * 2.0f / numPoints);
float currentAngle = 0.0f;
for(unsigned int i=0; i<numPoints; i++)
{
points[i].x = radius*cos(currentAngle);
points[i].y = radius*sin(currentAngle);

currentAngle += angleStep;
}

Connecting Points


If you connect every point to every other one, you end up with duplicate edges between vertices.

How do you get not create duplicate edges in the simplest possible way? Once you connect a certain point to all others, keep it out of the list of points to connect to. This can be done using two loops. The outer loop tracks the vertex we are connecting from, and in the inner loop tracks the vertex to which we are connecting.

unsigned int index = 0;
// The vertex we are connecting from.
for(unsigned int j=0; j<numPoints; j++)
{
// Connect to all other points.
// Lines have an origin and end point.
for(unsigned int k=j+1; k<numPoints; k++)
{
rosettePoints[index].x = points[j].x;
rosettePoints[index].y = points[j].y;
index++;
rosettePoints[index].x = points[k].x;
rosettePoints[index].y = points[k].y;
index++;
}
}


Drawing


Vertex Arrays


Using vertex arrays, we can build the entire rosette at startup, and then can send all the vertices to be drawn at once. Using an array of GLFloatPoint, causes the x's and y's in the structs to align in memory just as if they had been put into an array of GLfloat.

Conceptually,

/* Structs */
GLFloatPoint A, B, C;
GLFloatPoint pointArray[] = {A, B, C}
/* Manually */
GLfloat floatArray[] = {A.x,A.y,
B.x,B.y, C.x,C.y}

// You need to cast the pointers for this to work,
// but this is why I miss pointers in Java/Ruby.
GLFloatPoint* pointPtr = (GLFloatPoint*)floatArray;
pointPtr[0].x = // A.x
pointPtr[0].y = // A.y
pointPtr[1].x = // B.x

GLfloat* floatPtr = (GLfloat*)pointArray;
floatPtr[0] = // A.x
floatPtr[1] = // A.y
floatPtr[2] = // B.x
floatPtr[3] = // B.y


Struct Pointer Magic


In short, we can merrily use the array of GLFloatPoint in place of a big array of floats. This makes it easier to figure out where you are in the array quickly, since incrementing a GLFloatPoint* in a loop will move you forward one point. Also, you can use array notation, point[10], for the 11'th point, for instance.


// Allow us to use vertex arrays
glEnableClientState(GL_VERTEX_ARRAY);

// Set the array of points to use
glVertexPointer(2, GL_FLOAT, 0, rosettePoints);

// Render lines from the array vertices.
// rosetteSize = (numPoints-1)*numPoints/2*2.
// This comes from connecting every point to
// every other point without duplicates.
// The "*2" comes from two vertices per line.
glDrawArrays(GL_LINES, 0, rosetteSize);

Friday, February 20, 2009

Color Wheel Demo



This video was captured using xvidcap on my Linux box. It demonstrates the functionality of the color wheel demo in QtRuby. Colors are added by clicking in the center of the ring, and removed by clicking elsewhere. The color selecting tool is a standard widget provided by QColorDialog, which I've mentioned before.

This is my first screencast and it shows the programs functions nicely (though kinda fast), so I might be doing more of this in the future.

Thursday, February 5, 2009

Radial Space Filling Tree


I've been continuing work with my color wheel using radial space filling trees, inspired in part because of DocBurst. I've modified the original source code to allow multiple levels of rings, though only three are seen here (the center circle is considered a segment, but I set it to the background color). Children sectors in the ring are constrained to the angle bounds of its parent.

Further steps include click detection on segments based to select different segments, and extracting a child segment to form a new color wheel.

Wednesday, February 4, 2009

Rings of Color




I've been thinking of making a color wheel for playing around with color palettes. This is an initial concept that I came up where sectors display colors. To actually get the ring effect I painted all of the colors as pies, and then filled the center of the circle containing the color pies with the background color.



Adding more colors creates more sections of the ring and the spacers prevent them from getting too close together. Future steps are to add a feature to generate shades of a color at given steps from a certain hue based upon saturation or brightness. Adding and saving of color palettes and exporting as Qt style sheets would also be useful.

Creating and editing colors is done using the already provided QColorDialog. Unfortunately, it doesn't provide as many options as the Java Swing Color Chooser, but it gets the job done for now.