src/basic/S3Mesh.js
import S3Vertex from "./S3Vertex.js";
import S3Material from "./S3Material.js";
import S3TriangleIndex from "./S3TriangleIndex.js";
import S3System from "./S3System.js";
/**
* 3DCG用メッシュ(立体形状データ)を管理するクラス (mutable)
* 頂点・面・マテリアルを保持し、複数の形状や属性を一つにまとめます。
*
* @class
* @module S3
*/
export default class S3Mesh {
/**
* メッシュを作成します。
* @param {S3System} s3system S3Systemインスタンス
*/
constructor(s3system) {
/**
* システムインスタンス
* @type {S3System}
*/
this.sys = s3system;
/**
* 三角形インデックス追加時に面の頂点順序(表裏)を反転するかどうかを指定します。
* true の場合は addTriangleIndex() で自動的に面を裏返して追加します。
* @type {boolean}
*/
this.is_inverse = false;
this._init();
}
/**
* メッシュの内部状態を初期化します。
*/
_init() {
/**
* メッシュの構成要素
* @type {{vertex: Array<S3Vertex>, triangleindex: Array<S3TriangleIndex>, material: Array<S3Material>}}
*/
this.src = {
vertex: [],
triangleindex: [],
material: []
};
/**
* メッシュが確定済みかどうか
* @type {boolean}
*/
this.is_complete = false;
}
/**
* データを開放します
* @returns {void}
*/
dispose() {
this.src = null;
this.sys = null;
this.is_complete = false;
}
/**
* メッシュが確定済みかどうかを返します。
* @returns {boolean} 確定済みならtrue
*/
isComplete() {
return this.is_complete;
}
/**
* このメッシュのクローン(複製)を作成します。
* @param {typeof S3Mesh} [Instance] 複製時のクラス指定(省略時はS3Mesh)
* @returns {S3Mesh} 複製されたS3Meshインスタンス
*/
clone(Instance) {
if (!Instance) {
Instance = S3Mesh;
}
const mesh = new Instance(this.sys);
mesh.addVertex(this.getVertexArray());
mesh.addTriangleIndex(this.getTriangleIndexArray());
mesh.addMaterial(this.getMaterialArray());
return mesh;
}
/**
* メッシュの確定状態を設定します。
* @param {boolean} is_complete 確定済みかどうか
*/
setComplete(is_complete) {
this.is_complete = is_complete;
}
/**
* 三角形インデックスの順序を反転するモードを設定します。
* 反転時はaddTriangleIndexで自動的に面を裏返します。
* @param {boolean} inverse 反転するならtrue
*/
setInverseTriangle(inverse) {
this.setComplete(false);
this.is_inverse = inverse;
}
/**
* メッシュが保持する頂点配列を取得します。
* @returns {Array<S3Vertex>} 頂点配列
*/
getVertexArray() {
return this.src.vertex;
}
/**
* メッシュが保持する三角形インデックス配列を取得します。
* @returns {Array<S3TriangleIndex>} 三角形インデックス配列
*/
getTriangleIndexArray() {
return this.src.triangleindex;
}
/**
* メッシュが保持するマテリアル配列を取得します。
* @returns {Array<S3Material>} マテリアル配列
*/
getMaterialArray() {
return this.src.material;
}
/**
* 頂点(S3Vertexまたはその配列)をメッシュに追加します。
* @param {S3Vertex|Array<S3Vertex>} [vertex] 追加する頂点またはその配列
*/
addVertex(vertex) {
// immutableなのでシャローコピー
this.setComplete(false);
// 引数があった場合にのみ処理
if (vertex) {
const meshvertex = this.getVertexArray();
if (vertex instanceof S3Vertex) {
meshvertex[meshvertex.length] = vertex;
} else {
for (let i = 0; i < vertex.length; i++) {
meshvertex[meshvertex.length] = vertex[i];
}
}
}
}
/**
* 三角形インデックス(S3TriangleIndexまたはその配列)をメッシュに追加します。
* 反転モード時は面を裏返して追加します。
* @param {S3TriangleIndex|Array<S3TriangleIndex>} [ti] 追加する三角形インデックスまたはその配列
*/
addTriangleIndex(ti) {
// immutableなのでシャローコピー
this.setComplete(false);
// 引数がある場合に動作する
if (ti !== undefined) {
const meshtri = this.getTriangleIndexArray();
if (ti instanceof S3TriangleIndex) {
meshtri[meshtri.length] = this.is_inverse ? ti.inverseTriangle() : ti;
} else {
for (let i = 0; i < ti.length; i++) {
meshtri[meshtri.length] = this.is_inverse ? ti[i].inverseTriangle() : ti[i];
}
}
}
}
/**
* マテリアル(S3Materialまたはその配列)をメッシュに追加します。
* @param {S3Material|Array<S3Material>} [material] 追加するマテリアルまたはその配列
*/
addMaterial(material) {
// immutableなのでシャローコピー
this.setComplete(false);
const meshmat = this.getMaterialArray();
// 引数が設定されたとき動作する
if (material) {
if (material instanceof S3Material) {
meshmat[meshmat.length] = material;
} else {
for (let i = 0; i < material.length; i++) {
meshmat[meshmat.length] = material[i];
}
}
}
}
}