2010-11-18

MAC Samba 速度緩慢

為了改善速度,到目前為止做了以下調整:

1) 將 net.inet.tcp.delayed_ack 設為 0
2) 在 smb.conf 的 [global] 區段加入:

large readwrite = no  (此參數會造成檔案讀取錯誤)

read size = 1024
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_SNDBUF=8576 SO_RCVBUF=8576

Note:
參考 http://www.macosxhints.com/article.php?story=20040324053434397
參考 http://www.mobile01.com/topicdetail.php?f=177&t=183347&p=1
net.inet.tcp.delayed_ack 設定方法:

 sudo -s
Password:
 cd /etc
 touch sysctl.conf
 echo 'net.inet.tcp.delayed_ack=0' >sysctl.conf
 exit

檢查 net.inet.tcp.delayed_ack 的值:

 sysctl net.inet.tcp.delayed_ack

使用 vim 來修改 smb.conf:
 sudo vi /etc/smb.conf

鍵入 i 進入 INSERT 模式,ESC 離開。
鍵入 :wq 存檔離開。

2010-11-16

移除 MAC 上的 Skype 和 MSN

移除 Skype :
1) 刪除 Skype.app
2) 刪除 /Library/Preferences/com.skype.skype.plist
3) 刪除 /Users/username/Library/Preferences/com.skype.skype.plist
4) 刪除 /Users/Library/Application Support/Skype 目錄

5) 到 系統偏好設定 --> 帳號 --> 登入項目 移除 Skype

移除 MSN
1) 刪除 msn.app
2) 刪除 /Users/username/Library/Preferences/com.microsoft.Messenger.plist
3) 刪除 /Users/username/Library/Preferences/com.microsoft.Messenger.rtc.plist
4) 刪除 /Users/username/Library/Preferences/Microsoft/Microsoft Messenger User Cache.plist
5) 刪除 /Users/username/Documents/Microsoft Messenger.log


2010-11-05

Unity 3D + Lua 實作筆記


幾天前實作使用 Lua 當 Untiy 3D 的腳本語言,好處是只要用記事本修改 Lua Script 文字檔就可更改程式執行流程,不用重新編譯程式。這裡使用的方法是將 Lua 以 DLL Plugin 的方式掛在 Unity 3D 裡執行,底下是整個實作的流程 (  iOS 平台的實作請參考另一篇 ) :

1. 重新編譯讓 C# 可以 Import 的 Lua DLL 檔。
因為 C 和 .net 的 calling convention 方式不同以致於需要編譯一個 .net 使用的 calling convention 方式的 DLL 檔,可以參考這篇文章

1.1 到 http://www.lua.org/ftp/ 下載 lua5.1 原始碼,此時的最新版是 lua-5.1.4.tar.gz ,解開後可以看到原始碼在 src 目錄下。

1.2 用 VC 開啟新專案 (Visual C++ 的 Win32 Console Application),Application Type 的部分選擇 DLL,Additional options 的部分選擇 Empty project。

開啟新專案

Application Settings

1.3 引入 src 目錄內的原始檔(除 Makefile、lua.c、luac.c 外)。
1.4 設定 Calling Convention 為 _stdcall(在 Project Property -> Configuration Properties -> C/C++ -> Advanced -> Calling Convention)。

Calling Convention

1.5 在 Preprocessor Definitions ( Project Property -> Configuration Properties -> C/C++ -> Preprocessor->Preprocessor Definitions)裡加入 LUA_BUILD_AS_DLL 和 LUA_CORE 兩個定義。
Preprocessor Definitions

1.6 按下 Build 即可產生一個 DLL 檔。

2 將 DLL 檔複製到 Unity3D 專案的 plugins 目錄下 ("\Assets\Plugins"),測試 Lua DLL。

2.1 測試大約區分成三個部分,第一是 "開啟和關閉 Lua" ,第二是 "註冊 C# 的函數給 Lua",第三是 "執行 Lua Script" 並在 Script 內回呼之前註冊的 C# Function。

2.2 "開啟  Lua" 執行如下:
m_luaState = luaL_newstate();
luaL_openlibs(m_luaState);

其中 m_luaState 的定義是:
protected IntPtr m_luaState = IntPtr.Zero;

luaL_newstate() 和 luaL_openlibs() 這兩個函數在執行前須 Import :
[DllImport("lua514vc")] private static extern IntPtr luaL_newstate();
[DllImport("lua514vc")] private static extern void luaL_openlibs(IntPtr lua_State);
其中 lua514vc 是編譯的 Lua 的 DLL 檔名稱。

2.3 "關閉  Lua" 執行如下:
lua_close(m_luaState);

2.4 "註冊 C# 函數",底下是 Lua 註冊 C# Function 的函數:
protected static void lua_register(IntPtr pLuaState, string strFuncName, LuaFunction pFunc)
{
    lua_pushcclosure(pLuaState, pFunc, 0);
    lua_setfield(pLuaState, (int)LuaIndexes.LUA_GLOBALSINDEX, strFuncName);
}

其中 pLuaState 是開啟 Lua 之後取得的 m_luaState,strFuncName 是欲註冊的函數名稱, pFunc 是 C# 函數, LuaFunction 是函數指標,定義如下:
public delegate int LuaFunction(IntPtr pLuaState);

函數 lua_pushcclosure() 和 lua_setfield() 的 Import 方式如下:
[DllImport("lua514vc")]
private static extern void lua_pushcclosure(
    IntPtr lua_State, 
    [MarshalAs(UnmanagedType.FunctionPtr)] LuaFunction func, 
    int n);

[DllImport("lua514vc")]
private static extern void lua_setfield(
    IntPtr lua_State, 
    int idx, 
    string s);

例如現在有一個函數為:
int TestDisplay(IntPtr pLuaState)
{
    Debug.Log("LuaWrapper.TestDisplay()");
    return 0;
}

則註冊 TestDisplay() 函數的方法就是:
lua_register(m_luaState, "TestDisplay", TestDisplay);

2.5 "執行 Lua Script" 檔案:
執行 Lua Script 檔案的函數是:
protected static int luaL_dofile(IntPtr lua_State, string s)
{
    if (luaL_loadfile(lua_State, s) != 0)
        return 1;
 
    return lua_pcall(lua_State, 0, -1, 0);
}

其中 string s 表示 Lua Script 的檔案路徑。函數 luaL_loadfile和 lua_pcall 的 Import 方式為:
[DllImport("lua514vc")]
private static extern int lua_pcall(IntPtr lua_State, int nargs, int nresults, int errfunc);

[DllImport("lua514vc")]
private static extern int luaL_loadfile(IntPtr lua_State, string s);

最後,編輯一個文字檔,儲存檔名為 test.txt,其內容為:
TestDisplay()

然後在 C# 裡執行:
luaL_dofile( m_luaState , "test.txt" );

就會看到 Untiy3D 裡的 Console 視窗出現 "LuaWrapper.TestDisplay()" 字串了。

update 2012-07-05 :
範例程式碼可以在  https://github.com/phardera/unity3d_lua 下載

2010-10-28

Unity 3D 相關筆記

  • 2012-04-30
    • JSON Serializer/Deserializer 參考這篇,程式碼參考這裡
  • 2012-04-13
    • Unity3D 卸載未使用的資源指令 : Resources.UnloadUnusedAssets()
  • 2011-02-25
    • Unicode CJK (中文, 日文, 韓國) 字元範圍,參考這篇文章
  • 2010-12-13
    • Unity 3D 執行順序 (Link)
  • 2010-11-02
    • 以 DllImport 方式把 Lua 嵌在 C# 裡(適用於 Unity3D),參考這篇文章
  • 2010-10-28
    • 利用 Command 建立 AssetBundle 參考這篇討論。
    • 執行時期載入程式碼參考這篇討論。

2010-10-11

HTML Browser in Unity 3D

採用 Qt 裡的 WebKit 來瀏覽網頁並把網頁畫成 Image 之後由 Unity 3D 繪出。

yahoo 首頁

Youtube 播放影片

GoogleMaps

QtWebKit 可由 Qt SDK 取得並編譯成 DLL 檔,但 WebKit DLL 沒辦法直接由 Unity 3D 來呼叫使用,因此在 Unity 3D 和 WebKit DLL 中間再寫一個函數對應的 DLL,整個結構大概如下:



2010-09-03

C# firestream 讀檔、struct 和 byte 之間的轉換

using System.IO;
using System.Runtime.InteropServices;
using System;
 
//1. 把檔案讀成 Byte 形式
private byte[] readFile(string strFileName)
{
 
    byte[] buffer = null;
    FileStream fs = new FileStream(strFileName, FileMode.Open, FileAccess.Read);
    try
    {
        BinaryReader br = new BinaryReader(fs);
        int len = System.Convert.ToInt32(fs.Length);
 
        buffer = br.ReadBytes(len);
 
    }
    finally
    {
        fs.Close();
    }
    return buffer;
}
 
//2. struct 轉成 byte
static byte[] StructToBytes(object structObj)
{
    int size = Marshal.SizeOf(structObj);
    IntPtr buffer = Marshal.AllocHGlobal(size);
    try
    {
        Marshal.StructureToPtr(structObj, buffer, false);
        byte[] bytes = new byte[size];
        Marshal.Copy(buffer, bytes, 0, size);
        return bytes;
    }
    finally
    {
        Marshal.FreeHGlobal(buffer);
    }
}
 
//3. byte 轉成 struct
static object BytesToStruct(byte[] bytes, Type strcutType)
{
    int size = Marshal.SizeOf(strcutType);
    IntPtr buffer = Marshal.AllocHGlobal(size);
    try
    {
        Marshal.Copy(bytes, 0, buffer, size);
        return Marshal.PtrToStructure(buffer, strcutType);
    }
    finally
    {
        Marshal.FreeHGlobal(buffer);
    }
}

2010-09-02

Unity 3D 隱藏視窗外框

Unity3D 若要客製化視窗的外框,就本人所知的方法為:

1. 隱藏原本的視窗外框
2. 在視窗內畫出客製作的視窗外框

這邊概述隱藏視窗外框的方法:
1. 編譯一個 DLL 檔(目的用來呼叫 WIN32 API),DLL 檔內提供一個隱藏視窗的函數 HideWindow() 如下:
int __declspec(dllexport) __stdcall HideWindow()
{
 //finde window
 HWND hWin =GetActiveWindow();
 if (hWin ==0)
  return 0;

 RECT rc;
 GetClientRect(hWin, &rc);

 long lStyle =GetWindowLong(hWin, GWL_STYLE);
 lStyle =lStyle & (~WS_CAPTION);
 SetWindowLong( hWin, GWL_STYLE, lStyle);
 
 SetWindowPos(hWin, NULL, 0, 0, rc.right, rc.bottom, SWP_NOMOVE);

 return 2;

}
2. 將編譯出來的 DLL 檔加至 Project 的 plugin 目錄下。

3. 在 Unity3D 裡建立一個 C# Script,並在裡面加入,其中 winframehidden 為 DLL 檔名:
[DllImport("winframehidden")]
private static extern int HideWindow();

然後在 Start() 函數內呼叫 HideWindow() 即可。

2010-08-31

擷取 std::cout 字串

std::cout 方便我們把資料列印到 console 視窗,擷取這些字串可以拿來做其它用途,例如另存成 Log file、以其它方式顯示等...。底下的方法是當 cout 呼叫時, 會將 cout 的字串以 callback 的方式傳給 callback function。

1. 建立 cout wrapper class 繼承
std::basic_streambuf< char, std::char_traits< char > >

2. 在 class 的 constructor 加入(其中  m_pBuf 為暫存的 cout buffer):
m_pBuf = std::cout.rdbuf( this );

3.在 class 的 destructor 加入下列(還原原來的 cout buffer):
m_Stream.rdbuf( m_pBuf );

4. 利用此 class override 兩個 function 分別為 xsputn 及 overflow:
/**
* Override xsputn and make it forward data to the callback function.
*/
std::streamsize xsputn( const char* _Ptr, std::streamsize _Count )
{
 m_pCbFunc( _Ptr, _Count ); //m_pCbFunc 為使用者定義的 callback function
 return _Count;
}

/**
* Override overflow and make it forward data to the callback function.
*/
std::char_traits< char >::int_type overflow( std::char_traits< char >::int_type v )
{
 char ch = std::char_traits< char >::to_char_type( v );
 m_pCbFunc( &ch, 1 ); //m_pCbFunc 為使用者定義的 callback function

 return std::char_traits< char >::not_eof( v );
}

5. 程式建立此 class 之後,所有的 cout 呼叫都會將字串以 callback 方式傳給使用者定義的 callback function 了!

2010-08-25

在 Unity 3D 裡用 C# Script 產生 Mesh

首先建立一個 C# Script,這裡取名為 SimpleRect.cs,其內容如下(特別注意的是 class name 必須與檔名相同):
using UnityEngine;
using System.Collections;

public class SimpleRect : MonoBehaviour {

    // Use this for initialization
    void Start () {

        Mesh pm = new Mesh();
        pm.Clear();
        
        Vector3[] verts = new Vector3[4];
        verts[0].x = -0.5f;
        verts[0].y = 0.0f;
        verts[0].z = 0.5f;

        verts[1].x = 0.5f;
        verts[1].y = 0.0f;
        verts[1].z = 0.5f;

        verts[2].x = -0.5f;
        verts[2].y = 0.0f;
        verts[2].z = -0.5f;

        verts[3].x = 0.5f;
        verts[3].y = 0.0f;
        verts[3].z = -0.5f;
        pm.vertices = verts;

        int[] tris = new int[6];

        tris[0] = 0;
        tris[1] = 1;
        tris[2] = 2;
        
        tris[3] = 2;
        tris[4] = 1;
        tris[5] = 3;

        pm.triangles = tris;

        pm.RecalculateBounds();
        pm.RecalculateNormals();

        pm.Optimize();

        //建立 GameObject, 並指定 MeshFilter 的 Mesh:
        GameObject go = new GameObject();
        MeshFilter mf = go.AddComponent<meshfilter>();
        mf.mesh = pm;

        MeshRenderer mr = go.AddComponent<meshrenderer>(); 
    }

    // Update is called once per frame
    void Update () {

    }
}

082501
將 SimpleRect.cs 從 Project 拖移至 Hierarchy 視窗的 MainCamera 上


082502
點選 MainCamera 時,可看到 Inspector 裡多了 SimpleRect 的 Script


082503
此時進入 GameMode 就可以看到產生的 Rect