0013-09-17

0013-09-17 - Nao_uの日記 を含むブックマーク 0013-09-17 - Nao_uの日記 のブックマークコメント

影とブーストエフェクト追加。結局パーティクルじゃなくてプリミティブを組み合わせた方が早そう、という結論に。手裏剣かゆいところに手が届かなくて嫌い

YEIから返答が。Unityのサンプル


using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;

public class cube_rotator : MonoBehaviour{
	// Connect to the serial port the 3-Space Sensor is connected to
	public static SerialPort sp = new SerialPort("\\\\.\\COM13");
	
	// Command packet for getting the filtered tared orientation as a quaternion
	// {header byte, command byte, [data bytes], checksum byte}
	// checksum = (command byte + data bytes) % 256
    public static byte[] send_bytes = {0xf7, 0x00, 0x00};
    public static byte[] button_bytes = {0xf7, 0xfa, 0xfa};
    public static byte[] tare_bytes = {0xf7, 0x60, 0x60};

    public int counter = 0;

	// Use this for initialization
	void Start(){
		// Allow the user to set the appropriate properties.
		sp.BaudRate = 115200;
		sp.Parity = Parity.None;
		sp.DataBits = 8;
		sp.StopBits = StopBits.One;
		
		// Set the read/write timeouts
		sp.WriteTimeout = 500;
		sp.ReadTimeout = 500;
		
		sp.Open();
		
		sp.Write(send_bytes,0,3);
	}
	
    // Helper function for taking the bytes read from the 3-Space Sensor and converting them into a float
	float bytesToFloat(byte[] raw_bytes, int offset){
		byte[] big_bytes = new byte[4];
		big_bytes[0] = raw_bytes[offset+3];
		big_bytes[1] = raw_bytes[offset+2];
		big_bytes[2] = raw_bytes[offset+1];
		big_bytes[3] = raw_bytes[offset+0];
		return BitConverter.ToSingle(big_bytes,0);
	}

    void getButtonState(){
        sp.Write(button_bytes, 0, 3);

        byte[] read_bytes = new byte[1];
        int fail_counter = 0;

        // Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
        // through to make sure the bytes are read
        while (true){
            try{
                sp.Read(read_bytes, 0, 1);
                break;
            }
            catch{
                ++fail_counter;
                // Failed to read from serial port
            }
            if (fail_counter > 100){
                throw new System.Exception("Failed to read from port too many times." +
                    " This could mean the port is not open or the Mono serial read is not responding.");
            }
        }

        if (read_bytes[0] == 0){
            print("No buttons are pressed.");
        }
        else if (read_bytes[0] == 1){
            print("Right button is pressed.");
        }
        else if (read_bytes[0] == 2){
            print("Left button is pressed.");
        }
        else if (read_bytes[0] == 3){
            print("Left and Right buttons are pressed.");
        }
    }

    void tareSensor(){
        sp.Write(tare_bytes, 0, 3);
    }

	// Update is called once per frame
	void Update(){
        counter++;
		// A quaternion consists of 4 floats which is 16 bytes
        byte[] read_bytes = new byte[16];

        // Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
        // through to make sure the bytes are read and Mono also seems not to always read the amount asked
        // so we must also read one byte at a time
        int read_counter = 100;
        int byte_idx = 0;
        while (read_counter > 0){
            try{
                byte_idx += sp.Read(read_bytes, byte_idx, 1);
            }
            catch{
                // Failed to read from serial port
            }
            if (byte_idx == 16){
                break;
            }
            if (read_counter <= 0){
                throw new System.Exception("Failed to read quaternion from port too many times." +
                    " This could mean the port is not open or the Mono serial read is not responding.");
            }
            --read_counter;
        }

		// Convert bytes to floats
		float x = bytesToFloat(read_bytes,0);
		float y = bytesToFloat(read_bytes,4);
		float z = bytesToFloat(read_bytes,8);
		float w = bytesToFloat(read_bytes,12);
		
		// Create a quaternion
		Quaternion quat = new Quaternion(x,y,z,w);
		
		// Perform rotation
        transform.rotation = quat;

        if ((counter % 25) == 0){
            getButtonState();
        }
        else if (counter > 150){
            tareSensor();
            counter = 1;
        }
		
		// Send command
		sp.Write(send_bytes,0,3);
	}
}

using UnityEngine;
using System;
using System.Collections;
using System.IO.Ports;

public class cube_rotator_wireless : MonoBehaviour{
    // Connect to the serial port the 3-Space Dongle is connected to
    public static SerialPort sp = new SerialPort("\\\\.\\COM3");

    // Wireless Command packet for getting the filtered tared orientation as
    // a quaternion
    // {header byte, id byte + command byte, [data bytes], checksum byte}
    // checksum = (id byte + command byte + data bytes) % 256
    public static byte[] send_bytes = {0xf8, 0x00, 0x00, 0x00};
    public static byte[] button_bytes = {0xf8, 0x00, 0xfa, 0xfa};
    public static byte[] tare_bytes = {0xf8, 0x00, 0x60, 0x60};

    public int counter = 0;

    // Use this for initialization
    void Start(){
        // Allow the user to set the appropriate properties.
        sp.BaudRate = 115200;
        sp.Parity = Parity.None;
        sp.DataBits = 8;
        sp.StopBits = StopBits.One;

        // Set the read/write timeouts
        sp.WriteTimeout = 500;
        sp.ReadTimeout = 5;

        sp.Open();

        sp.Write(send_bytes, 0, 4);
    }

    // Helper function for taking the bytes read from the 3-Space Sensor and
    // converting them into a float
    float bytesToFloat(byte[] raw_bytes, int offset){
        byte[] big_bytes = new byte[4];
        big_bytes[0] = raw_bytes[offset + 3];
        big_bytes[1] = raw_bytes[offset + 2];
        big_bytes[2] = raw_bytes[offset + 1];
        big_bytes[3] = raw_bytes[offset + 0];
        return BitConverter.ToSingle(big_bytes, 0);
    }

    void getButtonState(){
        sp.Write(button_bytes, 0, 4);

        // Wireless packets always have a confirm and id byte pre-appened to the data
        byte[] confirm_byte = new byte[1];
        byte[] id_byte = new byte[1];
        int fail_counter = 0;

        // Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
        // through to make sure the bytes are read
        while (true){
            try{
                sp.Read(confirm_byte, 0, 1);
                sp.Read(id_byte, 0, 1);
                break;
            }
            catch{
                ++fail_counter;
                // Failed to read from serial port
            }
            if (fail_counter > 100){
                throw new System.Exception("Failed to read from port too many times." +
                    " This could mean the port is not open or the Mono serial read is not responding.");
            }
        }

        if (confirm_byte[0] == 0){
            // Read data length of packet
            byte[] length_byte = new byte[1];
            sp.Read(length_byte, 0, 1);

            byte length = length_byte[0];

            // Read the length of the data in the packet
            byte[] read_bytes = new byte[length];

            sp.Read(read_bytes, 0, length);


            if (read_bytes[0] == 0){
                print("No buttons are pressed.");
            }
            else if (read_bytes[0] == 1){
                print("Right button is pressed.");
            }
            else if (read_bytes[0] == 2){
                print("Left button is pressed.");
            }
            else if (read_bytes[0] == 3){
                print("Left and Right buttons are pressed.");
            }
        }
    }

    void tareSensor(){
        sp.Write(tare_bytes, 0, 4);

        // Wireless packets always have a confirm and id byte pre-appened to the data
        byte[] confirm_byte = new byte[1];
        byte[] id_byte = new byte[1];
        int fail_counter = 0;

        // Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
        // through to make sure the bytes are read
        while (true){
            try{
                sp.Read(confirm_byte, 0, 1);
                sp.Read(id_byte, 0, 1);
                break;
            }
            catch{
                ++fail_counter;
                // Failed to read from serial port
            }
            if (fail_counter > 100){
                throw new System.Exception("Failed to read from port too many times." +
                    " This could mean the port is not open or the Mono serial read is not responding.");
            }
        }

        if (confirm_byte[0] == 0){
            // Read data length of packet
            byte[] length_byte = new byte[1];
            sp.Read(length_byte, 0, 1);

            byte length = length_byte[0];

            // Read the length of the data in the packet
            byte[] read_bytes = new byte[length];

            sp.Read(read_bytes, 0, length);
        }
    }

    // Update is called once per frame
    void Update(){
        counter++;

        // Wireless packets always have a confirm and id byte pre-appened to the data
        byte[] confirm_byte = new byte[1];
        byte[] id_byte = new byte[1];
        int fail_counter = 0;

        // Mono, for some reason, seems to randomly fail on the first read after a wirte so we must loop
        // through to make sure the bytes are read
        while (true){
            try{
                sp.Read(confirm_byte, 0, 1);
                sp.Read(id_byte, 0, 1);
                break;
            }
            catch{
                ++fail_counter;
                // Failed to read from serial port
            }
            if (fail_counter > 100){
                throw new System.Exception("Failed to read from port too many times." +
                    " This could mean the port is not open or the Mono serial read is not responding.");
            }
        }

        if (confirm_byte[0] == 0){
            // Read data length of packet
            byte[] length_byte = new byte[1];
            sp.Read(length_byte, 0, 1);

            byte length = length_byte[0];

            // Read the length of the data in the packet
            byte[] read_bytes = new byte[length];

            sp.Read(read_bytes, 0, length);
            
            // Convert bytes to floats
            float x = bytesToFloat(read_bytes, 0);
            float y = bytesToFloat(read_bytes, 4);
            float z = bytesToFloat(read_bytes, 8);
            float w = bytesToFloat(read_bytes, 12);

            // Create a quaternion
            Quaternion quat = new Quaternion(x, y, z, w);

            // Perform rotation
            transform.rotation = quat;
        }

        if ((counter % 25) == 0){
            getButtonState();
        }
        else if (counter > 150){
            tareSensor();
            counter = 1;
        }

        sp.Write(send_bytes, 0, 4);
    }
}

IO.Portsが使えない問題:

http://d.hatena.ne.jp/shinobu_siv/20110622/1308746557

シリアルポートからの読み込みにSystem.IO.Portsパッケージを使っていますが、このパッケージはUnityが使用している.NET 2.0 Subsetには含まれていません。