src/gl/S3GLArray.js
import S3Vector from "../math/S3Vector.js";
import S3Matrix from "../math/S3Matrix.js";
/**
* WebGL用の配列(バッファ)を生成・管理するクラス。(immutable)
* 各種型(S3Vector, S3Matrix, 数値配列等)をWebGLバッファ(Float32Array/Int32Array)に変換し、
* 対応するGLSL型(vec3, mat4等)情報も保持します。
*
* @class
* @module S3
*/
export default class S3GLArray {
/**
* WebGL用の配列データを作成します(immutable)。
* 渡された値に応じて型変換・整形し、GLSLでそのまま利用可能な形にします。
*
* @param {number[]|number|S3Vector|S3Matrix|Float32Array|Int32Array} data 配列、数値、S3Vector/S3Matrix、あるいは既にTypedArrayの場合も可
* @param {number} dimension 配列の次元(例:3ならvec3やivec3になる)
* @param {S3GLArrayDataType} datatype 使用するバッファ型(S3GLArray.datatype)
*/
constructor(data, dimension, datatype) {
// 引数の情報(S3GLArray.datatype.instance)を用いて、
// JS用配列を、WEBGL用配列に変換して保存する
if (data instanceof datatype.instance) {
/**
* 本体データ(TypedArray: Float32Array または Int32Array)
* @type {Float32Array|Int32Array}
*/
this.data = data;
} else if (data instanceof S3Vector || data instanceof S3Matrix) {
this.data = data.toInstanceArray(datatype.instance, dimension);
} else if (data instanceof Array || data instanceof Float32Array || data instanceof Int32Array) {
this.data = new datatype.instance(data);
} else if (!isNaN(data)) {
this.data = new datatype.instance([data]);
} else {
throw "IllegalArgumentException";
}
/**
* 配列の次元(要素数やGLSL型を決定するための値)
* 例: 3 → vec3, 16 → mat4
* @type {number}
*/
this.dimension = dimension;
/**
* 配列のデータ型情報(TypedArray種別や型名などを格納したオブジェクト)
* @type {S3GLArrayDataType}
*/
this.datatype = datatype;
let instance = "";
if (data instanceof S3Vector) {
instance = "S3Vector";
} else if (data instanceof S3Matrix) {
instance = "S3Matrix";
} else {
instance = "Number";
}
// GLSL型(vec3, mat4など)を自動判別し、型名文字列として保存
/**
* GLSLの型名(vec3, mat4, float等)
* @type {string}
*/
this.glsltype = S3GLArray.gltypetable[datatype.name][instance][dimension];
}
}
/**
* TypedArrayのコンストラクタ型定義(Int32Array, Float32Array など)。
* @typedef {(typeof Float32Array | typeof Int32Array)} S3GLTypedArrayConstructor
*/
/**
* WebGL配列で利用できるデータ型情報(各種TypedArray型)。
*
* - instance: 対応するTypedArrayコンストラクタ(例:Float32Array, Int32Array)
* - name: 型の名前文字列("Float32Array"等)
*
* @typedef {Object} S3GLArrayDataType
* @property {S3GLTypedArrayConstructor} instance 対応するTypedArrayのコンストラクタ
* @property {string} name 型名("Float32Array"等)
*/
/**
* WebGLで利用できる配列データ型定数(Float32Array/Int32Array)。
* @type {{ Float32Array: S3GLArrayDataType, Int32Array: S3GLArrayDataType }}
*/
S3GLArray.datatype = {
Float32Array: {
instance: Float32Array,
name: "Float32Array"
},
Int32Array: {
instance: Int32Array,
name: "Int32Array"
}
};
/**
* GLSL型名("vec3"や"mat4"など)を配列次元や入力種別から自動判定するためのテーブル構造。
*
* - 第一階層キー:データ型名("Float32Array" または "Int32Array")
* - 第二階層キー:値種別("Number", "S3Vector", "S3Matrix")
* - 第三階層キー:配列次元や要素数(2, 3, 4, 9, 16など)
* - 値:対応するGLSL型名("vec3"等)を表す文字列
*
* 例)gltypetable["Float32Array"]["S3Matrix"][16] === "mat4"
*
* @typedef {Object<string, Object<string, Object<number, string>>>} S3GLArrayGLTypeTable
*/
/**
* GLSL型判定用テーブル。
* 値の型により適切なGLSL型名(vec3, mat4等)を自動で取得できます。
*
* @type {S3GLArrayGLTypeTable}
*/
S3GLArray.gltypetable = {
Float32Array: {
Number: {
1: "float",
2: "vec2",
3: "vec3",
4: "vec4"
},
S3Vector: {
2: "vec2",
3: "vec3",
4: "vec4"
},
S3Matrix: {
4: "mat2",
9: "mat3",
16: "mat4"
}
},
Int32Array: {
Number: {
1: "int",
2: "ivec2",
3: "ivec3",
4: "ivec4"
},
S3Vector: {
2: "ivec2",
3: "ivec3",
4: "ivec4"
}
}
};