From fd78db348db96b6152187bed46035d05fbee8614 Mon Sep 17 00:00:00 2001 From: Francois Date: Sun, 24 Sep 2023 18:09:06 -0400 Subject: [PATCH] Sorta getting there, math isn't quite right --- src/renderer/renderCylinder.ts | 52 +++++++++++++++++++----------- workbench/scenes/SingleCylinder.ts | 26 ++------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/renderer/renderCylinder.ts b/src/renderer/renderCylinder.ts index bc2f9b6..306973c 100644 --- a/src/renderer/renderCylinder.ts +++ b/src/renderer/renderCylinder.ts @@ -55,21 +55,17 @@ export function renderCylinder( const yAxisCameraSpace = yAxisWorldSpace.clone(); inverseCameraMatrix.extractRotation().applyToVector3(yAxisCameraSpace); - const cylinderScale = worldTransform.getScale().x; - const cylinderScaleFactor = cylinderScale * cameraZoom; - const Radius = cylinder.radius * cylinderScaleFactor; - // Top === -1 // Front === 0 // Bottom === 1 - const dotProduct = yAxisCameraSpace.dotProduct( - // cameraDirection.clone().multiply(-1) - Vector3(0, 0, 1) - ); + const dotProduct = yAxisCameraSpace.dotProduct(Vector3(0, 0, 1)); // This boils down to just taking the z component const dotProductAbsolute = Math.abs(dotProduct); + const isTopVisible = dotProduct > 0; + const cylinderScale = worldTransform.getScale().x; + const cylinderScaleFactor = cylinderScale * cameraZoom; + const Radius = cylinder.radius * cylinderScaleFactor; const ShortRadius = Radius * dotProductAbsolute; - const isTopVisible = dotProduct > 0; console.log( `scenario: ${isTopVisible ? "top" : "bottom"} @@ -164,9 +160,20 @@ export function renderCylinder( ); addStrokeAttribute(tubePath, cylinder, cylinderScaleFactor); - svg.appendChild(tubePath); + // Convert the light direction into camera space (not projected into screen space) + const directionalLightInCameraSpace = scene.directionalLight.direction + .clone() + .multiply(-1); + inverseCameraMatrix + .extractRotation() + .applyToVector3(directionalLightInCameraSpace); + // Then convert it into screen aligned cylinder space + Matrix4x4() + .makeRotationZ((xAxisRotation / 180) * Math.PI) + .applyToVector3(directionalLightInCameraSpace); + const uuid = crypto.randomUUID(); const fillUuid = uuid + "-fill"; const fillUrl = `url(#${fillUuid})`; @@ -198,19 +205,28 @@ export function renderCylinder( linearGradient.setAttribute("x2", rightOfTubeCenter.x.toString()); linearGradient.setAttribute("y2", rightOfTubeCenter.y.toString()); - const gradientStops = [ - { offset: 0, stopColor: ColorToCSS(cylinder.fill) }, - { offset: 1.0, stopColor: ColorToCSS(Color(0, 0, 0)) }, - ]; + // Add the gradient stops + const GradientSteps = Math.min(2, Math.max(255, Math.floor(Radius))); + + for (let i = 0; i < GradientSteps; i++) { + const normalized = i / (GradientSteps - 1); + const x = Math.sin(normalized * Math.PI); + const z = Math.cos(normalized * Math.PI + Math.PI); - for (let stop of gradientStops) { const stopElement = document.createElementNS( "http://www.w3.org/2000/svg", "stop" ); - - stopElement.setAttribute("offset", stop.offset.toString()); - stopElement.setAttribute("stop-color", stop.stopColor); + stopElement.setAttribute("offset", normalized.toFixed(3)); + stopElement.setAttribute( + "stop-color", + applyLighting( + scene.directionalLight.color, + cylinder.fill, + scene.ambientLightColor, + directionalLightInCameraSpace.dotProduct(Vector3(x, 0, z)) + ) + ); linearGradient.appendChild(stopElement); } diff --git a/workbench/scenes/SingleCylinder.ts b/workbench/scenes/SingleCylinder.ts index 6233aa8..f3cfa55 100644 --- a/workbench/scenes/SingleCylinder.ts +++ b/workbench/scenes/SingleCylinder.ts @@ -80,19 +80,6 @@ export default function () { const distanceNormalized = distance / referenceRadius; let degrees = distanceNormalized * 90; - //Math.cos(((distanceNormalized * 90) / 180) * Math.PI); - // console.log( - // degrees, - // event.clientX, - // event.clientY, - // centerX, - // centerY, - // diffX, - // diffY, - // distance, - // distanceNormalized - // ); - const spinMode: string = "z"; if (spinMode === "y") { @@ -100,7 +87,6 @@ export default function () { degrees *= -1; } lightSphere.position.x = Math.sin((degrees / 180) * Math.PI); - // lightSphere.position.y = 0.0; lightSphere.position.y = 0.5; lightSphere.position.z = Math.cos((degrees / 180) * Math.PI); @@ -111,17 +97,10 @@ export default function () { } else if (spinMode === "z") { lightSphere.position.x = Math.sin((degrees / 180) * Math.PI); lightSphere.position.y = Math.cos((degrees / 180) * Math.PI); - lightSphere.position.z = 0; // - // lightSphere.position.z = -0.5; // + lightSphere.position.z = 0; } lightSphere.position.normalize().multiply(lightDistance).add(position); - - // const x = event.clientX; - // const z = event.clientY; - // lightSphere.position.y = 0; - // const x = event.clientX; - // const y = event.clientY; }; document.addEventListener("pointerdown", onPointerEvent); document.addEventListener("pointermove", onPointerEvent); @@ -136,7 +115,8 @@ export default function () { // cylinder.rotation.x = now * 90; // cylinder.rotation.x = 45; - cylinder.rotation.y = now * 90; + cylinder.rotation.x = 90; + // cylinder.rotation.y = now * 90; // cylinder.rotation.x = now * 90;