Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import * as http from "http";
- import httpRequest = require("request");
- import {Box3, Material, Object3D, ObjectLoader, Texture} from "three";
- import * as THREE from "three";
- import {IModel3DStreamItem, IUserData} from "../../../../helpers/interfaces";
- import {IstreamObjectItem} from "../../../../models/interfaces";
- import {model3DModel} from "../../../../models/model3D/model3D";
- import {IModel3DDocument} from "../../../../models/model3D/schema";
- import {model3DStreamModel} from "../../../../models/model3D_stream/model3D_stream";
- import {fo, Logger, SkyviewerContext} from "../../../../services/logger";
- import {getUploadsPath} from "./helper";
- import {
- IModel3DBoundingBox,
- IModel3DCategorySortedObjects,
- IModel3DFile,
- IModel3DFileImage,
- IModel3DGhostObject,
- IModel3DMaterial,
- IModel3DMesh,
- IModel3DPreProcessDataItem,
- IModel3DStreamingClientMetaData,
- } from "./interfaces";
- const logger = new Logger(SkyviewerContext.SERVER);
- export async function preProcessModel(model3dGuid: string, userData: IUserData, token: string | string[]): Promise<IModel3DDocument> {
- try {
- const loader: ObjectLoader = new THREE.ObjectLoader();
- const model3D: IModel3DDocument = await model3DModel.getModel3DByGuid(userData.companyId, model3dGuid);
- const fileLocation: string = getUploadsPath() + model3D.stats.model3D.fileName;
- logger.log("File should be at: " + fileLocation);
- const file: string = await retrieveFile(fileLocation, token as string);
- const objectModel: IModel3DFile = JSON.parse(file);
- const model = await parseModel(objectModel, loader);
- return await processModel(model, model3dGuid, userData);
- } catch (error) {
- logger.error(`preProcessModel::${fo(error)}`);
- return error;
- }
- }
- export async function retrieveFile(fileLocation: string, token: string): Promise<string> {
- try {
- return new Promise((resolve: (data) => void, reject: (data) => void) => {
- try {
- httpRequest({
- uri: fileLocation,
- method: "GET",
- timeout: 1000000,
- headers: {
- "Authorization": token,
- "Accept": "*/*",
- "Accept-language": "en-US,en;q=0.8",
- },
- agent: new http.Agent({ keepAlive: false }),
- }, function(err: Error, res) {
- if (err) {
- console.log(err);
- reject("error on getting file data from Services3D");
- }
- resolve(res.body);
- });
- } catch (e) {
- logger.log(`error on getting file data from Services3D:: ${e}`);
- }
- });
- } catch (error) {
- logger.log(`error on getting file data from Services3DFunction::${fo(error)}`);
- return error;
- }
- }
- export async function parseModel(json: IModel3DFile, loader: ObjectLoader): Promise<Object3D> {
- try {
- const geometries: Object3D[] = loader.parseGeometries( json.geometries );
- const images: Array<{ url: string }> = await parseImages(json.images);
- const textures: Texture[] = loader.parseTextures( json.textures, images );
- const materials: Material[] = loader.parseMaterials( json.materials, textures );
- return loader.parseObject( json.object, geometries, materials );
- } catch (error) {
- logger.error(`ParseModel::${fo(error)}`);
- return error;
- }
- }
- export async function parseImages(images: IModel3DFileImage[]): Promise<Array<{ url: string }>> {
- try {
- const out: Array<{ url: string }> = [];
- if (images !== undefined) {
- images.forEach((value: { uuid: string, url: string}) => {
- out[value.uuid] = value.url;
- });
- }
- return out;
- } catch (error) {
- logger.error(`parseImages::${fo(error)}`);
- return error;
- }
- }
- export async function processModel(model: Object3D, modelGuid: string, userData: IUserData): Promise<IModel3DDocument> {
- try {
- model.scale.set(0.001, 0.001, 0.001);
- model.updateMatrixWorld(true);
- const ghostObjects: IModel3DGhostObject[] = await createGhostObjects(model);
- const streamingObjects: IstreamObjectItem[] = await createStreamingObjects(model, modelGuid);
- const materials: IModel3DMaterial[] = await createMaterialDefinitions(model);
- const boundingBox: IModel3DBoundingBox = await getModelBoundingBox(model);
- const categorySortedObjectList: string[] = await getCategorySortedObjectList(model);
- const streamingObjectList: string[] = await getStreamingObjectIds(model);
- const preProcessDataArray: IModel3DPreProcessDataItem[] = [];
- const clientMetaData: { modelBoundingBox: IModel3DBoundingBox } = {
- modelBoundingBox: boundingBox,
- };
- const preProcessData: IModel3DPreProcessDataItem = {
- type: "Generic",
- metaData: clientMetaData,
- listOfIdsToStreamFirst: categorySortedObjectList,
- };
- const q = model.quaternion;
- const p = model.position;
- model.children = [];
- const streamingClientMetaData: IModel3DStreamingClientMetaData = {
- modelBoundingBox: boundingBox,
- model: {
- quaternion: {x: q.x, y: q.y, z: q.z, w: q.w},
- position: {x: p.x, y: p.y, z: p.z},
- },
- materials,
- uuid: modelGuid,
- ghostObjects,
- };
- // TODO: Find the right type here
- const streamingData: IModel3DPreProcessDataItem = {
- type: "streaming",
- metaData: streamingClientMetaData,
- listOfIdsToStreamFirst: streamingObjectList,
- };
- preProcessDataArray.push(preProcessData);
- preProcessDataArray.push(streamingData);
- await model3DModel.updateModel3DPreProcessedDataArray(modelGuid, preProcessDataArray, userData);
- await model3DStreamModel.setModel3DStreamObjectItems(streamingObjects);
- await model3DModel.updateModel3DPreProcessedStatus(modelGuid, "done", userData);
- return await model3DModel.getModel3DByGuid(userData.companyId, modelGuid);
- } catch (error) {
- logger.error(`ProcessModel::${fo(error)}`);
- return error;
- }
- }
- export async function createGhostObjects(model: Object3D): Promise<IModel3DGhostObject[]> {
- try {
- const ghostObjects: IModel3DGhostObject[] = [];
- for (let i = 0; i < model.children.length; i++) {
- const child: Object3D = model.children[i];
- if (!child) { return; }
- const category = child.userData.category;
- let transparent = false;
- const meshes: IModel3DMesh[] = [];
- for (const mesh of child.children) {
- // @ts-ignore
- if (mesh && mesh.material) {
- // @ts-ignore
- if (mesh.material.transparent) {
- transparent = true;
- continue;
- }
- }
- const box: Box3 = new THREE.Box3().setFromObject(mesh);
- const boundingBox: IModel3DBoundingBox = {
- max: { x: box.max.x, y: box.max.y, z: box.max.z },
- min: { x: box.min.x, y: box.min.y, z: box.min.z },
- };
- meshes.push({
- uuid: mesh.uuid,
- boundingBox,
- visible: mesh.visible,
- });
- }
- let staticObject = false;
- // These objects are not removed when they are no longer visible on client side
- if (category === "Walls" || transparent) {
- staticObject = true;
- }
- const key = i;
- const uuid = child.uuid;
- const ghostObject: IModel3DGhostObject = {
- uuid,
- name: child.name,
- id: child.id,
- key,
- static: staticObject,
- userData: child.userData,
- meshes,
- };
- ghostObjects.push(ghostObject);
- }
- return ghostObjects;
- } catch (error) {
- logger.error(`CreateGhostObjects::${fo(error)}`);
- return error;
- }
- }
- export async function createStreamingObjects(model: Object3D, model3DGuid: string): Promise<IstreamObjectItem[]> {
- try {
- const streamingObjects: IstreamObjectItem[] = [];
- for (const child of model.children) {
- if (!child) { return; }
- const meshes: IModel3DMesh[] = [];
- for (const mesh of child.children) {
- // @ts-ignore
- if (mesh && mesh.material && mesh.geometry) {
- // @ts-ignore
- let geometry = mesh.geometry;
- // @ts-ignore
- if (mesh.geometry.type !== "BufferGeometry") {
- geometry = new THREE.BufferGeometry();
- // @ts-ignore
- geometry = geometry.fromGeometry(mesh.geometry);
- }
- const geometryCloned = geometry.clone();
- geometryCloned.applyMatrix(mesh.parent.matrix);
- meshes.push({
- uuid: mesh.uuid,
- // @ts-ignore
- materialId: mesh.material.uuid,
- position: geometryCloned.attributes.position.array,
- visible: mesh.visible,
- });
- }
- }
- const object: IModel3DStreamItem = {
- uuid: child.uuid,
- name: child.name,
- model3D: model3DGuid,
- meshes,
- };
- streamingObjects.push(object);
- }
- return streamingObjects;
- } catch (error) {
- logger.error(`CreateStreamingObjects::${fo(error)}`);
- return error;
- }
- }
- export async function createMaterialDefinitions(model: Object3D): Promise<IModel3DMaterial[]> {
- try {
- const materialMapping: IModel3DMaterial[] = [];
- for (const child of model.children) {
- if (!child) { return; }
- for (const mesh of child.children) {
- if (mesh && mesh.material && materialMapping[mesh.material.uuid] == null) {
- const material: IModel3DMaterial = {
- uuid: mesh.material.uuid,
- json: mesh.material.toJSON(),
- };
- materialMapping[material.uuid] = material;
- }
- }
- }
- return materialMapping;
- } catch (error) {
- logger.error(`CreateMaterialDefinitions::${fo(error)}`);
- return error;
- }
- }
- export async function getStreamingObjectIds(model: Object3D): Promise<string[]> {
- try {
- // Add categories that should be loaded last under OtherCategories
- const categorySortedObjects: IModel3DCategorySortedObjects = {
- Walls: [],
- Floors: [],
- Roofs: [],
- Topographies: [],
- OtherCategories: [],
- };
- // Sort each object into category array container
- for (const child of model.children) {
- if (child.userData && child.userData.category && categorySortedObjects[child.userData.category]) {
- categorySortedObjects[child.userData.category].push(child.uuid);
- } else {
- // categorySortedObjects["OtherCategories"].push(child.uuid);
- }
- }
- const categorySortedList: string[] = [];
- // Merge all the category object arrays in the order of the categorySortedObjects
- Object.keys(categorySortedObjects).forEach(function(key) {
- categorySortedObjects[key].forEach(function(id) {
- categorySortedList.push(id);
- });
- });
- return categorySortedList;
- } catch (error) {
- logger.error(`getStreamingObjectIds::${fo(error)}`);
- return error;
- }
- }
- export async function getCategorySortedObjectList(model: Object3D): Promise<string[]> {
- try {
- if (model.type === "Object3D") {
- // Add categories that should be loaded last under OtherCategories
- const categorySortedObjects: IModel3DCategorySortedObjects = {
- Walls: [],
- Floors: [],
- Roofs: [],
- Topographies: [],
- OtherCategories: [],
- };
- // Sort each object into category array container
- for (const child of model.children) {
- if (child.userData && child.userData.category && categorySortedObjects[child.userData.category]) {
- categorySortedObjects[child.userData.category].push(child.uuid);
- } else {
- categorySortedObjects.OtherCategories.push(child.uuid);
- }
- }
- const categorySortedList: string[] = [];
- // Merge all the category object arrays in the order of the categorySortedObjects
- Object.keys(categorySortedObjects).forEach(function(key) {
- categorySortedObjects[key].forEach(function(id) {
- categorySortedList.push(id);
- });
- });
- return categorySortedList;
- }
- } catch (error) {
- logger.error(`getCategorySortedObjectList::${fo(error)}`);
- return error;
- }
- }
- export async function getModelBoundingBox(object: Object3D, box: Box3 = new THREE.Box3()): Promise<IModel3DBoundingBox> {
- try {
- if (object.type === "Object3D") {
- box.setFromObject(object);
- return {
- max: { x: box.max.x, y: box.max.y, z: box.max.z },
- min: { x: box.min.x, y: box.min.y, z: box.min.z },
- };
- }
- } catch (error) {
- logger.error(`getModelBoudingBox::${fo(error)}`);
- return error;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement