[comp.sys.sgi] Personal Iris lighting problems

ringrose@fibula.ai.mit.edu (Robert Ringrose) (03/13/91)

I am running into a problem with lighting on the Personal Iris 4D/25.
(working with C and the gl libraries)

It works fine until I put in a call to a routine with the
following code, part of an attempt to get the current
projection and modelview matrices:


mmode(MPROJECTION);
mmode(MVIEWING);


I will grant that there is usually more code in between, but
I have observed the problem with the code in between commented
out AND the problem goes away when I comment out the
mmode(MPROJECTION) call.

Specifically, the problem is that the one infinite light I use,
bound to LIGHT1, is rotated and the rotation is increased every
time those two lines are executed.  I have tried re-defining and 
re-binding the light, without change.


Now, in an _old_ version of the manual it talks about keeping the
inverse transpose of part of the modelview matrix and updating
it as you go, for use with the lighting calculations.  Is it
possible that this matrix is getting messed up by the contents
of the projection matrix when you go through mmode(MPROJECTION)
with a non-unit projection matrix?  Or am I on the wrong track -
that section of the manual seems to be absent from version 4.0
(it was on 9-35 of the version 1.0 manual).



Suggestions, reasons, solutions, workarounds, etc. would be 
_greatly_ appreciated.  Please reply by E-mail to

ringrose@ai.mit.edu


	- Robert Ringrose


There's always one more bu6.

howardl@sgi.com (Howard Look) (03/13/91)

In article <13917@life.ai.mit.edu> ringrose@fibula.ai.mit.edu (Robert Ringrose) writes:
>
>I am running into a problem with lighting on the Personal Iris 4D/25.
>(working with C and the gl libraries)
>
>It works fine until I put in a call to a routine with the
>following code, part of an attempt to get the current
>projection and modelview matrices:
>
>
>mmode(MPROJECTION);
>mmode(MVIEWING);
>
>...
>
>Specifically, the problem is that the one infinite light I use,
>bound to LIGHT1, is rotated and the rotation is increased every
>time those two lines are executed.  I have tried re-defining and 
>re-binding the light, without change.

Using mmode(MPROJECTION) is not a usual thing to do. As a matter of
fact, for most applications, you really only need to go into mmode(MVIEWING)
once in your initialize routine. Projection calls (perspective, window,
ortho, ortho2) will replace the projection matrix anyway.

Here is an example of a rotating infinite light source. The light is
made to rotate by binding while a rotation is part of the current matrix.
The light is only bound once.

Hope this helps.

-- howard.

/*
 * light_motion.c
 * Compile with
 * cc light_motion.c -o light_motion -lsphere -lgl_s -lm
 */

#include <gl/gl.h>
#include <gl/device.h>
#include <gl/sphere.h>

/* macro to count the number of properties in an array */
#define NP(array) ((sizeof(array)/(sizeof(array[0]))))

void initialize(void);
void drawscene(void);

/* size of the window */
int xmax, ymax;

/* different light positions */
#define EYE 1
#define WORLD 2
#define MOVING 3

int light_position = MOVING;
int moving_eye = FALSE;

float light_model[] =
{
	AMBIENT, 0.1, 0.1, 0.1,
	ATTENUATION, 1.0, 0.0,
	LOCALVIEWER, 0.0,
	LMNULL
};

float white_light[] =
{
	AMBIENT, 0.2, 0.2, 0.2,
	POSITION, 0.0, 0.0, 10.0, 0.0,
	LCOLOR, 1.0, 1.0, 1.0,
	LMNULL
};

float green_plastic[] =
{
	DIFFUSE, 0.1, 1.0, 0.1,
	SPECULAR, 1.0, 1.0, 1.0,
	SHININESS, 10.0,
	LMNULL
};
	
float yellow_plastic[] =
{
	DIFFUSE, 1.0, 1.0, 0.1,
	SPECULAR, 1.0, 1.0, 1.0,
	SHININESS, 10.0,
	LMNULL
};
	

void
main ()
{
	Boolean exitflag = FALSE;
    short attached=0;               /* attached to window */
    short value;                  
    int dev;                      /* input device */
	
    initialize();

    while (exitflag == FALSE)
    {
		drawscene();
		
		while ((exitflag == FALSE) && (qtest() || !attached))
		{
	    	dev = qread (&value);
	    	if ((dev == ESCKEY) && (value == 0))
	    	{
				exitflag = TRUE;
	    	}
	    	else if (dev == REDRAW)
	    	{
				reshapeviewport();
	    	}
	    	else if (dev == INPUTCHANGE)
			{
				attached = value;	
			}   /*  end while qtest or not attached  */
		}
	}   /*  end while (exitflag == FALSE)  */
	exit(0);
}   /*  end main()  */


void
initialize(void)
{
    int gid;
	
    xmax = getgdesc(GD_XPMAX);
    ymax = getgdesc(GD_YPMAX);
    prefposition( xmax/4, xmax*3/4, ymax/4, ymax*3/4 );
    gid = winopen ("light1");
    minsize (xmax/10, ymax/10);
    keepaspect (xmax, ymax);
    winconstraints();

	RGBmode();
	doublebuffer();
    gconfig ();

	zbuffer(TRUE);
	
	qdevice(ESCKEY);
	qenter(REDRAW,gid);

	/* double matrix mode since using lighting */
	mmode(MVIEWING);

	/* define the light model, light source, and material */
	lmdef(DEFLMODEL, 1, NP(light_model), light_model);
	lmdef(DEFLIGHT, 1, NP(white_light), white_light);
	lmdef(DEFMATERIAL, 1, NP(green_plastic), green_plastic);
	lmdef(DEFMATERIAL, 2, NP(yellow_plastic), yellow_plastic);

	/* bind the light model */
	lmbind(LMODEL, 1);
}


void
drawscene(void)
{
	static int angle = 0;
	static float unit[] = {0.0,0.0,0.0,1.0};


    czclear(0x0, getgdesc(GD_ZMAX));

	perspective(450, (float)xmax/(float)ymax, 1.0, 10.0);

	/* Bound here, the light is positioned relative to the eye */
	if (light_position == EYE)
		lmbind(LIGHT0, 1);

    pushmatrix();
		if (moving_eye)
			polarview(5.0, angle, angle, 0);
		else
			polarview(5.0, 0, 0, 0);

		/* Bound here, the light is positioned relative to the world */
		if (light_position == WORLD)
			lmbind(LIGHT0, 1);

		if (light_position == MOVING)
		{
			pushmatrix();
				rotate(angle,'x');
				
				/* Bound here, the light rotates around the world x axis */
				lmbind(LIGHT0, 1);
			popmatrix();
		}
			
		pushmatrix();
			translate(-1.0, 0.0, 0.0);
			
			lmbind(MATERIAL,1);
			sphdraw(unit);
		popmatrix();
		
		pushmatrix();
			translate(1.0, 0.0, 0.0);
			
			lmbind(MATERIAL,2);
			sphdraw(unit);

			/* turn off material so later objects will not be lit */
			lmbind(MATERIAL,0);

		popmatrix();
	   
    popmatrix();
	
    swapbuffers();
	
    angle = angle + 20;
}



--
Howard Look   Silicon Graphics   howardl@sgi.com   (415) 335-1780
.__   One of these :) after being run over by one of these O-O

ringrose@fibula.ai.mit.edu (Robert Ringrose) (03/14/91)

In article <1991Mar13.062945.5092@odin.corp.sgi.com> howardl@sgi.com (Howard Look) writes:
>
>Using mmode(MPROJECTION) is not a usual thing to do.
No kidding, but is there another way to access the projection matrix so
you can go from points on the screen to points in world coordinates?

>Here is an example of a rotating infinite light source. The light is
>made to rotate by binding while a rotation is part of the current matrix.
>The light is only bound once.

[Example program deleted]

Howard:

I have taken your example program and made a few changes so that it
illustrates the bug I am running into.

As it is here, the lights do not move.  If, however, you uncomment the
line mmode(MPROJECTION), marked with a "+++" comment, the light source
begins to move, despite the fact that the very next line returns you
to MVIEWING mode.

Once again, I am running this on a Personal Iris 4D/25 and have no idea
if other SGI workstations have the same problem.


	- Robert Ringrose


"There's always one more bu6"
--------------- Cut here -------------------

/*
 * lights.c
 * Compile with
 * cc lights.c -o lights -lsphere -lgl_s -lm
 */

#include <gl/gl.h>
#include <gl/device.h>
#include <gl/sphere.h>

/* macro to count the number of properties in an array */
#define NP(array) ((sizeof(array)/(sizeof(array[0]))))

void initialize(void);
void drawscene(void);

/* size of the window */
int xmax, ymax;

/* different light positions */
#define EYE 1
#define WORLD 2
#define MOVING 3

int light_position = WORLD;
int moving_eye = FALSE;

float light_model[] =
{
	AMBIENT, 0.1, 0.1, 0.1,
	ATTENUATION, 1.0, 0.0,
	LOCALVIEWER, 0.0,
	LMNULL
};

float white_light[] =
{
	AMBIENT, 0.2, 0.2, 0.2,
	POSITION, 2.0, 2.0, -2.0, 0.0,
	LCOLOR, 1.0, 1.0, 1.0,
	LMNULL
};

float green_plastic[] =
{
	DIFFUSE, 0.1, 1.0, 0.1,
	SPECULAR, 1.0, 1.0, 1.0,
	SHININESS, 10.0,
	LMNULL
};
	
float yellow_plastic[] =
{
	DIFFUSE, 1.0, 1.0, 0.1,
	SPECULAR, 1.0, 1.0, 1.0,
	SHININESS, 10.0,
	LMNULL
};
	

void
main ()
{
	Boolean exitflag = FALSE;
    short attached=0;               /* attached to window */
    short value;                  
    int dev;                      /* input device */
	
    initialize();

    while (exitflag == FALSE)
      {
	drawscene();
		
	while ((exitflag == FALSE) && (qtest() || !attached))
	  {
	    dev = qread (&value);
	    if ((dev == ESCKEY) && (value == 0))
	      {
		exitflag = TRUE;
	      }
	    else if (dev == REDRAW)
	      {
		reshapeviewport();
	      }
	    else if (dev == INPUTCHANGE)
	      {
		attached = value;	
	      }   /*  end while qtest or not attached  */
	  }
      }   
    exit(0);
}   /*  end main()  */


void
initialize(void)
{
    int gid;
	
    xmax = getgdesc(GD_XPMAX);
    ymax = getgdesc(GD_YPMAX);
    prefposition( xmax/4, xmax*3/4, ymax/4, ymax*3/4 );
    gid = winopen ("light1");
    minsize (xmax/10, ymax/10);
    keepaspect (xmax, ymax);
    winconstraints();

	RGBmode();
	doublebuffer();
    gconfig ();

	zbuffer(TRUE);
	
	qdevice(ESCKEY);
	qenter(REDRAW,gid);

	/* double matrix mode since using lighting */
	mmode(MVIEWING);

	/* define the light model, light source, and material */
	lmdef(DEFLMODEL, 1, NP(light_model), light_model);
	lmdef(DEFLIGHT, 1, NP(white_light), white_light);
	lmdef(DEFMATERIAL, 1, NP(green_plastic), green_plastic);
	lmdef(DEFMATERIAL, 2, NP(yellow_plastic), yellow_plastic);

	/* bind the light model */
	lmbind(LMODEL, 1);
}


void
drawscene(void)
{
  static int angle = 0;
  static float unit[] = {0.0,0.0,0.0,1.0};


  czclear(0x0, getgdesc(GD_ZMAX));

  lmbind(LIGHT0, 1);

  pushmatrix();
  perspective(450, (float)xmax/(float)ymax, 1.0, 10.0);

  polarview(5.0, 0, 0, 0);

  rotate(-900, 'x');
/* +++ */
/*  mmode(MPROJECTION); */
  mmode(MVIEWING);

  pushmatrix();
  translate(-1.0, 0.0, 0.0);
  lmbind(MATERIAL,1);
  sphdraw(unit);
  popmatrix();
  
  pushmatrix();
  translate(1.0, 0.0, 0.0);
  
  lmbind(MATERIAL,2);
  sphdraw(unit);

  /* turn off material so later objects will not be lit */
  lmbind(MATERIAL,0);
  
  popmatrix();
	   
  popmatrix();
  
  swapbuffers();
}

nieswand@LISBOA.KS.UIUC.EDU (Benno Nieswand) (03/15/91)

Robert Ringrose writes:

> It works fine until I put in a call to a routine with the
> following code, part of an attempt to get the current
> projection and modelview matrices:
>
>
> mmode(MPROJECTION);
> mmode(MVIEWING);


I had similar problems and I worked on it for a long time. It's a  
while ago and I don't remember all the details but I discussed the  
problem with several people and tried almost every possibility to  
figure out the systematics behind the problem.
 I wanted to bind a light to the world coord frame and change  
projection and viewing. So I did mmode( MPERSPECTIVE) and change  
perspective() AND polarview() without changing the light binding  
then I did mmode(MVIEWING) again. This worked fine, as long as I  
didn't switch the light off and tried to rebind it. The new source  
direction(infinite far away, as supposed) was dependend on the last  
projection matrix before the rebind, in contrary to a determined  
relativ position to the world coord frame. I'm sure there is a bug.  
Another time I had the same problem Robert, so the source rotated.

If there is any solution, please let me know.
           Benno Nieswand