Re: [info-performer] Dynamic textures

New Message Reply Date view Thread view Subject view Author view

From: c.mottram (ucftchr++at++ucl.ac.uk)
Date: 01/29/2003 07:00:27


Okay the answer was
as sort of expected......
Looks like a fairly standard thing in performer, making sure things happen
at the right time the left channel was never getting the pfTexture::load I
reckon!
Looks very nice too.
 So in initialization
   chan->setTravFunc( PFTRAV_DRAW, DrawChannel);
    right->setTravFunc( PFTRAV_DRAW, DrawChannel);
 

then in main loop

        while(key!='q')
        {

                pfSync();
                                                draw();
                pfFrame();
        vid.GrabFrame(image); // load web cam view into image pointer from
// pfGetSharedArena

                copyim(); // makes sure image not transparent and puts bytes
//correct order
}

and then...
static void
DrawChannel (pfChannel *channel, void *data)
{
tex->load();

    channel->clear();
    /* invoke Performer draw-processing for this frame */
    pfDraw();

}

At 11:49 29/01/2003 +0000, you wrote:
>
>Well, my setup works in stereo (quad-buffered though). That's how I
>tested it.
>
>To make a long story short my PC development is done on my laptop which
>is at home :(.
>But I did alter your hello.cpp file to show the geometry in both windows
>to change
>the texture at the same time (I'm assuming the process of getting the
>texture from the webcam
>is not a problem). This works fine on an Onyx. The texture should change
>from black and white
>every one second.
>
>I attach the program altered. It's hello.cpp and most of the stuff is
>hardcoded but it should give
>you a good starting point.
>
>Regarding a VRML loader I'm working on one for Performer. It still
>doesn't have Script functionality.
>It will not be free, since it's a GSA product. Do you have a timescale
>of when do you need it.
>
>It's being done with time between my normal projects, so it's taking a
>while.
>
>Goncalo
>
>
>"c.mottram" wrote:
>>
>> This is a mini application to drive a pair of projectors or a head set in
>> stereo vision.
>> I'm trying to build it as a demonstrator for students, so I'm trying to keep
>> it fairly simple.
>> I thought getting a webcam image onto a polygon is something they'd find fun!
>> This is designed to run on window machines with dual head graphics cards so
>> I put the screens side by side.
>> I attach full code. This is not what I give the students!.
>> I have to give them little neat bundles on an accumulative basis.
>> So this is an untidy version of about two thirds of an eight week course.
>> IF you can suss out what might be wrong
>> I'd be very grateful
>> Cheers
>> Chiron P. Mottram
>> Bartlett Graduate School
>> UCL
>> London
>>
>
>--
>Goncalo Carvalho
>Digital Design Studio - Glasgow School of Art
>House for an Art Lover - Bellahouston Park
>10 Dumbreck Road
>Glasgow G41 5BW
>United Kingdom
>
>Tel: +44 (0) 141 353 4616
>Fax: +44 (0) 141 353 4422
>Mobile: +44 (0) 7766 295867
>mailto:g.carvalho++at++gsa.ac.uk
>
>
>#include <Performer/pf.h>
>#include <Performer/pfutil.h>
>#include <Performer/pfdu.h>
>#include <Performer/pfui.h>
>
>#include <Performer/pf/pfChannel.h>
>#include <Performer/pf/pfLightSource.h>
>#include <Performer/pf/pfText.h>
>#include <Performer/pr/pfLight.h>
>#include <Performer/pr/pfGeoMath.h>
>#include <Performer/pr/pfFont.h>
>#include <Performer/pr/pfString.h>
>#include <Performer/prmath.h>
>#include <Performer/pf/pfGeode.h>
>#include <Performer/pf/pfDCS.h>
>#include <Performer/pr/pfTexture.h>
>#include "ARFrameGrabber.h"
>#include <GL/gl.h>
>ARFrameGrabber vid;
>void copyim();
>
>#include <stdlib.h>
>static pfLight *Sun;
>int key=1;
>pfChannel *chan;
>pfTexEnv*tev ;
>pfChannel *left,*right;
>static float Iod = 2.f;
>static float Converge = .2f;
>static float Fov = 45.f;
>void draw();
>float fars = 10000.0f;
>float nears = .1f;
> int stereo;
>pfGeode* make_texture();
> pfGeoState *gstate;
>
>
> pfText *text;
>void setColour(pfGeode * gs , float red , float green , float blue );
>
>pfGeode* make_cube(float,float,float);
>pfScene *scene ;
>pfTexture *tex;
>unsigned char* image=NULL;
>int camerawidth,cameraheight;
>int
>main (int argc, char *argv[])
>{
> pfWSConnection dsp=NULL;
> pfVec3 xyzOffsets;
> pfVec3 hprOffsets;
> int *leftArg, *rightArg;
> float halfNearWidth;
> float eyeAngle;
> unsigned int mask;
> //CoInitialize(NULL);
>
> vid.Init(0);
> vid.DisplayProperties();
> vid.Getsize( camerawidth, cameraheight);
>
>
>
>
> // Initialize and configure OpenGL Performer
> pfInit();
>
> pfMultiprocess( PFMP_APPCULLDRAW );
> if(argv[1])
> pfdInitConverter(argv[1]);
>
> pfConfig();
>
> // Look for files in PFPATH, ".", and "/usr/share/Performer/data"
> //pfFilePath("c:\program files\silicon graphics\opengl performer\data");
>
> // Create a scene
> scene = new pfScene;
> // Create a lit scene pfGeoState for the scene
> pfGeoState *gstate = new pfGeoState;
> gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
> // attach the pfGeoState to the scene
> scene->setGState(gstate);
> // put a default light source in the scene
> scene->addChild(new pfLightSource);
> tex = new pfTexture;
> pfGeode *gt=make_texture();
> scene->addChild(gt);
>
>
> // Create 3D message and place in scene.
>
>
> pfString *str = new pfString;
> pfFont *fnt = pfdLoadFont_type1("Times-Elfin",PFDFONT_EXTRUDED);
> if (fnt == NULL)
> {
> pfNotify(PFNFY_WARN,PFNFY_PRINT, "Couldnt find font - Times-Elfin");
> //exit(1);
> }
> if(argv[1])
> {
> pfNode *root = pfdLoadFile(argv[1]);
> if(root)
> scene->addChild(root);
> }
> pfGeode *gs=make_cube(10,0,0);
> setColour(gs,1,0,0);
> str->setFont(fnt);
> str->setMode(PFSTR_JUSTIFY, PFSTR_MIDDLE);
> str->setColor(1.0f, 0.0f, 0.8f, 1.0f);
> str->setString("Hello Hello Hello");
> str->flatten();
> text = new pfText;
> text->addString(str);
> scene->addChild(text);
>
> // Create and configure a pfPipe and pfChannel.
> pfPipe *pipe = pfGetPipe(0);
> pfPipeWindow* pw = new pfPipeWindow(pipe);
> pfPipeWindow* pw2 = new pfPipeWindow(pipe);
>// OpenPipeWin(pw);
> pw->setWinType(PFPWIN_TYPE_X);
> pw->setName("left");
> pw->setOriginSize(0, 0, 300, 300);
> /* Open and configure the GL window. */
> pw->open();
> pw2->setWinType(PFPWIN_TYPE_X);
> pw2->setName("right");
> pw2->setOriginSize(300, 0, 300, 300);
> /* Open and configure the GL window. */
> pw2->open();
> //HWND blah = pipe->getPWin(0)->getWSWindow();
> chan = new pfChannel(pipe);
> right = new pfChannel(pipe);
> mask = chan->getShare();
> mask|=PFCHAN_SWAPBUFFERS;
> chan->setShare(mask);
> mask = chan->getShare();
> chan->attach(right);
> pw2->addChan(right);
> chan->setFOV(45.0f, 0.0f);
> chan->setScene(scene);
> int input;
> pfuInitInput(pw ,PFUINPUT_X);
>
> // Determine extent of scene's geometry.
> pfSphere bsphere;
> scene->getBound(&bsphere);
> // chan->setNearFar(1.0f, 10.0f*bsphere.radius);
> chan->setNearFar(nears, fars);
> //fars = bsphere.radius;
> //nears = 1.0;
> eyeAngle = PF_RAD2DEG(
> atanf(Iod *.5f
> /(Converge * (fars - nears) + nears)
> )
> );
>
> //* left eye
> hprOffsets=pfVec3( -eyeAngle, 0.f, 0.f);
> xyzOffsets= pfVec3( -Iod/2.f, 0.f, 0.f);
> chan->setViewOffsets(xyzOffsets, hprOffsets);
>
> //* right eye
> hprOffsets=pfVec3( eyeAngle, 0.f, 0.f);
> xyzOffsets= pfVec3( Iod/2.f, 0.f, 0.f);
> right->setViewOffsets(xyzOffsets, hprOffsets);
> chan->setView(pfVec3(0,-bsphere.radius,0), pfVec3(0,0,0));
> int s = vid.GetBufferSize2();
>
> //image = (long*)pfMalloc (sizeof(long)*s, pfGetSharedArena());
> //vid.GrabFrame(image);
> image = (unsigned char*)pfMalloc (512*512*4, pfGetSharedArena());
> copyim();
>
>
>tex->setImage( (unsigned int*)0, 4, 512, 512, 0 );
>tex->setFilter( PFTEX_MINFILTER, PFTEX_LINEAR );
>tex->setFilter( PFTEX_MAGFILTER, PFTEX_LINEAR );
>tex->setRepeat( PFTEX_WRAP_S, PFTEX_CLAMP );
>tex->setRepeat( PFTEX_WRAP_T, PFTEX_CLAMP );
>tex->setFormat( PFTEX_INTERNAL_FORMAT, GL_RGBA );
>tex->setFormat( PFTEX_SUBLOAD_FORMAT, PF_ON );
>
>tex->setLoadMode( PFTEX_LOAD_BASE, PFTEX_BASE_AUTO_SUBLOAD );
>
>tex->setLoadOrigin( PFTEX_ORIGIN_DEST, 0, 0 );
> tex->setLoadSize( 512, 512 );
>tex->setLoadImage( (unsigned int*)image);
>
> bool i = true;
> while(key!='q')
> {
>
> pfSync();
> tex->load();
>
> draw();
> pfFrame();
> //vid.GrabFrame(image); // load web cam view into image
>
> if( i )
> memset( image, 0x00, 512 * 512 * 4 );
> else
> memset( image, 0xFF, 512 * 512 * 4 );
>
> i = !i;
>
> sleep( 1 );
>
> //copyim(); // makes sure image not transparent
>//earlier attempts...
>//void * image = vid.GetBuffer();
>
>//tex->getImage(&img,&comp,&ns,&nt,&nr);
>//tex->setImage((unsigned int *)image,4,320,240,1);
>// tex->setImage((unsigned int *)image,4,320,240,0);
>// gstate->setAttr(PFSTATE_TEXTURE,tex);
>// tex->setLoadImage((unsigned int*)image);
>// tex->setLevel(1,tex);
>
>//tex->load();
>
> }
> pfExit();
> return 0;
>}
>
>pfMatrix head,body;
>void draw()
>{
>
> int dev;
> int val;
> pfuEventStream events;
> pfuGetEvents(&events);
> pfuMouse mouse;
> pfuGetMouse(&mouse);
> float normX, normY;
> pfuCalcNormalizedChanXY( &normX, &normY, chan, mouse.xpos, mouse.ypos );
>
> if( mouse.click & PFUDEV_MOUSE_LEFT_DOWN )
> {
>
>
> pfuCalcNormalizedChanXY( &normX, &normY, chan, mouse.xpos, mouse.ypos );
> }
> int numDevs = events.numDevs;
>
> for (int j = 0; j < numDevs; j++)
> {
> dev = events.devQ[j];
> val = events.devVal[j];
> val = val; /* suppress compiler warn */
>
> if (events.devCount[dev] > 0)
> {
> switch(dev)
> case PFUDEV_KEYBD:
> for (int i = 0; i < events.numKeys; i++)
> {
> key = events.keyQ[i];
> if (events.keyCount[key])
> {
>
> }
> }
>
> }
> }
>
> pfSphere bsphere;
> text->getBound(&bsphere);
> pfSphere bsphere2;
> scene->getBound(&bsphere2);
> // chan->setNearFar(nears, fars);
>
> pfCoord view;
> float s, c;
> static double t=0;
> pfVec3 dd = pfVec3(1,1,1);
> // Compute new view position, rotating around text.
> pfSinCos(45.0f*t, &s, &c);
> //view.hpr.set(45.0f*t, -5.0f*normY, normX*90.0f);
> view.xyz.set(
> 2.0f * bsphere.radius * s,
> -2.0f * bsphere.radius * c,
> 0.3f * bsphere.radius);
>
>// dd.scale(normY,dd);
>// view.hpr.set(0, 0, 0);
>// view.xyz.set(
>// 0,-bsphere2.radius,0);
>// chan->setView(view.xyz, view.hpr);
>static float onx = normX;
>static float ony = normY;
> pfMatrix mat;
> chan->getViewMat(mat);
> mat.preTrans(0,1.0*(normY-0.5),0,mat);
>
> if (key=='x')
> mat.preRot((0.5-normX)*1.0,1,0,0,mat);
> else if (key=='z')
> mat.preRot((0.5-normX)*1.0,0,1,0,mat);
> else
> mat.preRot((0.5-normX)*1.0,0,0,1,mat);
> //chan->setViewMat(mat);
> t+=0.1;
>onx = normX;
>ony = normY;
> // Initiate cull/draw processing for this frame.
>
>
>}
>
>
> static pfVec3 coords[8] =
> {
> pfVec3(-1.0, -1.0, 1.0),
> pfVec3( 1.0, -1.0, 1.0),
> pfVec3( 1.0, 1.0, 1.0),
> pfVec3(-1.0, 1.0, 1.0),
> pfVec3(-1.0, -1.0, -1.0),
> pfVec3( 1.0, -1.0, -1.0),
> pfVec3( 1.0, 1.0, -1.0),
> pfVec3(-1.0, 1.0, -1.0)
> };
>
> static pfVec3 norms2[8] =
> {
> pfVec3( -1.0, -1.0, 1.0),
> pfVec3( 1.0, -1.0, 1.0),
> pfVec3( 1.0, 1.0, 1.0),
> pfVec3( -1.0, 1.0, 1.0),
> pfVec3( -1.0, -1.0, -1.0),
> pfVec3(1.0, -1.0, -1.0),
> pfVec3( 1.0, 1.0, -1.0),
> pfVec3(-1.0, 1.0, -1.0)
> };
> static ushort nindex2[24]=
> {
> 0, 1, 2, 3, // front
> 0, 3, 7, 4, // left
> 4, 7, 6, 5, // back
> 1, 5, 6, 2, // right
> 3, 2, 6, 7, // top
> 0, 4, 5, 1 // bottom
> };
>
> static ushort cindex[24]=
> {
> 0, 1, 2, 3, // front
> 0, 3, 7, 4, // left
> 4, 7, 6, 5, // back
> 1, 5, 6, 2, // right
> 3, 2, 6, 7, // top
> 0, 4, 5, 1 // bottom
> };
>
> static pfVec3 norms[6] =
> {
> pfVec3( 0.0, 0.0, 1.0),
> pfVec3( 0.0, 0.0, -1.0),
> pfVec3( 0.0, 1.0, 0.0),
> pfVec3( 0.0, -1.0, 0.0),
> pfVec3( 1.0, 0.0, 0.0),
> pfVec3(-1.0, 0.0, 0.0)
> };
> static ushort nindex[6]=
> {
> 0,
> 5,
> 1,
> 4,
> 2,
> 3
> };
>static void*
> memdup(void *mem, size_t bytes, void *arena)
> {
> void *data = pfMalloc(bytes, arena);
> memcpy(data, mem, bytes);
> return data;
> }
>
>pfGeode * make_cube(float x,float y, float z)
>{
>
> /* Set up an indexed PFGS_QUADS pfGeoSet */
> pfGeoSet* gset = new pfGeoSet();
> gset->setPrimType(PFGS_QUADS);
>
> gset->setNumPrims(6);
>
>
> gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX,
> memdup(coords,8* sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(cindex,24* sizeof(ushort),
pfGetSharedArena()));
>
> gset->setAttr(PFGS_NORMAL3, PFGS_PER_VERTEX,
>
> memdup(norms2, 8*sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(nindex2, 24*sizeof(ushort),
pfGetSharedArena()));
>
>
> pfGeode * gs = new pfGeode();
>gs->addGSet(gset);
>
>pfDCS* tpmvt = new pfDCS;
>tpmvt->addChild(gs);
>tpmvt->setTrans(x,y,z);
>scene->addChild(tpmvt);
>return gs;
>}
>pfGeode * make_cube2(float x,float y, float z)
>{
>
> /* Set up an indexed PFGS_QUADS pfGeoSet */
> pfGeoSet* gset = new pfGeoSet();
> gset->setPrimType(PFGS_QUADS);
>
> gset->setNumPrims(6);
>
>
> gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX,
> memdup(coords,8* sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(cindex,24* sizeof(ushort),
pfGetSharedArena()));
>
> gset->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM,
>
> memdup(norms, 6*sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(nindex, 6*sizeof(ushort), pfGetSharedArena()));
>
>
>pfGeode * gs = new pfGeode();
>gs->addGSet(gset);
>
>pfDCS* tpmvt = new pfDCS;
>tpmvt->addChild(gs);
>tpmvt->setTrans(x,y,z);
>scene->addChild(tpmvt);
>return gs;
>}
>
>pfGeode * make_triangle(pfVec3 verts[3],pfVec3 norm,ushort index[3])
>{
>ushort nindex[1]={0};
> pfGeoSet* gset = new pfGeoSet();
> gset->setPrimType(PFGS_TRIS);
> gset->setNumPrims(1);
> gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX,
> memdup(verts,3* sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(index,3* sizeof(ushort), pfGetSharedArena()));
>
> gset->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM,
>
> memdup(&norm, 1*sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(nindex, 1*sizeof(ushort), pfGetSharedArena()));
>
>
>pfGeode * gs = new pfGeode();
>gs->addGSet(gset);
>pfDCS* tpmvt = new pfDCS;
>tpmvt->addChild(gs);
>scene->addChild(tpmvt);
>return gs;
>}
>
>
>pfGeode * make_polys(int n,int *lens,int nv,pfVec3 *verts ,ushort
*cindex,pfVec3 *norms,ushort *nindex)
>{
>int tot = 0;
> pfGeoSet* gset = new pfGeoSet();
> gset->setPrimType(PFGS_POLYS);
>
>int *lengths = (int*)pfMalloc(n * sizeof(int));//lengths is the nimber of
vertices in each polygon
> for (int z = 0;z<n;z++)
> {
> tot += lens[z];
> lengths[z] = lens[z];// can have different nimbers of vertices in each poly!
> }
> gset->setNumPrims(n);
> gset->setPrimLengths(lengths);
> gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX,
> memdup(verts,nv* sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(cindex,tot* sizeof(ushort),
pfGetSharedArena()));
>
> if(norms!=NULL) gset->setAttr(PFGS_NORMAL3, PFGS_PER_PRIM,//could set
the normal for each vertex!
> memdup(norms, n*sizeof(pfVec3), pfGetSharedArena()),
> (ushort*)memdup(nindex, n*sizeof(ushort), pfGetSharedArena()));
>
>
>pfGeode * gs = new pfGeode();
>gs->addGSet(gset);
> pfDCS* tpmvt = new pfDCS;
>tpmvt->addChild(gs);
>scene->addChild(tpmvt);
>return gs;
>}
>void setColour(pfGeode * gs , float red , float green , float blue )
>{
>pfVec4 v(red,green,blue,1);
> pfGeoSet *gset;
> int ng =gs->getNumGSets();
>if(ng==0)return ;
>for (int i = 0; i< ng ;i++)
>{
> //
> void *oldcols;
> unsigned short *b;
>
> gset = gs->getGSet( i);
> void *coords;
> ushort *indices;
> gset->getAttrLists( PFGS_COORD3, &coords, &indices);
> gset->getAttrLists(PFGS_COLOR4,&oldcols,&b);
> if(indices)
> b = indices;
> gset->setAttr(PFGS_COLOR4, PFGS_OVERALL,
> memdup(v.vec, 1 * sizeof(pfVec4), pfGetSharedArena()),
> b);
>}
>}
>
>pfGeode* make_texture()
>{
>
> pfVec3 *coords = (pfVec3*) new(4*sizeof(pfVec3)) pfMemory;
> coords[0].set(-1.0f, 0.0f, -1.0f);
> coords[1].set( 1.0f, 0.0f, -1.0f );
> coords[2].set( 1.0f, 0.0f, 1.0f );
> coords[3].set(-1.0f, 0.0f, 1.0f );
>
> ushort *vertexlist = (ushort*) new(4*sizeof(ushort)) pfMemory;
> vertexlist[0] = 0;
> vertexlist[1] = 1;
> vertexlist[2] = 2;
> vertexlist[3] = 3;
>
> pfVec4 *colors = (pfVec4*) new(4*sizeof(pfVec4)) pfMemory;
> colors[0].set(1.0f, 1.0f, 1.0f, 1.0f);
> colors[1].set(1.0f, 1.0f, 1.0f, 1.0f);
> colors[2].set(1.0f, 1.0f, 1.0f, 1.0f);
> colors[3].set(1.0f, 1.0f, 1.0f, 1.0f);
>
> ushort *colorlist = (ushort*) new(4*sizeof(ushort)) pfMemory;
> colorlist[0] = 0;
> colorlist[1] = 1;
> colorlist[2] = 2;
> colorlist[3] = 3;
>
> pfVec2 *texcoords = (pfVec2*) new(4*sizeof(pfVec2)) pfMemory;
> texcoords[0].set(0.0f, 0.0f);
> texcoords[1].set(1.0f, 0.0f);
> texcoords[2].set(1.0f, 1.0f);
> texcoords[3].set(0.0f, 1.0f);;
>
> ushort *texlist = (ushort*) new(4*sizeof(ushort)) pfMemory;
> texlist[0] = 0;
> texlist[1] = 1;
> texlist[2] = 2;
> texlist[3] = 3;
> uint *i;
> int nc=0, sx, sy, sz;
> gstate = new pfGeoState;
> gstate->setMode(PFSTATE_TRANSPARENCY, PFTR_BLEND_ALPHA);
> gstate->setMode(PFSTATE_ALPHAFUNC, PFAF_NOTEQUAL);
> gstate->setVal(PFSTATE_ALPHAREF, 0.0f);
> gstate->setAttr(PFSTATE_TEXTURE, tex);
> tev = new pfTexEnv;
> tev->setMode( PFTE_REPLACE );
> gstate->setAttr(PFSTATE_TEXENV, tev);
> gstate->setMode(PFSTATE_ENTEXTURE,1);
> gstate->setMode(PFSTATE_ENLIGHTING,0);
> gstate->setMode(PFSTATE_CULLFACE,PFCF_OFF);
>
> pfGeoSet *gset = new pfGeoSet;
> gset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, coords, vertexlist);
> gset->setAttr(PFGS_TEXCOORD2, PFGS_PER_VERTEX, texcoords, texlist);
> gset->setAttr(PFGS_COLOR4, PFGS_PER_VERTEX, colors, colorlist);
> gset->setPrimType(PFGS_QUADS);
> gset->setNumPrims(1);
> gset->setGState(gstate);
> // set up scene graph
> pfGeode *geode1 = new pfGeode;
> geode1->addGSet(gset);
>// copyim();
>return geode1;
> }
>
>void copyim()
>{
> uint *i;
> int nc, sx=camerawidth , sy= cameraheight, sz;
>// tex->getImage(&i, &nc, &sx, &sy, &sz);
> for( int x = 0 ; x< sx; x++)
> {
> for (int y = 0; y < sy; y++)
> {
> int mas = 0xFF000000;
> image[y*sx+x]=mas|image[y*sx+x];
> }
> }
>
>}
>


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2b29 : Wed Jan 29 2003 - 07:02:04 PST

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.