2016年5月10日 星期二

VS Code Setting

Visaul Studio Code Setting

MS官方說明安裝

https://marketplace.visualstudio.com/items?itemName=lukehoban.Go 照著安裝即可

安裝debug工具 delve

https//github.com/derekparker/delve

1. 用git取得delve的repository
2. install mingw-w64(gcc for win)
3. mingw-32-make install in delve folder
4. compiled exe file would be in environment %GO%/bin

2016年5月3日 星期二

sequelize- javascript ORM for mySQL....

Define model

//column option
field:'field_name'          //field name
type:Sequelize.STRING       //data type
allowNull: true             //
defaultValue:'value'        //default value
unique: true                //string value Sequelize.STRING 
unique: 'compositeIndex'    //string value, 不能相同string
primaryKey: true
autoIncrement: true         //auto increament column for integer
comment: 'this is comment'  //comment


var Foo = sequelize.define('foo', {
 // instantiating will automatically set the flag to true if not set
 flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},

 // default values for dates => current time
 myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },

 // setting allowNull to false will add NOT NULL to the column, which means an error will be
 // thrown from the DB when the query is executed if the column is null. If you want to check that a value
 // is not null before querying the DB, look at the validations section below.
 title: { type: Sequelize.STRING, allowNull: false},

 // Creating two objects with the same value will throw an error. The unique property can be either a
 // boolean, or a string. If you provide the same string for multiple columns, they will form a
 // composite unique key.
 someUnique: {type: Sequelize.STRING, unique: true},
 uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
 uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}

 // The unique property is simply a shorthand to create a unique index.
 someUnique: {type: Sequelize.STRING, unique: true}
 // It's exactly the same as creating the index in the model's options.
 {someUnique: {type: Sequelize.STRING}},
 {indexes: [{unique: true, fields: ['someUnique']}]}

 // Go on reading for further information about primary keys
 identifier: { type: Sequelize.STRING, primaryKey: true},

 // autoIncrement can be used to create auto_incrementing integer columns
 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },

 // Comments can be specified for each field for MySQL and PG
 hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" },

 // You can specify a custom field name via the "field" attribute:
 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" },

 // It is possible to create foreign keys:
 bar_id: {
   type: Sequelize.INTEGER,

   references: {
     // This is a reference to another model
     model: Bar,

     // This is the column name of the referenced model
     key: 'id',

     // This declares when to check the foreign key constraint. PostgreSQL only.
     deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
   }
 }
})

也可以reference 其他model

2016年4月28日 星期四

javaScript features (ECMAScript6)

Class

define

class Queue {
    _queue;      
  constructor(contents = []) {
    this._queue = [...contents];
  }
  pop() {
    const value = this._queue[0];
    this._queue.splice(0, 1);
    return value;
  }

extends

class PeekableQueue extends Queue {
  peek() {
    return this._queue[0];
  }
class Account extends Foo {
  constructor(balance) {
    this.balance = balance;
  }

  history(done) {
    someLongTask((err, data) => {
      // Do something with data
      done(null, data);
    });
  }

  deposit(amount) {
    this.balance += amount;
    return this.balance;
  }
}

// Currently, you can only declare functions in a class
Account.types = ['checking', 'savings'];

get,set

class Account {
  constructor() {
    this.balance = 0;
  }

  get underBudget() {
    return this.balance >= 0;
  }

  get overBudget() {
    return this.balance < 0;
  }
}

const myAccount = Account();
myAccount.balance = 100;
console.log(myAccount.underBudget); // true

Iterable Class

可建立iterable class,並且可用generator建立iterator。

class MyIterable {
  constructor(items) {
    this.items = items;
  }

  *[Symbol.iterator]() {
    for (let item of this.items) {
      yield `Hello, ${item}`;
    }
  }
}

const test = new MyIterable([1, 2, 3, 4, 5]);

for (let item of test) {
  console.log(item); // => Hello, 1...
}

Map

let map = new Map(arr);

for (let key of map.keys()) {
  console.log(key);
}

for (let value of map.values()) {
  console.log(value);
}

for (let item of map.entries()) {
  console.log(item[0], item[1]
}

Module

基本定義與引用

用ES6 export,就用import;不要用require

一個文件中不要export與default export一起用

不要在import中使用*,確保module中有一個default export

//定義模組 module.js

var privateVar = "privateVar";  
//不能被外部引用的成員
export var publicVar = "and this one is public";   
//export出去,可被外部引用的成員

export function getVar() {
   return privateVar;
};

//引用模組 use.js
import { getVar, publicVar } from 'mymodule'; 
//import getVar及publicVar兩個成員
console.log(getVar());

//一次引用這個模組的所有可引用成員
X import 'mm' from 'mymodule';
X import 'mymodule' as mm;
//或是這樣
import * as 'mm' from 'mymodule';  //不建議使用*
import abc =require('mymodule');

//不一定都有implement
import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";

console.log(mm.gerVar());

default export(無命名export) (文件中只有一個成員)

//------ myFunc.js ------
export default function () { ... };

//------ main1.js ------
import myFunc from 'myFunc';
myFunc();

//------ MyClass.js ------
export default class { ... };
 
//------ main2.js ------
import MyClass from 'MyClass';
let inst = new MyClass();

一個文件中同時有export(一般export)與default export(無命名export)

//------ underscore.js ------
export default function (obj) {
    ...
};

export function each(obj, iterator, context) {
    ...
}
export { each as forEach };

//------ main.js ------
import _, { each } from 'underscore';
...

default export就是another named export

//以下兩者相同
import { default as foo } from 'lib';
import foo from 'lib';

//以下兩個模組export相同
//------ module1.js ------
export default 123;

//------ module2.js ------
const D = 123;
export { D as default };

commonJS的module

//------ underscore.js ------
var _ = function (obj) {
    ...
};
var each = _.each = _.forEach =
    function (obj, iterator, context) {
        ...
    };
module.exports = _;
 

//------ main.js ------
var _ = require('underscore');
var each = _.each;
...

//------ lib.js ------
var sqrt = Math.sqrt;
function square(x) {
    return x * x;
}
function diag(x, y) {
    return sqrt(square(x) + square(y));
}
module.exports = {
    sqrt: sqrt,
    square: square,
    diag: diag,
};
 
//------ main.js ------
var square = require('lib').square;
var diag = require('lib').diag;
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5


2016年3月17日 星期四

頂點及索引

Vertex and Index

頂點 ->索引
v0 -> 0
v1 -> 1
v2 -> 2
v3 -> 3

index決定三角形構成方式
[0,1,2,2,3,0]
v0->v1->v2
v2->v3->v0
決定了兩個三角形構成,
也就是決定了兩個面

頂點代表多重意義,基本上是多種屬性的重疊
一般封裝的方式有兩種:

struct Vertex {
  Vector3 Position;
  Vector3 Normal;
  Vector3 Color;
}

Vector3[] Vertices;
Vector3[] normals;
Vector3[] colors;

Vertex Buffer

存放vertices的區域,稱為vertex buffer
在DX/OpenGL中,我們需要
1 申請vertex buffer
2 綁定buffer
3 上傳vertex資料
4 一個模型對應一個buffer

在unity中, 這些已經被封裝了

Gluint vertexbuffer;
glGenBuffer(1,&vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAM);

Index Buffer

存放index資料的暫存區,稱為index buffer

不同的向量方向,構成的三角形不同

[0,1,2]構成 v0->v1, v1->v2兩個向量
[2,1,0]構成v2->v1,v1->v2兩個向量
兩者的法向量不同,所以是不同三角形


 三角形的正面及背面





Dx以情況A為正向,依據左手系統,法向量朝我方。

OpenGL以情況B為正向,依據右手系統,法向量朝我方。


索引的意義


1 每三個索引,決定一個三角形(面數)
2 索引順序不同,構成三角形不同
3 DX預設順時針為正向,OpenGL預設逆時針為正向
4 索引會決定三角形的正面、背面
5 索引可表示重複使用的頂點,可減少記憶體使用
6 索引是簡單整數,有些設備一個物件只支援65535個索引=21845個三角形

Unity物件頂點數限制65000個,也是從此而來。

物件頂點數超過65535個,可進行頂點資料及索引拆分,分成兩份資料。

7 合併緩衝區

用索引決定渲染

渲染整個模型,索引從0到最後
渲染某部分,更改索引起始位置及結束位置

合併緩衝區

就是把兩個物件的頂點緩衝區及索引緩衝區合併,當成一個物件處理。

假設三個物件的vertexBuffer及indexBuffer:
v0   v1  v2 => 0,1,2
m0 m1 m2 => 0,1,2
n0  n1   n2 => 0,1,2

合併後
[v0,v1,v2,m0,m1,m2,n0,n1,n2]
[0,1,2,(0+3),(1+3),(2+3),(0+6),(1+6),(2+6)]

0+3=4,表示是vertex的第四個=m0
1+4=5,表示是vertex的第五個=m2

這就是unity draw call batching的原理
合併緩衝區在物件是靜態時,效果最好,
如果非static卻一直合併緩衝區,就適得其反。
所以unity draw call batching 有分dynamic及static,
確保物件是static才使用static方法。

顏色

顏色表示法


假設使用向量表示顏色,最小值為0,最大值為1。
三原色可表示為:

r=(1,0,0)
g=(0,1,0)
b=(0,0,1)

8位元表示法,最小值為0,最大值為255
r=(255,0,0)
g=(0,255,0)
b=(0,0,255)

[0,1]對應到[0,255],只要每個分量除255即可。



顏色運算

加法

r+g=(1,0,0)+(0,1,0)=(1,1,0)

減法

(1,1,0)-(0,1,0)=(1,0,0)

數乘

0.5*(1,1,1)=(0.5,0.5,0.5)

分量乘法

(r0,r1,r2)*(g0,g1,g2)=(r0*g0,r1*g1,r2*g2)

分量乘法應用
假設c0=(1,1,1) 太陽光
c1=(0.5,0.25,0.5)  材質反射率

c0*c1=(0.5,0.25,0.5)
就是太陽光照射材質後,反射出來的光

向量點積、向量叉積對顏色無意義


顏色分量要限縮在0-1之間,超過這個範圍就無意義




2016年3月8日 星期二

射線 平面

射線

定義

定義射線需要起點,方向,長度
起點p0
方向=單位向量u
長度=t

向量相加為所形成平行四邊形的對角線
得到射線p(t)=p0+tu


Unity Raycast API

public static bool Raycast(Vector3 origin, Vector3 direction, float maxDistance)
其實就和射線定義相同(起點,方向,長度)


平面

定義

p為平面上任意點,n為平面法向量,p1為法向量交於平面的點

p-p1向量=p-p1 假設為(ax,ay,az)
n假設為 (bx,by,bz)
p-p1與n垂直
向量點積公式 (a長)*(b長)*Cos(90)=0
向量點積算法(ax*bx+ay*by+cz*bz)
得到n.(p-p1)=0


射線與平面相交


射線
p=p0+tu

平面
n.(p-p1)=0

把射線p帶入平面

n.(p0+tu - p1)=0

n.p0+n.tu-n.p1=0

n.tu=n.p1-n.p0

t=n.p1-n.p0/n.u

這裡 (.)是點積

若t>=0,射線與平面相交,且交點為p0+tu
若t<0,兩不相交

矩陣

矩陣運算

矩陣相加   對應元素相加
矩陣相減   對應元素相減
矩陣相乘   每個元素就是兩個矩陣的行與列點積。所以兩個矩陣的行與列維度要相同。
矩陣數乘   每個元素乘上一個數
矩陣相等   對應的每個元素相等

矩陣相乘

條件

假設A矩陣*B矩陣
則A行向量的元素個數=B列向量元素個數
(大陸橫為行,直為列)
否則無法相乘


A=[1- 5 -4]
     [3   2  1]

B=[2  1  0 ]
     [0  -2  1]
     [-1  2   3]

AB=[(-1,5,-4).(2,0,-1)   (-1,5,-4).(1,-2,2)   (-1,5,-4).(0,1,3)]
        [(3,2,1).(2,0,1)       (3,2,1).(1,-1,2)      (3,2,1)(0,1,3)]

行.列  (點積)

矩陣乘法不滿足交換率

A*B != B*A

矩陣乘法滿足結合率

A(B+C)=AB+AB
(AB)C=A(BC)


矩陣除法

矩陣運算沒有除法

向量矩陣

行向量矩陣
A=[1 3 3]

列向量矩陣
B= [2]
      [2]
      [3]

向量-矩陣乘法

OpenGL 左乘方式--矩陣在左,向量在右    記憶法(O在左)
DirectX    右乘方式--矩陣在右,向量在左    記憶法(X在右)

因為矩陣乘法不反足交換率,所以在左在右結果不同。


轉置矩陣(Transpose)

把一個矩陣的行和列互換。mxn的轉置矩陣就是nxm。
原矩陣的行向量=轉置矩陣的列向量

A=[1  1  1 ]
     [2  2   2]

C=A.transpose
[1 2]
[1 2]
[1 2]


B=[a b c d]

D=B.transpose
[a]
[b]
[c]
[d]

A*B=(D*C).transpose

範例
A,B兩向量
C=A.transpose
D=B.transpose

A*B    ↘︎  C*D    =>  A*B=D*C      兩個剛好交錯
B*A   ↗︎   D*C    =>  B*A=C*D

矩陣乘以向量

1 矩陣維度與向量元素個數不需相同

2 矩陣*向量  =>變成向量

3 矩陣*向量=向量*矩陣轉置(要自己計算)

向量 X=(1,2,3,4);

A=[1  1  1 1]
     [2  2   2 2]
     [3  3  3  3]
     [4  4  4  4]

A*X=(1111.(1234)  2222.(1234)  3333.(1234)   4444.(1234))

A.transpose=
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]
[1 2 3 4]

X*A.transpose
((1234)(1111)   (1234)(2222)  (1234)(3333)  (1234)(4444))


 Unity中矩陣乘以向量

可以直接矩陣*向量
不能向量*矩陣  (要自己計算)

矩陣A
向量V

A*V  =>ok
V*A  =>error


單位矩陣

1 是正方形矩陣

2 中心左上右下斜對角線(back slash)的元素都是1

3 其他元素都是0

4 任何矩陣*單位矩陣,結果不變

5 單位矩陣就是矩陣中的數字1(跟單位向量相同)

[1  0   0]
[0  1   0]
[0  0   1]

逆矩陣(Inverse)

1 矩陣運算沒有除法

2 只有正方形矩陣才能夠逆運算

3 一個nxn的矩陣的逆矩陣,仍然是nxn的矩陣

4 不是所有的矩陣都有逆矩陣,有逆矩陣的矩陣稱為可逆

5 如果有可逆矩陣,這個逆矩陣一定是唯一的

6 將一個矩陣與他的逆矩陣相乘,結果一定為單位矩陣

有矩陣A,B,C,且A=B*C,且D為C的逆矩陣
A=BC
AD=BDC (DC=1)
AD=B

範例

有一點a
一矩陣b
d=b的逆矩陣
轉換後的點c = a*b

cd=a*b*d  (bd=1)
cd=a

可找到原始的a點

常用來把點從局部空間轉換到世界空間,
或從世界空間轉換回局部空間。


矩陣計算平移

1 點的位移向量,使用DirectX要寫在矩陣第四行的前三個,
   因為如果寫在前三行,那會被x,y,z乘到
   只能寫在第四行的前三個,經過計算後就分別被x,y,z加

   使用OpenGL則分別寫在前三行的最後一元素

    directX與openGL可使用矩陣轉置來切換

2 矩陣的每個位置數字都有意義,都是經過設計的

3 因為3x3不夠用,所以擴充為4x4,自己新增w

4 當w=0,(x,y,z,0) 就是用來描述向量 =>可得到原始向量

5 當w=1,(x,y,z,1) 就是用來描述點    =>可算出位移後的點


DirectX計算(右乘,矩陣在右,向量在左)


A=[x,y,z,w] 行向量

M= 單位矩陣
       1  0  0  0
       0  1  0  0
       0  0  1  0
       0  0  0  1

A*M=

x*1+y*0+z*0+w*0=x
x*0+y*1+z*0+w*0=y
x*0+y*0+z*1+w*0=z
x*0+y*0+z*0+w*1=w

假設位移向量B=(tx,ty,tz),則A位移後的點為(x+tx,y+ty,z+tz)
tx,ty,tz寫在矩陣最下行靠左

m=
1  0   0   0
0  1   0   0
0   0  1   0
tx  ty tz  1

A*m=[x,y,z,w] *m=

x*1+y*0+z*0+w*tx=x+wtx
x*0+y*1+z*0+w*ty=y+wty
x*0+y*0+z*1+w*tz=z+wtz
x*0+y*0+z*0+w*1=w

當w=1,結果就是 x+tx,y+ty,z+tz,1
因為w是我們自己擴充的,所以可設為1

所以經由以上算法,點A的位移,利用矩陣運算可得到結果。
矩陣每個位置的數字都有固定意義,都事先設定好的。


OpenGL計算(左乘,矩陣在左,向量在右 =Unity的系統 )

A=[x,y,z,w] 行向量

M= 單位矩陣
       1  0  0  0
       0  1  0  0
       0  0  1  0
       0  0  0  1

M*A=

x*1+y*0+z*0+w*0=x
x*0+y*1+z*0+w*0=y
x*0+y*0+z*1+w*0=z
x*0+y*0+z*0+w*1=w

假設位移向量B=(tx,ty,tz),則A位移後的點為(x+tx,y+ty,z+tz)
tx,ty,tz寫在矩陣前三行最末位

m=
1  0   0   tx
0  1   0   ty
0   0  1   tz
0  0  0    1

m*A=m*[x,y,z,w] =

1*x+0*y+0*z+w*tx=x+wtx
0*x+1*y+0*z+w*ty=y+wty
0*x+0*y+1*z+w*tz=z+wtz
0*x+0*y+0*z+w*1=w

當w=1,結果就是 x+tx,y+ty,z+tz,1
因為w是我們自己擴充的,所以可設為1

矩陣計算縮放

1 縮放就是倍數的關係,所以(x,y,z)要能分別乘以縮放的數字

2 因此只能放在斜對角線的元素位置上

sx 0  0  0
0  sy 0  0
0  0  sz 0
0  0  0  0

假設x放大2,y所小0.5,z放大3,那就是

2     0  0  0
0  0.5  0  0
0     0  3  0
0     0  0  0

範例

矩陣A=
[1 0  0      0]
[0  2  0     0]
[0  0  0.5  0]
[0  0  0     1]

向量V=[x,y,z,w]

v*A=
x*1+y*0+z*0+w*0=x
x*0+y*2+z*0+w*0=2y
x*0+y*0+z*0.5+w*0=0.5z
x*0+y*0+z*0+w*0=w

=[x,2y,0.5z,0]
=x不變,y放大2,z縮小0.5


矩陣計算旋轉

1 旋轉要考慮軸

2 旋轉要考率角度(非弧度)


假設延n軸旋轉 n=(x,y,z)
轉 a角度
c=cos(a)
s=sin(a)

矩陣為:

c+(1-c)*x*x        (1-c)*x*y+s*z      (1-c)*x*z-s*y      0
(1-c)*x*y-s*z       c+(1-c)*y*y       (1-c)*y*z+s*x     0
(1-c)*x*z+s*y     (1-c)*y*z-s*x       c+(1-c)*z*z        0
0                           0                            0                          1

範例

假設延x軸旋轉 (1,0,0)

1   0             0             0
0  cos(a)   sin(a)      0
0  -sin(a)    cos(a)    0
0  0             0              1


矩陣組合


1 如果一次要計算三個矩陣(平移矩陣,縮放矩陣,旋轉矩陣),太消耗資源

2 利用矩陣乘法分配律,可以把三個矩陣先相乘,在跟向量相乘,可以少算2/3次

3 同時三個矩陣組成一個,也方便處理

4 組合方式是三個矩陣相乘