Skip to content

Instantly share code, notes, and snippets.

@maxmonax
Created August 11, 2020 08:22
Show Gist options
  • Save maxmonax/2ce7e92f5311348af5c671d10765b297 to your computer and use it in GitHub Desktop.
Save maxmonax/2ce7e92f5311348af5c671d10765b297 to your computer and use it in GitHub Desktop.
import * as THREE from 'three';
import { ThreeLoader } from '../loaders/ThreeLoader';
import { Params } from '../data/Params';
import { LogMng } from '../utils/LogMng';
import { MyMath } from '../utils/MyMath';
import * as ShipData from '../data/ShipData';
import { Config } from '../data/Config';
type SlotPosData = {
pos: THREE.Vector3,
rot: THREE.Euler
};
type ModuleData = {
model: THREE.Group,
matBase: THREE.MeshStandardMaterial,
material: THREE.MeshStandardMaterial,
mat_color: string
};
export class SpaceShip extends THREE.Group {
private ship_id = -1;
private tex_name = '';
private ship: THREE.Group;
private mat: THREE.MeshStandardMaterial;
private matUniforms: any;
private color_h = 1.0;
private color_s = 1.0;
private color_l = .6;
private slotsPosData: SlotPosData[] = [];
private modules: ModuleData[] = [];
//private slot_mat: MeshStandardMaterial;
dirVec = new THREE.Vector3(0, 0, -1);
constructor(a_ship_id: number, a_ship_mod: string) {
super();
this.ship_id = a_ship_id;
this.tex_name = ShipData.shipParams.texture;
let loader = Params.loader;
let shipData = ShipData.SHIP_DATA[this.ship_id];
let shipModelAlias = ShipData.getShipModelAlias(this.ship_id);
LogMng.debug('shipModelAlias = ' + shipModelAlias);
this.ship = loader.getModelGLB(shipModelAlias).scene;
//this.ship.rotation.y = MyMath.toRadian(180);
//this.ship.scale.set(0.2, 0.2, 0.2);
if (Params.isDebugMode) console.log('Ship model:', this.ship);
let color_alias = ShipData.getShipTextureColorAlias(this.tex_name);
LogMng.debug('ship texture color_alias: ' + color_alias);
let t_color = loader.getTexture(color_alias) || null;
let t_map = loader.getTexture(ShipData.getShipTextureMapAlias(this.tex_name)) || null;
let t_map_ems = loader.getTexture(ShipData.getShipTextureMapEmsAlias(this.tex_name)) || null;
if (!t_map_ems) t_map_ems = t_map;
//t_color.flipY = t_map.flipY = t_map_ems.flipY = false;
if (t_color) {
t_color.wrapS = THREE.MirroredRepeatWrapping;
t_color.wrapT = THREE.MirroredRepeatWrapping;
}
if (t_map) {
t_map.wrapS = THREE.MirroredRepeatWrapping;
t_map.wrapT = THREE.MirroredRepeatWrapping;
}
if (t_map_ems) {
t_map_ems.wrapS = THREE.MirroredRepeatWrapping;
t_map_ems.wrapT = THREE.MirroredRepeatWrapping;
}
this.add(this.ship);
let col = new THREE.Color();
//col.setHSL(this.color_h, this.color_s, this.color_l);
col.setHex(0xFFFFFF);
this.mat = new THREE.MeshStandardMaterial({
map: t_color,
color: col,
roughnessMap: t_map,
metalnessMap: t_map,
emissiveMap: t_map_ems,
emissiveIntensity: 3
//roughness: 1,
//metalness: 1,
});
//this.mat.blending = CustomBlending;
//this.mat.blending = NormalBlending;
//this.mat.blending = NoBlending;
this.matUniforms = {
hueShift: { value: 0 },
};
this.mat.onBeforeCompile = shader => {
shader.uniforms.hueShift = this.matUniforms.hueShift;
let main = 'void main('
let out = 'gl_FragColor = vec4( outgoingLight, diffuseColor.a );'
shader.fragmentShader = shader.fragmentShader.split(main).join(`
uniform float hueShift;
vec3 hsl2rgb(vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0);
return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
}
vec3 rgb2hsl(vec3 c){
float cMin=min(min(c.r,c.g),c.b),
cMax=max(max(c.r,c.g),c.b),
delta=cMax-cMin;
vec3 hsl=vec3(0.,0.,(cMax+cMin)/2.);
if(delta!=0.0){ //If it has chroma and isn't gray.
if(hsl.z<.5){
hsl.y=delta/(cMax+cMin); //Saturation.
}else{
hsl.y=delta/(2.-cMax-cMin); //Saturation.
}
float deltaR=(((cMax-c.r)/6.)+(delta/2.))/delta,
deltaG=(((cMax-c.g)/6.)+(delta/2.))/delta,
deltaB=(((cMax-c.b)/6.)+(delta/2.))/delta;
//Hue.
if(c.r==cMax){
hsl.x=deltaB-deltaG;
}else if(c.g==cMax){
hsl.x=(1./3.)+deltaR-deltaB;
}else{ //if(c.b==cMax){
hsl.x=(2./3.)+deltaG-deltaR;
}
hsl.x=fract(hsl.x);
}
return hsl;
}
` + main).split(out).join(out + `
vec3 hsl = rgb2hsl(gl_FragColor.rgb);
hsl.x = fract(hsl.x + hueShift);
gl_FragColor.rgb = hsl2rgb(hsl);
`);
}
this.setEmsColor(ShipData.shipParams.lightsColor);
let t_color_noz = loader.getTexture('ship_fire');
LogMng.debug('t_color_noz:');
console.log(t_color_noz);
t_color_noz.flipY = false;
let matFire = new THREE.MeshBasicMaterial({
map: t_color_noz,
//emissiveIntensity: 3
});
// разбор планетных секторов
this.ship.traverse((child: THREE.Object3D) => {
if (child instanceof THREE.Mesh) {
if (child.name.indexOf('Noz') >= 0) {
// fire
child.material = matFire;
}
else {
child.material = this.mat;
child.castShadow = true;
child.receiveShadow = true;
}
}
});
this.updateSlotsData();
this.add(this.ship);
}
public get shipSize(): ShipData.Size {
let shipData = ShipData.SHIP_DATA[this.ship_id];
return shipData.size;
}
getShipTexture(a_tex_type: string, a_tex_name: string): THREE.MeshStandardMaterial {
let loader = Params.loader;
let t_color = loader.getTexture(ShipData.getShipTextureColorAlias(a_tex_name));
let t_map = loader.getTexture(ShipData.getShipTextureMapAlias(a_tex_name));
let t_map_ems = loader.getTexture(ShipData.getShipTextureMapEmsAlias(a_tex_name));
let res = new THREE.MeshStandardMaterial({
map: t_color,
color: 0xFFFFFF,
roughnessMap: t_map,
metalnessMap: t_map,
emissiveMap: t_map_ems,
emissiveIntensity: 3
//roughness: 1,
//metalness: 1,
});
if (!t_map_ems) t_map_ems = t_map;
//t_color.flipY = t_map.flipY = t_map_ems.flipY = false;
if (t_color) {
t_color.wrapS = THREE.MirroredRepeatWrapping;
t_color.wrapT = THREE.MirroredRepeatWrapping;
}
if (t_map) {
t_map.wrapS = THREE.MirroredRepeatWrapping;
t_map.wrapT = THREE.MirroredRepeatWrapping;
}
if (t_map_ems) {
t_map_ems.wrapS = THREE.MirroredRepeatWrapping;
t_map_ems.wrapT = THREE.MirroredRepeatWrapping;
}
return res;
}
setTexture(a_tex_name: string) {
this.tex_name = a_tex_name;
let loader = Params.loader;
//let shipData = ShipData.SHIP_DATA[this.ship_id];
let t_color = loader.getTexture(ShipData.getShipTextureColorAlias(this.tex_name));
let t_map = loader.getTexture(ShipData.getShipTextureMapAlias(this.tex_name));
let t_map_ems = loader.getTexture(ShipData.getShipTextureMapEmsAlias(this.tex_name));
if (!t_map_ems) t_map_ems = t_map;
//t_color.flipY = t_map.flipY = t_map_ems.flipY = false;
if (t_color) {
t_color.wrapS = THREE.MirroredRepeatWrapping;
t_color.wrapT = THREE.MirroredRepeatWrapping;
this.mat.map = t_color;
}
if (t_map) {
t_map.wrapS = THREE.MirroredRepeatWrapping;
t_map.wrapT = THREE.MirroredRepeatWrapping;
this.mat.roughnessMap = t_map;
this.mat.metalnessMap = t_map;
}
if (t_map_ems) {
t_map_ems.wrapS = THREE.MirroredRepeatWrapping;
t_map_ems.wrapT = THREE.MirroredRepeatWrapping;
this.mat.emissiveMap = t_map_ems;
}
//emissiveIntensity: 3,
//roughness: 1,
//metalness: 1,
}
setEmsColor(aShipEmsColor: string) {
let clr = new THREE.Color(aShipEmsColor);
this.mat.emissive = clr;
}
setEmsIntens(aEmsIntens: number) {
this.mat.emissiveIntensity = aEmsIntens;
}
setColor(aShipEmsColor: string) {
let clr = new THREE.Color(aShipEmsColor);
this.mat.color = clr;
}
setColorHue(h: number, s: number) {
LogMng.debug('Ship.setColorHue()...');
this.color_h = h;
this.color_s = s;
//this.color_l = aShipHueColor;
this.mat.color.setHSL(this.color_h, this.color_s, this.color_l);
}
setColorHue2(h: number) {
LogMng.debug('Ship.setColorHue()...');
this.matUniforms.hueShift.value = h;
}
updateSlotsData() {
this.slotsPosData = ShipData.getShipSlotsData(this.ship_id, ShipData.shipParams.mod);
}
updateSlot(slot_id: number, slot_name: string, slot_tex: string, slot_color: string) {
let currSlotMesh = this.modules[slot_id];
if (currSlotMesh) {
this.remove(currSlotMesh.model);
this.modules[slot_id] = null;
}
let loader = Params.loader;
let shipData = ShipData.SHIP_DATA[this.ship_id];
let moduleAlias = ShipData.getModuleAlias(slot_name, shipData.size);
let mPosData = this.slotsPosData[slot_id];
let moduleMesh = loader.getModelGLB(moduleAlias);
if (!moduleMesh) return;
let modMesh = moduleMesh.scene.clone(true);
// base material
let t_module_color = loader.getTexture('module_texture');
let t_module_chn = loader.getTexture('module_texture_chn');
//t_module_color.wrapS = t_module_chn.wrapS = MirroredRepeatWrapping;
//t_module_color.wrapT = t_module_chn.wrapT = MirroredRepeatWrapping;
t_module_color.flipY = false;
//t_module_chn.flipY = false;
let modBaseMat = new THREE.MeshStandardMaterial({
map: t_module_color,
//color: clr,
roughnessMap: t_module_chn,
metalnessMap: t_module_chn,
});
// color material
let clr = new THREE.Color(slot_color);
let modTexMat = this.getShipTexture(shipData.texture_type, slot_tex);
modTexMat.color = clr;
// save data
this.modules[slot_id] = {
model: modMesh,
matBase: modBaseMat,
material: modTexMat,
mat_color: slot_color
};
console.log('mod mesh:', modMesh);
modMesh.traverse((child: THREE.Object3D) => {
if (child instanceof THREE.Mesh) {
child.geometry.computeVertexNormals();
let isBase = child.name.indexOf('Bas') >= 0;
if (isBase) {
child.material = modBaseMat;
}
else {
child.material = modTexMat;
}
}
});
modMesh.position.copy(mPosData.pos);
modMesh.rotation.copy(mPosData.rot);
this.add(modMesh);
}
updateSlotTexture(slot_id: number, slot_tex: string) {
let moduleData = this.modules[slot_id];
if (!moduleData) {
return;
}
let loader = Params.loader;
let shipData = ShipData.SHIP_DATA[this.ship_id];
let t_color = loader.getTexture(ShipData.getShipTextureColorAlias(slot_tex));
let t_map = loader.getTexture(ShipData.getShipTextureMapAlias(slot_tex));
let t_map_ems = loader.getTexture(ShipData.getShipTextureMapEmsAlias(slot_tex));
//if (!t_map_ems) t_map_ems = t_map;
//t_color.flipY = t_map.flipY = t_map_ems.flipY = false;
if (t_color) {
t_color.wrapS = THREE.MirroredRepeatWrapping;
t_color.wrapT = THREE.MirroredRepeatWrapping;
moduleData.material.map = t_color;
}
if (t_map) {
t_map.wrapS = THREE.MirroredRepeatWrapping;
t_map.wrapT = THREE.MirroredRepeatWrapping;
moduleData.material.roughnessMap = t_map;
moduleData.material.metalnessMap = t_map;
}
if (t_map_ems) {
t_map_ems.wrapS = THREE.MirroredRepeatWrapping;
t_map_ems.wrapT = THREE.MirroredRepeatWrapping;
moduleData.material.emissiveMap = t_map_ems;
}
}
updateSlotColor(slot_id: number, slot_color: string) {
let moduleData = this.modules[slot_id];
if (!moduleData) {
return;
}
let clr = new THREE.Color(slot_color);
moduleData.mat_color = slot_color;
moduleData.material.color = clr;
}
doSlotsColorLikeShipColor() {
let clr = this.mat.color;
for (let i = 0; i < this.modules.length; i++) {
const moduleData = this.modules[i];
if (!moduleData) continue;
if (moduleData.material) {
moduleData.material.color = clr;
}
}
}
clearSlots() {
for (let i = 0; i < this.modules.length; i++) {
const moduleData = this.modules[i];
if (!moduleData) continue;
if (moduleData.model) {
this.remove(moduleData.model);
this.modules[i] = null;
}
}
}
update(dt: number) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment