import { createIndexBuffer, createVertexArray, createVertexBuffer, GLProgram, IndexBuffer, VertexArray, VertexBuffer } from "./glWrapper"; import {OBJ} from "webgl-obj-loader"; import { assertBoolean } from "./util"; type VertexType = "position" | "normal" | "textureUV"; type Vertexes = {[key in VertexType]:VertexBuffer}; export class Model{ vertexes : Vertexes; ibo :IndexBuffer; vao :VertexArray; constructor(gl:WebGL2RenderingContext,vertex:Vertexes,index :IndexBuffer){ this.vertexes = vertex; this.vao = createVertexArray(gl); this.ibo = index; } ready(gl:WebGL2RenderingContext,p : GLProgram){ const VertexLayouts = { "position":{ count:3, type:gl.FLOAT, normalize:false, stride:0, offset:0 }, "normal":{ count:3, type:gl.FLOAT, normalize:false, stride:0, offset:0 }, "textureUV":{ count:2, type:gl.FLOAT, normalize:false, stride:0, offset:0 } } this.vao.bind(gl); for(const [name,buf] of Object.entries(this.vertexes)){ const loc = p.getAttribLocation(gl,name); assertBoolean(loc >= 0,"there is no",name,"attribute"); this.vao.addBuffer(gl,buf,loc,VertexLayouts[name]); } this.ibo.bind(gl); this.vao.unbind(gl); } draw(gl:WebGL2RenderingContext){ this.vao.bind(gl); gl.drawElements(gl.TRIANGLES,this.ibo.count,gl.UNSIGNED_SHORT,0); this.vao.unbind(gl); } static async loadFromOBJ(gl:WebGL2RenderingContext,src:RequestInfo,init?:RequestInit){ const response = await fetch(src,init); const text = await response.text(); const mesh = new OBJ.Mesh(text); const position = createVertexBuffer(gl,mesh.vertices); const normal = createVertexBuffer(gl,mesh.vertexNormals); const texture = createVertexBuffer(gl,mesh.textures); const index = createIndexBuffer(gl,mesh.indices); return new Model(gl,{ position: position, normal: normal, textureUV: texture }, index); } }