diff --git a/src/renderer/renderCylinder.ts b/src/renderer/renderCylinder.ts index f47923b..63c6ade 100644 --- a/src/renderer/renderCylinder.ts +++ b/src/renderer/renderCylinder.ts @@ -4,7 +4,7 @@ // https://observablehq.com/d/011f054fc7eaf966 import { projectToScreenCoordinate } from "../cameras/Camera"; -import { ColorToCSS } from "../colors/Color"; +import { Color, ColorToCSS } from "../colors/Color"; import { applyLighting } from "../lighting/LightingModel"; import { Matrix4x4 } from "../math/Matrix4x4"; import { Vector3 } from "../math/Vector3"; @@ -24,7 +24,7 @@ export function renderCylinder( cylinder: CylinderShape, viewport: Viewport, worldTransform: Matrix4x4, - _cameraZoom: number, + cameraZoom: number, cameraDirection: Vector3, _inverseCameraMatrix: Matrix4x4, inverseAndProjectionMatrix: Matrix4x4 @@ -47,10 +47,51 @@ export function renderCylinder( const yAxis = Vector3(0, 1, 0); worldTransform.extractBasis(Vector3(0, 0, 0), yAxis, Vector3(0, 0, 0)); + const addCylinderEnd = ( + { x, y }: Vector3, + radius: number, + dotProduct: number, + fill: Color + ) => { + const dotProductAbsolute = Math.abs(dotProduct); + // Create a 'circle' element + const circle = document.createElementNS( + "http://www.w3.org/2000/svg", + "ellipse" + ); + + circle.id = "sphere"; + circle.setAttribute("cx", x.toString()); + circle.setAttribute("cy", y.toString()); + + // TODO: Factor in camera projection matrix, this currectly + // ignores all zoom factors. Can we even handle skew with sphere?! + // I don't think we can. + circle.setAttribute("rx", radius.toString()); + circle.setAttribute("ry", (radius * dotProductAbsolute).toString()); + + circle.setAttribute("fill", ColorToCSS(fill)); + + svg.appendChild(circle); + }; + + const cylinderScale = worldTransform.getScale().x; + const cylinderScaleFactor = cylinderScale * cameraZoom; + const Radius = cylinder.radius * cylinderScaleFactor; + // Top === -1 - // Bottom === 1 // Front === 0 - console.log(yAxis.dotProduct(cameraDirection)); + // Bottom === 1 + const dotProduct = yAxis.dotProduct(cameraDirection); + console.log(dotProduct); + const isTopVisible = yAxis.dotProduct(cameraDirection) > 0; + + addCylinderEnd( + isTopVisible ? points[CylinderEnds.Top] : points[CylinderEnds.Bottom], + cylinder.radius, + dotProduct, + isTopVisible ? Color(255, 0, 0) : Color(0, 0, 255) + ); // Scenarios we can view the cylinder from: // 1. From the top/bottom (can't see the tube) @@ -59,8 +100,7 @@ export function renderCylinder( // Are we viewing the cylinder from the top or bottom? - points.forEach(({ x, y }) => { - // Create a 'circle' element + points.forEach(({ x, y }, index) => { const circle = document.createElementNS( "http://www.w3.org/2000/svg", "circle" @@ -73,9 +113,12 @@ export function renderCylinder( // TODO: Factor in camera projection matrix, this currectly // ignores all zoom factors. Can we even handle skew with sphere?! // I don't think we can. - circle.setAttribute("r", "10"); + circle.setAttribute("r", (5).toString()); - circle.setAttribute("fill", ColorToCSS(cylinder.fill)); + circle.setAttribute( + "fill", + index === CylinderEnds.Top ? "rgb(128,0,0)" : "rgb(0,0,128)" + ); svg.appendChild(circle); }); diff --git a/workbench/scenes/SingleCylinder.ts b/workbench/scenes/SingleCylinder.ts index c7a756b..e550b47 100644 --- a/workbench/scenes/SingleCylinder.ts +++ b/workbench/scenes/SingleCylinder.ts @@ -20,7 +20,7 @@ import { Axii } from "../Axii"; import { type } from "os"; export default function () { - const referenceRadius = 75; + const referenceRadius = 50; const lightSpeed = 0.3; const lightDistance = 100; @@ -33,6 +33,16 @@ export default function () { }); const position = Vector3(0, referenceRadius / 2, 0); + const cylinder = Cylinder({ + id: "reference", + position, + radius: referenceRadius, + height: referenceRadius * 4, + // radius: referenceRadius, + fill: Color(255, 0, 0), + stroke: Color(0, 0, 0), + strokeWidth: 0, + }); const scene: Scene = { ...getLighting("reference"), @@ -44,14 +54,7 @@ export default function () { // rotation: Vector3(45, 0, 0), // scale: 3, // children: [ - Cylinder({ - id: "reference", - position, - radius: referenceRadius, - fill: Color(255, 0, 0), - stroke: Color(0, 0, 0), - strokeWidth: 0, - }), + cylinder, // ], // }), lightSphere, @@ -60,7 +63,7 @@ export default function () { lightSphere.position = Vector3(1, 1, -1); - const { viewport, camera, updateCamera } = getCamera("isometric"); + const { viewport, camera, updateCamera } = getCamera("top"); const onPointerEvent = (event: PointerEvent) => { // return; @@ -127,8 +130,11 @@ export default function () { const cameraSpeed = 0.1; // const cameraSpeed = 0.0; updateCamera(now * cameraSpeed * 360 + 45, 20); + // updateCamera(45, 20); + cylinder.rotation.x = now * 90; + // lightSphere.position.x = // Math.sin(now * Math.PI * 2 * lightSpeed) * lightDistance; // lightSphere.position.y = 0;