⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skyfly.c

📁 嵌入式GUI OpenGL源代码。OpenGL是嵌入式开发中常用的一种GUI系统。
💻 C
📖 第 1 页 / 共 2 页
字号:

/*
 * skyfly.c     $Revision: 1.5 $
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <GL/glut.h>
#include <math.h>
#include "skyfly.h"

#if !defined(GL_VERSION_1_1)
#if defined(GL_EXT_texture_object)
#define glBindTexture(A,B)     glBindTextureEXT(A,B)
#define glGenTextures(A,B)     glGenTexturesEXT(A,B)
#define glDeleteTextures(A,B)  glDeleteTexturesEXT(A,B)
#else
#define glBindTexture(A,B)
#define glGenTextures(A,B)
#define glDeleteTextures(A,B)
#endif
#if defined(GL_EXT_texture)
#define GL_RGB5 GL_RGB5_EXT
#else
#define GL_RGB5 GL_RGB
#endif
#endif

#define ERR_WARNING                     0x1
#define ERR_FATAL                       0x2
#define ERR_SYSERR                      0x4

#define AMALLOC(a, type, num, func)     {                     \
	if((int)(a = (type*)malloc(sizeof(type)*(num))) <= 0)     \
		err_msg(ERR_FATAL, func, "amalloc failed");           \
}

float   ScaleZ   = 2.3;     /* Terrain height scale factor */
int     CellDim = 4;        /* Terrain cell is CellDim X Celldim quads */
int     NumCells = 36;      /* Terrain grid is NumCells X NumCells cells */
int     GridDim;            /* Terrain grid is GridDim X GridDim quads */
float   XYScale;            /* Conversion from world-space to grid index */
float   CellSize;           /* World-space size of cell */

int     Init_pos;           /* if true, set initial position and kbd mode */
float   Init_x, Init_y, Init_z, Init_azimuth;
int     rgbmode = GL_TRUE;

/* Color index ramp info */
int sky_base, terr_base;
int plane_colors[3];

/*
 * Data that changes from frame to frame needs to be double-buffered because
 * two processes may be working on two different frames at the same time.
 */
typedef struct buffered_data_struct {

        /* objects */
        perfobj_t       paper_plane_pos_obj[NUM_PLANES];
        perfobj_t       viewer_pos_obj;

        /* flags */
        unsigned int   paper_plane_pos_flags[2];
        unsigned int   viewer_pos_flags[2];

        /* data */
        float  paper_plane_position[NUM_PLANES][6];
        float  viewer_position[4];

} buffered_data;

/*
 * This is the per-pipe data structure which holds pipe id, semaphores,
 * and variable data buffers. Both gfxpipe and buffer structures live in
 * shared memory so the sim can communicate with its forked children.
 */
typedef struct gfxpipe_data_struct {
        int             gfxpipenum;
		buffered_data   **buffers;

} gfxpipe_data;

static gfxpipe_data     *gfxpipe;       /* A processes' gfxpipe struct */
static gfxpipe_data     *gfxpipes[1];   /* Maximum of 1 graphics pipe */
static int              num_pipes;
float           		fog_params[4];  /* Fog and clear color */
static float            fog_density = 0.025*2;
float           		far_cull  = 31.;    /* Far clip distance from eye */
int			mipmap = 0;
static int              texmode = GL_NEAREST;

static int              threecomp = 1;

int 	dither = GL_TRUE, fog = GL_TRUE;
int     Wxsize = 320, Wysize = 240; /* Default to 320x240 window */

/*
 * All non-variable data like geometry is stored in shared memory. This way
 * forked processes avoid duplicating data unnecessarily.
 */
shared_data     *SharedData;

/* //////////////////////////////////////////////////////////////////////// */

void sim_proc(void);
void sim_cyclops(void);
void sim_dualchannel(void);
void sim_singlechannel(void);
void cull_proc(void);
void draw_proc(void);
void sim_exit(void);
void init_misc(void); 
void init_shmem(void); 
void init_terrain(void);
void init_clouds(void);
void init_paper_planes(void);
void init_positions(void);
void init_gfxpipes(void);
void init_gl(int gfxpipenum);
void err_msg(int type, char* func, char* error);
void fly(perfobj_t *viewer_pos);
void fly_paper_planes(perfobj_t *paper_plane_pos);
float terrain_height(void);

void init_skyfly(void)
{
    init_shmem();
    init_gfxpipes();
    init_clouds();
    init_terrain();
    init_paper_planes();
    init_positions();

    gfxpipe = gfxpipes[0];
    init_gl(gfxpipe->gfxpipenum);
}

/*
 * This is a single-channel version of the dual-channel simulation
 * described above.
 */
void sim_singlechannel(void)
{
	buffered_data  **buffered = gfxpipes[0]->buffers;

	fly(&(buffered[0]->viewer_pos_obj));
	fly_paper_planes(buffered[0]->paper_plane_pos_obj);
}

/*-------------------------------------- Cull ------------------------------*/

/*
 *   The cull and draw processes operate in a classic producer/consumer, 
 * write/read configuration using a ring buffer. The ring consists of pointers
 * to perfobj's instead of actual geometric data. This is important because
 * you want to minimize the amount of data 'shared' between two processes that
 * run on different processors in order to reduce cache invalidations.
 *   enter_in_ring and get_from_ring spin on ring full and ring empty 
 * conditions respectively.
 *   Since cull/draw are shared group processes(sproc), the ring buffer is
 * in the virtual address space of both processes and shared memory is not
 * necessary.
*/

#define RING_SIZE   1000    /* Size of ring */

typedef struct render_ring_struct {
    volatile unsigned int      head, tail;
    perfobj_t                   **ring;
} render_ring;

render_ring ringbuffer;

void        enter_in_ring(perfobj_t *perfobj);
perfobj_t*  get_from_ring(void);

void cull_proc(void)
{

    static struct cull {
        perfobj_t       **cells;
        perfobj_t       viewer_pos_obj[2];
        unsigned int   viewer_pos_flags[4];
        float           viewer_position[2][4];
        float           fovx, side, farr, epsilon, plane_epsilon;
    } cull;

    static int init = 0;

    if (!init) {
        int             x, y;

        cull.fovx = FOV *(float) Wxsize /(float) Wysize;
        cull.side = far_cull / cosf(cull.fovx / 2.);
        cull.farr = 2.* cull.side * sinf(cull.fovx / 2.);
        cull.epsilon = sqrtf(2.) * CellSize / 2.;
        cull.plane_epsilon = .5;

        cull.cells = (perfobj_t **) malloc(NumCells * NumCells * sizeof(perfobj_t *));
        for (x = 0; x < NumCells; x++)
            for (y = 0; y < NumCells; y++)
                cull.cells[x * NumCells + y] =
                    &(SharedData->terrain_cells[x * NumCells + y]);

        ringbuffer.ring = malloc(RING_SIZE * sizeof(perfobj_t *));
        ringbuffer.head = ringbuffer.tail = 0;

        cull.viewer_pos_obj[0].flags = cull.viewer_pos_flags;
        cull.viewer_pos_obj[0].vdata = cull.viewer_position[0];
        cull.viewer_pos_obj[1].flags = cull.viewer_pos_flags;
        cull.viewer_pos_obj[1].vdata = cull.viewer_position[1];

        *(cull.viewer_pos_flags) = PD_VIEWER_POS;
        *(cull.viewer_pos_flags + 1) = PD_END;
        init = 1;
    }

	{
	float           *viewer;
	float           vX, vY, vazimuth, px, py;
	float           left_area, right_area;
	float           left_dx, left_dy, right_dx, right_dy;
	float           ax, ay, bx, by, cx, cy;
	float           minx, maxx, miny, maxy;
	int             i, buffer = 0;
	int             x, y, x0, y0, x1, y1;
	perfobj_t      *viewer_pos, *paper_plane_pos;
	buffered_data  *buffered;
	perfobj_t      *terrain_texture = &(SharedData->terrain_texture_obj);
	perfobj_t      *paper_plane = &(SharedData->paper_plane_obj);
	perfobj_t      *paper_plane_start = &(SharedData->paper_plane_start_obj);
	perfobj_t      *paper_plane_end = &(SharedData->paper_plane_end_obj);
	perfobj_t      *clouds_texture = &(SharedData->clouds_texture_obj);
	perfobj_t      *clouds = &(SharedData->clouds_obj);

	buffered = gfxpipe->buffers[buffer];

	viewer_pos = &(buffered->viewer_pos_obj);
	paper_plane_pos = buffered->paper_plane_pos_obj;

	vX = *((float *) viewer_pos->vdata + 0);
	vY = *((float *) viewer_pos->vdata + 1);
	vazimuth = *((float *) viewer_pos->vdata + 3);

	viewer = cull.viewer_position[buffer];

	viewer[0] = vX;
	viewer[1] = vY;
	viewer[2] = *((float *) viewer_pos->vdata + 2);
	viewer[3] = vazimuth;

	/*
	 * Begin cull to viewing frustrum
	 */
	ax = (vX - sinf(-vazimuth + cull.fovx *.5) * cull.side);
	ay = (vY + cosf(-vazimuth + cull.fovx *.5) * cull.side);
	bx = vX;
	by = vY;
	cx = (vX + sinf(vazimuth + cull.fovx *.5) * cull.side);
	cy = (vY + cosf(vazimuth + cull.fovx *.5) * cull.side);

	minx = MIN(MIN(ax, bx), cx);
	miny = MIN(MIN(ay, by), cy);
	maxx = MAX(MAX(ax, bx), cx);
	maxy = MAX(MAX(ay, by), cy);

	x0 = MAX((int) (minx / CellSize), 0);
	x1 = MIN((int) (maxx / CellSize) + 1, NumCells);
	y0 = MAX((int) (miny / CellSize), 0);
	y1 = MIN((int) (maxy / CellSize) + 1, NumCells);

	left_dx = ax - bx;
	left_dy = ay - by;
	right_dx = cx - bx;
	right_dy = cy - by;

	enter_in_ring(&cull.viewer_pos_obj[buffer]);

	if (viewer[2]<SKY_HIGH) {
	   /* draw clouds first */
	   enter_in_ring(clouds_texture);
	   enter_in_ring(clouds);
	}

	enter_in_ring(terrain_texture);
	/*
	 * Add visible cells to ring buffer 
	 */
	for (x = x0; x < x1; x++) {
		for (y = y0; y < y1; y++) {
			float           cntrx =(x +.5) * CellSize;
			float           cntry =(y +.5) * CellSize;

			left_area = left_dx * (cntry - by) - left_dy * (cntrx - bx);
			right_area = right_dx * (cntry - by) - right_dy * (cntrx - bx);

			if ((left_area < cull.epsilon * cull.side && right_area > -cull.epsilon * cull.side)) {
					enter_in_ring(cull.cells[x * NumCells + y]);
			}
		}
	}

	enter_in_ring(paper_plane_start);
	/*
	 * Add visible planes to ring buffer
	*/
	for (i = 0; i < NUM_PLANES; i++) {

		px = *((float *) paper_plane_pos[i].vdata + 0);
		py = *((float *) paper_plane_pos[i].vdata + 1);
		left_area = left_dx * (py - by) - left_dy * (px - bx);
		right_area = right_dx * (py - by) - right_dy * (px - bx);

		if (left_area < cull.plane_epsilon * cull.side && right_area > -cull.plane_epsilon * cull.side) {
			enter_in_ring(&paper_plane_pos[i]);
			enter_in_ring(paper_plane);
		}
	}

	enter_in_ring(paper_plane_end);

	if (viewer[2]>SKY_HIGH) {
	   /* draw clouds after everything else */
	   enter_in_ring(clouds_texture);
	   enter_in_ring(clouds);
	}

	enter_in_ring((perfobj_t *) 0);     /* 0 indicates end of frame */

	buffer = !buffer;
	}
}

void enter_in_ring(perfobj_t *perfobj)
{
	while (ringbuffer.head == RING_SIZE+ringbuffer.tail-1) {}
	ringbuffer.ring[ringbuffer.head % RING_SIZE] = perfobj;
	ringbuffer.head++;
}

perfobj_t* get_from_ring(void)
{
    static perfobj_t *pobj;

    while(ringbuffer.tail == ringbuffer.head) {}
    pobj = ringbuffer.ring[ringbuffer.tail % RING_SIZE];
    ringbuffer.tail++;
    return pobj;        
}

/*-------------------------------------- Draw ------------------------------*/

void draw_proc(void)
{
	perfobj_t      *too_draw;

	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	while ((too_draw = get_from_ring())) {
		drawperfobj(too_draw);
	}
}


/*------------------------------- Init -----------------------------------*/

void init_texture_and_lighting(void);
void init_buffered_data(buffered_data *buffered);

void init_misc(void)
{
	float   density;

	threecomp = rgbmode;

	/*
	 * Compute fog and clear color to be linear interpolation between blue
	 * and white.
	 */
	density = 1.- expf(-5.5 * fog_density * fog_density *
							  far_cull * far_cull);
	density = MAX(MIN(density, 1.), 0.);

	fog_params[0] = .23 + density *.57;
	fog_params[1] = .35 + density *.45;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -