/** *Structdescribingtheverticesintrianglestrip
*/ struct vertex_strip { /** The first vertex in the strip */
GLint first; /** The number of consecutive vertices in the strip after the first */
GLint count;
};
/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */ typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
/** *Structrepresentingagear.
*/ struct gear { /** The array of vertices comprising the gear */
GearVertex *vertices; /** The number of vertices comprising the gear */ int nvertices; /** The array of triangle strips comprising the gear */ struct vertex_strip *strips; /** The number of triangle strips comprising the gear */ int nstrips;
};
typedefstruct { /* The view rotation [x, y, z] */
GLfloat view_rot[GTK_GEARS_N_AXIS];
/* Allocate memory for the gear */
gear = g_malloc (sizeof *gear);
/* Calculate the radii used in the gear */
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
/* Allocate memory for the triangle strip information */
gear->nstrips = STRIPS_PER_TOOTH * teeth;
gear->strips = g_malloc0_n (gear->nstrips, sizeof (*gear->strips));
/* Allocate memory for the vertices */
gear->vertices = g_malloc0_n (VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
v = gear->vertices;
for (i = 0; i < teeth; i++) { /* A set of macros for making the creation of the gears easier */ #define GEAR_POINT(p, r, da) do { p.x = (r) * c[(da)]; p.y = (r) * s[(da)]; } while(0) #define SET_NORMAL(x, y, z) do { \
normal[0] = (x); normal[1] = (y); normal[2] = (z); \
} while(0)
/* Front face */
START_STRIP;
SET_NORMAL(0, 0, 1.0);
v = GEAR_VERT(v, 0, +1);
v = GEAR_VERT(v, 1, +1);
v = GEAR_VERT(v, 2, +1);
v = GEAR_VERT(v, 3, +1);
v = GEAR_VERT(v, 4, +1);
v = GEAR_VERT(v, 5, +1);
v = GEAR_VERT(v, 6, +1);
END_STRIP;
/* Inner face */
START_STRIP;
QUAD_WITH_NORMAL(4, 6);
END_STRIP;
/* Back face */
START_STRIP;
SET_NORMAL(0, 0, -1.0);
v = GEAR_VERT(v, 6, -1);
v = GEAR_VERT(v, 5, -1);
v = GEAR_VERT(v, 4, -1);
v = GEAR_VERT(v, 3, -1);
v = GEAR_VERT(v, 2, -1);
v = GEAR_VERT(v, 1, -1);
v = GEAR_VERT(v, 0, -1);
END_STRIP;
/* Outer face */
START_STRIP;
QUAD_WITH_NORMAL(0, 2);
END_STRIP;
for (i = 0; i < 16; i++) {
tmp[i] = 0;
d = div(i, 4);
row = n + d.quot * 4;
column = m + d.rem; for (j = 0; j < 4; j++)
tmp[i] += row[j] * column[j * 4];
}
memcpy(m, &tmp, sizeof tmp);
}
/** *Rotatesa4x4matrix. * *@param[in,out]mthematrixtorotate *@paramangletheangletorotate *@paramxthexcomponentofthedirectiontorotateto *@paramytheycomponentofthedirectiontorotateto *@paramzthezcomponentofthedirectiontorotateto
*/ staticvoid
rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{ double s = sin (angle); double c = cos (angle);
GLfloat r[16] = {
x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0, 0, 0, 0, 1
};
// Extract and invert the translation part 't'. The inverse of a // translation matrix can be calculated by negating the translation // coordinates.
t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];
// Invert the rotation part 'r'. The inverse of a rotation matrix is // equal to its transpose.
m[12] = m[13] = m[14] = 0;
transpose(m);
/* Translate and rotate the gear */
memcpy(model_view, transform, sizeof (model_view));
translate(model_view, x, y, 0);
rotate(model_view, 2 * G_PI * angle / 360.0, 0, 0, 1);
/* Create and set the ModelViewProjectionMatrix */
memcpy(model_view_projection, priv->ProjectionMatrix, sizeof(model_view_projection));
multiply(model_view_projection, model_view);
/* Set the gear color */
glUniform4fv(priv->MaterialColor_location, 1, color);
/* Set the vertex buffer object to use */
glBindBuffer(GL_ARRAY_BUFFER, gear_vbo);
/* Set up the position of the attributes in the vertex buffer object */
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
/* Enable the attributes */
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
/* Draw the triangle strips that comprise the gear */ for (n = 0; n < gear->nstrips; n++) {
glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count);
}
/* Disable the attributes */
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
}
/* new window size or exposure */ staticvoid
gtk_gears_reshape (GtkGLArea *area, int width, int height)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) area);
staticconstchar vertex_shader_gl[] = "#version 150\n" "\n" "in vec3 position;\n" "in vec3 normal;\n" "\n" "uniform mat4 ModelViewProjectionMatrix;\n" "uniform mat4 NormalMatrix;\n" "uniform vec4 LightSourcePosition;\n" "uniform vec4 MaterialColor;\n" "\n" "smooth out vec4 Color;\n" "\n" "void main(void)\n" "{\n" " // Transform the normal to eye coordinates\n" " vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" "\n" " // The LightSourcePosition is actually its direction for directional light\n" " vec3 L = normalize(LightSourcePosition.xyz);\n" "\n" " // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" " // to get the actual color that we will use to draw this vertex with\n" " float diffuse = max(dot(N, L), 0.0);\n" " Color = diffuse * MaterialColor;\n" "\n" " // Transform the position to clip coordinates\n" " gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" "}";
staticconstchar vertex_shader_gles[] = "attribute vec3 position;\n" "attribute vec3 normal;\n" "\n" "uniform mat4 ModelViewProjectionMatrix;\n" "uniform mat4 NormalMatrix;\n" "uniform vec4 LightSourcePosition;\n" "uniform vec4 MaterialColor;\n" "\n" "varying vec4 Color;\n" "\n" "void main(void)\n" "{\n" " // Transform the normal to eye coordinates\n" " vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" "\n" " // The LightSourcePosition is actually its direction for directional light\n" " vec3 L = normalize(LightSourcePosition.xyz);\n" "\n" " // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" " // to get the actual color that we will use to draw this vertex with\n" " float diffuse = max(dot(N, L), 0.0);\n" " Color = diffuse * MaterialColor;\n" "\n" " // Transform the position to clip coordinates\n" " gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" "}";
/* Compile the vertex shader */ if (gdk_gl_context_get_use_es (context))
p = vertex_shader_gles; else
p = vertex_shader_gl;
v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &p, NULL);
glCompileShader(v);
glGetShaderInfoLog(v, sizeof msg, NULL, msg);
g_print ("vertex shader info: %s\n", msg);
/* Compile the fragment shader */ if (gdk_gl_context_get_use_es (context))
p = fragment_shader_gles; else
p = fragment_shader_gl;
f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &p, NULL);
glCompileShader(f);
glGetShaderInfoLog(f, sizeof msg, NULL, msg);
g_print ("fragment shader info: %s\n", msg);
/* Create and link the shader program */
program = glCreateProgram();
glAttachShader(program, v);
glAttachShader(program, f);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "normal");
/* Enable the shaders */
glUseProgram(program);
priv->program = program;
/* Get the locations of the uniforms so we can access them */
priv->ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
priv->NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix");
priv->LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition");
priv->MaterialColor_location = glGetUniformLocation(program, "MaterialColor");
/* Set the LightSourcePosition uniform which is constant throughout the program */
glUniform4fv(priv->LightSourcePosition_location, 1, priv->LightSourcePosition);
/* make the gears */
priv->gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
/* Store the vertices in a vertex buffer object (VBO) */
glGenBuffers (1, &(priv->gear_vbo[0]));
glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[0]);
glBufferData (GL_ARRAY_BUFFER,
priv->gear1->nvertices * sizeof(GearVertex),
priv->gear1->vertices,
GL_STATIC_DRAW);
if (priv->first_frame_time == 0)
{ /* No need for changes on first frame */
priv->first_frame_time = frame_time; if (priv->fps_label)
gtk_label_set_label (priv->fps_label, "FPS: ---"); return G_SOURCE_CONTINUE;
}
/* glxgears advances 70 degrees per second, so do the same */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.