AnitaKishore (kishore++at++electrogig.com)
Thu, 20 Jun 1996 09:40:32 -0700
We too experienced some problems at the begining, trying to get it to
work. But thanks to Simon Hui, we were able to make it work with his help.
Here is a sample code of doing video texturing in OpenGL using Performer
libpf library. Hope this helps.
-anita
-------------------------------------------------------------------------------
/* File Name : lv.c */
/*********************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <getopt.h>
/* X Window includes */
#include <X11/X.h>
#include <X11/Xlib.h>
/* VL includes */
#include <vl/vl.h>
#include <vl/dev_sirius.h>
#define PF_CPLUSPLUS_API 0
#include <Performer/pf.h>
typedef struct lvStruct {
Display * Dsp;
pfPipeWindow * pw;
pfGeoState * gst;
VLServer vlServer;
VLPath vlPath;
} lvType, * lvHandle;
static int
VideoInit( lvHandle lvData, VLControlValue * vlSize,
VLControlValue * vlTiming,
VLControlValue * vlTexPack );
static void VideoExit(lvHandle lvData);
static void
setVideoTextureParameters( lvHandle lvData,
VLControlValue * vlSize,
VLControlValue * vlTiming,
VLControlValue * vlTexPack );
static int loadTextureMatrixCB(pfGeoState *gs, void *userData);
static int loadIDMatrixCB(pfGeoState *gs, void *userData);
pfGroup *MkScene();
pfGeoSet *MakeTexCube(void);
void channelDraw(pfChannel *chan, void *data);
static float idmat[4][4] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
/* setup parameters */
static int TexSource = PFTEX_SOURCE_VIDEO;
static int glTexFormat = PFTEX_RGB_5; /* PFTEX_RGB_4, PFTEX_RGBA_8 */
static int TexComp = 3;
static int interlace = 0;
static int dofields = 0;
static int isrealityengine = 1;
pfTexture **tex;
lvHandle lvData;
GLXVideoSourceSGIX videosource;
void
OpenPipeWin(pfPipeWindow *pw)
{
VLControlValue vlSize, vlTiming, vlTexPack;
pfOpenPWin(pw);
VideoInit ( lvData, &vlSize, &vlTiming, &vlTexPack );
setVideoTextureParameters( lvData, &vlSize, &vlTiming, &vlTexPack );
}
int
main(long argc, char *argv[])
{
pfPipe *p;
pfChannel *chan;
pfScene *scene;
pfGroup *root;
pfCoord view;
void *arena=NULL;
pfInit();
arena = pfGetSharedArena();
tex = (pfTexture **) pfMalloc(sizeof(pfTexture *), arena);
lvData = ( lvHandle )pfMalloc( sizeof ( lvType ), arena);
pfMultiprocess ( PFMP_APPCULLDRAW );
pfConfig();
scene = pfNewScene();
root = MkScene();
pfAddChild(scene, root);
p = pfGetPipe(0);
lvData -> pw = pfNewPWin(p);
pfPWinType( lvData -> pw, PFWIN_TYPE_X);
pfPWinName( lvData -> pw, "Live Video");
pfPWinOriginSize( lvData -> pw, 100, 100, 720, 486);
lvData -> Dsp = pfGetCurWSConnection();
pfPWinConfigFunc ( lvData -> pw, OpenPipeWin);
pfConfigPWin ( lvData -> pw);
chan = pfNewChan(p);
pfChanScene(chan, scene);
pfChanNearFar(chan, 1.0f, 10000.0f);
pfChanFOV(chan, 10.0f, -1.0f);
pfSetVec3(view.hpr, 0, 0, 0);
pfSetVec3(view.xyz, 0, -50, 0);
pfChanView(chan, view.xyz, view.hpr);
pfChanTravFunc(chan, PFTRAV_DRAW, channelDraw );
/* set some basic formats for doing dynamic textures */
//pfTexFormat(*tex, PFTEX_SUBLOAD_FORMAT, 1);
while(TRUE)
{
pfSync();
pfFrame();
}
VideoExit( lvData );
pfExit();
return 0;
}
void channelDraw(pfChannel *chan, void *data)
{
int f;
f = glXMakeCurrentReadSGI(lvData -> Dsp,
pfGetPWinWSDrawable(lvData -> pw),
videosource,
pfGetPWinGLCxt(lvData -> pw));
if (!f) printf("MakeCurrenRead failed in channelDraw()\n");
pfClearChan(chan);
pfLoadTex(*tex);
pfDraw();
}
pfGroup *MkScene()
{
pfGroup *group;
pfGeode *cube;
pfGeoSet *coloredCube;
group = pfNewGroup();
cube = pfNewGeode();
coloredCube = MakeTexCube();
pfAddGSet(cube, coloredCube);
pfAddChild(group,cube);
return group;
}
#define CUBE_SIZE 1.0f
pfGeoSet *MakeTexCube(void)
{
pfGeoSet *gset;
pfTexEnv *tenv;
static pfVec3 verts[] ={{-CUBE_SIZE, 0, -CUBE_SIZE},
{ CUBE_SIZE, 0, -CUBE_SIZE},
{ CUBE_SIZE, 0, CUBE_SIZE},
{-CUBE_SIZE, 0, CUBE_SIZE}};
static ushort vindex[] ={0, 1, 2, 3}; /* front */
static pfVec3 norms[] ={{ 0.0f, -1.0f, 0.0f}};
static ushort nindex[] ={0};
static pfVec2 tcoords[] ={{0.0f, 0.0f},
{1.0f, 0.0f},
{1.0f, 1.0f},
{0.0f, 1.0f}};
static ushort tindex[] ={0, 1, 2, 3};
gset = pfNewGSet(pfGetSharedArena());
pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, verts, vindex);
pfGSetAttr(gset, PFGS_NORMAL3, PFGS_PER_PRIM, norms, nindex);
pfGSetAttr(gset, PFGS_TEXCOORD2, PFGS_PER_VERTEX, tcoords, tindex);
pfGSetPrimType(gset, PFGS_QUADS);
pfGSetNumPrims(gset, 1);
lvData -> gst = pfNewGState(pfGetSharedArena());
pfGStateMode( lvData -> gst, PFSTATE_ENTEXTURE, 1);
pfGSetGState(gset, lvData -> gst);
*tex = pfNewTex(pfGetSharedArena());
//pfLoadTexFile(*tex,
"/disk4/people/kishore/performer/data/smallGlobeDesat.rgb");
/* set some basic formats for doing dynamic textures */
pfTexFormat(*tex, PFTEX_SUBLOAD_FORMAT, 1);
pfTexFilter(*tex, PFTEX_MINFILTER, PFTEX_BILINEAR);
tenv = pfNewTEnv(pfGetSharedArena());
//pfTEnvMode(tenv, PFTE_DECAL);
pfGStateAttr(lvData -> gst, PFSTATE_TEXENV, tenv);
pfGStateAttr(lvData -> gst, PFSTATE_TEXTURE, *tex);
return gset;
}
static int
VideoInit( lvHandle lvData, VLControlValue * vlSize,
VLControlValue * vlTiming,
VLControlValue * vlTexPack )
{
VLControlValue vlCaptureType;
VLNode vlSrc, vlDrn;
int vlInSrc = VL_ANY, vlDevice = VL_ANY;
fprintf ( stderr, "video init\n");
/* open the server */
if (!(lvData -> vlServer = vlOpenVideo(""))) {
vlPerror("vlOpenVideo");
fprintf(stderr, "couldn't open video server!\n");
return 1;
}
/* Get the Video source */
vlSrc = vlGetNode(lvData -> vlServer, VL_SRC, VL_VIDEO, vlInSrc);
/* Get the Texture drain */
vlDrn = vlGetNode(lvData -> vlServer, VL_DRN, VL_TEXTURE, 0);
/* Create path */
lvData -> vlPath = vlCreatePath(lvData -> vlServer, vlDevice, vlSrc,
vlDrn);
if (lvData -> vlPath < 0)
{
vlPerror("vlCreatePath");
return -1;
}
/* setup path */
if (vlSetupPaths(lvData -> vlServer, (VLPathList)&lvData ->
vlPath,1,VL_SHARE, VL_SHARE) < 0) {
vlPerror("vlSetupPaths");
return -1;
}
/* select the appropriate events */
if (vlSelectEvents(lvData -> vlServer, lvData -> vlPath,
VLStreamPreemptedMask |
VLControlChangedMask ) < 0)
{
vlPerror("Select Events");
return -1;
}
#ifdef XXX
if (isrealityengine) {
if (dofields) {
vlCaptureType.intVal = VL_CAPTURE_NONINTERLEAVED;
} else {
vlCaptureType.intVal = VL_CAPTURE_INTERLEAVED;
}
vlSetControl(lvData -> vlServer, lvData -> vlPath, vlDrn, VL_CAP_TYPE,
&vlCaptureType);
}
#endif
vlCaptureType.intVal = VL_CAPTURE_INTERLEAVED;
vlSetControl(lvData -> vlServer, lvData -> vlPath, vlDrn, VL_CAP_TYPE,
&vlCaptureType);
switch( glTexFormat )
{
case PFTEX_RGBA_4:
vlTexPack -> intVal = SIR_TEX_PACK_RGBA_4;
break;
case PFTEX_RGB_5:
vlTexPack -> intVal = SIR_TEX_PACK_RGB_5;
break;
case PFTEX_RGBA_8:
vlTexPack -> intVal = SIR_TEX_PACK_RGBA_8;
break;
default:
vlTexPack -> intVal = SIR_TEX_PACK_RGB_5;
glTexFormat = PFTEX_RGB_5;
break;
}
/* Set the Texture packing mode */
vlSetControl(lvData -> vlServer, lvData -> vlPath, vlDrn, VL_PACKING,
vlTexPack);
/* Get the timing from input source */
vlGetControl(lvData -> vlServer, lvData -> vlPath, vlSrc, VL_TIMING,
vlTiming);
/* Set texture drain's timing to input source */
vlSetControl(lvData -> vlServer, lvData -> vlPath, vlDrn, VL_TIMING,
vlTiming);
/* Get corresponding size */
vlGetControl(lvData -> vlServer, lvData -> vlPath, vlSrc, VL_SIZE, vlSize);
fprintf ( stderr, "vl stuff done, now doing OpenGL\n");
#ifndef IRISGL /* OPENGL */
{
int f;
pfWSDrawable drawable;
pfGLContext context;
const char *gl_extensions;
int has_interlace;
videosource = glXCreateGLXVideoSourceSGIX(lvData -> Dsp, 0 /* screen
*/,
lvData -> vlServer, lvData ->
vlPath, VL_TEXTURE,
vlDrn);
if (videosource == None) {
fprintf(stderr, "can't create video source\n");
exit(EXIT_FAILURE);
}
else
fprintf ( stderr, "video source ok\n");
drawable = pfGetPWinWSDrawable( lvData -> pw);
context = pfGetPWinGLCxt( lvData -> pw) ;
fprintf ( stderr, "drawable %x context %x\n", drawable, context );
f = glXMakeCurrentReadSGI( lvData -> Dsp, pfGetPWinWSDrawable(lvData ->
pw), videosource,
pfGetPWinGLCxt(lvData -> pw));
fprintf ( stderr, "f = %d\n", f );
#ifdef XXX
if (interlace) {
gl_extensions = glGetString(GL_EXTENSIONS);
if (!gl_extensions) {
fprintf(stderr, "can't get GL_EXTENSIONS\n");
}
has_interlace = strstr((const char *) gl_extensions,
"GL_SGIX_interlace") != NULL;
glEnable(GL_INTERLACE_SGIX);
if (!has_interlace || !glIsEnabled(GL_INTERLACE_SGIX)) {
fprintf(stderr, "can't enable interlace extension\n");
exit(EXIT_FAILURE);
}
}
#endif
}
#endif
fprintf ( stderr, "video init done\n" );
return 0;
}
static void
setVideoTextureParameters( lvHandle lvData,
VLControlValue * vlSize,
VLControlValue * vlTiming,
VLControlValue * vlTexPack )
{
pfMatrix *tmat;
float s_scale, t_scale;
int vlTexWidth, vlTexHeight;
fprintf ( stderr, "video init %d %d %x %d\n", isrealityengine, TexComp,
glTexFormat, interlace );
if ((vlTiming -> intVal == VL_TIMING_525_SQ_PIX)
|| (vlTiming -> intVal == VL_TIMING_525_CCIR601)) {
vlTexWidth = 1024;
vlTexHeight = 512;
} else {
vlTexWidth = 1024;
vlTexHeight = 1024;
}
/* create texture matrix for scaling texcoords to valid part of texture */
tmat = (pfMatrix*) pfCalloc(sizeof(pfMatrix), 1, pfGetSharedArena() );
pfMakeIdentMat(*tmat);
s_scale = vlSize -> xyVal.x / (float) vlTexWidth;
t_scale = vlSize -> xyVal.y / (float) vlTexHeight;
(*tmat)[0][0] = s_scale;
(*tmat)[1][1] = -t_scale; /* invert in y because of video origin */
(*tmat)[3][1] = t_scale; /* this is really a translate */
/* gset callbacks to manage texture matrix - put matrix in userData */
pfGStateFuncs( lvData -> gst, loadTextureMatrixCB, loadIDMatrixCB, tmat);
if (dofields) {
pfTexImage(*tex, NULL, TexComp, vlTexWidth, vlTexHeight/2, 1);
if (isrealityengine) {
pfTexLoadSize(*tex, 768, vlSize -> xyVal.y/2);
} else {
pfTexLoadSize(*tex, vlSize -> xyVal.x, vlSize -> xyVal.y/2);
}
} else {
pfTexImage(*tex, NULL, TexComp, vlTexWidth, vlTexHeight, 1);
if (isrealityengine) {
pfTexLoadSize(*tex, 768, vlSize -> xyVal.y);
} else {
pfTexLoadSize(*tex, vlSize -> xyVal.x, vlSize -> xyVal.y);
}
}
/* specify the texture format, this is the default */
pfTexFormat ( *tex, PFTEX_INTERNAL_FORMAT, glTexFormat );
pfTexLoadMode ( *tex, PFTEX_LOAD_SOURCE, PFTEX_SOURCE_VIDEO );
}
static void
VideoExit( lvHandle lvData )
{
vlEndTransfer (lvData -> vlServer, lvData -> vlPath);
vlDestroyPath (lvData -> vlServer, lvData -> vlPath);
vlCloseVideo (lvData -> vlServer);
exit(0);
}
/* callback to load texture matrix to invert the video image */
static int
loadTextureMatrixCB(pfGeoState *gs, void *userData)
{
pfMatrix *tmat = (pfMatrix *)(userData);
/*
int i,j;
for ( i =0; i < 4; i++, fprintf ( stderr,"\n") )
for ( j =0; j < 4; j++ )
fprintf ( stderr, "%f ", (*tmat)[i][j] );
fprintf ( stderr, "loadTextureMatrixCB %x\n", tmat);
*/
#ifdef IRISGL
mmode(MTEXTURE);
pfLoadMatrix(*tmat);
mmode(MVIEWING);
#else
glMatrixMode(GL_TEXTURE);
pfLoadMatrix(*tmat);
glMatrixMode(GL_MODELVIEW);
#endif
return 0;
}
static int
loadIDMatrixCB(pfGeoState *gs, void *userData)
{
#ifdef IRISGL
mmode(MTEXTURE);
pfLoadMatrix(idmat);
mmode(MVIEWING);
#else
glMatrixMode(GL_TEXTURE);
pfLoadMatrix(idmat);
glMatrixMode(GL_MODELVIEW);
#endif
return 0;
}
--------------------------------------------------------------------------------
makefile:
SHELL = /bin/sh
#-- provide a list of alternate locations for file searches
UNIQUE = .
#-- alternate locatins for included files
INCLUDE = \
-I${UNIQUE} \
-I/usr/include/Performer
#SRCLIBOPT=_igl
SRCLIBOPT=_ogl
PERFORMER = \
-lpfdu${SRCLIBOPT} \
-lpfutil${SRCLIBOPT} \
-lpf${SRCLIBOPT}
#-- IRIX 4.x uses shared gl {gl_s} library {System-V Make lacks #if
movietex.cs}#LIBGL1 = -lgl
LIBGL1 = -lGL
LIBGL2 = ${LIBGL1:.4=_s}
LIBGL = ${LIBGL2:.5=}
SYSTEM = \
-lInventor \
-lmpc \
-lvl \
-limage \
-lfm \
${LIBGL} \
-lX11 \
-lm \
-lfpe \
-lC
LIBRARIES = \
${PERFORMER} ${SYSTEM}
#-- select c-compiler options
CFLAGS = -xansi -g -D__STDC__ ${INCLUDE} ${COPT} -DPF_C_API=1 \
-DPF_CPLUSPLUS_API=0 \
-DPF_MAJOR_VERSION=2 -Xcpluscomm
#-DIRISGL
#-- base name of program
TARGET = lv
#-- object files from which target built {some are in the common directory}
OBJECTS = \
lv.o
${TARGET}: ${OBJECTS}
${CC} ${CFLAGS} -o $++at++ ${OBJECTS} ${LIBRARIES}
#-- objects are built from either unique or common files
lv.o: ${UNIQUE}/lv.c
${CC} ${CFLAGS} -c lv.c -o $++at++
clean :
rm -f lv lv.o
--------------------------------------------------------------------------------
=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer.html
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:53:02 PDT