1/11

日記

2026/01/11

Object.defineProperty

const o = {
  _key: undefined,
};

Object.defineProperty(o, "key", {
  get() {
    return this._key;
  },
  set(v) {
    this._key = v;
  },
});
// 使用例
o.key = "hello";
console.log(o.key); // "hello"
console.log(o._key); // "hello"(直接アクセスも可能)

Three.js

クラス継承

MeshStandardMaterialをクラス継承する。this.setValues()でjsでいうMeshStandardMaterial({...params})のparamsを渡せる。
super()にも渡せるが、this.definesでglslにdefinesを定義する場合definesの後に書く必要があるので、this.setValues()を使う。

水面

近傍セルを読む

vec4 north = texture2D( heightmap, uv + vec2( 0.0, cellSize.y ) );
vec4 south = texture2D( heightmap, uv + vec2( 0.0, - cellSize.y ) );
vec4 east  = texture2D( heightmap, uv + vec2( cellSize.x, 0.0 ) );
vec4 west  = texture2D( heightmap, uv + vec2( - cellSize.x, 0.0 ) );

float newHeight =
  ( ( north.x + south.x + east.x + west.x ) * 0.5
    - heightmapValue.y ) * viscosity;

newHeightの箇所は離散化した 2D波動方程式

1D波動

波を作るのは、「自分と隣がズレているかどうか」

0 0 5 0 0

左右との差がある
→引っ張られる
→動く

左右平均との差

平均との差 = (左 + 右) / 2 - 自分

自分だけ高い→マイナス
自分だけ低い→プラス

前回との差も足す

前回との差 = 自分 - 前回の自分

これらから、「次の位置」を求めたい。

何も無ければどうなる?

next = current

永遠に同じ。

前回と同じ動きを続けたい。

velocity = current - previous;
next = current + velocity;

previousが3, currentが5とすると、velocituは2。
nextはcurrentから2だけ大きくなる。これは前回と同じ動きを続けている。

ただ、これだと大きいところは等速直線運動的に大きくなり続ける。

戻そうとする力を入れる

neighborAvg = (left + right) / 2;
neighborDiff = neighborAvg - current;

neighborDiffは
自分が高い→マイナス
自分が低い→プラス

全部足して次の点を決める

next = current + (current - previous) + neighborDiff;

0 0 5 0 0

0 1 6 1 0

0 2 4 2 0

0 1 2 1 0

0 0 -1 0 0

となる。これが波。

2Dで同じことをする

n = x + (x - y) + (avg - x)

n = x - y + avg

float newHeight = heightmapValue.x - heightmapValue.y + ((north.x + south.x + east.x + west.x) / 4.0);

よっしゃ、似たような結果が得られた。

高さマップの法線

高さマップで法線を計算する場合、「高さは上方向」という前提を固定して、
高さマップ限定の裏技的なやつが勾配の使用

水面の例では上下左右の高さマップをワールド座標に変換して簡単に法線を計算する方法をつかっていた。

感想

マグカップとスティックコーヒーも買って朝いい感じ。

I bought a mag and stick coffee set. so mornings feel good.