Created
August 11, 2020 08:22
-
-
Save maxmonax/2ce7e92f5311348af5c671d10765b297 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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