summaryrefslogtreecommitdiff
path: root/progs/directfb/df_reflect.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/directfb/df_reflect.c')
-rw-r--r--progs/directfb/df_reflect.c489
1 files changed, 489 insertions, 0 deletions
diff --git a/progs/directfb/df_reflect.c b/progs/directfb/df_reflect.c
new file mode 100644
index 0000000000..ce4d12f749
--- /dev/null
+++ b/progs/directfb/df_reflect.c
@@ -0,0 +1,489 @@
+/*
+ (c) Copyright 2001 convergence integrated media GmbH.
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@convergence.de> and
+ Andreas Hundt <andi@convergence.de>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <directfb.h>
+
+#include <GL/glu.h>
+#include <GL/directfbgl.h>
+
+#include "util/showbuffer.c"
+#include "util/readtex.c"
+
+
+/* the super interface */
+IDirectFB *dfb;
+
+/* the primary surface (surface of primary layer) */
+IDirectFBSurface *primary;
+
+/* the GL context */
+IDirectFBGL *primary_gl;
+
+/* our font */
+IDirectFBFont *font;
+
+/* event buffer */
+IDirectFBEventBuffer *events;
+
+/* macro for a safe call to DirectFB functions */
+#define DFBCHECK(x...) \
+ { \
+ err = x; \
+ if (err != DFB_OK) { \
+ fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
+ DirectFBErrorFatal( #x, err ); \
+ } \
+ }
+
+static int screen_width, screen_height;
+
+static unsigned long T0 = 0;
+static GLint Frames = 0;
+static GLfloat fps = 0;
+
+static inline unsigned long get_millis()
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+/*******************************/
+
+#define DEG2RAD (3.14159/180.0)
+
+#define TABLE_TEXTURE "../images/tile.rgb"
+
+static GLint ImgWidth, ImgHeight;
+static GLenum ImgFormat;
+static GLubyte *Image = NULL;
+
+#define MAX_OBJECTS 2
+static GLint table_list;
+static GLint objects_list[MAX_OBJECTS];
+
+static GLfloat xrot, yrot;
+static GLfloat spin;
+
+static GLint Width = 400, Height = 300;
+static GLenum ShowBuffer = GL_NONE;
+
+
+static void make_table( void )
+{
+ static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
+ static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
+
+ table_list = glGenLists(1);
+ glNewList( table_list, GL_COMPILE );
+
+ /* load table's texture */
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
+/* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
+
+ /* draw textured square for the table */
+ glPushMatrix();
+ glScalef( 4.0, 4.0, 4.0 );
+ glBegin( GL_POLYGON );
+ glNormal3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
+ glEnd();
+ glPopMatrix();
+
+ glDisable( GL_TEXTURE_2D );
+
+ glEndList();
+}
+
+
+static void make_objects( void )
+{
+ GLUquadricObj *q;
+
+ static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
+ static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
+ static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
+
+ q = gluNewQuadric();
+ gluQuadricDrawStyle( q, GLU_FILL );
+ gluQuadricNormals( q, GLU_SMOOTH );
+
+ objects_list[0] = glGenLists(1);
+ glNewList( objects_list[0], GL_COMPILE );
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
+ glMaterialfv( GL_FRONT, GL_EMISSION, black );
+ gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
+ glEndList();
+
+ objects_list[1] = glGenLists(1);
+ glNewList( objects_list[1], GL_COMPILE );
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
+ glMaterialfv( GL_FRONT, GL_EMISSION, black );
+ gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
+ glEndList();
+}
+
+
+static void init( void )
+{
+ make_table();
+ make_objects();
+
+ Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
+ if (!Image) {
+ printf("Couldn't read %s\n", TABLE_TEXTURE);
+ exit(0);
+ }
+
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
+ ImgFormat, GL_UNSIGNED_BYTE, Image);
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ xrot = 30.0;
+ yrot = 50.0;
+ spin = 0.0;
+
+ glShadeModel( GL_FLAT );
+
+ glEnable( GL_LIGHT0 );
+ glEnable( GL_LIGHTING );
+
+ glClearColor( 0.5, 0.5, 0.9, 0.0 );
+
+ glEnable( GL_NORMALIZE );
+}
+
+
+
+static void reshape(int w, int h)
+{
+ GLfloat yAspect = 2.5;
+ GLfloat xAspect = yAspect * (float) w / (float) h;
+ Width = w;
+ Height = h;
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+
+
+
+static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
+{
+ (void) eyex;
+ (void) eyey;
+ (void) eyez;
+#ifndef USE_ZBUFFER
+ if (eyex<0.5) {
+#endif
+ glPushMatrix();
+ glTranslatef( 1.0, 1.5, 0.0 );
+ glRotatef( spin, 1.0, 0.5, 0.0 );
+ glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+ glCallList( objects_list[0] );
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
+ glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+ glRotatef( spin, 1.0, 0.5, 0.0 );
+ glScalef( 0.5, 0.5, 0.5 );
+ glCallList( objects_list[1] );
+ glPopMatrix();
+#ifndef USE_ZBUFFER
+ }
+ else {
+ glPushMatrix();
+ glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
+ glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+ glRotatef( spin, 1.0, 0.5, 0.0 );
+ glScalef( 0.5, 0.5, 0.5 );
+ glCallList( objects_list[1] );
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( 1.0, 1.5, 0.0 );
+ glRotatef( spin, 1.0, 0.5, 0.0 );
+ glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+ glCallList( objects_list[0] );
+ glPopMatrix();
+ }
+#endif
+}
+
+
+
+static void draw_table( void )
+{
+ glCallList( table_list );
+}
+
+
+
+static void draw( void )
+{
+ static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
+ GLfloat dist = 20.0;
+ GLfloat eyex, eyey, eyez;
+
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+
+ eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
+ eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
+ eyey = dist * sin(xrot*DEG2RAD);
+
+ /* view from top */
+ glPushMatrix();
+ gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
+
+ glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
+
+ /* draw table into stencil planes */
+ glDisable( GL_DEPTH_TEST );
+ glEnable( GL_STENCIL_TEST );
+ glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
+ glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
+ glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+ draw_table();
+ glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+
+ glEnable( GL_DEPTH_TEST );
+
+ /* render view from below (reflected viewport) */
+ /* only draw where stencil==1 */
+ if (eyey>0.0) {
+ glPushMatrix();
+
+ glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
+ glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
+ glScalef( 1.0, -1.0, 1.0 );
+
+ /* Reposition light in reflected space. */
+ glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
+
+ draw_objects(eyex, eyey, eyez);
+ glPopMatrix();
+
+ /* Restore light's original unreflected position. */
+ glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
+ }
+
+ glDisable( GL_STENCIL_TEST );
+
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ glEnable( GL_TEXTURE_2D );
+ draw_table();
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_BLEND );
+
+ /* view from top */
+ glPushMatrix();
+
+ draw_objects(eyex, eyey, eyez);
+
+ glPopMatrix();
+
+ glPopMatrix();
+
+ if (ShowBuffer == GL_DEPTH) {
+ ShowDepthBuffer(Width, Height, 1.0, 0.0);
+ }
+ else if (ShowBuffer == GL_STENCIL) {
+ ShowStencilBuffer(Width, Height, 255.0, 0.0);
+ }
+ else if (ShowBuffer == GL_ALPHA) {
+ ShowAlphaBuffer(Width, Height);
+ }
+}
+
+/*******************************/
+
+int main( int argc, char *argv[] )
+{
+ int quit = 0;
+ DFBResult err;
+ DFBSurfaceDescription dsc;
+
+ DFBCHECK(DirectFBInit( &argc, &argv ));
+
+ /* create the super interface */
+ DFBCHECK(DirectFBCreate( &dfb ));
+
+ /* create an event buffer for all devices with these caps */
+ DFBCHECK(dfb->CreateInputEventBuffer( dfb, DICAPS_ALL, DFB_FALSE, &events ));
+
+ /* set our cooperative level to DFSCL_FULLSCREEN
+ for exclusive access to the primary layer */
+ dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN );
+
+ /* get the primary surface, i.e. the surface of the
+ primary layer we have exclusive access to */
+ dsc.flags = DSDESC_CAPS;
+ dsc.caps = (DFBSurfaceCapabilities)(DSCAPS_PRIMARY | DSCAPS_DOUBLE);
+
+ DFBCHECK(dfb->CreateSurface( dfb, &dsc, &primary ));
+
+ /* get the size of the surface and fill it */
+ DFBCHECK(primary->GetSize( primary, &screen_width, &screen_height ));
+ DFBCHECK(primary->FillRectangle( primary, 0, 0,
+ screen_width, screen_height ));
+
+ /* create the default font and set it */
+ DFBCHECK(dfb->CreateFont( dfb, NULL, NULL, &font ));
+ DFBCHECK(primary->SetFont( primary, font ));
+
+ /* get the GL context */
+ DFBCHECK(primary->GetGL( primary, &primary_gl ));
+
+ DFBCHECK(primary_gl->Lock( primary_gl ));
+
+ init();
+ reshape(screen_width, screen_height);
+
+ DFBCHECK(primary_gl->Unlock( primary_gl ));
+
+ T0 = get_millis();
+
+ while (!quit) {
+ DFBInputEvent evt;
+ unsigned long t;
+
+ DFBCHECK(primary_gl->Lock( primary_gl ));
+
+ draw();
+
+ DFBCHECK(primary_gl->Unlock( primary_gl ));
+
+ if (fps) {
+ char buf[64];
+
+ sprintf(buf, "%4.1f FPS\n", fps);
+ primary->SetColor( primary, 0xff, 0, 0, 0xff );
+ primary->DrawString( primary, buf, -1, screen_width - 5, 5, DSTF_TOPRIGHT );
+ }
+
+ primary->Flip( primary, NULL, (DFBSurfaceFlipFlags)0 );
+ Frames++;
+
+
+ t = get_millis();
+ if (t - T0 >= 1000) {
+ GLfloat seconds = (t - T0) / 1000.0;
+
+ fps = Frames / seconds;
+
+ T0 = t;
+ Frames = 0;
+ }
+
+
+ while (events->GetEvent( events, DFB_EVENT(&evt) ) == DFB_OK) {
+ switch (evt.type) {
+ case DIET_KEYPRESS:
+ switch (DFB_LOWER_CASE(evt.key_symbol)) {
+ case DIKS_ESCAPE:
+ quit = 1;
+ break;
+ case DIKS_CURSOR_UP:
+ xrot += 3.0;
+ if ( xrot > 85 )
+ xrot = 85;
+ break;
+ case DIKS_CURSOR_DOWN:
+ xrot -= 3.0;
+ if ( xrot < 5 )
+ xrot = 5;
+ break;
+ case DIKS_CURSOR_LEFT:
+ yrot += 3.0;
+ break;
+ case DIKS_CURSOR_RIGHT:
+ yrot -= 3.0;
+ break;
+ case DIKS_SMALL_D:
+ ShowBuffer = GL_DEPTH;
+ break;
+ case DIKS_SMALL_S:
+ ShowBuffer = GL_STENCIL;
+ break;
+ case DIKS_SMALL_A:
+ ShowBuffer = GL_ALPHA;
+ break;
+ default:
+ ShowBuffer = GL_NONE;
+ }
+ break;
+ case DIET_AXISMOTION:
+ if (evt.flags & DIEF_AXISREL) {
+ switch (evt.axis) {
+ case DIAI_X:
+ yrot += evt.axisrel / 2.0;
+ break;
+ case DIAI_Y:
+ xrot += evt.axisrel / 2.0;
+ break;
+ default:
+ ;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ spin += 2.0;
+ yrot += 3.0;
+ }
+
+ /* release our interfaces to shutdown DirectFB */
+ primary_gl->Release( primary_gl );
+ primary->Release( primary );
+ font->Release( font );
+ events->Release( events );
+ dfb->Release( dfb );
+
+ return 0;
+}
+