Angus Dorbie (dorbie++at++sgi.com)
Thu, 21 May 1998 15:04:31 -0700
For this type of config (symmetrically rotated projectors) you can't
overlap the video channels in ircombine and make the projection work.
Your video config should do what it does now (array the video
horizontally or vertically, it doesn't matter, but your pfChannels
should include the FOV for the full channel and the heading offset
(pre viewing rotation about Z) should match the angle between
projector headings. The offset should therefore be less than the
FOV to provide the right overlap in the video images at the
expense of a little redundant rendering.
You then do something like draw a 3D test pattern to match the screen
and align the channels on the display surface.
You should be able to drive 3++at++1280x1024_60 from the DG5-8 in your
ONYX2 iR if you have 2 Raster Managers. If you only have one
RM your managed area will be limited to 2*1280x1024 or equivalent
so you'll have to go with a smaller video resolution or build a
.cmb file with DVR resize built in.
I've attached some C OpenGL code to render a test pattern for
the above alignment procedure. It assumes a managed area of
3840*1024 and horizontally arrayed video channels or 1280x1024.
with left to right video matching left to right channel alignment.
Adjust the field of view & resolution settings and the heading
offset rotation for your display file and managed area size.
Note any cylindricalor spherical screen section with horizontal
top & base will lose pixels in the top and bottom center of each
channel when correctly aligned.
Cheers,Angus.
-- "Only the mediocre are always at their best." -- Jean GiraudouxFor advanced 3D graphics Performer + OpenGL based examples and tutors: http://www.dorbie.com/
/* * Copyright (c) 1998 Silicon Graphics, All rights Reserved. * multifrust.c * * To compile: * cc -o multifrust -O2 -n32 -mips3 multifrust.c -lGL -lX11 -lm */
#include <stdlib.h> #include <stdarg.h> #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #include <time.h> #include <ctype.h> #include <string.h> #include <GL/glx.h> #include <GL/glu.h> #include <math.h>
#define WIN_SIZEX (1280*3) /* maximum window width/height */ #define WIN_SIZEY 1024 /* maximum window width/height */
#define DEGTORAD (M_PI/180.0f)
Display *display; /* connection to X server */ XVisualInfo *vi; /* window visual */ Window window; /* window for drawing */ GLXContext context; /* graphics context */
int RGBattributes[] = { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None };
/* * wait_for_map_notify * * Callback for XIfEvent. */
int wait_for_map_notify(Display *display, XEvent *event, char *arg) { return(event->type == MapNotify && event->xmap.window == (Window)arg); }
/* * open_window * * Create an X window. */
void open_window(void) { XSetWindowAttributes swa; XSizeHints hints; XEvent event; XVisualInfo template; int c, x, y;
display = XOpenDisplay(0); if (display == NULL) { fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY")); exit(1); } vi = glXChooseVisual(display, DefaultScreen(display), RGBattributes); if (vi == NULL) { fprintf(stderr, "can't find appropriate visual\n"); exit(1); } swa.border_pixel = 0; swa.override_redirect = 1; swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask; x = (DisplayWidth(display, vi->screen) - WIN_SIZEX) / 2; y = (DisplayHeight(display, vi->screen) - WIN_SIZEY) / 2; window = XCreateWindow(display, RootWindow(display, vi->screen), x, y, WIN_SIZEX, WIN_SIZEY, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &swa); if (window == 0) { fprintf(stderr, "could not create a window\n"); exit(1); } XStoreName(display, window, "Perspective Quad Warp"); hints.x = x; hints.y = y; hints.width = WIN_SIZEX; hints.height = WIN_SIZEY; hints.flags = USPosition | PSize; XSetNormalHints(display, window, &hints); XMapWindow(display, window); XIfEvent(display, &event, wait_for_map_notify, (char *)window); context = glXCreateContext(display, vi, 0, GL_TRUE); glXMakeCurrent(display, window, context); }
void draw_test_pat(void) { float angle; int i, elevation; GLubyte *texdata;
/* draw azimuth lines */ glBegin(GL_LINES); for(angle = 0.0f, i=0; angle < M_PI*2; angle += DEGTORAD, i++) { if(!(i%10)) glColor3f(1.0f, 1.0f, 1.0f); else { if(!(i%5)) glColor3f(0.5f, 0.5f, 0.5f); else glColor3f(0.25f, 0.25f, 0.25f); } glVertex3f(sinf(angle)*10.0f, -100.0, cosf(angle)*10.0f); glVertex3f(sinf(angle)*10.0f, 100.0, cosf(angle)*10.0f); } glEnd();
/* draw elevation lines */ for(elevation = -88; elevation < 89; elevation++) { glBegin(GL_LINE_LOOP); for(angle = 0.0f; angle < M_PI*2; angle += DEGTORAD) { if(!(elevation%10)) glColor3f(1.0f, 1.0f, 1.0f); else { if(!(elevation%5)) glColor3f(0.5f, 0.5f, 0.5f); else glColor3f(0.25f, 0.25f, 0.25f); } glVertex3f(sinf(angle)*10.0f, tanf(DEGTORAD*(float)elevation)*10.0f, cosf(angle)*10.0f); } glEnd(); }
/* draw markers */ glColor3f(1.0f, 1.0f, 1.0f); glPushMatrix(); for(i=0; i<18; i++) { glRotatef(20.0f, 0.0f, 1.0f, 0.0f); glBegin(GL_LINES); glVertex3f(0.1f, 0.1f, 10.0f); glVertex3f(0.2f, 0.2f, 10.0f); glVertex3f(-0.1f,-0.1f, 10.0f); glVertex3f(-0.2f, -0.2f, 10.0f); glVertex3f(0.1f,-0.1f, 10.0f); glVertex3f(0.2f, -0.2f, 10.0f); glVertex3f(-0.1f,0.1f, 10.0f); glVertex3f(-0.2f, 0.2f, 10.0f); glEnd(); } glPopMatrix();
glPushMatrix(); glRotatef(10.0f, 0.0f, 1.0f, 0.0f); for(i=0; i<18; i++) { glRotatef(20.0f, 0.0f, 1.0f, 0.0f); glBegin(GL_LINES); glVertex3f(0.1f, 0.2f, 10.0f); glVertex3f(0.2f, 0.1f, 10.0f); glVertex3f(-0.1f, 0.2f, 10.0f); glVertex3f(-0.2f, 0.1f, 10.0f); glVertex3f(-0.1f, -0.2f, 10.0f); glVertex3f(-0.2f, -0.1f, 10.0f); glVertex3f(0.1f, -0.2f, 10.0f); glVertex3f(0.2f, -0.1f, 10.0f); glEnd(); } glPopMatrix(); }
/* float hfov = 48.0f; float vfov = 41.0f; float hoff = 36.0f; */
float hfov = 58.0f; float vfov = 44.0f; float hoff = 50.0f;
void main(int argc, char **argv) { open_window();
glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-tanf(DEGTORAD*hfov/2), tanf(DEGTORAD*hfov/2), -tanf(DEGTORAD*vfov/2), tanf(DEGTORAD*vfov/2), 1.0, 1000.0); glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_FRONT); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glViewport(0, 0, WIN_SIZEX/3.0f, WIN_SIZEY); glLoadIdentity(); glRotatef(-hoff, 0.0f, 1.0f, 0.0f); draw_test_pat();
glViewport(WIN_SIZEX/3.0f, 0, WIN_SIZEX/3.0f, WIN_SIZEY); glLoadIdentity(); draw_test_pat();
glViewport(2.0f * WIN_SIZEX/3.0f, 0, WIN_SIZEX/3.0f, WIN_SIZEY); glLoadIdentity(); glRotatef(hoff, 0.0f, 1.0f, 0.0f); draw_test_pat();
glFinish(); while(1); }
======================================================================= List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/ Submissions: info-performer++at++sgi.com Admin. requests: info-performer-request++at++sgi.com
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:57:25 PDT