-
+
+
-
-
-
+
+
+ - Press I to show/hide interface
+ - |
+ -
+ Source code
+
+
@@ -39,6 +61,8 @@
+
+
+
diff --git a/main.js b/main.js
index 1f999a6..4f366ea 100644
--- a/main.js
+++ b/main.js
@@ -25,6 +25,8 @@ var defaultProgram;
var envMapProgram;
var carPS2Program;
+var backgroundColor = [0, 0, 0, 0];
+
function deg2rad(d) { return d / 180.0 * Math.PI; }
var rotating, zooming;
@@ -81,6 +83,15 @@ InitRW()
{
console.log("InitRW()");
let canvas = document.querySelector('#glcanvas');
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+
+ // Get background color from stylesheet
+ var bgColorStr = window.getComputedStyle(canvas, null).getPropertyValue("background-color");
+ bgColorStr = bgColorStr.substring(4, bgColorStr.length-1);
+ backgroundColor = bgColorStr.replace(" ", "").split(",");
+ backgroundColor = [parseFloat(backgroundColor[0])/255, parseFloat(backgroundColor[1])/255, parseFloat(backgroundColor[2])/255, 1.0];
+
gl = canvas.getContext('webgl');
if(!gl){
@@ -159,18 +170,6 @@ displayFrames(frame, parelem)
}
}
-function
-putControl()
-{
-// let ctl = document.getElementById('control');
-// let reloadbtn = document.createElement('input');
-// reloadbtn.type = "button";
-// reloadbtn.value = "reload";
-// reloadbtn.onclick = reload;
-// ctl.appendChild(reloadbtn);
-}
-
-
function
loadCarIII(filename)
{
@@ -203,11 +202,11 @@ loadCarSA(filename)
setupSACar(myclump);
setVehicleColors(modelinfo,
carColors[0], carColors[1], carColors[2], carColors[3]);
-// setVehicleLightColors(modelinfo,
-// [ 128, 0, 0, 255 ],
-// [ 128, 0, 0, 255 ],
-// [ 128, 0, 0, 255 ],
-// [ 128, 0, 0, 255 ]);
+ setVehicleLightColors(modelinfo,
+ [ 255, 255, 255, 255 ],
+ [ 255, 255, 255, 255 ],
+ [ 255, 255, 255, 255 ],
+ [ 255, 255, 255, 255 ]);
main();
});
}
@@ -238,8 +237,6 @@ main()
if(!running){
running = true;
- putControl();
-
let then = 0;
function render(now){
now *= 0.001; // convert to seconds
@@ -309,6 +306,11 @@ setVehicleColors(vehinfo, c1, c2, c3, c4)
vehinfo.thirdMaterials[i].color = c3;
for(let i = 0; i < vehinfo.fourthMaterials.length; i++)
vehinfo.fourthMaterials[i].color = c4;
+
+ if(c1) document.getElementById("custom-color0").value = RGB2HTML(c1);
+ if(c2) document.getElementById("custom-color1").value = RGB2HTML(c2);
+ if(c3) document.getElementById("custom-color2").value = RGB2HTML(c3);
+ if(c4) document.getElementById("custom-color3").value = RGB2HTML(c4);
}
function
@@ -362,6 +364,10 @@ processVehicle(clump)
fourthLightMaterials: [], // back right
clump: clump
};
+
+ // Wheel atomic to clone
+ let wheel = null;
+
for(let i = 0; i < clump.atomics.length; i++){
a = clump.atomics[i];
f = a.frame;
@@ -369,17 +375,41 @@ processVehicle(clump)
f.name.endsWith("_lo") ||
f.name.endsWith("_vlo"))
a.visible = false;
+
+ if(f.name === "wheel") {
+ wheel = a;
+ }
+
findEditableMaterials(a.geometry, vehicleInfo);
}
+
+ // Clone wheels
+ let frame = clump.frame.child;
+ while(wheel && frame) {
+ if(["wheel_rb_dummy", "wheel_rm_dummy", "wheel_lf_dummy", "wheel_lb_dummy", "wheel_lm_dummy"].includes(frame.name)) {
+ let wheel2 = RpAtomicClone(wheel);
+ mat4.copy(wheel2.frame.ltm, frame.ltm);
+ if(["wheel_lf_dummy", "wheel_lb_dummy", "wheel_lm_dummy"].includes(frame.name)) {
+ // Rotate cloned wheel
+ mat4.rotate(wheel2.frame.ltm, wheel2.frame.ltm, Math.PI, [0, 0, 1]);
+ }
+ frame.child = wheel2.frame;
+ clump.atomics.push(wheel2);
+ }
+ frame = frame.next;
+ }
+
return vehicleInfo;
}
function
drawScene(deltaTime)
{
-// camYaw += deltaTime;
+ if(window.autoRotateCamera) {
+ camYaw += deltaTime * 0.9;
+ }
- gl.clearColor(0.5, 0.5, 0.5, 1.0);
+ gl.clearColor(backgroundColor[0], backgroundColor[1], backgroundColor[2], 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
@@ -428,3 +458,16 @@ loadDFF(filename, cb)
req.send(null);
}
+
+function
+rgbToCSSString(r, g, b)
+{
+ return ["rgb(",r,",",g,",",b,")"].join("");
+}
+
+function
+RGB2HTML(color)
+{
+ let decColor = 0x1000000 + color[2] + 0x100 * color[1] + 0x10000 * color[0];
+ return '#' + decColor.toString(16).substr(1);
+}
diff --git a/rw.js b/rw.js
index 4bf7242..53eb11b 100644
--- a/rw.js
+++ b/rw.js
@@ -269,6 +269,20 @@ RpAtomicCreate()
};
}
+function
+RpAtomicClone(a)
+{
+ let a2 = RpAtomicCreate();
+ a2.type = a.type;
+ a2.visible = a.visible;
+ a2.frame = RwFrameClone(a.frame);
+ a2.geometry = a.geometry;
+ a2.pipeline = a.pipeline;
+ a2.frame.objects = [];
+ a2.frame.objects[0] = a2;
+ return a2;
+}
+
function
RpAtomicSetFrame(a, f)
{
@@ -488,6 +502,18 @@ rwFrameInit(f)
mat4.copy(f.ltm, f.matrix);
}
+function
+RwFrameClone(f) {
+ let f2 = RwFrameCreate();
+ mat4.copy(f2.matrix, f.matrix);
+ mat4.copy(f2.ltm, f.ltm);
+ f2.child = f.child;
+ f2.name = f.name;
+ f2.parent = f.parent;
+ f2.root = f.root;
+ return f2;
+}
+
function
rpMaterialInit(m)
{
diff --git a/ui.js b/ui.js
new file mode 100644
index 0000000..01a7e75
--- /dev/null
+++ b/ui.js
@@ -0,0 +1,78 @@
+showInterface = true;
+autoRotateCamera = false;
+
+function hex2rgb(hex) {
+ let r = parseInt(hex.slice(1, 3), 16);
+ let g = parseInt(hex.slice(3, 5), 16);
+ let b = parseInt(hex.slice(5, 7), 16);
+ return [r, g, b];
+}
+
+function updateVehicleCustomColors() {
+ let colors = [];
+ for(let i = 0; i < 4; i++) {
+ let cStr = document.getElementById("custom-color" + i).value;
+ let c = hex2rgb(cStr);
+ c[3] = 255;
+ colors[i] = c;
+ }
+ setVehicleColors(modelinfo, colors[0], colors[1], colors[2], colors[3]);
+}
+
+for(let i = 0; i < 4; i++) {
+ document.getElementById("custom-color" + i).addEventListener("input", updateVehicleCustomColors, false);
+}
+
+document.addEventListener("keypress",
+function(e) {
+ if(e.key === "i") {
+ showInterface = !showInterface;
+ document.querySelectorAll(".ui").forEach((v) => {
+ v.style.visibility = showInterface ? "unset" : "hidden";
+ });
+ }
+
+ else if(e.key === "r") {
+ autoRotateCamera = !autoRotateCamera;
+ }
+},
+false);
+
+document.getElementById("objects").addEventListener("keypress",
+function(e) {
+ e.preventDefault();
+ return false;
+},
+false);
+
+var lastModelChangeViaKey = 0;
+document.getElementById("objects").addEventListener("keydown",
+function(e) {
+ if(e.keyCode !== 38 && e.keyCode !== 40) {
+ return true;
+ }
+
+ if(Date.now() - lastModelChangeViaKey < 750) {
+ e.preventDefault();
+ return false;
+ }
+
+ lastModelChangeViaKey = Date.now();
+},
+false);
+
+
+document.getElementById("objects").addEventListener("keyup",
+function(e) {
+ if(e.keyCode !== 38 && e.keyCode !== 40) {
+ return true;
+ }
+
+ lastModelChangeViaKey -= 400;
+
+ let model = document.getElementById("objects").value;
+ if(model !== CurrentModel.model) {
+ SelectModel(model);
+ }
+},
+false);
diff --git a/webgl.css b/webgl.css
index 2d293b7..f834ca3 100644
--- a/webgl.css
+++ b/webgl.css
@@ -1,7 +1,144 @@
-canvas {
- border: 2px solid black;
- background-color: black;
+html {
+ height: 100%;
}
+
+body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ overflow: hidden;
+}
+
+a {
+ color: black;
+}
+
+body, canvas {
+ background-color: #808080;
+}
+
video {
display: none;
-}
\ No newline at end of file
+}
+
+#objects {
+ outline: none;
+ height: calc(100% - 18.4px);
+ width: 110px;
+ border: unset;
+}
+
+.select-panel {
+ position: absolute;
+ float: left;
+ height: 100%;
+}
+
+#control {
+ text-align: center;
+}
+
+.objects-wrapper {
+ float: left;
+ height: 100%;
+ width: calc(100%);
+}
+
+.viewer-panel {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+option {
+ padding-left: 5px;
+ font-size: 14px;
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+option:hover {
+ cursor: pointer;
+}
+
+#colors {
+ position: absolute;
+ bottom: 20px;
+ left: 130px;
+
+ /*background-color: todo;*/
+ border-radius: 2px;
+ padding: 5px;
+}
+
+#colors td {
+ border: 1px solid white;
+}
+
+#colors td:hover {
+ cursor: pointer;
+}
+
+.frames-wrapper {
+ position: absolute;
+ top: 0;
+ right: 100px;
+}
+
+.bottom-links {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ margin: 0;
+}
+
+.bottom-links ul {
+ list-style-type: none;
+}
+
+.bottom-links li {
+ float: left;
+ margin-left: 10px;
+ list-style-type: none;
+}
+
+.custom-colors {
+ position: absolute;
+ bottom: 210px;
+ left: 130px;
+}
+
+.custom-colors input:hover {
+ cursor: pointer;
+}
+
+@media (prefers-color-scheme: dark)
+{
+ body, canvas {
+ background-color: #181818;
+ }
+
+ body, a, #objects {
+ color: #f5f5f5;
+ }
+
+ #objects {
+ background-color: #292929;
+ }
+
+ option:checked, option:hover {
+ background-color: #4f4f4f !important;
+ }
+
+ #colors, .custom-colors input {
+ background-color: #343434;
+ }
+
+ #colors td {
+ border: 1px solid white;
+ }
+
+ .custom-colors input {
+ border-radius: 2px;
+ }
+}
From 56a6dddd705d678d68854c4b2d771154e9af545d Mon Sep 17 00:00:00 2001
From: lopezloo <7338099+lopezloo@users.noreply.github.com>
Date: Thu, 9 Feb 2023 06:22:27 +0100
Subject: [PATCH 2/4] Tweak code style
---
ui.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/ui.js b/ui.js
index 01a7e75..991bb76 100644
--- a/ui.js
+++ b/ui.js
@@ -1,14 +1,16 @@
showInterface = true;
autoRotateCamera = false;
-function hex2rgb(hex) {
+function
+hex2rgb(hex) {
let r = parseInt(hex.slice(1, 3), 16);
let g = parseInt(hex.slice(3, 5), 16);
let b = parseInt(hex.slice(5, 7), 16);
return [r, g, b];
}
-function updateVehicleCustomColors() {
+function
+updateVehicleCustomColors() {
let colors = [];
for(let i = 0; i < 4; i++) {
let cStr = document.getElementById("custom-color" + i).value;
From d2663f6ede2662cc52695c5d9c10e73806013109 Mon Sep 17 00:00:00 2001
From: lopezloo <7338099+lopezloo@users.noreply.github.com>
Date: Thu, 9 Feb 2023 06:47:06 +0100
Subject: [PATCH 3/4] Tweak
---
index.html | 4 ++--
main.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/index.html b/index.html
index ba13de5..dab14e6 100644
--- a/index.html
+++ b/index.html
@@ -43,7 +43,7 @@