Home Reference Source

scripts/model/model.js

import {EVENT_LOADED, EVENT_LOADING, EVENT_GLTF_READY} from '../core/events.js';
import {EventDispatcher, Vector3, Mesh} from 'three';
import {Floorplan} from './floorplan.js';
import {Scene} from './scene.js';

import {OBJExporter} from '../exporters/OBJExporter.js';

import GLTFExporter from 'three-gltf-exporter';

/**
 * A Model connects a Floorplan and a Scene.
 */
export class Model extends EventDispatcher
{
	/** Constructs a new model.
	 * @param textureDir The directory containing the textures.
	 */
	constructor(textureDir)
	{
		super();
		this.floorplan = new Floorplan();
		this.scene = new Scene(this, textureDir);
		this.roomLoadingCallbacks = null;
		this.roomLoadedCallbacks = null;
		this.roomSavedCallbacks = null;
		this.roomDeletedCallbacks = null;

	}

	switchWireframe(flag)
	{
		this.scene.switchWireframe(flag);
	}

	loadSerialized(json)
	{
		// TODO: better documentation on serialization format.
		// TODO: a much better serialization format.
		this.dispatchEvent({type: EVENT_LOADING, item: this});
		//      this.roomLoadingCallbacks.fire();

		var data = JSON.parse(json);
		this.newRoom(data.floorplan, data.items);

		this.dispatchEvent({type: EVENT_LOADED, item: this});
		//      this.roomLoadedCallbacks.fire();
	}

	exportMeshAsObj()
	{
		var exporter = new OBJExporter();
		return exporter.parse(this.scene.getScene());
	}

	exportForBlender()
	{
		var scope = this;
		var gltfexporter = new GLTFExporter();
		var meshes = [];
		this.scene.getScene().traverse( function(child)
		{
			if (child instanceof Mesh)
			{
				if(child.material)
				{
					if(child.material.length || child.material.visible)
					{
						var op = (child.material.transparent)? child.material.opacity: undefined;
						meshes.push(child);
						if(op)
						{
							child.material.opacity = op;
						}
					}
				}
			}
		  });

		gltfexporter.parse(meshes, function(result)
		{
			var output = JSON.stringify( result, null, 2 );
			scope.dispatchEvent({type:EVENT_GLTF_READY, item: this, gltf: output});
		});
	}

	exportSerialized()
	{
		var items_arr = [];
		var objects = this.scene.getItems();
		for (var i = 0; i < objects.length; i++)
		{
			var obj = objects[i];
//			items_arr[i] = {item_name: obj.metadata.itemName,item_type: obj.metadata.itemType,model_url: obj.metadata.modelUrl,xpos: obj.position.x,ypos: obj.position.y,zpos: obj.position.z,rotation: obj.rotation.y,scale_x: obj.scale.x,scale_y: obj.scale.y,scale_z: obj.scale.z,fixed: obj.fixed};
			items_arr[i] = obj.getMetaData();
		}

		var room = {floorplan: (this.floorplan.saveFloorplan()),items: items_arr};
		return JSON.stringify(room);
	}

	newRoom(floorplan, items)
	{
		this.scene.clearItems();
		this.floorplan.loadFloorplan(floorplan);
		items.forEach((item) => {
			var matColors = (item.material_colors) ? item.material_colors : [];
			var position = new Vector3(item.xpos, item.ypos, item.zpos);
			var metadata = {itemName: item.item_name,resizable: item.resizable,format: item.format, itemType: item.item_type, modelUrl: item.model_url, materialColors: matColors};
			var scale = new Vector3(item.scale_x,item.scale_y,item.scale_z);
			this.scene.addItem(item.item_type,item.model_url,metadata,position,item.rotation,scale,item.fixed);
		});
	}
}