SimpleExample.c 8.44 KB
Newer Older
1 2
/* -*- c -*- *****************************************************************
** Copyright (C) 2003 Sandia Corporation
3 4 5 6
** Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
** the U.S. Government retains certain rights in this software.
**
** This source code is released under the New BSD License.
7
**
Kenneth Moreland's avatar
Kenneth Moreland committed
8
** This test provides a simple example of using IceT to perform parallel
9 10 11
** rendering.
*****************************************************************************/

12
#include <IceTGL.h>
13
#include "test_util.h"
14 15 16 17
#include "test_codes.h"

#include <stdlib.h>
#include <stdio.h>
Kenneth Moreland's avatar
Kenneth Moreland committed
18 19 20 21 22
#include <math.h>

#ifndef M_PI
#define M_PI        3.14159265358979323846264338327950288   /* pi */
#endif
23

24 25
IceTInt rank;
IceTInt num_proc;
26

Kenneth Moreland's avatar
Kenneth Moreland committed
27 28 29 30 31 32
#define SPHERE_RESOLUTION 20
#define SPHERE_RADIUS 0.5f
#define SPHERE_NUM_QUADS (SPHERE_RESOLUTION*SPHERE_RESOLUTION/2)
#define SPHERE_NUM_VERTICES (SPHERE_NUM_QUADS*4)

static void GetSphereArrays(GLfloat **vertex_array_p, GLfloat **normal_array_p)
33
{
Kenneth Moreland's avatar
Kenneth Moreland committed
34 35 36 37 38 39 40 41 42 43 44 45 46
    static GLfloat vertex_array[SPHERE_NUM_VERTICES*3];
    static GLfloat normal_array[SPHERE_NUM_VERTICES*3];
    static GLboolean arrays_initialized = 0;

    if (!arrays_initialized)
    {
        GLfloat cos_table[SPHERE_RESOLUTION+1];
        GLfloat sin_table[SPHERE_RESOLUTION+1];
        int theta_index, phi_index;

        // Fill out tables.
        for (theta_index = 0; theta_index <= SPHERE_RESOLUTION; theta_index++)
        {
Kenneth Moreland's avatar
Kenneth Moreland committed
47 48 49 50
            cos_table[theta_index] =
                    (GLfloat)cos((2*M_PI/SPHERE_RESOLUTION)*theta_index);
            sin_table[theta_index] =
                    (GLfloat)sin((2*M_PI/SPHERE_RESOLUTION)*theta_index);
Kenneth Moreland's avatar
Kenneth Moreland committed
51
        }
52

Kenneth Moreland's avatar
Kenneth Moreland committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
        // Compute the vertices and normals.
        GLfloat *vertex_p = vertex_array;
        GLfloat *normal_p = normal_array;
        for (phi_index = 0; phi_index < SPHERE_RESOLUTION/2; phi_index++)
        {
            for (theta_index = 0; theta_index<SPHERE_RESOLUTION; theta_index++)
            {
#define SET_VERT(t_index, p_index) \
    normal_p[0] = cos_table[t_index]*sin_table[p_index]; \
    normal_p[1] = sin_table[t_index]*sin_table[p_index]; \
    normal_p[2] = cos_table[p_index]; \
    vertex_p[0] = normal_p[0]*SPHERE_RADIUS; \
    vertex_p[1] = normal_p[1]*SPHERE_RADIUS; \
    vertex_p[2] = normal_p[2]*SPHERE_RADIUS; \
    normal_p += 3; vertex_p += 3;
                SET_VERT(theta_index, phi_index);
                SET_VERT(theta_index, phi_index+1);
                SET_VERT(theta_index+1, phi_index+1);
                SET_VERT(theta_index+1, phi_index);
            }
        }

        arrays_initialized = 1;
76 77
    }

Kenneth Moreland's avatar
Kenneth Moreland committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    *vertex_array_p = vertex_array;
    *normal_array_p = normal_array;
}

static void draw(void)
{
    GLfloat *vertex_array;
    GLfloat *normal_array;

    GetSphereArrays(&vertex_array, &normal_array);
    glVertexPointer(3, GL_FLOAT, 0, vertex_array);
    glNormalPointer(GL_FLOAT, 0, vertex_array);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

93 94 95 96 97 98 99
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* When changing the modelview matric in the draw function, you must be
   * wary of two things.  First, make sure the modelview matrix is restored
   * to what is was when the function is called.  Remember, the draw
   * function may be called multiple times and transformations may be
   * commuted.  Also, the bounds of the drawn geometry must be correctly
Kenneth Moreland's avatar
Kenneth Moreland committed
100
   * transformed before given to IceT.  IceT has no way of knowing about
101 102 103 104
   * transformations done here.  It is an error to change the projection
   * matrix in the draw function. */
    glPushMatrix();
      glMatrixMode(GL_MODELVIEW);
Ken Martin's avatar
Ken Martin committed
105
      glTranslatef((float)rank, 0, 0);
Kenneth Moreland's avatar
Kenneth Moreland committed
106
      glDrawArrays(GL_QUADS, 0, SPHERE_NUM_VERTICES);
107 108 109
    glPopMatrix();
}

110
static int SimpleExampleRun()
111 112 113 114
{
    float angle;

  /* Normally, the first thing that you do is set up your communication and
Kenneth Moreland's avatar
Kenneth Moreland committed
115
   * then create at least one IceT context.  This has already been done in
116 117
   * the calling function (i.e. icetTests_mpi.c).  See the init_mpi in
   * test_mpi.h for an example.
118 119 120 121 122 123 124 125 126
   */

  /* If we had set up the communication layer ourselves, we could have
   * gotten these parameters directly from it.  Since we did not, this
   * provides an alternate way. */
    icetGetIntegerv(ICET_RANK, &rank);
    icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);

  /* We should be able to set any color we want, but we should do it BEFORE
127
   * icetGLDrawFrame() is called, not in the callback drawing function.
128 129
   * There may also be limitations on the background color when performing
   * color blending. */
Ken Martin's avatar
Ken Martin committed
130
    glClearColor(0.2f, 0.5f, 0.1f, 1.0f);
131

Kenneth Moreland's avatar
Kenneth Moreland committed
132
  /* Give IceT a function that will issue the OpenGL drawing commands. */
133
    icetGLDrawCallback(draw);
134

Kenneth Moreland's avatar
Kenneth Moreland committed
135
  /* Give IceT the bounds of the polygons that will be drawn.  Note that
136
   * we must take into account any transformation that happens within the
Kenneth Moreland's avatar
Kenneth Moreland committed
137
   * draw function (but IceT will take care of any transformation that
138
   * happens before icetGLDrawFrame). */
139
    icetBoundingBoxd(-0.5+rank, 0.5+rank, -0.5, 0.5, -0.5, 0.5);
140 141 142 143 144 145 146

  /* Set up the tiled display.  Normally, the display will be fixed for a
   * given installation, but since this is a demo, we give two specific
   * examples. */
    if (num_proc < 4) {
      /* Here is an example of a "1 tile" case.  This is functionally
       * identical to a traditional sort last algorithm. */
Ken Martin's avatar
Ken Martin committed
147 148
        icetResetTiles();
        icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    } else {
      /* Here is an example of a 4x4 tile layout.  The tiles are displayed
       * with the following ranks:
       *
       *               +---+---+
       *               | 0 | 1 |
       *               +---+---+
       *               | 2 | 3 |
       *               +---+---+
       *
       * Each tile is simply defined by grabing a viewport in an infinite
       * global display screen.  The global viewport projection is
       * automatically set to the smallest region containing all tiles.
       *
       * This example also shows tiles abutted against each other.
       * Mullions and overlaps can be implemented by simply shifting tiles
       * on top of or away from each other.
       */
Ken Martin's avatar
Ken Martin committed
167
        icetResetTiles();
168 169 170 171 172 173 174 175
        icetAddTile(0, (IceTInt)SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
        icetAddTile((IceTInt)SCREEN_WIDTH,
                    (IceTInt)SCREEN_HEIGHT,
                    SCREEN_WIDTH,
                    SCREEN_HEIGHT,
                    1);
        icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 2);
        icetAddTile((IceTInt)SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 3);
176 177
    }

Kenneth Moreland's avatar
Kenneth Moreland committed
178
  /* Tell IceT what strategy to use.  The REDUCE strategy is an all-around
179 180 181 182 183 184 185 186 187 188 189 190 191
   * good performer. */
    icetStrategy(ICET_STRATEGY_REDUCE);

  /* Set up the projection matrix as you normally would. */
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-0.75, 0.75, -0.75, 0.75, -0.75, 0.75);

  /* Other normal OpenGL setup. */
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    if (rank%8 != 0) {
Ken Martin's avatar
Ken Martin committed
192 193 194 195
        GLfloat color[4];
        color[0] = (float)(rank%2);
        color[1] = (float)((rank/2)%2);
        color[2] = (float)((rank/4)%2);
196
        color[3] = 1.0f;
Ken Martin's avatar
Ken Martin committed
197
        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
198 199 200 201
    }

  /* Here is an example of an animation loop. */
    for (angle = 0; angle < 360; angle += 10) {
Kenneth Moreland's avatar
Kenneth Moreland committed
202
      /* We can set up a modelview matrix here and IceT will factor this
203
       * in determining the screen projection of the geometry.  Note that
Kenneth Moreland's avatar
Kenneth Moreland committed
204
       * there is further transformation in the draw function that IceT
205 206
       * cannot take into account.  That transformation is handled in the
       * application by deforming the bounds before giving them to
Kenneth Moreland's avatar
Kenneth Moreland committed
207
       * IceT. */
Ken Martin's avatar
Ken Martin committed
208 209
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
210 211 212
        glRotated(angle, 0.0, 1.0, 0.0);
        glScaled(1.0f/num_proc, 1.0, 1.0);
        glTranslated(-(num_proc-1)/2.0, 0.0, 0.0);
213 214

      /* Instead of calling draw() directly, call it indirectly through
Kenneth Moreland's avatar
Kenneth Moreland committed
215
       * icetDrawFrame().  IceT will automatically handle image
216
       * compositing. */
217
        icetGLDrawFrame();
218

Kenneth Moreland's avatar
Kenneth Moreland committed
219
      /* For obvious reasons, IceT should be run in double-buffered frame
220 221 222
       * mode.  After calling icetDrawFrame, the application should do a
       * synchronize (a barrier is often about as good as you can do) and
       * then a swap buffers. */
Ken Martin's avatar
Ken Martin committed
223
        swap_buffers();
224 225 226 227
    }

    return TEST_PASSED;
}
228 229 230 231 232 233 234 235 236

int SimpleExample(int argc, char * argv[])
{
    /* To remove warning */
    (void)argc;
    (void)argv;

    return run_test(SimpleExampleRun);
}