Team Updates

Hackaton NASA 18
view raw 1 hosted with ❤ by GitHub
:host {
overflow: hidden;
width: 100%;
height: 100%;
display: flex;
}
.model {
width: 100%;
height: 100%;
}
<canvas #canvas class="model" (click)="onClick($event)"></canvas>
import {
Component,
ElementRef,
EventEmitter,
HostListener,
OnInit,
Output,
ViewChild,
Input
} from '@angular/core';
import { Object3D, TextureLoader, Group, TGALoader, MeshPhongMaterial, CanvasTexture, Vector3 } from 'three';
import * as THREE from 'three';
import './js/EnableThreeExamples';
import 'three/examples/js/loaders/OBJLoader';
import 'three/examples/js/loaders/MTLLoader';
import 'three/examples/js/loaders/TDSLoader';
import 'three/examples/js/loaders/TGALoader';
import 'three/examples/js/controls/OrbitControls';
import 'three/examples/js/controls/TrackballControls.js';
import { ThreeDModel } from '../models/3d.model';
@Component({
selector: 'app-scene',
templateUrl: './app-scene.component.html',
styleUrls: ['./app-scene.component.css']
})
export class AppSceneComponent implements OnInit {
_selectedModel: ThreeDModel;
@Input()
set selectedModel(value: ThreeDModel) {
this._selectedModel = value;
this.changeModel();
}
get selectedModel(): ThreeDModel {
return this._selectedModel;
}
@Input() selectedLogo: ThreeDModel;
@Input() imageSize: number;
@Output() clickIntersect = new EventEmitter<Object3D>();
@ViewChild('canvas') private canvasRef: ElementRef;
private renderer: THREE.WebGLRenderer;
private camera: THREE.PerspectiveCamera;
public advertCanvas: HTMLCanvasElement;
public scene: THREE.Scene;
public controls: THREE.OrbitControls;
private currentObject: Object3D;
private object: Object3D;
private loader;
public color: THREE.Color;
public texture: THREE.CanvasTexture;
private normalLoader: TextureLoader;
private textureLoader: TGALoader;
public fieldOfView = 60;
public nearClippingPane = 1;
public farClippingPane = 1100;
public canvasSize = 4096;
private animationTimer;
backgroundScene: THREE.Scene;
backgroundCamera: THREE.Camera;
/* LIFECYCLE */
ngOnInit() {
window['a'] = this;
this.createBackground();
this.createCamera();
this.createLight();
this.startRendering();
this.addControls();
}
createBackground(): any {
const texture = THREE.ImageUtils.loadTexture('assets/background.jpg');
const backgroundMesh = new THREE.Mesh(
new THREE.PlaneGeometry(4, 4, 0),
new THREE.MeshBasicMaterial({
map: texture
}));
(backgroundMesh .material as any).depthTest = false;
(backgroundMesh .material as any).depthWrite = false;
// Create your background scene
this.backgroundScene = new THREE.Scene();
this.backgroundCamera = new THREE.Camera();
this.backgroundScene.add(this.backgroundCamera);
this.backgroundScene.add(backgroundMesh);
}
private get canvas(): HTMLCanvasElement {
return this.canvasRef.nativeElement;
}
private changeModel() {
if (!this.selectedModel) {
return;
}
this.initNewScene();
let obj;
if (obj = this.scene.getObjectByName('currObj')) {
obj.parent.remove(obj);
this.animationTimer = null;
this.render();
}
// if (this.selectedModel.name === 'Astronaut') {
// this.animationTimer = null;
// this.createSce();
// return;
// }
if (this.selectedModel.name === 'Astronaut') {
this.animationTimer = null;
this.createAstronaut2();
return;
}
if (this.selectedModel.name === 'Arian-1') {
this.animationTimer = null;
this.createRocket();
return;
}
this.createScene();
}
private createRocket() {
let texture;
const manager = new THREE.LoadingManager(() => { });
this.textureLoader = new THREE.TextureLoader(manager);
texture = this.textureLoader.load('assets/rocket1/rocket.jpg');
this.loader = new (THREE as any).MTLLoader();
this.loader.setPath(`assets/rocket1/`);
this.loader.load(`12217_rocket_v1_l1.mtl`, e => {
e.preload();
new (THREE as any).OBJLoader()
.setPath('assets/rocket1/')
.load('12217_rocket_v1_l1.obj', (object) => {
this.object = object;
window['r'] = this.object;
this.object.position.set(0, -5.5, 0);
this.object.scale.set(0.01, 0.01, 0.01);
this.object.receiveShadow = false;
this.animationTimer = this.startObjectAnimation(this.object);
// this.camera.lookAt(this.object.position);
this.object.traverse(child => {
this.addCanvasTexture(child, this.object, texture);
});
this.object.name = 'currObj';
this.scene.add(this.object);
this.render();
}, x => { }, err => { });
});
}
private createSce() {
this.loader = new (THREE as any).TDSLoader();
this.loader.setResourcePath(`assets/astronaut/textures/`);
this.loader.load(`assets/astronaut/astronaut.3ds`, e => this.onAstroLoading(e));
this.textureLoader = new THREE.TGALoader();
this.render();
}
private createAstronaut2() {
new (THREE as any).OBJLoader()
.setPath('assets/astronaut2/')
.load('astronaut2.obj', (object) => {
this.object = object;
window['e'] = this.object;
this.object.traverse(child => {
this.addCanvasTexture(child, this.object, texture);
});
this.object.position.set(0, -7, 0);
this.object.receiveShadow = false;
this.object.scale.set(8, 8, 8);
this.animationTimer = this.startObjectAnimation(this.object);
this.object.name = 'currObj';
this.scene.add(this.object);
this.render();
}, x => { }, err => { });
let texture;
const manager = new THREE.LoadingManager(() => { });
this.textureLoader = new THREE.TextureLoader(manager);
texture = this.textureLoader.load('assets/astronaut2/z2_Color_s.jpg');
// this.loader = new (THREE as any).MTLLoader();
// this.loader.setPath(`assets/astronaut2/`);
// this.loader.load(`astronaut2.mtl`, e => {
// e.preload();
// });
}
startObjectAnimation(object: Object3D) {
return setInterval(() => {
object.rotateY(0.1);
this.render();
}, 100);
}
private onAstroLoading(collada: Group) {
collada.children.forEach((e: THREE.Mesh) => {
const text = this.textureLoader.load('assets/astronaut/textures/astnt1_1.tga');
this.addCanvasTexture(e, this.object, text);
});
collada.name = 'currObj';
this.scene.add(collada);
}
private createScene() {
this.loader = new (THREE as any).TDSLoader();
this.normalLoader = new TextureLoader();
const normal = this.normalLoader.load(`assets/${this.selectedModel.path}/textures/${this.selectedModel.normal}`);
this.loader.setResourcePath(`assets/${this.selectedModel.path}/textures/`);
this.loader.load(`assets/${this.selectedModel.path}/${this.selectedModel.path}.3ds`,
e => this.onModelLoadingCompleted(e, normal));
}
private initNewScene() {
this.scene = new THREE.Scene();
// this.scene.add(new THREE.AxesHelper(200));
const light = new THREE.HemisphereLight();
this.scene.add(light);
if (this.camera) {
this.scene.add(this.camera);
}
}
private onModelLoadingCompleted(collada, normal) {
this.currentObject = collada;
this.currentObject.traverse(object => {
this.addCanvasTexture(object, this.currentObject, normal, true);
});
this.currentObject.receiveShadow = false;
this.currentObject.name = 'currObj';
this.scene.add(this.currentObject);
this.animationTimer = this.startObjectAnimation(this.currentObject);
this.render();
}
private setupCanvas(): void {
this.advertCanvas = document.createElement('canvas');
this.advertCanvas.width = this.canvasSize;
this.advertCanvas.height = this.canvasSize;
this.color = new THREE.Color();
this.texture = new THREE.CanvasTexture(this.advertCanvas);
}
private addCanvasTexture(object, currentObject, normal, isNormal = false): void {
this.setupCanvas();
const child = object as any;
if (!object.isMesh && !child.material) {
return;
}
isNormal ? child.material.normalMap = normal : child.material.map = normal;
child.material.lightMap = normal;
currentObject.add(new THREE.Mesh(child.geometry, new MeshPhongMaterial({
map: this.texture,
alphaTest: 0.5
})));
}
private createLight() {
// var directionalLight = new THREE.DirectionalLight( 0xffeedd );
// directionalLight.position.set( 0, 0, 2 );
// this.scene.add( directionalLight );
}
private createCamera() {
const aspectRatio = this.getAspectRatio();
this.camera = new THREE.PerspectiveCamera(
this.fieldOfView,
aspectRatio,
this.nearClippingPane,
this.farClippingPane
);
/**
* x: -13.51642127467603
y: 0.20744722870848967
z: -19.82593506593228
*/
// Set position and look at
this.camera.position.x = -10;
this.camera.position.y = 0.75;
this.camera.position.z = -17;
this.camera.rotation.x = -2;
this.camera.rotation.y = 0;
this.camera.rotation.z = -2;
}
private getAspectRatio(): number {
const height = this.canvas.clientHeight;
if (height === 0) {
return 0;
}
return this.canvas.clientWidth / this.canvas.clientHeight;
}
private startRendering() {
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
antialias: true
});
this.renderer.setPixelRatio(devicePixelRatio);
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.renderer.setClearColor(0x1B1B1B, 1);
this.renderer.autoClear = true;
this.render();
}
public render() {
if (this.renderer && this.scene) {
this.renderer.autoClear = false;
this.renderer.clear();
this.renderer.render(this.backgroundScene , this.backgroundCamera);
this.renderer.render(this.scene, this.camera);
}
}
public addControls() {
this.controls = new THREE.OrbitControls(this.camera);
this.controls.rotateSpeed = 1.0;
this.controls.zoomSpeed = 1.2;
this.controls.addEventListener('change', () => this.render());
}
/* EVENTS */
public onClick(event: MouseEvent) {
// Example of mesh selection/pick:
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
mouse.x = ((event.clientX - 300) / this.renderer.domElement.clientWidth) * 2 - 1;
mouse.y = - (event.clientY / this.renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
const obj: THREE.Object3D[] = [];
this.findAllObjects(obj, this.scene);
const intersects = raycaster.intersectObjects(obj);
// console.log('Scene has ' + obj.length + ' objects');
// console.log(intersects.length + ' intersected objects found');
if (intersects && intersects.length) {
intersects.forEach((intersect, index) => {
if (index > 1) {
return;
}
// console.log(intersect);
const object = intersect.object;
if (intersect.uv && object && (object as any).material && (object as any).material.map instanceof CanvasTexture) {
this.addCanvasObject({
offsetX: intersect.uv.x * this.canvasSize,
offsetY: (1 - intersect.uv.y) * this.canvasSize
});
}
this.clickIntersect.emit(object);
});
}
}
public addCanvasObject(event: { offsetX: number, offsetY: number }): void {
if (!this.selectedLogo) {
return;
}
const ctx = this.advertCanvas.getContext('2d');
const image = new Image(750, 750);
image.src = this.selectedLogo.path;
ctx.drawImage(image,
event.offsetX - this.imageSize / 2,
event.offsetY - this.imageSize / 2,
this.imageSize, this.imageSize
);
this.texture.needsUpdate = true;
this.render();
}
private findAllObjects(pred: THREE.Object3D[], parent: THREE.Object3D) {
// NOTE: Better to keep separate array of selected objects
if (parent.children.length > 0) {
parent.children.forEach((i) => {
pred.push(i);
this.findAllObjects(pred, i);
});
}
}
@HostListener('window:resize', ['$event'])
public onResize() {
this.canvas.style.width = '100%';
this.canvas.style.height = '100%';
// console.log('onResize: ' + this.canvas.clientWidth + ', ' + this.canvas.clientHeight);
this.camera.aspect = this.getAspectRatio();
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
this.render();
}
public splitByMaterial(geometry, materials) {
const parts = [];
const faces = ['a', 'b', 'c'];
let geo, vMap, iMat;
geometry.faces.forEach(face => {
if (face.materialIndex !== iMat) {
if (iMat) {
this.addPart(materials, iMat, parts, geo);
}
geo = new THREE.Geometry();
vMap = {};
iMat = face.materialIndex;
}
const f = face.clone();
faces.forEach(p => {
const iv = face[p];
if (!vMap.hasOwnProperty(iv)) {
vMap[iv] = geo.vertices.push(geometry.vertices[iv]) - 1;
}
f[p] = vMap[iv];
});
geo.faces.push(f);
});
this.addPart(materials, iMat, parts, geo);
return parts;
}
private addPart(materials, iMat, parts, geo): void {
const mat = materials ? Object.assign({}, materials[iMat]) : {};
mat.side = THREE.DoubleSide;
parts.push(new THREE.Mesh(geo, mat));
}
}
THREE=require('three');
yauheni.dzirvukYauheni Dzirvuk
Team Stream Item
yauheni.dzirvukYauheni Dzirvuk
NASA Logo

SpaceApps is a NASA incubator innovation program.