2005.02.02

Mac で Java な覚え書き

その1: アプリケーションメニューのタイトルを変更する。

 System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Hoge Hoge");
 もしくは、起動時のオプション -Xdock:name="Hoge Hoge" で。
 ちなみに16文字以内という制限あり。

その2: メタルっぽい Look&Feel にしちゃう。

 System.setProperty("apple.awt.brushMetalLook", "true");

その3: 右下のリサイズのつまみの箇所のギザギザを消す。

 System.setProperty("apple.awt.showGrowBox", "false");

| | コメント (3) | トラックバック (0)

2005.01.09

TeBaSaKi

もちょい更新

デモ用にここのネタ&画像をまんま無承諾で拝借。
訴えられるかの?
ま、「おまえのものはおれのもの、おれのものはおれのもの」
ってジャイアンも言ってたから、いっか。

| | コメント (1) | トラックバック (0)

2005.01.02

TeBaSaKi

おいておこ。
ここ
何ソレ?って言われても、そんなもん、としか言いようが。。
とりあえず自分で使えればいいレベルなので、いいのじゃ。

| | コメント (6) | トラックバック (0)

2004.07.04

WonderSwan で Java Communications API してみる逃避

なんか最近、ひきまくりなネタばっかなので、たまにはコード書くヵ・・・

なわけで、WonderSwan を使ってぐるぐる 3D の中を歩き回るものを作ってみる。
詳細は、以下の図を見て理解してくんなまし。

分かりやすい図

用意するもの:

・WonderSwan
・WonderWitch
・Java Communications API
・サンプルコードに WonderSwan 使って 3D の中をぐるぐるするので JOGL

WonderSwan とのやりとりは WonderSwan.java にまとめた。
なんか名前、勝手に witchlet なんてつけてるし。

/*
* @(#)WonderSwan.java        $Revision:$
*
* Copyright (C) 2004 Samuuo. All rights reserved.
* $Id:$
*/
package samuuo.witchlet;

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.CommPortOwnershipListener;
import javax.comm.NoSuchPortException;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

/**
* WonderSwan
*
* @author  Samuuo
* @version $Revision:$
*/
public class WonderSwan
        implements CommPortOwnershipListener, SerialPortEventListener {
    /** CommPortIdentifier */
    private CommPortIdentifier commPortId;

    /** SerialPort */
    private SerialPort serialPort;

    /** The parameters of the serial port */
    protected SerialParameters parameters;

    /** Timeout for opening the serial port */
    protected int serialPortOpenTimeout;

    /** Timeout for receiving the data from the serial port */
    protected int serialPortReceiveTimeout;

    /** Serial Port Output Stream */
    protected OutputStream out;

    /** Serial Port Input Stream */
    protected InputStream in;

    /** WonderSwan's key listeners */
    protected List listeners = new ArrayList(1);

    /** The flag of the START key of the WonderSwan */
    public static final int KEY_START  = 0x002;

    /** The flag of the A key of the WonderSwan */
    public static final int KEY_A      = 0x004;

    /** The flag of the B key of the WonderSwan */
    public static final int KEY_B      = 0x008;

    /** The flag of the X1 key of the WonderSwan */
    public static final int KEY_UP1    = 0x010;

    /** The flag of the X2 key of the WonderSwan */
    public static final int KEY_RIGHT1 = 0x020;

    /** The flag of the X3 key of the WonderSwan */
    public static final int KEY_DOWN1  = 0x040;

    /** The flag of the X4 key of the WonderSwan */
    public static final int KEY_LEFT1  = 0x080;

    /** The flag of the Y1 key of the WonderSwan */
    public static final int KEY_UP2    = 0x100;

    /** The flag of the Y2 key of the WonderSwan */
    public static final int KEY_RIGHT2 = 0x200;

    /** The flag of the Y3 key of the WonderSwan */
    public static final int KEY_DOWN2  = 0x400;

    /** The flag of the Y4 key of the WonderSwan */
    public static final int KEY_LEFT2  = 0x800;

    /** The flag of the X1 key of the WonderSwan */
    public static final int KEY_X1 = KEY_UP1;

    /** The flag of the X2 key of the WonderSwan */
    public static final int KEY_X2 = KEY_RIGHT1;

    /** The flag of the X3 key of the WonderSwan */
    public static final int KEY_X3 = KEY_DOWN1;

    /** The flag of the X4 key of the WonderSwan */
    public static final int KEY_X4 = KEY_LEFT1;

    /** The flag of the Y1 key of the WonderSwan */
    public static final int KEY_Y1 = KEY_UP2;

    /** The flag of the Y2 key of the WonderSwan */
    public static final int KEY_Y2 = KEY_RIGHT2;

    /** The flag of the Y3 key of the WonderSwan */
    public static final int KEY_Y3 = KEY_DOWN2;

    /** The flag of the Y4 key of the WonderSwan */
    public static final int KEY_Y4 = KEY_LEFT2;

    /** Default timeout for opening the serial port */
    private static final int DEFAULT_SERIAL_PORT_OPEN_TIMEOUT = 30000;

    /** Default timeout for receiving the data from the serial port */
    private static final int DEFAULT_SERIAL_PORT_RECEIVE_TIMEOUT = 30;

    /**
     * Constructor.
     *
     * @param props The parameters of the serial port
     */
    public WonderSwan(Properties props) {
        this(new SerialParameters(props));
    }

    /**
     * Constructor.
     *
     * @param parameters The parameters of the serial port
     */
    public WonderSwan(SerialParameters parameters) {
        this.parameters = parameters;
        serialPortOpenTimeout = DEFAULT_SERIAL_PORT_OPEN_TIMEOUT;
        serialPortReceiveTimeout = DEFAULT_SERIAL_PORT_RECEIVE_TIMEOUT;
    }

    /**
     * Opens the serial port.
     *
     * @exception WonderSwanException if some kind of exception is occurred.
     */
    public synchronized void open() throws WonderSwanException {
        try {
            if (serialPort != null) {
                throw new WonderSwanException("already opened");
            }
            commPortId =
                CommPortIdentifier.getPortIdentifier(parameters.getPortName());
            serialPort = (SerialPort)commPortId.open(
                "witchlet", serialPortOpenTimeout);
            serialPort.setSerialPortParams(parameters.getBaudRate(),
                parameters.getDatabits(), parameters.getStopbits(),
                parameters.getParity());
            serialPort.setFlowControlMode(parameters.getFlowControlIn() |
                parameters.getFlowControlOut());
            out = serialPort.getOutputStream();
            in = serialPort.getInputStream();
            serialPort.addEventListener(this);
            serialPort.notifyOnDataAvailable(true);
            serialPort.notifyOnBreakInterrupt(true);
            serialPort.enableReceiveTimeout(serialPortReceiveTimeout);
            commPortId.addPortOwnershipListener(this);
        } catch (NoSuchPortException e) {
            throw new WonderSwanException(e);
        } catch (PortInUseException e) {
            throw new WonderSwanException(e);
        } catch (UnsupportedCommOperationException e) {
            close();
            throw new WonderSwanException(e);
        } catch (IOException e) {
            close();
            throw new WonderSwanException(e);
        } catch (TooManyListenersException e) {
            close();
            throw new WonderSwanException(e);
        }
    }

    /**
     * Closes the serial port.
     */
    public synchronized void close() {
        try {
            if (out != null) {
                out.close();
                out = null;
            }
            if (in != null) {
                in.close();
                in = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serialPort != null) {
                serialPort.close();
                serialPort = null;
            }
            if (commPortId != null) {
                commPortId.removePortOwnershipListener(this);
            }
        }
    }

    /**
     * Checks whether the serial port is opened or not.
     *
     * @return true if the serial port is opened.
     */
    public boolean isOpen() {
        return serialPort != null;
    }

    /**
     * Sends break to the serial port.
     */
    public void sendBreak() {
        if (serialPort != null) {
            serialPort.sendBreak(1000);
        }
    }

    /**
     * Adds the specified WonderSwanListener.
     *
     * @param listener WonderSwanListener
     */
    public void addWonderSwanKeyListener(WonderSwanListener listener) {
        synchronized (listeners) {
            listeners.add(listener);
        }
    }

    /**
     * Removes the specified WonderSwanListener.
     *
     * @param listener WonderSwanListener
     */
    public void removeWonderSwanKeyListener(WonderSwanListener listener) {
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }

    /**
     * Propagates a SerialPortEvent event.
     *
     * @param event the event from the serial port
     */
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
        case SerialPortEvent.DATA_AVAILABLE:
            try {
                int c1;
                int c2;
                while ((c1 = in.read()) != -1 && (c2 = in.read()) != -1) {
                    for (int i = 0; i < listeners.size(); i++) {
                        ((WonderSwanListener)listeners.get(i)).keyPressed(
                            c2 << 8 | c1);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        case SerialPortEvent.BI:
            // ignore for the time being
            break;
        }
    }

    /**
     * Propagates a CommPortOwnership event.
     *
     * @param type the chenged type
     */
    public void ownershipChange(int type) {
        if (type == CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED) {
            // what should i do?
        }
    }
}

その他適当に用意したクラスは以下。

/*
* @(#)WonderSwanListener.java        $Revision:$
*
* Copyright (C) 2004 Samuuo. All rights reserved.
* $Id:$
*/
package samuuo.witchlet;

/**
* WonderSwanListener
*
* @author  Samuuo
* @version $Revision:$
*/
public interface WonderSwanListener {
    /**
     * Pressed the keys of the WonderSwan.
     *
     * @param key The status of the keys.
     */
    void keyPressed(int key);
}

/*
* @(#)WonderSwanException.java        $Revision:$
*
* Copyright (C) 2004 Samuuo. All rights reserved.
* $Id:$
*/
package samuuo.witchlet;

/**
* WonderSwanException
*
* @author  Samuuo
* @version $Revision:$
*/
public class WonderSwanException extends Exception {
    /** The target exception */
    private Throwable target;

    /**
     * Constructor.
     */
    public WonderSwanException() {
        super();
    }

    /**
     * Constructor.
     *
     * @param target The target exception
     */
    public WonderSwanException(Throwable target) {
        super();
        this.target = target;
    }

    /**
     * Constructor.
     *
     * @param s The detail message
     */
    public WonderSwanException(String s) {
        super(s);
    }

    /**
     * Constructor.
     *
     * @param target The target exception
     * @param s The detail message
     */
    public WonderSwanException(Throwable target, String s) {
        super(s);
        this.target = target;
    }

    /**
     * Gets the target exception.
     *
     * @return The target exception
     */
    public Throwable getTargetException() {
        return target;
    }
}

/*
* @(#)SerialParameters.java        $Revision:$
*
* Copyright (C) 2004 Samuuo. All rights reserved.
* $Id:$
*/
package samuuo.witchlet;

import java.util.Properties;
import javax.comm.SerialPort;

/**
* SerialParameters
*
* @author  Samuuo
* @version $Revision:$
*/
public class SerialParameters {
    /** The name of the port */
    private String portName;

    /** The baud rate */
    private int baudRate;

    /** Type of flow control for receiving */
    private int flowControlIn;

    /** Type of flow control for sending */
    private int flowControlOut;

    /** The number of data bits */
    private int databits;

    /** The number of stop bits */
    private int stopbits;

    /** The type of parity */
    private int parity;

    /** The baud rate: 9600 */
    public static final int BAUD_RATE_9600  = 9600;

    /** The baud rate: 38400 */
    public static final int BAUD_RATE_38400 = 38400;

    /**
     * Constructor.
     */
    public SerialParameters () {
        this("", BAUD_RATE_38400,
            SerialPort.FLOWCONTROL_NONE, SerialPort.FLOWCONTROL_NONE,
            SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
            SerialPort.PARITY_NONE);
    }

    /**
     * Constructs a instance from a property file.
     *
     * The properties specification:
     * serial.portname: The name of the port
     * serial.baudrate: The baud rate
     * serial.flowcontrol.in: Type of flow control for receiving
     * srial.flowcontrol.out: Type of flow control for sending
     * serial.databits: The number of data bits
     * serial.stopbits: The number of stop bits
     * serial.parity: The type of parity
     *
     * @param props The parameters of the serial port
     */
    public SerialParameters(Properties props) {
        setPortName(props.getProperty("serial.portname"));
        setBaudRate(Integer.parseInt(props.getProperty("serial.baudrate")));
        setFlowControlIn(props.getProperty("serial.flowcontrol.in"));
        setFlowControlOut(props.getProperty("srial.flowcontrol.out"));
        setDatabits(Integer.parseInt(props.getProperty("serial.databits")));
        setStopbits(props.getProperty("serial.stopbits"));
        setParity(props.getProperty("serial.parity"));
    }

    /**
     * Constructor.
     *
     * @param portName The name of the port
     * @param baudRate The baud rate
     * @param flowControlIn Type of flow control for receiving
     * @param flowControlOut Type of flow control for sending
     * @param databits The number of data bits
     * @param stopbits The number of stop bits
     * @param parity The type of parity
     */
    public SerialParameters(String portName, int baudRate,
            int flowControlIn, int flowControlOut,
            int databits, int stopbits, int parity) {
            this.portName = portName;
            this.baudRate = baudRate;
            this.flowControlIn = flowControlIn;
            this.flowControlOut = flowControlOut;
            this.databits = databits;
            this.stopbits = stopbits;
            this.parity = parity;
    }

    public void setPortName(String portName) {
        this.portName = portName;
    }

    public String getPortName() {
        return portName;
    }

    public void setBaudRate(int baudRate) {
        if (baudRate != BAUD_RATE_9600 && baudRate != BAUD_RATE_38400) {
            throw new IllegalArgumentException("Bad baud rate " + baudRate);
        }
        this.baudRate = baudRate;
    }

    public int getBaudRate() {
        return baudRate;
    }

    public void setFlowControlIn(int flowControlIn) {
        if (!isValidFlowControl(flowControlIn)) {
            throw new IllegalArgumentException(
                "Bad flow control in: " + flowControlIn);
        }
        this.flowControlIn = flowControlIn;
    }

    public void setFlowControlIn(String flowControlIn) {
        this.flowControlIn = stringToFlow(flowControlIn);
    }

    public int getFlowControlIn() {
        return flowControlIn;
    }

    public String getFlowControlInString() {
        return flowToString(flowControlIn);
    }

    public void setFlowControlOut(int flowControlOut) {
        if (!isValidFlowControl(flowControlOut)) {
            throw new IllegalArgumentException(
                "Bad flow control out: " + flowControlOut);
        }
        this.flowControlOut = flowControlOut;
    }

    public void setFlowControlOut(String flowControlOut) {
        this.flowControlOut = stringToFlow(flowControlOut);
    }

    public int getFlowControlOut() {
        return flowControlOut;
    }

    public String getFlowControlOutString() {
        return flowToString(flowControlOut);
    }

    private boolean isValidFlowControl(int flowControl) {
        return flowControl == SerialPort.FLOWCONTROL_NONE ||
            flowControl == SerialPort.FLOWCONTROL_XONXOFF_OUT ||
            flowControl == SerialPort.FLOWCONTROL_XONXOFF_IN ||
            flowControl == SerialPort.FLOWCONTROL_RTSCTS_IN ||
            flowControl == SerialPort.FLOWCONTROL_RTSCTS_OUT;
    }

    public void setDatabits(int databits) {
        if (databits != SerialPort.DATABITS_5 &&
            databits != SerialPort.DATABITS_6 &&
            databits != SerialPort.DATABITS_7 &&
            databits != SerialPort.DATABITS_8) {
            throw new IllegalArgumentException("Bad data bits: " + databits);
        }
        this.databits = databits;
    }

    public int getDatabits() {
        return databits;
    }

    public void setStopbits(int stopbits) {
        if (stopbits != SerialPort.STOPBITS_1 &&
            stopbits != SerialPort.STOPBITS_1_5 &&
            stopbits != SerialPort.STOPBITS_2) {
            throw new IllegalArgumentException("Bad stop bits: " + stopbits);
        }
        this.stopbits = stopbits;
    }

    public void setStopbits(String stopbits) {
        if (stopbits.equals("1")) {
            this.stopbits = SerialPort.STOPBITS_1;
        } else if (stopbits.equals("1.5")) {
            this.stopbits = SerialPort.STOPBITS_1_5;
        } else if (stopbits.equals("2")) {
            this.stopbits = SerialPort.STOPBITS_2;
        } else {
            throw new IllegalArgumentException("Bad stop bits: " + stopbits);
        }
    }

    public int getStopbits() {
        return stopbits;
    }

    public String getStopbitsString() {
        switch (stopbits) {
        case SerialPort.STOPBITS_1:
            return "1";
        case SerialPort.STOPBITS_1_5:
            return "1.5";
        case SerialPort.STOPBITS_2:
            return "2";
        default:
            return null;
        }
    }

    public void setParity(int parity) {
        if (parity != SerialPort.PARITY_NONE &&
            parity != SerialPort.PARITY_EVEN &&
            parity != SerialPort.PARITY_ODD) {
            throw new IllegalArgumentException("Bad parity: " + parity);
        }
        this.parity = parity;
    }

    public void setParity(String parity) {
        if (parity.equals("None")) {
            this.parity = SerialPort.PARITY_NONE;
        } else if (parity.equals("Even")) {
            this.parity = SerialPort.PARITY_EVEN;
        } else if (parity.equals("Odd")) {
            this.parity = SerialPort.PARITY_ODD;
        } else {
            throw new IllegalArgumentException("Bad parity: " + parity);
        }
    }

    public int getParity() {
        return parity;
    }

    public String getParityString() {
        switch (parity) {
        case SerialPort.PARITY_NONE:
            return "None";
        case SerialPort.PARITY_EVEN:
            return "Even";
        case SerialPort.PARITY_ODD:
            return "Odd";
        default:
            return null;
        }
    }

    public static int stringToFlow(String flowControl) {
        if (flowControl.equals("None")) {
            return SerialPort.FLOWCONTROL_NONE;
        } else if (flowControl.equals("Xon/Xoff Out")) {
            return SerialPort.FLOWCONTROL_XONXOFF_OUT;
        } else if (flowControl.equals("Xon/Xoff In")) {
            return SerialPort.FLOWCONTROL_XONXOFF_IN;
        } else if (flowControl.equals("RTS/CTS In")) {
            return SerialPort.FLOWCONTROL_RTSCTS_IN;
        } else if (flowControl.equals("RTS/CTS Out")) {
            return SerialPort.FLOWCONTROL_RTSCTS_OUT;
        }
        throw new IllegalArgumentException("Bad flow control: " + flowControl);
    }

    public static String flowToString(int flowControl) {
        switch (flowControl) {
        case SerialPort.FLOWCONTROL_NONE:
            return "None";
        case SerialPort.FLOWCONTROL_XONXOFF_OUT:
            return "Xon/Xoff Out";
        case SerialPort.FLOWCONTROL_XONXOFF_IN:
            return "Xon/Xoff In";
        case SerialPort.FLOWCONTROL_RTSCTS_IN:
            return "RTS/CTS In";
        case SerialPort.FLOWCONTROL_RTSCTS_OUT:
            return "RTS/CTS Out";
        }
        throw new IllegalArgumentException("Bad flow control: " + flowControl);
    }
}

以上のものたちを使った 3D ぐるぐるするサンプルコード。

import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.nio.*;
import java.util.*;
import javax.imageio.ImageIO;
import net.java.games.jogl.*;
import samuuo.witchlet.*;

public class Yaa extends Frame implements GLEventListener, WonderSwanListener {
    private WonderSwan wonderSwan;
    private Animator animator;
    private int textureName;
    private double eyex = 0.0;
    private double eyey = 10.0;
    private double eyez = 2.0;
    private double centerY = -500.0;
    private float rotate;
    private double sinr;
    private double cosr = 1.0;

    private static final float MAP_WIDTH  = 300.0f;
    private static final float MAP_HEIGHT = 300.0f;

    public Yaa(Properties props) throws Exception {
        super("やあ");

        wonderSwan = new WonderSwan(props);

        GLCapabilities glc = new GLCapabilities();

        Button openButton = new Button("Open");
        openButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                open();
            }
        });
        Button closeButton = new Button("Close");
        closeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                close();
            }
        });
        Panel buttonPanel = new Panel(new FlowLayout());
        buttonPanel.add(openButton);
        buttonPanel.add(closeButton);

        GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(glc);
        canvas.setSize(800, 600);
        canvas.addGLEventListener(this);

        setLayout(new BorderLayout());
        add(BorderLayout.CENTER, canvas);
        add(BorderLayout.SOUTH, buttonPanel);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                quit();
            }
        });
        pack();
        setVisible(true);

        animator = new Animator(canvas);
        animator.start();
    }

    private void open() {
        try {
            wonderSwan.open();
            wonderSwan.addWonderSwanKeyListener(this);
            System.out.println("Serial port has opened");
        } catch (WonderSwanException e) {
            if (e.getTargetException() != null) {
                e.getTargetException().printStackTrace();
            } else {
                e.printStackTrace();
            }
        }
    }

    private void close() {
        if (wonderSwan != null) {
            wonderSwan.removeWonderSwanKeyListener(this);
            wonderSwan.close();
            System.out.println("Serial port has closed");
        }
    }

    private void quit() {
        close();
        animator.stop();
        System.exit(0);
    }

    public void keyPressed(int key) {
        float rotate = this.rotate;
        double eyex = this.eyex;
        double eyey = this.eyey;
        double eyez = this.eyez;
        double centerY = this.centerY;
        double sinr = Math.sin(Math.PI * rotate);
        double cosr = Math.cos(Math.PI * rotate);
        boolean isFast = (key & WonderSwan.KEY_A) != 0;
        if ((key & WonderSwan.KEY_B) != 0) {
        }
        if ((key & WonderSwan.KEY_Y1) != 0) {
            eyey += 0.1;
        } else if ((key & WonderSwan.KEY_Y3) != 0) {
            eyey -= 0.1;
        }
        if ((key & WonderSwan.KEY_Y2) != 0) {
            centerY -= 4.0;
        } else if ((key & WonderSwan.KEY_Y4) != 0) {
            centerY += 4.0;
        }
        if ((key & WonderSwan.KEY_X1) != 0) {
            if (isFast) {
                eyex -= 0.4 * sinr;
                eyez -= 0.4 * cosr;
            } else {
                eyex -= 0.1 * sinr;
                eyez -= 0.1 * cosr;
            }
        } else if ((key & WonderSwan.KEY_X3) != 0) {
            if (isFast) {
                eyex += 0.4 * sinr;
                eyez += 0.4 * cosr;
            } else {
                eyex += 0.1 * sinr;
                eyez += 0.1 * cosr;
            }
        }
        if ((key & WonderSwan.KEY_X2) != 0) {
            rotate -= 0.01;
        } else if ((key & WonderSwan.KEY_X4) != 0) {
            rotate += 0.01;
        }
        this.rotate = rotate;
        this.sinr = Math.sin(Math.PI * rotate);
        this.cosr = Math.cos(Math.PI * rotate);
        if (eyex > MAP_WIDTH / 2) {
            eyex = MAP_WIDTH / 2;
        } else if (eyex < - MAP_WIDTH / 2) {
            eyex = - MAP_WIDTH / 2;
        }
        if (eyez > MAP_HEIGHT / 2) {
            eyez = MAP_HEIGHT / 2;
        } else if (eyez < - MAP_HEIGHT / 2) {
            eyez = - MAP_HEIGHT / 2;
        }
        this.eyex = eyex;
        this.eyey = eyey;
        this.eyez = eyez;
        this.centerY = centerY;
    }

    public void display(GLDrawable drawable) {
        GL gl = drawable.getGL();
        GLU glu = drawable.getGLU();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
        glu.gluLookAt(eyex, eyey, eyez,
            -1000 * sinr, centerY, -1000 * cosr, 0.0, 1.0, 0.0);
        if (textureName == 0) {
            try {
                prepareTexture(gl, "yaa.gif");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        gl.glBindTexture(GL.GL_TEXTURE_2D, textureName);
        gl.glBegin(GL.GL_QUADS);
        gl.glTexCoord2f(0.0f, 1.0f);
        gl.glVertex3f(-MAP_WIDTH / 2, 0.0f,  MAP_HEIGHT / 2);
        gl.glTexCoord2f(1.0f, 1.0f);
        gl.glVertex3f( MAP_WIDTH / 2, 0.0f,  MAP_HEIGHT / 2);
        gl.glTexCoord2f(1.0f, 0.0f);
        gl.glVertex3f( MAP_WIDTH / 2, 0.0f, -MAP_HEIGHT / 2);
        gl.glTexCoord2f(0.0f, 0.0f);
        gl.glVertex3f(-MAP_WIDTH / 2, 0.0f, -MAP_HEIGHT / 2);
        gl.glEnd();
        gl.glFlush();
    }

    public void displayChanged(
            GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }

    public void init(GLDrawable drawable) {
        GL gl = drawable.getGL();
        gl.glClearColor(0.0f, 0.4f, 0.75f, 1.0f);
        gl.glEnable(GL.GL_TEXTURE_2D);
        gl.glTexEnvf(
            GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
    }

    public void reshape(
            GLDrawable drawable, int x, int y, int width, int height) {
        GL gl = drawable.getGL();
        GLU glu = drawable.getGLU();
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(90, (double)width / height, 0.1, 30);
    }

    private static ColorModel GL_ALPHA_COLOR_MODEL = new ComponentColorModel(
        ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 },
        true, false, ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);

    private static ColorModel GL_COLOR_MODEL = new ComponentColorModel(
        ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 0 },
        false, false, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE);

    private void prepareTexture(GL gl, String name) throws Exception {
        BufferedImage image = ImageIO.read(Yaa.class.getResource('/' + name));
        int texWidth = 2;
        int texHeight = 2;
        while (texWidth < image.getWidth()) {
            texWidth *= 2;
        }
        while (texHeight < image.getHeight()) {
            texHeight *= 2;
        }
        BufferedImage texImage;
        int format;
        if (image.getColorModel().hasAlpha()) {
            WritableRaster raster = Raster.createInterleavedRaster(
                DataBuffer.TYPE_BYTE, texWidth, texHeight, 4, null);
            texImage = new BufferedImage(
                GL_ALPHA_COLOR_MODEL, raster, false, new Hashtable());
            format = GL.GL_RGBA;
        } else {
            WritableRaster raster = Raster.createInterleavedRaster(
                DataBuffer.TYPE_BYTE, texWidth, texHeight, 3, null);
            texImage = new BufferedImage(
                GL_COLOR_MODEL, raster, false, new Hashtable());
            format = GL.GL_RGB;
        }
        Graphics g = texImage.getGraphics();
        g.setColor(new Color(0.0f, 0.0f, 0.0f, 0.0f));
        g.fillRect(0, 0, texWidth, texHeight);
        g.drawImage(image, 0, 0, null);
        g.dispose();

        byte[] data =
            ((DataBufferByte)texImage.getRaster().getDataBuffer()).getData();
        texImage.flush();
        ByteBuffer imageBuffer = ByteBuffer.allocateDirect(data.length);
        imageBuffer.order(ByteOrder.nativeOrder());
        imageBuffer.put(data, 0, data.length);

        int[] tmp = new int[1];
        gl.glGenTextures(1, tmp);
        textureName = tmp[0];
        gl.glBindTexture(GL.GL_TEXTURE_2D, textureName);

        gl.glTexParameteri(
            GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
        gl.glTexParameteri(
            GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);

        gl.glTexParameteri(
            GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
        gl.glTexParameteri(
            GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);

        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA,
            image.getWidth(), image.getHeight(),
            0, format, GL.GL_UNSIGNED_BYTE, imageBuffer);
    }

    public static void main(String[] args) throws Exception {
        InputStream in = Yaa.class.getResourceAsStream("/witchlet.properties");
        Properties props = new Properties();
        props.load(in);
        in.close();
        Yaa applet = new Yaa(props);
    }
}

そんでもって、WonderWitch 上で動かすコード。
超テキトー。

/*
* @(#)witchlet.c        $Revision:$
*
* Copyright (C) 2004 Samuuo. All rights reserved.
* $Id:$
*/

#include <stdlib.h>
#include <sys/bios.h>

void exit()
{
    comm_close();
    bios_exit();
}

void main(int argc, char *argv[])
{
    int keys = KEY_UP1 | KEY_RIGHT1 | KEY_DOWN1 | KEY_LEFT1 |
               KEY_UP2 | KEY_RIGHT2 | KEY_DOWN2 | KEY_LEFT2 | KEY_A | KEY_B;
    int *key;
    int received;
    text_screen_init();
    text_put_string(0, 0, "Witchlet :P");
    text_put_string(0, 2, "SEND: ");
    text_put_string(0, 3, "RECV: ");
    comm_open();
    while (TRUE) {
        *key = key_press_check();
        if (*key == KEY_START) {
            break;
        } else if (*key & keys) {
            comm_send_block(key, 2);
            text_put_numeric(6, 2, 16, NUM_HEXA, *key);
        }
        received = comm_receive_with_timeout(0);
        text_put_numeric(6, 3, 16, NUM_HEXA, received);
        sys_wait(1);
    }
    exit();
}

シリアルポートのパラメータは、witchlet.properties に以下のように書いてみる。

# COM1, COM2...
serial.portname: COM1

# 9600, 38400
serial.baudrate: 9600

# "None", "Xon/Xoff Out", "Xon/Xoff In", "RTS/CTS In", "RTS/CTS Out"
serial.flowcontrol.in: None

# "None", "Xon/Xoff Out", "Xon/Xoff In", "RTS/CTS In", "RTS/CTS Out"
srial.flowcontrol.out: None

# 5, 6, 7, 8
serial.databits: 8

# 1, 1.5, 2
serial.stopbits: 1

# "None", "Even", "Odd"
serial.parity: None

以下が実行中の画面。
これだけ見ても、よくわからんけど、この画面の中をぐるぐるウォークスルーするわけで。
WonderSwan がコントローラーになるわけで、ちょっとは便利かもと。。

WonderSwan でぐるぐる

オチ、な~~~し -_-

| | コメント (4) | トラックバック (0)

2004.06.21

JOGL (Java Bindings for OpenGL) で 3D してみる逃避

なわけで、まずは材料から。
こちらの URL

  JOGL API Project: https://jogl.dev.java.net/

へ行って、以下の2つの JAR ファイルを拝借してきました。
あ。これは Windows な環境の場合ってことで。

  - jogl.jar
  - jogl-native-win32.jar

で、jogl-native-win32.jar を怪盗、ルパ~ンさ~んせぇ~~、じゃなくって解凍すると以下の2つの DLL ファイルがでてきました。

  - jogl.dll
  - jogl_cg.dll

で、結局 JOGL 使う際に必要なのは、以下の3つらしい。

  - jogl.jar
  - jogl.dll
  - jogl_cg.dll

Mac OSX で使う場合には、jogl-natives-macosx.jar を拝借してきて、それをやっぱり怪盗、ルパ~ンさ~んせぇ~~ (しつこい… -_-) 解凍して libjogl.jnilib を取り出します。
Mac OSX で JOGL するときに必要なのは、以下の2つになるらしい。

  - jogl.jar
  - libjogl.jnilib

で、このサイトにもパイナップル、じゃなくってサンプルはあるけど、Google で何か他のパイナップル (しつこい… -_-) サンプルのコードを物色してきました。
何書いてあるのかツッパリ、ゴルァ!じゃなくって、サッパリ分からんけど、とりあえずここにある GLTest.java を拝借~
何語じゃろ?
ドイチェ?
  http://wwwmath.uni-muenster.de/u/tr/ss04/cg/

ま、ともかく何書いてあるのか分からんので、勝手にコンパイル&実行~
おおお。三角錐と立方体がグルグル回ってまする。
#三角錐って漢字、知らんかった… -_-
ちなみに iBook G4 で動かしたほうがサクサク回る。
この辺は、グラフィックチップ次第?

JOGL (Java Bindings for OpenGL)

いい感じですなぁ。
なんかもう、描画は全て JOGL でやっちゃおうかなって思ってしまったりして。

この立方体や三角錐に iSight から Streaming してそれをテクスチャマッピングするのは、やっぱきついかな?
って、そんなことは、Java DeskTop System がやってるか?

あ。またオチなし… -_-

| | コメント (4) | トラックバック (0)

2004.06.20

iSight を監視カメラにしてみる逃避

簡易 HTTP Server 作って、そこにアクセスされると昨日の逃避ネタを使って iSight のキャプチャ画像を JPEG にして送るようにしただけなんだけど。。

外から家の LAN の iBook の簡易 HTTP Server にアクセスできるように、ルータのとあるポートが叩かれたら iBook のこのサーバを叩くように設定する必要があるというのは、いわずもがなで。
携帯画面を広く使うために 160x120 でキャプチャした画像を 120x160 に90度回転してっと。
まじめにやるならば、UserAgent 毎にサイズやフォーマットなどを変えるべきだけど、逃避なのでそんなことまではしまへん。
で、こんな感じに。

←携帯からアクセスして取得した画像 その1

携帯からアクセスして画像を取れているところを写そうとしたら、アクセス中の画面が…
はっ!そりゃ、そうか!と、あとで気づく… -_-

なわけで、急にブタさんが家に侵入してきても、このようにバッチリ映像で捕らえることができるかもしれませんなどとはやっぱり言いません… -_-

←携帯からアクセスして取得した画像 その2

さて、お買い物に行って、ふと、おうちに泥棒が入っていないかアクセスしてみると、なぜか反応がない…
こ、これはもしや、泥棒が iBook もろとも持ち去ったのか!?
と思いきや、家に帰るとすっかり iBook スリープしてやがりました… -_-
こんなアフォなことするより節電しろよ、と、言いたいらしい…

| | コメント (0) | トラックバック (0)

2004.06.19

iSight を Java でキャプチャしてみる逃避

用意したもの。
iBook G4 と iSight だけ。
もちろん iSight は FireWire とかいう口に差し込んでおく。と。
QuickTime for Java は、いつのまにやら入ってた。
で、コンパイルするとき、クラスパスに以下を追加してあげまする。
    /System/Library/Java/Extensions/QTJava.zip
ちなみに OS は Mac OSX 10.3.4 で、Java は 1.4.2_03 らしぃ。

なわけで、でけた。

Java で iSight

ついでに画面の隅に時間の経過を drawString してみた。
にしても、数回に1回しか、まともに動作してくんない…
Illegal instruction とか Segmentation fault って言われまくる。。
ま、逃避ネタなので、いいや。

QuickTime なコード部分はうっとうしいので、別クラスに分けました。
リソースの開放とか、めちゃ適当。
てかね、QuickTime for Java の JavaDoc、全然役に立たないことしか書いてない気がする。。
誰か直したり指摘してくれると、うれしいです。

あ。オチがなかった… -_-

とりあえず QuickTime for Java な部分のコードのみ。
あ。このコードで何かマシンに問題が発生しても責任は負えませんので、手からず、じゃなくって、あしからず~。

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import quicktime.QTRuntimeException;
import quicktime.QTRuntimeHandler;
import quicktime.QTSession;
import quicktime.qd.PixMap;
import quicktime.qd.QDConstants;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDRect;
import quicktime.std.StdQTConstants;
import quicktime.std.sg.SequenceGrabber;
import quicktime.std.sg.SGVideoChannel;
import quicktime.util.RawEncodedImage;

public class VideoCapture {
    private SequenceGrabber grabber;
    private SGVideoChannel channel;
    private RawEncodedImage rowEncodedImage;

    private int width;
    private int height;
    private int videoWidth;

    private int[] pixels;
    private BufferedImage image;
    private WritableRaster raster;

    public VideoCapture(int width, int height) throws Exception {
        this.width = width;
        this.height = height;
        try {
            QTSession.open();
            QDRect bounds = new QDRect(width, height);
            QDGraphics graphics = new QDGraphics(bounds);
            grabber = new SequenceGrabber();
            grabber.setGWorld(graphics, null);
            channel = new SGVideoChannel(grabber);
            channel.setBounds(bounds);
            channel.setUsage(StdQTConstants.seqGrabPreview);
            channel.settingsDialog();
            grabber.prepare(true, false);
            grabber.startPreview();
            PixMap pixMap = graphics.getPixMap();
            rowEncodedImage = pixMap.getPixelData();

            videoWidth = width + (rowEncodedImage.getRowBytes() - width * 4) / 4;
            pixels = new int[videoWidth * height];
            image = new BufferedImage(
                videoWidth, height, BufferedImage.TYPE_INT_RGB);
            raster = WritableRaster.createPackedRaster(DataBuffer.TYPE_INT,
                videoWidth, height,
                new int[] { 0x00ff0000, 0x0000ff00, 0x000000ff }, null);
            raster.setDataElements(0, 0, videoWidth, height, pixels);
            image.setData(raster);
            QTRuntimeException.registerHandler(new QTRuntimeHandler() {
                public void exceptionOccurred(
                        QTRuntimeException e, Object eGenerator,
                        String methodNameIfKnown, boolean unrecoverableFlag) {
                    System.out.println("what should i do?");
                }
            });
        } catch (Exception e) {
            QTSession.close();
            throw e;
        }
    }

    public void dispose() {
        try {
            grabber.stop();
            grabber.release();
            grabber.disposeChannel(channel);
            image.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            QTSession.close();
        }
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public int getVideoWidth() {
        return videoWidth;
    }

    public int getVideoHeight() {
        return height;
    }

    public void getNextPixels(int[] pixels) throws Exception {
        grabber.idle();
        rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
    }

    public Image getNextImage() throws Exception {
        grabber.idle();
        rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
        raster.setDataElements(0, 0, videoWidth, height, pixels);
        image.setData(raster);
        return image;
    }
}

追記:
メソッド getNextImage とか getNextPixels とかって言ってるけど、1個前?の状態が見えてるような気がする。。
ま、細かいおかしなところは、許してちょんまげ。
だて、QuickTime の API 全然ちゃんと分かってないし。。。

| | コメント (6) | トラックバック (1)

2004.06.15

Java で Shockwave Flash してみる逃避

ま、ようするに、Flash のコンテンツを Java で作ってみる逃避。
そんなわけで、こんなものがあった。

JavaSWF2 - A Java Toolkit for Macromedia Flash Parsing and Generation
http://www.anotherbigidea.com/javaswf/

なわけで、本日の成果: オチなし

だから、オチはまったくありません。
どこか1ドットをクリックすると何かが起こるかもということもありません。
てヵ、まだそんな難しいこと、やり方分からんし… -_-
サンプルのコードをちっといじくっただけだし。。
ほれ。ソースコード見ても、何にもオチはありません。

import java.io.FileInputStream;
import com.anotherbigidea.flash.movie.Font;
import com.anotherbigidea.flash.movie.FontLoader;
import com.anotherbigidea.flash.movie.Frame;
import com.anotherbigidea.flash.movie.ImageUtil;
import com.anotherbigidea.flash.movie.Instance;
import com.anotherbigidea.flash.movie.Movie;
import com.anotherbigidea.flash.movie.MovieClip;
import com.anotherbigidea.flash.movie.Shape;
import com.anotherbigidea.flash.movie.Text;
import com.anotherbigidea.flash.movie.Transform;
import com.anotherbigidea.flash.structs.Color;

public class Test {
    public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream( "test.jpg" );
        int[] size = new int[2];
        Shape image = ImageUtil.shapeForImage(in, size);
        int width = size[0];
        int height = size[1];
        in.close();

        image.defineLineStyle(1, null);
        image.setLineStyle(1);
        image.line(width, 0);
        image.line(width, height);
        image.line(0, height);
        image.line(0, 0);

        Font font = new Font(FontLoader.loadFont("VerdanaFont.swf"));
        Text text = new Text(null);
        text.row(font.chars("aya", 28), new Color(0, 0, 255), -100, 0, true, true);
        text.row(font.chars("yayaya", 20), new Color(0, 255, 0), 0, 0, false, false);

        MovieClip clip = new MovieClip();
        Frame frame = clip.appendFrame();
        Instance inst = frame.placeSymbol(text, 0, 0);

        for (int i = 2; i < 360; i += 2) {
            Transform matrix = new Transform(i * Math.PI / 180.0, 0.0, 0.0);
            frame = clip.appendFrame();
            frame.alter(inst, matrix, null);
        }

        Movie movie = new Movie();
        movie.setBackColor(new Color(255, 255, 0));
        frame = movie.appendFrame();
        frame.placeSymbol(image, 0, 0);
        frame.stop();

        frame.placeSymbol(clip, 100, 100);
        frame.placeSymbol(clip, 200, 100);

        movie.write("result.swf");
    }
}

各メソッドの意味とか引数、分からんまんまに叩いてるし。

そんなこんなで、Flash のコンテンツを作るのって、おそらく Macromedia のウン万円もするソフトを買って作るんだろうけど、これだとタダで作れちゃうね。
やったね!

なんつて。。
そんなにいろいろがんばらないといけないんだったら、ウン万円、出すわな… -_-

| | コメント (0) | トラックバック (0)

2004.06.14

Java Media Framework してみる逃避

本日は、JMF (Java Media Framework) で逃避。
てヵ、ダウンロードしてテストプログラムを実行しただけ…

JMF 2.1.1e には、なにやら以下の4種類があった。

・Windows Performance Pack
・Linux Performance Pack
・Solaris SPARC Performance Pack
・Cross-platform Java

手っ取り早く USB なカメラで逃避したかったので、Windows Performance Pack をば拝借。
ちなみに、サポートしてるフォーマットやデバイスはこちら。
http://java.sun.com/products/java-media/jmf/2.1.1/formats.html

Java Media Framework してみる逃避

ふむ。認識した。
おしまい… -_-

冷蔵庫にカメラを入れといて、外出先から自宅の冷蔵庫の中を携帯で確認できるアプリを作って逃避しようと思ったんだけど、そこまでの逃避力はなかった…
ほら、お買い物中に、「まだパックのお茶、残ってたっけ?納豆、まだ残ってたっけ?」というときに威力を発揮するかと思ったんだけど…

でね、冷蔵庫の中、真っ暗でなんも見えんじゃん。
という、全然オチになってないオチにしようかと… -_-

| | コメント (0) | トラックバック (0)

2004.06.13

QuickTime for Java してみる逃避

また逃避…

本日の逃避ネタは、QuickTime for Java で。
ソースコードは割愛。

できあがったムービーはこちら
  フォーマット: MOV
  サイズ: 53,874bytes
見ないほうがいいです。
ぇぇ。

オチ、なし。。 -_-

なにかっつーと、自分がキャンバスに描いたストロークを全部 MOV に録画しちゃう。
ただそんだけ…
逃避なので、細かい調整はしてまへん。

| | コメント (2) | トラックバック (0)

2004.06.12

Mac OSX で JNI してみる逃避

ちょっと、Mac OSX で JNI (Java Native Interface) ライブラリを作ってみる逃避おば。。

Obaka.java を作成する。

public class Obaka {
    static {
        System.loadLibrary("Obaka");
    }
    public native String getName();
    public native String getFavoriteFood();
    public native String execute(String command);
}

$ javac Obaka.java
→ Obaka.class ができる

$ javah -jni Obaka
→ Obaka.h ができる。

Obaka.cpp を作成しておもむろにコンパイル。

#include "Obaka.h"

JNIEXPORT jstring JNICALL Java_Obaka_getName
  (JNIEnv *env, jobject obj)
{
    return env->NewStringUTF("ayaya");
}

JNIEXPORT jstring JNICALL Java_Obaka_getFavoriteFood
  (JNIEnv *env, jobject obj)
{
    return env->NewStringUTF("ayaya");
}

JNIEXPORT jstring JNICALL Java_Obaka_execute
  (JNIEnv *env, jobject obj, jstring command)
{
    return env->NewStringUTF("ayaya");
}

$ g++ -dynamiclib -I/System/Library/Frameworks/JavaVM.framework/Versions/1.3.1/Headers/ Obaka.cpp -o libObaka.jnilib
→libObaka.jnilib ができる。

この Headers へのパスが、1.3.1 なのが、ちとおばか。
1.4.2 使ってるんだけど、なんか、無い… -_-
ほんとは
  /System/Library/Frameworks/JavaVM.framework/Headers
あたりを指定するんだろうけど。。

で、このライブラリを使うテストコードを書いて実行してみる。

public class Test {
    public static void main(String[] args) {
        Obaka obaka = new Obaka();
        System.out.println(obaka.getName());
        System.out.println(obaka.getFavoriteFood());
        System.out.println(obaka.execute("dance"));
    }
}

実行結果:
  $ javac Test.java
  $ java Test
  ayaya
  ayaya
  ayaya

何を聞いても何をやらせても、ayaya としか答えない JNI ライブラリの完成。

TIPS:
  libObaka.jnilib を適当なディレクトリに置いた場合は、DYLD_LIBRARY_PATH でパスを設定すればよい。

おわりに:
  拡張子は dylib ではなくって jnilib なので、ちとハマッた…
  逃避ネタ的には、ちょうどよかた… -_-


追記:
ADC にある Java 1.4.2 Developer Package に、無いと思われていたヘッダファイルがありそう。

追記2:
ヘッダファイル、これ↑にあった。

| | コメント (3) | トラックバック (0)