2014年9月29日 星期一

Kanzi: Render Transparent Objects


在Kanzi裡畫半透明物件,比想像中麻煩一點,因為它不是你把物件用半透明材質,然後給個Transparent Queue就會幫你排序做好。

首先,必須在Composing > Pipeline 裡,加一個Property is Equal Filter。在Property Type選blendMode,Operation 選Include,Blend Mode選你的半透明物件所在的Mode。(這邊在弄時有發生怪事,Blend Mode怎麼設都不鳥我,preview視窗重開好幾次也沒用,後來不知怎突然可以用了...)

另一個要注意的點是,它是照物件上的Property排,所以你把BlendMode在Material裡設好,以為用了這個Material就會知道這個屬性。別傻了,它會當你是Opaque的物件....

接者同上步驟建一個畫Opaque的Filter。

然後在Composer建2個render pass 第一個畫Opaque物件。第二個畫半透明的Filter。(在Render Pass的Object Source選剛才的Filter)。把Color Buffer :Clear Enable > false, Depth Buffer: Clear Enable > False,Test Enable打開,Write Enable關掉。


發現怪事了嗎?

ZTest、ZWrite、甚至是Back , Front Culling不在Material上,而是在Render Pass上...WTF....Material要是複雜一點,不是要用一堆Render Pass..... 想到頭皮就發麻....

設完後,疑....排序怎是錯的....原來排序要自己再建一個Sorting Filter,Filter的Source選剛才的Transparent objects。同理,如果用到Tag Filter的話...我已經不敢想那個排列組合了.....

2014年9月24日 星期三

Kanzi StateMachine


在Editor中使用StateMachine 發現幾點要注意的地方

一開始想做一個循環的button,循環某一個State Manager

所以使用Toggle Button。

例如我有5個State,讓Toggle Button也有5個State對應。

首先先將Button中 加入一個Number of Toggle Button屬性,設成5

接著,新增Button: Toggle State 這個Trigger。之後,就對文件中的說明看不懂,試了很久才發現:

1.在Trigger Settings中,新增一個Condition,Property > Button Toggle State, Condition > =, Fixed Value > 0

2. Add一個Set property的Action,把State的值設成0。

3. 5個State的話,就要新增5個Button : Toggle State。

如果要有要使用State Manager: State Entered 這個Trigger的話,要加在Target物件(後面測試State Object跟Target都可以),而不是State Group,也不是Button上。同樣地也要在這個Trigger Setting中,設定Condition,不然只要State改變,都會進去。注意: Condition 中的Message Source要改成target物件。不能用預設值  後來發覺跟Message Source無關,是我的property名稱叫State,如果直接在下拉選單key入state 搜尋,會變成MessageArgument.StateManager.State ,但若在選單裡自己找,用選的,就會是我的state。應該是跟內建的名稱衝到,選到第一個是內建的名稱。

如果要用State Manager改變Target物件的屬性,記得要把Target上的對應屬性移掉。例如,在State Object上有Ambient Color這個屬性,要改變Sphere上的Ambient Color的話,要把Sphere上的Ambient Color 移掉。

這個設定成功後,才發現,原來Trigger 裡有一個State Manager: Go to Preview State 這個屬性。但一開始也試不出來,也沒文件。 後來試出,State Group 名稱設成要用的State Manager下的State Group,再把Dispatch Settings中的Routing Target,設成Target物件 (有State Manager那個)

這樣這個就可以做左右的循環State

後記:又出現問題了....用Go to Preview State的方式,沒辦法讓Target物件用它的State Property來判斷現在是在哪個State,前面的方式無法用。目前還找不到對應的值是什麼。後來用了一個蠢方法,在Property Type再增加一個叫State Name的property。在State Object上加入這個屬性,之後在Target物件上的Condition來判斷這個Name,就可以知道是在哪個State......不知正統的解法什麼

經過測試,在State Object上也可以用trigger知道State Enter,但State Left我搞不懂它的邏輯,在同一個State Object上,設Enter跟Left,在進入這個State時,會同時觸發。感覺是別人Left進這個State.....但又不知是誰的State進來呀 X的.... wtf

 用了一個蠢方式,設一個空Node 叫Pre State,上面有個像之前的StateName property。因為Left會發生在Enter之前,所以在Enter時,用Set Property 把空Node的StateName設定Current的名稱,因為left 進入時還沒更改,所以會抓到pre state,這樣就可以知道從哪State出來了..........應該有標準做法吧...但文件沒寫... x的

2014年9月23日 星期二

QNX專案設定

待補充....

剛建好專案,發覺無法Run。
原因是在Documentation中有一段講Communication with the QNX Neutrino RTOS

似乎在PC上debug也一定要有個平台才行

所以我用VMware跑一個評估版的QNX,ip在192.168.6.128

上面說裡面一定要跑一個qconn 的program, 評估版的本來就有

然後在專案裡,Perspective > QNX System Information
在Target Navigator view裡建一個New QNX Target
輸入剛才的ip,然後Finish

這樣IDE中的執行檔就可以Run

此外,如果發覺編完找不到Library,記得在Project Preference裡,加入Extra的library

(libscreen只要打screen就好,前面的lib不用打。)





2014年9月16日 星期二

從vmware的QNX連到 win7的shared folder

試了很久,google了半天,找不到為何連不過去

後來發現原因,原來是電腦名稱和別人衝到.....把名稱改了後就可以....囧 

在vm 裝評估版的QNX 在Windows開一個Shared folder

例如我的分享資料夾叫 Share, QNX的叫 mnt 然後打

 fs-cifs -l -vvvvvv //電腦名稱:電腦ip:/Share /mnt 

-l 是要輸入user name和password
-v 是debug訊息的多寡

 電腦名稱大小寫沒差
 username大小寫也沒差

2014年9月15日 星期一

Create Image form memory

最近在測試從網路上抓 Google map下來,但不知該怎把抓下來的圖轉成Kanzi可用的。

這個軟體目前資源很少呀,用的人不多,不像Unity3D,可以很簡單就做到。

跟網路的溝通我是用POCO這個library



 std::string url = URIinit();
 URI uri(url);
 std::string path(uri.getPathAndQuery());
 if (path.empty()) path = "/";

 HTTPClientSession session(uri.getHost(), uri.getPort());
 HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
 HTTPResponse response;
 session.sendRequest(request);
 std::istream &is = session.receiveResponse( response );


在Kanzi建立需要的資源:

 
 struct KzuResourceManager* resourceManager 
  = kzuUIDomainGetResourceManager(kzaApplicationGetUIDomain(application));

 struct KzcMemoryManager* memoryManager = kzcMemoryGetManager(resourceManager);
 struct KzcImage* image;
 struct KzuImageTexture* texture;

把拿到的stream轉成 char* buffer再轉成Kanzi 的stream格式。

 std::ostringstream oss( std::ios_base::binary);
 oss << is.rdbuf();
 std::string strConst = oss.str();
 int size = strConst.length();
 
 const char* buffer = strConst.c_str();
 

 kzsException error;
 struct KzcInputStream* outstrem;
 error = kzcInputStreamCreateFromMemory(memoryManager, (kzByte*)buffer, size,  KZC_IO_STREAM_ENDIANNESS_UNSPECIFIED, &outstrem);


再用Kanzi的load png的Api: kzcImageLoadPNG,因為我已經知道抓下來是png的格式,若是其它的,要用其它的函式。之前本來想直接用kzuImageTextureCreateFromMemory,這個函式,但發現抓下來的是png,在設定 KZU_TEXTURE_CHANNELS時會有問題,因為png用的是索引色,不是用R8G8B8這種格式,還要把抓下來的raw data做轉換。
 error = kzcImageLoadPNG(memoryManager, outstrem, false, &image);
 /* Create texture from image. */
 result = kzuImageTextureCreateFromImage(resourceManager, "Widget Texture", 
  image, KZU_TEXTURE_FILTER_BILINEAR, 
  KZU_TEXTURE_WRAP_REPEAT, 0.0f, 
  &texture);
 kzsErrorForward(result);
 struct KzuObjectNode* screenNode 
  = kzuScreenToObjectNode(kzaApplicationGetScreen(application));
 
 struct KzuObjectNode* plane = kzuObjectNodeGetRelative(screenNode, "#Plane");
 result = kzuObjectNodeSetResourceIDResourceProperty(plane, KZU_PROPERTY_TYPE_TEXTURE,  kzuImageTextureToResource(texture));
 kzsErrorForward(result);


如果是直接從file中讀取,也可以用這個方式。之前拿來debug用的。把從網路上抓下來的部分改成下面這段就可以
 std::fstream myfile("myfile.png", std::ios::in | std::ios::binary);
 std::filebuf* pbuf = myfile.rdbuf();
 std::size_t size = pbuf->pubseekoff (0,myfile.end,myfile.in);
 pbuf->pubseekpos (0,myfile.in);
 char* buffer=new char[size];
 // get file data
 pbuf->sgetn (buffer,size);
 myfile.close();


Kanzi C++ project

除了在設定中的:
C/C++
 -Advanced: Compiled as -> 改成 Compiled as C++ Code 外

也要把
-Code Generation: Enable C++ Exceptions 設成 /EHsc

參照:http://msdn.microsoft.com/zh-tw/library/1deeycx5.aspx

如果沒改,在編一些第三方函式庫會編不過...




2014年9月4日 星期四

建立Custom Component

1. 建立自已的KzuUiComponentNodeClass

2. 在configuration->onStartup = startup; 時註冊Factory

3. 為了2. 所以要建2個function:
       a. FactoryCreate //用來create component
       b. RegisterToFactory //用來註冊, 如果有要註冊Custom message也可以寫在這
   這會對應到在Editor中,建立的Custom Component name

4. 如果有要處理Message, Handler加在KzuUiComponentNodeClass的initialize function中。

 要在editor preview的話,編GL_21_release版的,ps:要把Editor關掉才能把dll蓋掉。

註冊custom message


 const struct KzuMessageType* MESSAGE_TEXTUREFONT_CHANGRD;
 {
  struct KzcMemoryManager* memoryManager = kzcMemoryGetManager(factory);
  struct KzuMessageType* messageType;
                
  //Message.Custom.FontChange 對應Editor裡的Custom Message Name
  result = kzuMessageRegistryAddMessageType(memoryManager, "Message.Custom.FontChange", KZU_MESSAGE_ROUTING_TUNNELLING_BUBBLING,        &messageType);
  kzsErrorForward(result);

  MESSAGE_TEXTUREFONT_CHANGRD = messageType;
 }

取得/設定 custom property

 {
    struct KzuPropertyType* UV_SET; 
    struct KzcVector4 uvs;

    //get property type
    UV_SET = kzuPropertyRegistryFindPropertyType("uv_modify");
    kzsAssert(kzcIsValidPointer(UV_SET));

    //get property
    uvs = kzuObjectNodeGetVector4PropertyDefault(textrue_font->planeNode, UV_SET);
    uvs.data[0] = (kzFloat)(uv_sets[index].x);
    uvs.data[1] = (kzFloat)(uv_sets[index].y);
    uvs.data[2] = (kzFloat)(uv_sets[index].z);
    uvs.data[3] = (kzFloat)(uv_sets[index].w);

    //set property
    result = kzuObjectNodeSetVector4Property(textrue_font->planeNode, UV_SET, uvs);
    kzsErrorForward(result);
}
在scene node底下的mesh的material,可以從node就直接get property來set,不用去get它的material