/* * Copyright 2013, kaj dijkstra , * Author, Kaj Dijkstra. * All rights reserved. * */ import subMesh from './subMesh.js'; import boundingBox from './boundingBox.js'; /** * Mesh object **/ class mesh{ constructor( ){ this.gl = gl; this._className = 'mesh'; this.fileName; this.name = "new"; this.shaderName; this.vertexIndexBuffer; this.vertexPositionBuffer; this.vertexNormalBuffer; this.textureCoordBuffer; this.binormalBuffer = false; this.tangentBuffer = false; this.materials = []; this.subMeshes = []; this.jsonStruture; this.shader; this.forwardShader; this.renderType = "indexed"; this.materialName; this.materialId = 1.0; this.useParallax = false; this.colorInfoShader; this.infoShader; this.materialName; //this.customShader = new shader(); //this.customShader.createLibraryFomFile("shaders/custom.default.shader"); this.heightmap; this.useNormal = false; this.draw_type = gl.TRIANGLES; this.shape = 3; this.entityID = 0; }; /** * set viewport * @param {(viewport)} viewport **/ setViewport( viewport ){ this.viewport = viewport; this.gl = viewport.gl; } /** * Set custom shader (Not yet in use) * @param {(String)} name **/ setCustomShader( name ) { this.customShader = new shader(); this.customShader.createLibraryFomFile("shaders/custom."+name+".shader"); } /** * Set custom shader (Not yet in use) * @param {(String)} name **/ addHeightmap( heightmap ) { this.heightmap = heightmap; this.colorInfoShader.setUniform("heightmap", heightmap ); this.infoShader.setUniform("heightmap", heightmap ); } /** * set material id * @param {(int)} material id **/ setMaterialId( id ) { this.materialId = id; //this.colorInfoShader.setUniform("materialId", this.materialId / 256 ); } /** * Load mesh from file * @param {(String)} url to file **/ loadMeshFromFile( url ) { this.jsonStruture = JSON.parse(kepler.loadTextFileSynchronous('media/models/'+url)); this.fileName = url; this.parseLoadedMesh(); } /** * Combine displacement and normal data in one texture * @param {(Array)} displacement data * @param {(Array)} normal data * @return {(Sampler)} sampler **/ combineDisplacementNormal( displacement, normal ) { var displacementImage = displacement.data; var normalImage = normal.data; var canvas = document.createElement('Canvas'); var width = displacement.width; var height = displacement.height; canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(displacementImage, 0, 0, width, height); var displacementpixelData = canvas.getContext('2d').getImageData(0, 0, width, height).data; canvas.getContext('2d').drawImage(normalImage, 0, 0, width, height); var normalpixelData = canvas.getContext('2d').getImageData(0, 0, width, height).data; var dataArray = []; for(var x = 0; x 0) name += "_normal"; if(material.useParallax) name += "_parallax"; if(material.textures.length > 0) name += "_texture"; if(material.transparencyMaps.length > 0) name += "_transparent"; if(material.specularMaps.length > 0) name += "_specular"; this.shaderName = name; } /** * add material to mesh * @param {(MaterialObject)} Material **/ addMaterial( material ) { if(!material.created) { material.create(); } this.material = material; this.material.setViewport( this.viewport ); this.material.entityID = this.entityID; /* this.shader = new shader(); this.shader.definePragma("TEXTURE", (material.textures.length > 0) ? 1.0 : 0.0 ); this.shader.definePragma("NORMAL_MAP", (material.normals.length > 0) ? 1.0 : 0.0 ); this.shader.definePragma("ROUGHNESS_MAP", (material.roughnessMaps.length > 0) ? 1.0 : 0.0 ); this.shader.definePragma("SHADING_MODEL_ID", material.shadingModelID ); this.shader.definePragma("PARALLAX", (material.useParallax) ? 1.0 : 0.0 ); this.shader.definePragma("DEFERRED", 1.0 ); this.shader.createFomFile("shaders/color.shader"); this.updateShader(material, this.shader); this.forwardShader = new shader(); this.forwardShader.definePragma("TEXTURE", (material.textures.length > 0) ? 1.0 : 0.0 ); this.forwardShader.definePragma("NORMAL_MAP", (material.normals.length > 0) ? 1.0 : 0.0 ); this.forwardShader.definePragma("ROUGHNESS_MAP", (material.roughnessMaps.length > 0) ? 1.0 : 0.0 ); this.forwardShader.definePragma("SHADING_MODEL_ID", material.shadingModelID ); this.forwardShader.definePragma("PARALLAX", (material.useParallax) ? 1.0 : 0.0 ); this.forwardShader.definePragma("DEFERRED", 0 ); this.forwardShader.createFomFile("shaders/color.shader"); this.updateShader(material, this.forwardShader); //forwardShader this.updateMaterial(); */ } updateShader( material, shader ) { shader.setUniform("far", kepler.mainCamera.far ); //this.shader = kepler.resources.getShader("shaders/color.shader"); shader.setUniform("reflectionSampler", kepler.system.reflectionSampler ); if( material.textures.length > 0 ) { material.textures[0].anisotropic = 4; if( material.textures.length > 0 ) { shader.setUniform("diffuseSampler", material.textures[0] ); } if( material.transparencyMaps.length > 0 ) { shader.setUniform("transparencyMapSampler", material.transparencyMaps[0] ); } if( material.normals.length > 0 ) { shader.setUniform("normalSampler", material.normals[0] ); } if( material.roughnessMaps.length > 0 ) { shader.setUniform("normalSampler", material.roughnessMaps[0] ); } if( material.displacementMaps.length > 0 ) { shader.setUniform("heightSampler", material.displacementMaps[0]); } } else { shader.setUniform("diffuseColor", material.diffuseColor ); //var color = material.color; //this.shader.setUniform("rgb", color ); } shader.setUniform("roughness", material.roughness ); shader.setUniform("id", material.id ); shader.setUniform("clearCoat", 1 ); shader.setUniform("clearCoatThickness", 1 ); shader.setUniform("clearCoatIOR", 1 ); shader.setUniform("anisotropy", 1 ); shader.setUniform("lightIntensity", 2); shader.setUniform("environmentLuminance", 1 ); shader.setUniform("lightGeometry", [1,1,1] ); shader.setUniform("clearCoatColor", [1,1,1] ); shader.setUniform("lightColor", [1,1,1] ); var sphericalHarmonics = []; for(var c = 0; c<8; c++) { sphericalHarmonics.push([1,1,1]); } shader.setUniform("sphericalHarmonics", sphericalHarmonics ); } updateMaterial( ) { this.shader.setUniform("roughness", this.material.roughness ); this.forwardShader.setUniform("roughness", this.material.roughness ); this.forwardShader.setUniform("alpha", this.material.alpha ); console.log("roughness", this.material.roughness,this.shader ); } /** * load object from file >?> * @param {(string)} url **/ loadObjFromFile( url ) { var objText = kepler.loadTextFileSynchronous(url); var obj = {}; var vertexMatches = objText.match(/^v( -?\d+(\.\d+)?){3}$/gm); if (vertexMatches) { console.log(obj.vertices = vertexMatches.map(function(vertex) { var vertices = vertex.split(" "); vertices.shift(); return vertices; })); } } /** * parse mesh, load extra mesh data into buffers * @param {(string)} url **/ parseLoadedMesh( url ) { var subMeshObject = new subMeshObject(); if(this.jsonStruture.indices) { this.renderType = "indexed"; subMeshObject.indices = this.jsonStruture.indices; this.vertexIndexBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer); //if(kepler.extensions.elementIndexUint) this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(subMeshObject.indices), this.gl.STATIC_DRAW); //else // this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(subMeshObject.indices), this.gl.STATIC_DRAW); this.vertexIndexBuffer.itemSize = 3; this.vertexIndexBuffer.numItems = subMeshObject.indices.length; this.vertexIndexBuffer.data = subMeshObject.indices; } else { this.renderType = "array"; } subMeshObject.vertices = this.jsonStruture.positions; this.vertexPositionBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(subMeshObject.vertices), this.gl.STATIC_DRAW); this.vertexPositionBuffer.itemSize = 3; this.vertexPositionBuffer.numItems = subMeshObject.vertices.length / 3; this.vertexPositionBuffer.data = subMeshObject.vertices; if(this.jsonStruture.uv) { subMeshObject.textcoords = this.jsonStruture.uv; this.textureCoordBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.textureCoordBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(subMeshObject.textcoords), this.gl.STATIC_DRAW); this.textureCoordBuffer.itemSize = 2; this.textureCoordBuffer.numItems = subMeshObject.textcoords.length / 2; this.textureCoordBuffer.data = subMeshObject.textcoords; } if(this.jsonStruture.normals) { subMeshObject.normals = this.jsonStruture.normals; this.vertexNormalBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexNormalBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(subMeshObject.normals), this.gl.STATIC_DRAW); this.vertexNormalBuffer.itemSize = 3; this.vertexNormalBuffer.numItems = subMeshObject.normals.length / 3; this.vertexNormalBuffer.data = subMeshObject.normals; } this.subMeshes.push(subMeshObject); } copyMesh( mesh ) { this.createdBuffers = false; this.indices = mesh.indices; this.vertices = mesh.vertices; this.normals = mesh.normals; this.textureCoordinates = mesh.textureCoordinates; this.tangents = mesh.tangents; this.binormals = mesh.binormals; } /** * Create mesh from arrays * @param {(array)} indices * @param {(array)} vertices * @param {(array)} normals * @param {(array)} uvs * @param {(array)} tangents * @param {(array)} binormals **/ createMeshFromArrays( indices, vertices, normals, textureCoordinates, tangents, binormals ) { //todo: loop trough sub meshes //var subMeshObject = new subMesh(); this.createdBuffers = false; this.indices = indices; this.vertices = vertices; this.normals = normals; this.textureCoordinates = textureCoordinates; this.tangents = tangents; this.binormals = binormals; /* if(indices) { this.renderType = "indexed"; //subMeshObject.indices = indices; this.vertexIndexBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer); //if(kepler.extensions.elementIndexUint) // this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(subMeshObject.indices), this.gl.STATIC_DRAW); //else this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indices), this.gl.STATIC_DRAW); this.vertexIndexBuffer.itemSize = 3; this.vertexIndexBuffer.numItems = indices.length; this.vertexIndexBuffer.data = indices; } else { this.renderType = "array"; } //subMeshObject.vertices = vertices; this.vertexPositionBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(vertices), this.gl.STATIC_DRAW); this.vertexPositionBuffer.itemSize = 3; this.vertexPositionBuffer.numItems = vertices.length / 3; this.vertexPositionBuffer.data = vertices; if(uvs) { //subMeshObject.textcoords = uvs; this.textureCoordBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.textureCoordBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(uvs), this.gl.STATIC_DRAW); this.textureCoordBuffer.itemSize = 2; this.textureCoordBuffer.numItems = uvs.length / 2; this.textureCoordBuffer.data = uvs; } if(normals) { //subMeshObject.normals = normals; this.vertexNormalBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexNormalBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(normals), this.gl.STATIC_DRAW); this.vertexNormalBuffer.itemSize = 3; this.vertexNormalBuffer.numItems = normals.length / 3; this.vertexNormalBuffer.data = normals; } if(tangents) { //subMeshObject.tangents = tangents; this.tangentBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.tangentBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(tangents), this.gl.STATIC_DRAW); this.tangentBuffer.itemSize = 3; this.tangentBuffer.numItems = tangents.length / 3; this.tangentBuffer.data = tangents; } else { this.createTangentAndBinormal(); } if(binormals) { this.binormalBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.binormalBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(binormals), this.gl.STATIC_DRAW); this.binormalBuffer.itemSize = 3; this.binormalBuffer.numItems = binormals.length / 3; this.binormalBuffer.data = binormals; } */ //this.subMeshes.push(subMeshObject); this.boundingBox = new boundingBox(); this.boundingBox.fitBoxToPoints_( vertices ); } createBuffers() { if(!this.createdBuffers) { if(this.indices) { this.renderType = "indexed"; this.vertexIndexBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer); //if(kepler.extensions.elementIndexUint) // this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(subMeshObject.indices), this.gl.STATIC_DRAW); //else this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(this.indices), this.gl.STATIC_DRAW); this.vertexIndexBuffer.itemSize = this.shape; this.vertexIndexBuffer.numItems = this.indices.length; this.vertexIndexBuffer.data = this.indices; } else { this.renderType = "array"; } this.vertexPositionBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexPositionBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.vertices), this.gl.STATIC_DRAW); this.vertexPositionBuffer.itemSize = 3; this.vertexPositionBuffer.numItems = this.vertices.length / 3; this.vertexPositionBuffer.data = this.vertices; if(this.textureCoordinates) { this.textureCoordBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.textureCoordBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.textureCoordinates), this.gl.STATIC_DRAW); this.textureCoordBuffer.itemSize = 2; this.textureCoordBuffer.numItems = this.textureCoordinates.length / 2; this.textureCoordBuffer.data = this.textureCoordinates; } if(this.normals) { this.vertexNormalBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexNormalBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.normals), this.gl.STATIC_DRAW); this.vertexNormalBuffer.itemSize = 3; this.vertexNormalBuffer.numItems = this.normals.length / 3; this.vertexNormalBuffer.data = this.normals; } if(this.tangents) { this.tangentBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.tangentBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.tangents), this.gl.STATIC_DRAW); this.tangentBuffer.itemSize = 3; this.tangentBuffer.numItems = this.tangents.length / 3; this.tangentBuffer.data = this.tangents; } else { if(this.draw_type != this.gl.LINES) this.createTangentAndBinormal(); } if(this.binormals) { this.binormalBuffer = this.gl.createBuffer(); this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.binormalBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.binormals), this.gl.STATIC_DRAW); this.binormalBuffer.itemSize = 3; this.binormalBuffer.numItems = this.binormals.length / 3; this.binormalBuffer.data = this.binormals; } this.createdBuffers = true; } } /** * write content to ext console * @param {(string)} content **/ writeConsole(content) { top.consoleRef=window.open('','myconsole', 'width=350,height=250' +',menubar=0' +',toolbar=1' +',status=0' +',scrollbars=1' +',resizable=1') top.consoleRef.document.writeln( 'Console' +'' +content +'' ) top.consoleRef.document.close() } /** * Show tangent * @param {(subMeshObject)} **/ showTangent( subMeshObject ) { writeConsole( this.fileName + ' Tangent ' + JSON.stringify(this.tangentBuffer.data) ); } /** * Show Binormal * @param {(subMeshObject)} **/ showBinormal( subMeshObject ) { var tangentArray = this.binormalBuffer.data; var a = []; for(var c = 0; c