swtのlwjglサンプルをscala化して整理

http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet195.java?view=markup&content-type=text%2Fvnd.viewcvs-markup&revision=HEAD
scala化してswtOpenGLを分離してみた

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout;
import org.eclipse.swt.widgets;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;


object Snippet195 {
  def main(args: Array[String]) {
    val display = new widgets.Display();
    val shell = new widgets.Shell(display);
    shell.setLayout(new layout.FillLayout());
    shell.setText("SWT/LWJGL Example");
    shell.setSize(640, 480);
    val comp = new widgets.Composite(shell, SWT.NONE);
    comp.setLayout(new layout.FillLayout());
    val data = new GLData ();
    data.doubleBuffer = true;
    val canvas = new GLCanvas(comp, SWT.NONE, data);

    val gl=new GLController;

    canvas.setCurrent();
    gl.useContext(canvas)
    gl.initialize()

    canvas.addListener(SWT.Resize, new widgets.Listener() {
        def handleEvent(event: widgets.Event) {
          val bounds = canvas.getBounds();
          canvas.setCurrent();
          gl.useContext(canvas)
          gl.resize(bounds.width, bounds.height);
        }
      });

    display.asyncExec(new Runnable() {
        def run() {
          if (!canvas.isDisposed()) {
            canvas.setCurrent();
            gl.useContext(canvas)
            gl.update();
            gl.draw()
            canvas.swapBuffers();
            display.asyncExec(this);
          }
        }
      });

    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()){
        display.sleep();
      }
    }
    display.dispose();
  }
}

display.asyncExecでアニメーションさせている。
逆にアニメーションさせない場合は、ループで画面更新するはずだけどどうするのだろう・・・

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GLContext;


class RotateView(fovy: Float, near: Float, far: Float) {
  var rot = 0.0f;
  var fAspect=1.0f;

  def resize(w: Int, h: Int){
    fAspect = w.toFloat / h.toFloat;
  }

  def update(){
    rot+=1;
  }

  def draw(){
    // projection
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(fovy, fAspect, near, far);
    // position
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    GL11.glTranslatef(0.0f, 0.0f, -10.0f);
    GL11.glRotatef(0.15f * rot, 2.0f * rot, 10.0f * rot, 1.0f);
    GL11.glRotatef(0.3f * rot, 3.0f * rot, 1.0f * rot, 1.0f);
  }
}


class GLController {

  val view=new RotateView(45.0f, 0.5f, 400.0f);
  val scene=List(new Torus(1, 1.9f, 15, 15));

  def initialize(){
    GL11.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    GL11.glColor3f(1.0f, 0.0f, 0.0f);
    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
    GL11.glClearDepth(1.0);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
  }

  def useContext(context: Object){
    try {
      GLContext.useContext(context);
    } catch {
      case e: LWJGLException => e.printStackTrace();
    }
  }

  def resize(w: Int, h: Int){
    GL11.glViewport(0, 0, w, h);
    view.resize(w, h)
  }

  def update() {
    view.update()
    for(drawable <- scene){
      drawable.update()
    }
  }

  def draw() {
    // clear
    GL11.glClearColor(.3f, .5f, .8f, 1.0f);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    // view
    view.draw()
    // draw scene
    for(drawable <- scene){
      drawable.draw()
    }
  }
}
import org.lwjgl.opengl.GL11;


class Torus(r: Float, baseR: Float, nsides: Int, rings: Int){

  var rot=0;
  var R=baseR;

  def update(){
    R=baseR+math.sin((0.004f * rot)).toFloat
    rot+=1;
  }

  def draw() {
    GL11.glLineWidth(2);
    GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
    GL11.glColor3f(0.9f, 0.9f, 0.9f);
    val ringDelta = 2.0f * math.Pi.toFloat / rings;
    val sideDelta = 2.0f * math.Pi.toFloat / nsides;
    var theta = 0.0f;
    var cosTheta = 1.0f;
    var sinTheta = 0.0f;
    for(i <- 0 until rings){
      val theta1 = theta + ringDelta;
      val cosTheta1 = math.cos(theta1).toFloat;
      val sinTheta1 = math.sin(theta1).toFloat;
      GL11.glBegin(GL11.GL_QUAD_STRIP);
      var phi = 0.0f;
      for (j <- 0 to nsides) {
        phi += sideDelta;
        val cosPhi = math.cos(phi).toFloat;
        val sinPhi = math.sin(phi).toFloat;
        val dist = R + r * cosPhi;
        GL11.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
        GL11.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
        GL11.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
        GL11.glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
      }
      GL11.glEnd();
      theta = theta1;
      cosTheta = cosTheta1;
      sinTheta = sinTheta1;
    }
  }
}