Files
Kepler/engine/assimp.js

795 lines
17 KiB
JavaScript
Raw Normal View History

2025-11-17 17:18:43 +01:00
/*
* 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};