UNPKG

rl-loadout-lib

Version:

Load Rocket League assets into three.js

331 lines 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const three_1 = require("three"); const object_1 = require("../object"); const util_1 = require("../../utils/util"); const axle_settings_1 = require("../../model/axle-settings"); const wheel_1 = require("../../model/wheel"); const constants_1 = require("../constants"); const skeleton_1 = require("../../utils/three/skeleton"); const chassis_material_1 = require("../../webgl/chassis-material"); const material_factory_1 = require("./material-factory"); /** * Class that handles loading the 3D model of the car body. */ class BodyModel extends object_1.AbstractObject { /** * Create a body model object. You should **not** use this unless you know what you are doing. Use {@link createBodyModel} instead. * @param body car body to load the model of * @param decal car decal to load the textures of * @param bodyAssets body assets * @param decalAssets decal assets * @param paints paints to be applied to the body */ constructor(body, decal, bodyAssets, decalAssets, paints) { super(bodyAssets); this.body = body; this.bodyAssets = bodyAssets; this.wheelRoll = 0; this.bodyMaterial = material_factory_1.getBodyMaterial(body); this.bodyMesh.material = this.bodyMaterial; this.chassisMaterial = new chassis_material_1.ChassisMaterial(); this.chassisMesh.material = this.chassisMaterial; this.applyAssets(paints, decalAssets); } applyAssets(paints, decalAssets) { this.chassisMaterial.map = util_1.htmlImageToTexture(this.bodyAssets.chassisD); this.chassisMaterial.normalMap = util_1.htmlImageToTexture(this.bodyAssets.chassisN); this.chassisMaterial.rgbaMap = util_1.htmlImageToTexture(this.bodyAssets.chassisN); this.chassisMaterial.paintable = this.body.chassis_paintable; this.chassisMaterial.accentColor = paints.accent; this.chassisMaterial.paintColor = paints.body; this.chassisMaterial.skinning = true; this.chassisMaterial.needsUpdate = true; this.applyDecalAssets(paints, decalAssets); } applyDecalAssets(paints, decalAssets) { if (decalAssets.baseTexture) { this.bodyMaterial.map = util_1.htmlImageToTexture(decalAssets.baseTexture); } else { this.bodyMaterial.map = util_1.htmlImageToTexture(this.bodyAssets.baseSkin); } this.bodyMaterial.rgbaMap = util_1.htmlImageToTexture(this.bodyAssets.blankSkin); this.bodyMaterial.decalMap = util_1.htmlImageToTexture(decalAssets.rgbaMap); this.bodyMaterial.primaryColor = paints.primary; this.bodyMaterial.accentColor = paints.accent; this.bodyMaterial.paintColor = paints.decal; this.bodyMaterial.bodyPaintColor = paints.body; this.bodyMaterial.needsUpdate = true; } dispose() { super.dispose(); util_1.disposeIfExists(this.bodyMaterial); util_1.disposeIfExists(this.chassisMaterial); this.wheelsModel = undefined; } handleModel(scene) { if ('hitbox' in scene.userData) { this.hitboxConfig = scene.userData.hitbox; } if ('wheelSettings' in scene.userData) { this.wheelSettings = { frontAxle: axle_settings_1.AxleSettings.fromObject(scene.userData.wheelSettings.frontAxle), backAxle: axle_settings_1.AxleSettings.fromObject(scene.userData.wheelSettings.backAxle) }; } this.hatSocket = scene.getObjectByName('HatSocket'); this.antennaSocket = scene.getObjectByName('AntennaSocket'); if (this.frontPivots == undefined) { this.frontPivots = []; } scene.traverse(object => { if (object['isBone'] && this.skeleton == undefined) { this.skeleton = object; } else if (object['isMesh']) { const mat = object.material; const matName = mat.name.toLowerCase(); if (matName.includes('body')) { this.bodyMesh = object; } else if (matName.includes('chassis')) { const mesh = object; this.chassisMesh = mesh; // @ts-ignore this.frontPivots.push(mesh.skeleton.getBoneByName('FL_Pivot_jnt')); // @ts-ignore this.frontPivots.push(mesh.skeleton.getBoneByName('FR_Pivot_jnt')); } else if (matName === 'window_material') { mat.envMapIntensity = 3.0; mat.needsUpdate = true; } } }); this.getWheelPositions(); } getWheelPositions() { this.wheelConfig = []; this.skeleton.traverse(object => { if (object.name.endsWith('Disc_jnt')) { const config = new wheel_1.WheelConfig(); const wheelType = object.name.substr(0, 2).toLowerCase(); config.front = wheelType[0] === 'f'; config.right = wheelType[1] === 'r'; config.joint = object; if (this.wheelSettings != undefined) { if (config.front) { config.offset = this.wheelSettings.frontAxle.wheelMeshOffsetSide; config.width = this.wheelSettings.frontAxle.wheelWidth; config.radius = this.wheelSettings.frontAxle.wheelMeshRadius; } else { config.offset = this.wheelSettings.backAxle.wheelMeshOffsetSide; config.width = this.wheelSettings.backAxle.wheelWidth; config.radius = this.wheelSettings.backAxle.wheelMeshRadius; } } this.wheelConfig.push(config); } }); } /** * Add wheels to the body. This creates 4 copies of the wheel model and attaches them to the wheel joints. Replaces existing wheels. * @param wheelsModel the wheels */ addWheelsModel(wheelsModel) { this.clearWheelsModel(); this.wheelsModel = wheelsModel; this.applyWheelConfig(); for (const wheel of this.wheels) { wheel.config.joint.add(wheel.model); } } applyWheelConfig() { if (this.wheelConfig == undefined) { return; } const config = this.wheelConfig; this.wheels = []; for (const conf of config) { const widthScale = conf.width / constants_1.BASE_WHEEL_MESH_WIDTH; const radiusScale = conf.radius / constants_1.BASE_WHEEL_MESH_RADIUS; const offset = conf.offset; const wheel = skeleton_1.SkeletonUtils.clone(this.wheelsModel.scene); const position = new three_1.Vector3(); position.copy(conf.position); if (!conf.right) { wheel.rotation.set(-Math.PI / 2, 0, Math.PI); position.add(new three_1.Vector3(0, offset, 0)); } else { wheel.rotation.set(Math.PI / 2, 0, 0); position.add(new three_1.Vector3(0, -offset, 0)); } wheel.scale.set(radiusScale, radiusScale, widthScale); wheel.position.copy(position); let spinnerJoint; wheel.traverse(object => { if (object['isBone']) { if (object.name === 'spinner_jnt') { spinnerJoint = object; } } }); this.wheels.push({ model: wheel, config: conf, spinnerJoint }); } } /** * Remove the wheels from the body. */ clearWheelsModel() { for (const conf of this.wheelConfig) { for (let i = conf.joint.children.length - 1; i >= 0; i--) { conf.joint.remove(conf.joint.children[i]); } } this.wheels = []; this.wheelsModel = undefined; } /** * Add a topper to the body and attach it to the topper socket. It replaces existing toppers. * @param topperModel the topper */ addTopperModel(topperModel) { this.clearTopperModel(); this.topperModel = topperModel; this.topperModel.applyAnchor(this.hatSocket); this.topperModel.addToScene(this.scene); } /** * Remove the topper from the body. */ clearTopperModel() { if (this.topperModel != undefined) { this.topperModel.removeFromScene(this.scene); this.topperModel = undefined; } } /** * Add an antenna to the body and attach it to the antenna anchor. It replaces existing antennas. * @param antennaModel the antenna */ addAntennaModel(antennaModel) { this.clearAntennaModel(); this.antennaModel = antennaModel; this.antennaModel.applyAnchor(this.antennaSocket); this.antennaModel.addToScene(this.scene); } /** * Remove the antenna from the body. */ clearAntennaModel() { if (this.antennaModel != undefined) { this.antennaModel.removeFromScene(this.scene); this.antennaModel = undefined; } } /** * Set the paint color of this body. * @param color paint color */ setPaintColor(color) { this.bodyMaterial.bodyPaintColor = color; this.bodyMaterial.needsUpdate = true; this.chassisMaterial.paintColor = color; this.chassisMaterial.needsUpdate = true; } /** * Replace the current decal with a new one. * @param decalAssets decal assets * @param paints paint config needed for decal colors */ changeDecal(decalAssets, paints) { this.applyDecalAssets(paints, decalAssets); } /** * Set the primary color. * @param color THREE Color object */ setPrimaryColor(color) { this.bodyMaterial.primaryColor = color; } /** * Set the accent color. * @param color THREE Color object */ setAccentColor(color) { this.bodyMaterial.accentColor = color; } /** * Set the paint color of the decal. * @param color THREE Color object */ setDecalPaintColor(color) { this.bodyMaterial.paintColor = color; } /** * Set the yaw rotation (turn) of the front wheels. * @param angle yaw in radians * @param clamped if true, the angle will be clamped and the absolute value will not be higher than {@link MAX_WHEEL_YAW} */ setFrontWheelYaw(angle, clamped = true) { if (clamped) { angle = Math.max(Math.min(angle, constants_1.MAX_WHEEL_YAW), -constants_1.MAX_WHEEL_YAW); } for (const pivot of this.frontPivots) { pivot.rotation.z = angle; } } /** * Set roll rotation of the wheels. * @param angle roll angle in radians */ setWheelRoll(angle) { this.wheelRoll = angle; for (const wheel of this.wheels) { if (wheel.config.right) { wheel.model.rotation.z = -angle; } else { wheel.model.rotation.z = Math.PI + angle; } if (wheel.spinnerJoint != undefined) { if (wheel.config.right) { wheel.spinnerJoint.rotation.y = angle; } else { wheel.spinnerJoint.rotation.y = -angle; } } } } animate(time) { var _a; if (this.wheels != undefined) { for (const wheel of this.wheels) { (_a = this.wheelsModel) === null || _a === void 0 ? void 0 : _a.animate(time, wheel, this.wheelRoll); } } } copy(other) { super.copy(other); this.clearWheelsModel(); this.bodyAssets = other.bodyAssets; if (other.wheelsModel != undefined) { this.addWheelsModel(other.wheelsModel.clone()); } } clone() { const m = new BodyModel(); m.copy(this); return m; } } exports.BodyModel = BodyModel; //# sourceMappingURL=body-model.js.map