795 lines
17 KiB
JavaScript
Executable File
795 lines
17 KiB
JavaScript
Executable File
/*
|
|
* Copyright 2019, kaj dijkstra,
|
|
* Author, Kaj Dijkstra.
|
|
* All rights reserved.
|
|
*
|
|
*/
|
|
|
|
import scene from './scene.js';
|
|
|
|
import shader from './shader.js';
|
|
|
|
import mesh from './mesh.js';
|
|
|
|
import material from './material.js';
|
|
|
|
import sampler2D from './sampler2D.js';
|
|
|
|
import entity from './entity.js';
|
|
|
|
import {matrix3, matrix4} from './math.js';
|
|
|
|
import boundingBox from './boundingBox.js';
|
|
|
|
/**
|
|
* Player object
|
|
**/
|
|
class assimp
|
|
{
|
|
constructor() {
|
|
|
|
this.baseUrl = "http://localhost:4000";
|
|
this.modelPath = '/media/models/';
|
|
|
|
this.meshes = [];
|
|
this.scene = new scene();
|
|
this.shader = new shader();
|
|
|
|
this.filesToLoad = [];
|
|
this.name = "new";
|
|
|
|
this.models = [];
|
|
|
|
this.animations;
|
|
|
|
this.skeleton;
|
|
|
|
this.lightNames = ["PhotometricLight", "FPoint"];
|
|
|
|
this.shadingModelIDS = [];
|
|
|
|
this.bindMaterial("$ColladaAutoName$_108", 10.0);
|
|
this.bindMaterial("Box002", 1.0);
|
|
|
|
this.json;
|
|
|
|
this.materialCache;
|
|
|
|
}
|
|
|
|
|
|
stringStartsWith( string, compare ) {
|
|
if (string.substring(0, compare.length) == compare)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
nameIsLight( name ) {
|
|
for(var c = 0; c<this.lightNames.length; c++) {
|
|
if(this.stringStartsWith(name, this.lightNames[c])) {
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
addModel( json ) {
|
|
|
|
|
|
|
|
this.models.push(json);
|
|
}
|
|
|
|
bindMaterial( entityName, shadingModelID ) {
|
|
this.shadingModelIDS.push({name:entityName, id:shadingModelID});
|
|
}
|
|
|
|
getShadingIdByEntityName( entityName ) {
|
|
for(var c = 0; c<this.shadingModelIDS.length; c++) {
|
|
console.log(this.shadingModelIDS[c].name, entityName);
|
|
if(this.shadingModelIDS[c].name == entityName)
|
|
return this.shadingModelIDS[c].id;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
serializeUrl( url, part_two ) {
|
|
if(url) {
|
|
// Remove backslash
|
|
var urlParts = url.split("\\");
|
|
|
|
url = urlParts[urlParts.length-1];
|
|
|
|
|
|
|
|
// Force extension to png
|
|
urlParts = url.split(".");
|
|
|
|
|
|
|
|
urlParts[urlParts.length-1] = "png";
|
|
|
|
url = urlParts.join(".");
|
|
|
|
// type
|
|
urlParts = url.split("_");
|
|
if(urlParts.length > 1) {
|
|
urlParts[urlParts.length-1] = part_two + ".png";
|
|
|
|
} else {
|
|
|
|
|
|
}
|
|
|
|
url = urlParts.join("_");
|
|
|
|
//remove slash
|
|
urlParts = url.split("/");
|
|
|
|
return urlParts[ urlParts.length - 1 ];
|
|
|
|
} else {
|
|
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* update object
|
|
**/
|
|
load( jsonFilename, scene ) {
|
|
|
|
console.log("load file", this.modelPath + jsonFilename);
|
|
|
|
var filenameParts = jsonFilename.split(".");
|
|
|
|
this.name = filenameParts[0];
|
|
|
|
this.scene = scene;
|
|
|
|
var data = this.loadTextFileSynchronous( this.baseUrl + this.modelPath + jsonFilename );
|
|
|
|
this.processFiles(data);
|
|
|
|
console.log("filesToLoad", jsonFilename, this);
|
|
|
|
}
|
|
|
|
get_filesize(url, callback) {
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open("HEAD", url, true); // Notice "HEAD" instead of "GET",
|
|
// to get only the header
|
|
|
|
xhr.onreadystatechange = function(ev) {
|
|
|
|
if (this.readyState == this.DONE) {
|
|
|
|
console.log('evevev', ev.target.responseURL);
|
|
var url = ev.target.responseURL;
|
|
var size = parseInt(ev.target.getResponseHeader("Content-Length"));
|
|
//kepler.loader.add(url, size );
|
|
|
|
}
|
|
};
|
|
|
|
xhr.engine = kepler;
|
|
xhr.send();
|
|
}
|
|
|
|
|
|
/**
|
|
* load url
|
|
* @param {string} url
|
|
*/
|
|
loadTextFileSynchronous(url, callback) {
|
|
/*
|
|
this.get_filesize( url );
|
|
|
|
|
|
|
|
var fileContent = kepler.resources.getFile(url)
|
|
|
|
if(fileContent) {
|
|
return fileContent.data;
|
|
}
|
|
*/
|
|
var request;
|
|
|
|
if (window.XMLHttpRequest) {
|
|
request = new XMLHttpRequest();
|
|
if (request.overrideMimeType) {
|
|
request.overrideMimeType('text/plain');
|
|
}
|
|
} else if (window.ActiveXObject) {
|
|
request = new ActiveXObject('MSXML2.XMLHTTP.3.0');
|
|
} else {
|
|
throw 'XMLHttpRequest is disabled';
|
|
}
|
|
|
|
|
|
|
|
request.onprogress = callback = function (evt) {
|
|
|
|
console.log("onupdate", evt);
|
|
|
|
//kepler.loader.update( evt.target.responseURL, evt.loaded, evt.total );
|
|
|
|
};
|
|
|
|
request.onload = function (evt) {
|
|
if (request.readyState === request.DONE) {
|
|
if (request.status === 200) {
|
|
//console.log(request.response);
|
|
//console.log(request.responseText);
|
|
this.assimp.filesToLoad.push({data: request.responseText, filename: request.responseURL });
|
|
//'this.assimp.filesToLoad.push(evt.responseText);
|
|
|
|
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
request.onreadystatechange = function (evt) {
|
|
|
|
console.log("finish", evt.target.readyState);
|
|
|
|
if(evt.target.readyState == 4) {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
request.open('GET', url, false);
|
|
|
|
request.engine = this.engine;
|
|
|
|
request.assimp = this;
|
|
|
|
request.send();
|
|
|
|
var data = request.responseText;
|
|
|
|
return data;
|
|
}
|
|
|
|
|
|
processFiles(json)
|
|
{
|
|
|
|
//var json = this.filesToLoad[0];
|
|
|
|
this.json = JSON.parse( json );
|
|
|
|
this.json.parsedMeshes = new Array();
|
|
|
|
var materials = this.json.materials;
|
|
|
|
var meshes = this.json.meshes;
|
|
|
|
var rootnode = this.json.rootnode;
|
|
|
|
var children = rootnode.children;
|
|
|
|
this.animations = this.json.animations;
|
|
|
|
|
|
var materialCache = new Array();
|
|
|
|
|
|
// get materials
|
|
for(var c = 0; c < materials.length; c++) {
|
|
|
|
var Material = materials[c];
|
|
var properties = Material.properties;
|
|
|
|
var name = this.getPropertyByName(properties, '?mat.name', 0).value;
|
|
var diffuseAdress = this.serializeUrl( this.getPropertyByName(properties, '$tex.file', 1).value, "diff");
|
|
var normalAdress = this.serializeUrl( this.getPropertyByName(properties, '$tex.file', 1).value, "ddn");
|
|
var roughAdress = this.serializeUrl( this.getPropertyByName(properties, '$tex.file', 1).value, "rough");
|
|
var depthAdress = this.serializeUrl( this.getPropertyByName(properties, '$tex.file', 1).value, "depth");
|
|
|
|
|
|
var diffuseColor = this.getPropertyByName(properties, "$clr.diffuse", 0).value;
|
|
var opacity = this.getPropertyByName(properties, "$mat.opacity", 0).value;
|
|
var roughness = this.getPropertyByName(properties, "$mat.shinpercent", 0).value;
|
|
|
|
|
|
console.log('diffuseAdress', diffuseAdress);
|
|
var normalTexture = kepler.resources.getTexture("0_floorTiles_ddn.png");
|
|
var normalSampler = new sampler2D();
|
|
normalSampler.addTexture(normalTexture);
|
|
|
|
var diffuseTexture = kepler.resources.getTexture("0_floorTiles_diff.png");
|
|
var diffuseSampler = new sampler2D();
|
|
diffuseSampler.addTexture(diffuseTexture);
|
|
|
|
|
|
var currentMaterial = new material( );
|
|
|
|
//if(diffuseAdress)
|
|
//currentMaterial.addTexture(diffuseSampler);
|
|
//currentMaterial.addNormal(normalSampler);
|
|
|
|
if(!diffuseColor) {
|
|
currentMaterial.diffuseColor = [1,1,1];
|
|
//currentMaterial.diffuseColor = [Math.random(), Math.random(), Math.random()];
|
|
} else {
|
|
currentMaterial.diffuseColor = diffuseColor;
|
|
|
|
}
|
|
|
|
|
|
//currentMaterial.diffuseColor = [Math.random(), Math.random(), Math.random()];
|
|
if(kepler.resources.getTexture( this.name + "/" + diffuseAdress )){
|
|
//currentMaterial.addTexture(diffuseSampler);
|
|
//currentMaterial.addNormal(normalSampler);
|
|
} else {
|
|
|
|
|
|
}
|
|
//instanceMaterial.addRoughness(roughnessSampler);
|
|
//instanceMaterial.shadingModelID = material.id;
|
|
currentMaterial.roughness = 0.0;
|
|
|
|
currentMaterial.alpha = 1;
|
|
//currentMaterial.create();
|
|
currentMaterial.roughness = .01;
|
|
currentMaterial.reflectance = .01;
|
|
|
|
materialCache[c] = currentMaterial;
|
|
|
|
}
|
|
|
|
// get meshes
|
|
for(var mesh_id = 0; mesh_id < meshes.length; mesh_id++) {
|
|
|
|
this.json.parsedMeshes[mesh_id] = [];
|
|
|
|
var meshInfo = meshes[mesh_id];
|
|
|
|
this.parseMesh( meshInfo, mesh_id );
|
|
|
|
|
|
}
|
|
|
|
this.addModel( this.json );
|
|
|
|
|
|
|
|
|
|
//kepler.resources.loadNextTexture();
|
|
|
|
this.buildModels(materialCache);
|
|
|
|
}
|
|
|
|
parseMesh( meshInfo, mesh_id ) {
|
|
|
|
|
|
/*
|
|
if(meshInfo.faces.length > 60000) {
|
|
var cutFaces = meshInfo.faces.splice(60000, meshInfo.faces.length);
|
|
|
|
var newMesh = JSON.parse(JSON.stringify( meshInfo ));
|
|
|
|
newMesh.faces = cutFaces;
|
|
newMesh.name = "sliced mesh";
|
|
|
|
|
|
this.parseMesh( newMesh, mesh_id );
|
|
}
|
|
*/
|
|
//facesOriginal =
|
|
|
|
//console.log("meshInfo.faces", meshInfo.faces.length);
|
|
|
|
|
|
//flatten
|
|
var indices = [];
|
|
var vertices = [];
|
|
var normals = [];
|
|
|
|
for(var i = 0; i<meshInfo.faces.length; i++) {
|
|
var face = meshInfo.faces[i];
|
|
|
|
|
|
|
|
indices[i * 3] = face[0];
|
|
indices[i * 3 + 1] = face[1];
|
|
indices[i * 3 + 2] = face[2];
|
|
|
|
}
|
|
|
|
|
|
var min = getMin(indices);
|
|
var max = getMax(indices);
|
|
|
|
|
|
var minVert = min;
|
|
var maxVert = ((max ) ) - minVert; // number of items (x,y,z) = 3, 3 x 3 = face
|
|
|
|
var minUV = min;
|
|
var maxUV = ((max)) - minUV;
|
|
|
|
|
|
for(var i = 0; i<indices.length; i++) {
|
|
|
|
// indices[i] = indices[i] ;// - min;
|
|
|
|
|
|
}
|
|
|
|
//console.log(min, max);
|
|
|
|
//console.log("meshInfo.vertices", meshInfo.vertices.length);
|
|
|
|
|
|
|
|
|
|
function getMax(arr) {
|
|
let len = arr.length;
|
|
let max = -Infinity;
|
|
|
|
while (len--) {
|
|
max = arr[len] > max ? arr[len] : max;
|
|
}
|
|
return max;
|
|
}
|
|
|
|
function getMin(arr) {
|
|
let len = arr.length;
|
|
let min = Infinity;
|
|
|
|
while (len--) {
|
|
min = arr[len] < min ? arr[len] : min;
|
|
}
|
|
return min;
|
|
}
|
|
|
|
//console.log(getMax(indices));
|
|
|
|
var currentMesh = new mesh();
|
|
|
|
if( meshInfo.texturecoords ){
|
|
|
|
console.log( meshInfo, "Meshinfo" );
|
|
|
|
var sliced_vertices = meshInfo.vertices;//.splice(minVert, maxVert);//.slice(min, max);
|
|
|
|
var sliced_normals = meshInfo.normals;//splice(minVert, maxVert);
|
|
|
|
var sliced_tangents = meshInfo.tangents;
|
|
|
|
var sliced_uv = meshInfo.texturecoords[0];//.slice(minUV, maxUV);
|
|
|
|
currentMesh.createMeshFromArrays( indices, sliced_vertices, sliced_normals, sliced_uv, sliced_tangents, meshInfo.bitangents );
|
|
|
|
currentMesh.material = meshInfo.materialindex;
|
|
|
|
}
|
|
|
|
this.json.parsedMeshes[mesh_id].push(currentMesh);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
parseNode( currentAssimpJson, assimpNode, parentEntity, scene, materialCache ) {
|
|
|
|
var currentEntity = new entity(this.engine);
|
|
currentEntity.name = assimpNode.name;
|
|
currentEntity.transform.world = matrix4.fromArray(assimpNode.transformation);
|
|
currentEntity.transform.local = matrix4.fromArray(assimpNode.transformation);
|
|
|
|
if(this.nameIsLight(currentEntity.name)) {
|
|
currentEntity.type = "PointLight";
|
|
|
|
scene.addEntity( currentEntity );
|
|
} else {
|
|
|
|
if(assimpNode.meshes) {
|
|
currentEntity.type = "Actor";
|
|
} else {
|
|
currentEntity.type = "transform";
|
|
scene.addEntity( currentEntity );
|
|
}
|
|
|
|
}
|
|
|
|
if(assimpNode.meshes) {
|
|
|
|
|
|
var meshID = assimpNode.meshes[0];
|
|
var meshes = currentAssimpJson.parsedMeshes[meshID];
|
|
|
|
for(var c = 0;c<meshes.length;c++) {
|
|
|
|
var currentMesh = meshes[c];
|
|
|
|
var currentEntity = new entity(this.engine);
|
|
currentEntity.name = assimpNode.name;
|
|
currentEntity.transform.world = matrix4.fromArray(assimpNode.transformation);
|
|
currentEntity.transform.local = matrix4.fromArray(assimpNode.transformation);
|
|
currentEntity.type = "Actor";
|
|
|
|
//if(global_material_id < 30) {
|
|
//var mesh = currentAssimpJson.parsedMeshes[meshID];
|
|
|
|
var transformation = assimpNode.transformation;
|
|
//var materialInfo = mesh.material;//new material();
|
|
var materialID = currentMesh.material;
|
|
|
|
|
|
var Material = materialCache[materialID];
|
|
|
|
|
|
if(Material) {
|
|
|
|
|
|
|
|
currentMesh.addMaterial(Material);
|
|
|
|
|
|
|
|
currentEntity.addMesh(currentMesh);
|
|
|
|
//currentEntity.transform.world = matrix4.mul( matrix4.fromArray(transformation), matrix4.fromArray( rootnode.transformation ) );
|
|
|
|
|
|
currentEntity.transform.local = matrix4.fromArray(transformation);
|
|
currentEntity.transform.position = matrix4.getWorldPosition(currentEntity.transform.local);
|
|
currentEntity.transform.scale = matrix3.getScale( currentEntity.transform.local );
|
|
currentEntity.transform.rotation = matrix3.getRotation( currentEntity.transform.local );
|
|
currentEntity.transform.world = currentEntity.transform.local;//matrix4.mul( parentEntity.transform.world, entity.transform.local );
|
|
//entity.objectTransform = matrix4.mul( matrix4.fromArray(transformation), matrix4.fromArray( rootnode.transformation ) );
|
|
|
|
var normMatrix = matrix3.normalizeMatrix( currentEntity.transform.local ) ;
|
|
|
|
//currentEntity.mesh.boundingBox = new boundingBox();
|
|
//currentEntity.mesh.boundingBox.fitBoxToPoints_( currentMesh.subMeshes[0].vertices, normMatrix );
|
|
|
|
scene.addEntity( currentEntity, currentEntity.transform.local, materialCache );
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
parentEntity.addChild(currentEntity);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
parentEntity.addChild(currentEntity);
|
|
|
|
}
|
|
|
|
|
|
|
|
//if(child.name == "Bip001") {
|
|
|
|
//this.parseSkeleton( child );
|
|
|
|
//}
|
|
|
|
if(assimpNode.children) {
|
|
var children = assimpNode.children;
|
|
|
|
for(var i = 0; i < children.length; i++) {
|
|
var child = children[i];
|
|
|
|
this.parseNode(currentAssimpJson, child, currentEntity, scene, materialCache);
|
|
}
|
|
}
|
|
|
|
//console.log(this.engine.system.scene);
|
|
}
|
|
|
|
|
|
|
|
buildModels( materialCache ) {
|
|
|
|
var scene = this.scene;
|
|
//var materialCache = this.materialCache;
|
|
|
|
var rootEntity = new entity(this.engine);
|
|
rootEntity.name = "root";
|
|
rootEntity.transform.world = matrix4.identity();
|
|
|
|
//this.engine.system.scene.rootEntity = rootEntity;
|
|
scene.rootEntity = rootEntity;
|
|
|
|
|
|
if(materialCache) {
|
|
|
|
for(var c = 0; c<materialCache.length; c++) {
|
|
var materialInfo = materialCache[c];
|
|
/*
|
|
var currentMaterial = new material( );
|
|
|
|
|
|
|
|
var diffuseTexture = materialInfo.diffuseTexture; //kepler.resources.getTexture( materialInfo.name + "_diffuse");
|
|
|
|
if(diffuseTexture) {
|
|
var diffuseSampler = new sampler2D();
|
|
|
|
diffuseSampler.addTexture(diffuseTexture);
|
|
|
|
//currentMaterial.addTexture(diffuseSampler);
|
|
|
|
console.log(materialInfo.name + "_diffuse", currentMaterial);
|
|
} else{
|
|
console.log("noo _diffuse", currentMaterial);
|
|
|
|
}
|
|
|
|
var normalTexture = kepler.resources.getTexture(materialInfo.name + "_normal");
|
|
|
|
if(normalTexture) {
|
|
var normalSampler = new sampler2D();
|
|
normalSampler.addTexture(normalTexture);
|
|
//currentMaterial.addNormal(normalSampler);
|
|
}
|
|
|
|
var roughnessTexture = kepler.resources.getTexture(materialInfo.name + "_normal");
|
|
|
|
if(roughnessTexture) {
|
|
var roughnessSampler = new sampler2D();
|
|
roughnessSampler.addTexture(roughnessTexture);
|
|
//currentMaterial.addRoughness(roughnessSampler);
|
|
}
|
|
|
|
var depthTexture = kepler.resources.getTexture(materialInfo.name + "_depth");
|
|
|
|
if(depthTexture) {
|
|
//var roughnessSampler = new sampler2D(this.engine);
|
|
//roughnessSampler.addTexture(depthTexture);
|
|
//material.addDisplacement(roughnessSampler);
|
|
}
|
|
|
|
|
|
|
|
currentMaterial.diffuseColor = materialInfo.diffuseColor;
|
|
currentMaterial.roughness = materialInfo.roughness;
|
|
|
|
|
|
currentMaterial.alpha = materialInfo.opacity;
|
|
|
|
//var shadingModelID = this.getShadingIdByEntityName(material.id);
|
|
|
|
//material.setShadingModelID(shadingModelID);
|
|
|
|
//currentMaterial.create();
|
|
|
|
materialCache[c] = currentMaterial;
|
|
*/
|
|
}
|
|
|
|
var models = this.models;
|
|
|
|
// matrix4.fromArray( rootnode.transformation );
|
|
|
|
|
|
|
|
for(var c = 0; c<models.length; c++) {
|
|
var currentAssimpJson = models[c];
|
|
var rootnode = currentAssimpJson.rootnode;
|
|
var children = rootnode.children;
|
|
|
|
|
|
|
|
this.parseNode(currentAssimpJson, rootnode, rootEntity, scene, materialCache);
|
|
}
|
|
}
|
|
}
|
|
|
|
parseSkeleton( child ) {
|
|
|
|
this.skeleton = this.engine.createObject("skeleton");
|
|
|
|
this.skeleton.parse(child, this.rootnode);
|
|
this.skeleton.parseAnimation(this.animations[0].channels);
|
|
|
|
|
|
|
|
var bones = this.skeleton.bones;
|
|
|
|
|
|
for(var c = 0; c<bones.length; c++) {
|
|
|
|
var bone = bones[c];
|
|
|
|
this.skeleton.animate(bone, 0);
|
|
|
|
|
|
|
|
var transform = bone.globalTransformation;
|
|
|
|
var mesh = this.meshes[1];
|
|
|
|
var currentEntity = new entity(this.engine);
|
|
|
|
|
|
//var diffuseTexture = kepler.resources.getTexture(mesh.material.name + "_diffuse");
|
|
//var diffuseSampler = new sampler2D(this.engine);
|
|
//diffuseSampler.texture = diffuseTexture;
|
|
|
|
var material = mesh.material;
|
|
//material.addTexture(diffuseSampler);
|
|
|
|
|
|
mesh.addMaterial(material);
|
|
|
|
currentEntity.addMesh(mesh);
|
|
currentEntity.bone = bone;
|
|
currentEntity.transform.world = transform;
|
|
|
|
|
|
bone.entity = currentEntity;
|
|
|
|
//this.engine.system.scene.addEntity(entity);
|
|
|
|
}
|
|
|
|
//this.animate();
|
|
|
|
|
|
//console.log(this.skeleton);
|
|
}
|
|
|
|
|
|
animate( ) {
|
|
var entitys = this.scene.getEntitys();
|
|
|
|
for(var c = 0; c<entitys.length; c++) {
|
|
|
|
var bone = entitys[c].bone;
|
|
if(bone) {
|
|
|
|
var bone = this.skeleton.animate(bone, floor(asdasd/2));
|
|
|
|
entitys[c].transform.world = bone.globalTransformation;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getPropertyByName( properties, name, semantic ) {
|
|
|
|
for(var c = 0; c<properties.length; c++) {
|
|
var property = properties[c];
|
|
|
|
if(property.key == name && property.semantic == semantic)
|
|
return property;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export {assimp as default}; |