Identifisering
Børre Stenseth
Å tegne:>Bordlampe

En bordlampe

Hva
lamps
Demonstrasjon av spotlight og identfikasjon av objekter

denne modulen beskriver uttegning og manipulasjon av 4 enkle lamper på et bord.

Lampene er konstruerte med quadrics. Hver lampe hae 4 manipulerbare ledd, og alle bevegelser er musestyrte.

Struktur

Ei lampe består av sylindere (fot, 2 armer og lampeskjermen). Leddene er lage med kuler.

enlampe fig1

oneLamp

Lampene er plasserte på et rundt bord som ligger i xy-planet. En lampe er implementert i klassen oneLamp:

package tablelamp;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;
/**
 *
 * @author borres
 */
public class oneLamp 
{
    // nice to have
    private final float G2R=0.01745277777778f;
    private final float R2G=57.29577951308f;
    //id for lamp
    int m_LampID;    
    // the geometry of the lamp
    // length of the three arms
    int[] m_Arm={40,50,10};
    // angles for armposition:
    // thickness of arm
    int m_ArmW=3;
    // radius for spheres in elbows
    int m_ElbowRadius=6;
    // base board
    int m_BaseRadius=40;
    int m_BaseHeight=2;
    // lamps head
    float m_TopR=10;
    float m_OpenR=30;
    float m_HeadCyl=30;
    float m_HeadSpread=30;;
    
    // angles for each rotation
    float    m_v1=0.0f;
    float    m_v2=0.0f;
    float    m_v3=10.0f;
    float    m_v4=30.0f;
    
    // spot smoothness
    float m_SpotExp=0.0f;
    // quadric drawing precision
    int nLong=10;
    int nRound=20;
    // which lightsource
    int m_MyLight;
    boolean    m_LampIsOn=false;

    public oneLamp(int LampID)
    {

        m_MyLight=GL.GL_LIGHT0+LampID+1;
        m_LampID=LampID;
    }
    public void draw(GL gl)
    {
    GLU glu=new GLU();
    // preserve modelview
    gl.glPushMatrix();
    if(!m_LampIsOn)
        gl.glDisable(m_MyLight);
    // use a quadric to draw parts of lamp
    GLUquadric glpQ=glu.gluNewQuadric();
    // material
    int baseMaterial=stdMaterials.MAT_GREEN_PLASTIC;
    int elbowMaterial=stdMaterials.MAT_GREEN_PLASTIC;
    int armMaterial=stdMaterials.MAT_WARM_WHITE;
    // scale the integer coordinates down to unit box
    gl.glScalef(0.01f,0.01f,0.01f);
    // display the lamp
    // use lightsource as ID for lamp
    gl.glLoadName(m_LampID*10+0);
    // base, foot
    stdMaterials.setMaterial(gl,baseMaterial,GL.GL_FRONT);
    gl.glTranslatef(0.0f,0.0f,(float)-m_BaseHeight);
    glu.gluDisk(glpQ,0.0f,(float)m_BaseRadius,20,20);
    glu.gluCylinder(glpQ,(float)m_BaseRadius,(float)m_BaseRadius,
                         (float)m_BaseHeight,nRound,nLong);
    gl.glTranslatef(0.0f,0.0f,(float)m_BaseHeight);
    glu.gluDisk(glpQ,0,(float)m_BaseRadius,nRound,nRound);
    stdMaterials.setMaterial(gl,elbowMaterial,GL.GL_FRONT);
    glu.gluSphere(glpQ,(float)m_ElbowRadius,20,20);
    // first arm, basic orientation around z-axis
    gl.glLoadName(m_LampID*10+1);
    gl.glRotatef(m_v1,0.0f,0.0f,1.0f);
    // from now on all arms are rotated around y-axis
    gl.glRotatef(m_v2,0.0f,1.0f,0.0f);
    stdMaterials.setMaterial(gl,armMaterial,GL.GL_FRONT);
    glu.gluCylinder(glpQ,m_ArmW,m_ArmW,m_Arm[0],nRound,nLong);
    gl.glTranslatef(0.0f,0.0f,(float)m_Arm[0]);
    
    stdMaterials.setMaterial(gl,elbowMaterial,GL.GL_FRONT);
    glu.gluSphere(glpQ,m_ElbowRadius,nRound,nRound);
    // second arm
    gl.glLoadName(m_LampID*10+2);
    gl.glRotatef(m_v3,0.0f,1.0f,0.0f);
    stdMaterials.setMaterial(gl,armMaterial,GL.GL_FRONT);
    glu.gluCylinder(glpQ,m_ArmW,m_ArmW,m_Arm[1],nRound,nLong);
    gl.glTranslatef(0.0f,0.0f,(float)m_Arm[1]);
    stdMaterials.setMaterial(gl,elbowMaterial,GL.GL_FRONT);
    glu.gluSphere(glpQ,m_ElbowRadius,nRound,nRound);

    // head
    gl.glLoadName(m_LampID*10+3);
    gl.glTranslatef(0.0f,0.0f,(float)m_ElbowRadius);
    gl.glRotatef(m_v4,0.0f,1.0f,0.0f);
    gl.glTranslatef(0.0f,0.0f,(float)-m_HeadCyl/2.0f);
    stdMaterials.setMaterial(gl,elbowMaterial,GL.GL_FRONT);
    glu.gluDisk(glpQ,0.0,m_TopR,nRound,nRound);
    glu.gluCylinder(glpQ,m_TopR,m_TopR,m_HeadCyl,nRound,nLong);
    gl.glTranslatef(0.0f,0.0f,(float)m_HeadCyl);
    glu.gluCylinder(glpQ,m_TopR,m_OpenR,m_HeadSpread,nRound,nLong);
    //lighton
    // lightbulb and inner screen
    if(m_LampIsOn)
    {
        // light inside of head
        stdMaterials.setMaterial(gl,stdMaterials.MAT_BRIGHT_WHITE,GL.GL_FRONT);
        glu.gluCylinder(glpQ,m_TopR-0.1f,m_OpenR-0.1f,m_HeadSpread,nRound,nLong);
        
        // specify and set the spotlight
        float spambient[] =    {0.2f,0.2f,0.2f,1.0f };
        float spdiffuse[] =    {0.8f,0.8f,0.8f,1.0f };
        float spspecular[] =    {0.8f,0.8f,0.8f,1.0f };
        float spposition[] =    {0.0f,0.0f,0.0f,1.0f};
        float spdirection[] = {0.0f,0.0f,1.0f};
        float spotangle= R2G*(float)Math.atan((m_OpenR-m_TopR)/m_HeadSpread)+10;
        gl.glLightfv(m_MyLight, GL.GL_AMBIENT,        spambient,0);
        gl.glLightfv(m_MyLight, GL.GL_DIFFUSE,        spdiffuse,0);
        gl.glLightfv(m_MyLight, GL.GL_SPECULAR,        spspecular,0);
        gl.glLightfv(m_MyLight, GL.GL_POSITION,        spposition,0);
        gl.glLightfv(m_MyLight, GL.GL_SPOT_DIRECTION,    spdirection,0);
        gl.glLightf (m_MyLight, GL.GL_SPOT_CUTOFF,    spotangle);
        gl.glLightf(m_MyLight, GL.GL_SPOT_EXPONENT, m_SpotExp);
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(m_MyLight);
        // light the bulb
        float[] ev={1.0f,1.0f,1.0f};
        float[] nev={0.0f,0.0f,0.0f};
        gl.glMaterialfv(GL.GL_FRONT,GL.GL_EMISSION,ev,0);
        gl.glTranslatef(0.0f,0.0f,m_HeadSpread/5.0f);
        glu.gluSphere(glpQ,m_TopR,nRound,nRound);
        gl.glMaterialfv(GL.GL_FRONT,GL.GL_EMISSION,nev,0);
    }
    glu.gluSphere(glpQ,m_TopR,nRound,nRound);
   //eoflighton
    // finished with quadric, kill it
    glu.gluDeleteQuadric(glpQ);
    // reset matrix
    gl.glPopMatrix();
    }
    public float GetAngle(int ix)
    {
        switch(ix)
        {
        case 0: return m_v1;
        case 1:return m_v2;
        case 2:return m_v3;
        case 3:return m_v4;
        default: return 0.0f;
        }
    }
    public void SetAngle(int x,float v)
    {
        switch(x)
        {
        case 0:m_v1=v; break;
        case 1:m_v2=v; break;
        case 2:m_v3=v; break;
        case 3:m_v4=v; break;
        default: ;
        }
    }
    public void SetLightOn(boolean on){m_LampIsOn=on;}
    public boolean GetLightOn() {return m_LampIsOn;}
    public void setSpotExponent(int v) {m_SpotExp=v/10.0f;}
}

Rendering

Klassen GLrenderer kontrollerer uttegningen av scenen Lampene holdes i en Vector:

private Vector<oneLamp> pLamp

Methoden display administrerer uttegningen:

public void display(GLAutoDrawable drawable)
{
    GL gl = drawable.getGL();
    // Clear the color and depth buffers.
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
    if(m_pressed)// we have pressed right mousebutton
    {
        m_pressed=false;
        int n=pickSelected(m_thePanel.getGL(),m_lastX,m_lastY);
        if(n!=NO_OBJECT)
        {
            m_hilitedPart=n%10; // lamp part
            m_hilitedLamp=n/10; // lampindex
            m_bIsManipulating=true;
        }
        else
        {
            m_hilitedLamp=NO_OBJECT; // to make sure
        }            
    }
    DrawScene(gl);
}

Methoden DrawScene er slik:

private void DrawScene(GL gl)
{
    GLU glu=new GLU();
    // Set up for scene
    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glLoadIdentity();
    glu.gluLookAt(m_zx,m_zy,m_zz,   // eye
                0.0f,0.0f,0.0f,     // VRF
                0.0f,0.0f,1.0f);    // VUP
    // interactive movement
    // rotate around z-axis
    gl.glRotatef(m_zv,0.0f,0.0f,1.0f);
    // rotate around x-axis
    gl.glRotatef(m_xv,1.0f,0.0f,0.0f);
     // set a name;NO_OBJECT on anything irrelevant we draw
    gl.glLoadName(NO_OBJECT);
    GLUquadric glpQ=glu.gluNewQuadric();
    //----------------
    // draw table
    gl.glPushMatrix();
    gl.glTranslatef(0.0f, 0.0f, -0.01f);
    stdMaterials.setMaterial(gl, stdMaterials.MAT_EMERALD, GL.GL_FRONT_AND_BACK);
    glu.gluDisk(glpQ,0.0,2.0,table_res,table_res);
    gl.glPopMatrix();
    //-----------------
    // draw lamps
    // lamp 0
    gl.glPushMatrix();
    gl.glTranslatef(-1.0f,1.0f,0.0f);
    gl.glLoadName(0);
    pLamp.elementAt(0).draw(gl);
    gl.glPopMatrix();
    // lamp 1
    gl.glPushMatrix();
    gl.glTranslatef(1.0f,1.0f,0.0f);
    gl.glLoadName(1);
    pLamp.elementAt(1).draw(gl);
    gl.glPopMatrix();
    // lamp 2
    gl.glPushMatrix();
    gl.glTranslatef(1.0f,-1.0f,0.0f);
    gl.glLoadName(2);
    pLamp.elementAt(2).draw(gl);
    gl.glPopMatrix();
    // lamp 3
    gl.glPushMatrix();
    gl.glTranslatef(-1.0f,-1.0f,0.0f);
    gl.glLoadName(2);
    pLamp.elementAt(3).draw(gl);
    gl.glPopMatrix();
    // set a name on anything irrelevant we draw
    gl.glLoadName(NO_OBJECT);
    // finnish drawing
    gl.glFlush();
}

Navngivning

Vi vet at vi må identifisere, sette navn på, alle delene som skal kunne identifiseres ved når vi peker med musa. I dette tilfellet betyr det at vi må kunne identifisere hvar lampe og hver lampes del. Vi bruker en enkel strategi der lampene nummereres fra 0 og delene slik: 10*lamppnumber + partnumber. I DrawScene:

	// lamp 1
	gl.glPushMatrix();
	gl.glTranslatef(1.0f,1.0f,0.0f);
	gl.glLoadName(1);
	pLamp.elementAt(1).draw(gl);
	gl.glPopMatrix();
 

og i uttegning av hver lampe:

 	// first arm, basic orientation around z-axis
	gl.glLoadName(m_LampID*10+1);
	...
 

Mekanismen for å velger er lik den som er brukt i Identifikasjon og er implementert i metodepickSelected in GLRenderer.

Applet failed to run. No Java plug-in was found.

Lyssetting

Lyskontroll er en kombinasjon av tre effekter

  • Vi vil ha en spotlight som "passer" til lampeskjermen
  • Vi vil at lyspæra skal være lysende eller mørk
  • Vi vil at innsiden av lampeskjermen skal være lys eller mørk.
// lightbulb and inner screen
 if(m_LampIsOn)
 {
     // light inside of head
     stdMaterials.setMaterial(gl,stdMaterials.MAT_BRIGHT_WHITE,GL.GL_FRONT);
     glu.gluCylinder(glpQ,m_TopR-0.1f,m_OpenR-0.1f,m_HeadSpread,nRound,nLong);
     
     // specify and set the spotlight
     float spambient[] =    {0.2f,0.2f,0.2f,1.0f };
     float spdiffuse[] =    {0.8f,0.8f,0.8f,1.0f };
     float spspecular[] =    {0.8f,0.8f,0.8f,1.0f };
     float spposition[] =    {0.0f,0.0f,0.0f,1.0f};
     float spdirection[] = {0.0f,0.0f,1.0f};
     float spotangle= R2G*(float)Math.atan((m_OpenR-m_TopR)/m_HeadSpread)+10;
     gl.glLightfv(m_MyLight, GL.GL_AMBIENT,        spambient,0);
     gl.glLightfv(m_MyLight, GL.GL_DIFFUSE,        spdiffuse,0);
     gl.glLightfv(m_MyLight, GL.GL_SPECULAR,        spspecular,0);
     gl.glLightfv(m_MyLight, GL.GL_POSITION,        spposition,0);
     gl.glLightfv(m_MyLight, GL.GL_SPOT_DIRECTION,    spdirection,0);
     gl.glLightf (m_MyLight, GL.GL_SPOT_CUTOFF,    spotangle);
     gl.glLightf(m_MyLight, GL.GL_SPOT_EXPONENT, m_SpotExp);
     gl.glEnable(GL.GL_LIGHTING);
     gl.glEnable(m_MyLight);
     // light the bulb
     float[] ev={1.0f,1.0f,1.0f};
     float[] nev={0.0f,0.0f,0.0f};
     gl.glMaterialfv(GL.GL_FRONT,GL.GL_EMISSION,ev,0);
     gl.glTranslatef(0.0f,0.0f,m_HeadSpread/5.0f);
     glu.gluSphere(glpQ,m_TopR,nRound,nRound);
     gl.glMaterialfv(GL.GL_FRONT,GL.GL_EMISSION,nev,0);
 }
 glu.gluSphere(glpQ,m_TopR,nRound,nRound);

Merk at bruken av GL_SPOT_EXPONENT som glatter kantene på spoten. Kombinert med oppløsningen på bordplate (og de andre lampene) gir dette oss bra kontroll over spoten. Begge deler, spoteksponenten og oppløsningen på bordplate, kan manipuleres i programmet. Se ogsp Module Skygge og glatting

Referanser

Lamp (JOGL/Netbeans): https://svn.hiof.no/svn/psource/JOGL/lamp

Vedlikehold
B.Stenseth, modifisert mai 2010
(Velkommen) Å tegne:>Bordlampe (Trampoline)