How to create an emissive (and reflective) line or curve in THREE.js - reflection

I have a series of curves in the format:
var curve = new THREE.CatmullRomCurve3( [
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
] );
var points = curve.getPoints( 50 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 , linewidth:100} );
var curveObject = new THREE.Line( geometry, material );
scene.add(curveObject)
I want these to have a reflection visible on the surface of a shiny MeshPhong (material) Plane - preferably white. I can make the lines 'glow' using a BloomPass, however, I am more interested in producing a warped reflection on the surface.
Since LineBasicMaterial does not have an emissivity attribute in what ways can such an effect be achieved?

Related

how to make an arc rotating around a center in ExtendScript After Effects?

I want to make a loading animation in After Effects using scripts
I get no arc only white screen with shape layer there
and this is what gets rendered in the app
This is my code that doesn't work
app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);
app.newProject();
app.beginUndoGroup("Create Comp");
// Create a new composition with a solid layer
var comp = app.project.items.addComp("My Composition", 1920, 1080, 1, 10, 24);
comp.openInViewer();
var solid = comp.layers.addSolid([1, 1, 1], "My Solid", 1920, 1080, 1, 10);
// Create a new shape layer
var shapeLayer = comp.layers.addShape();
// shapeLayer.moveToStart();
shapeLayer.enabled= true;
// Set position of the shape layer
var shapePosition = shapeLayer.property("ADBE Transform Group").property("ADBE Position");
shapePosition.setValue([960,540]);
var path = shapeLayer.property("ADBE Root Vectors Group").addProperty("ADBE Vector Shape - Group");
// make a arc
path.property("ADBE Vector Shape").setValue(new Shape());
path.property("ADBE Vector Shape").value.vertices = [[0, 0], [100, 100], [200, 0]];
path.property("ADBE Vector Shape").value.inTangents = [[-50, -50], [0, 0]];
path.property("ADBE Vector Shape").value.outTangents = [[0, 0], [50, 50]];
path.property("ADBE Vector Shape").value.closed = true;
path.enabled = true;
var stroke = shapeLayer.property("ADBE Root Vectors Group").addProperty("ADBE Vector Graphic - Stroke");
stroke.property("ADBE Vector Stroke Width").setValue(5);
stroke.property("ADBE Vector Stroke Color").setValue([1, 0, 0]);
stroke.enabled = true;
var fill = shapeLayer.property("ADBE Root Vectors Group").addProperty("ADBE Vector Graphic - Fill");
fill.property("ADBE Vector Fill Color").setValue([1, 0, 0]);
fill.enabled = true;
// Create an animation for the rotation property
var rotation = shapeLayer.property("ADBE Transform Group").property("ADBE Rotate Z");
rotation.setValueAtTime(0, 0);
rotation.setValueAtTime(5, 180);
// Set the composition duration to 10 seconds
comp.duration = 10;
app.endUndoGroup();
Properties in AE can't be set by assigning values to them. You need to use the setValue() method. Additionally in this instance you want to set the values of the shape object before assigning it to the path property.
var theShape = new Shape();
theShape.vertices = [[0, 0], [100, 100], [200, 0]];
theShape.inTangents = [[-50, -50], [0, 0]];
theShape.outTangents = [[0, 0], [50, 50]];
theShape.closed = true;
path.property("ADBE Vector Shape").setValue(theShape);
Also, as an AE developer:

How to calculate rotation for a box based on a set of four points?

I’m a bit new to working with 3D space and rotation. I have a list of four Vector3 points that represent the corners of a rectangle. What I want to do is use those points to create a box mesh that is rotated to exactly match the angle of rotation of the points.
Here is a babylonjs playground demo showing what I mean. In it you can see I’ve drawn a simple line mesh between the points. That is great and the rectangle drawn is at the expected angle given the data. I’ve also created a box mesh and configured its dimensions to match and placed its center point in the proper center of the points. So far so good, however I cannot figure out how to rotate the box so that it’s top face is parallel with the face of the rectangle.
https://playground.babylonjs.com/#SN5K8L#2
var createScene = function () {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);
// This creates and positions a free camera (non-mesh)
var target = new BABYLON.Vector3(1.5, 4, 0)
var camera = new BABYLON.ArcRotateCamera("camera1", Math.PI / 2 + Math.PI, Math.PI / 4, 10, target, scene)
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
const axes = new BABYLON.AxesViewer(scene)
const points = [
new BABYLON.Vector3(1, 5, 1),
new BABYLON.Vector3(2, 5, 1),
new BABYLON.Vector3(2, 3, -1),
new BABYLON.Vector3(1, 3, -1)
]
const lines = BABYLON.MeshBuilder.CreateLines("lines", {
points: [...points, points[0]] // add a duplicate of first point to close polygon
}, scene)
const centerPoint = new BABYLON.Vector3(
(points[0].x + points[1].x + points[2].x + points[3].x) / 4,
(points[0].y + points[1].y + points[2].y + points[3].y) / 4,
(points[0].z + points[1].z + points[2].z + points[3].z) / 4
)
const width = Math.sqrt(
Math.pow(points[1].x - points[0].x, 2) +
Math.pow(points[1].y - points[0].y, 2) +
Math.pow(points[1].z - points[0].z, 2)
)
const depth = Math.sqrt(
Math.pow(points[2].x - points[1].x, 2) +
Math.pow(points[2].y - points[1].y, 2) +
Math.pow(points[2].z - points[1].z, 2)
)
const height = 0.15
const box = BABYLON.CreateBox("box", { width, height, depth}, scene)
box.position = centerPoint
//box.rotation = ???
return scene;
};
You can use Vector3.RotationFromAxis to compute the required rotation in Euler angles:
const rotationAxisX = points[1].subtract(points[0])
const rotationAxisZ = points[1].subtract(points[2])
const rotationAxisY = rotationAxisZ.cross(rotationAxisX)
// RotationFromAxis has the side effect of normalising the input vectors
// so retrieve the box dimensions here
const width = rotationAxisX.length()
const depth = rotationAxisZ.length()
const height = 0.15
const rotationEuler = BABYLON.Vector3.RotationFromAxis(
rotationAxisX,
rotationAxisY,
rotationAxisZ
)
const box = BABYLON.CreateBox("box", { width, height, depth}, scene)
box.position = centerPoint
box.rotation = rotationEuler

Center mesh at world origin in Babylon.js

I have a set of 3D face scan obj files I need to display, and I am looking to center each mesh in the world origin.
I have an example below with one of the actual meshes, but if you look, I just tweaked some numbers and rotated it to look right:
mesh.position.x = .1;
mesh.position.y = .46;
mesh.position.z = 0;
mesh.setPivotPoint(mesh.getBoundingInfo().boundingBox.center);
mesh.rotate(BABYLON.Axis.Y, -(Math.PI / 2), BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.X, -(Math.PI / 2), BABYLON.Space.WORLD);
I enabled the bounding box and that is correct.
How can I render each one centered on the origin without magic numbers?
Thanks!
var canvas = document.getElementById("renderCanvas"); // Get the canvas element
var engine = new BABYLON.Engine(canvas, true);
var createScene = function () {
var scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.FromInts(1, 1, 1);
//Adding a light
var light = new BABYLON.PointLight("Omni", new BABYLON.Vector3(20, 20, 100), scene);
//Adding an Arc Rotate Camera
// var camera = new BABYLON.ArcRotateCamera("Camera", 3, 0, .7, BABYLON.Vector3.Zero(), scene);
var camera = new BABYLON.ArcRotateCamera("Camera", -(Math.PI/2), Math.PI/2, .5, BABYLON.Vector3.Zero(), scene);
// camera.panningAxis = new BABYLON.Vector3(0, 1, 0);
camera.attachControl(canvas, false);
BABYLON.SceneLoader.ImportMesh("" , "https://dl.dropboxusercontent.com/s/n4gwsdn9en6pi86/", "test_ms_simple.obj", scene, function (newMeshes) {
camera.target = BABYLON.Vector3.Zero();
// var mesh = newMeshes[0].getChildMeshes()[0];
var mesh = newMeshes[0];
mesh.showBoundingBox = true;
mesh.position.x = .1;
mesh.position.y = .46;
mesh.position.z = 0;
mesh.setPivotPoint(mesh.getBoundingInfo().boundingBox.center);
mesh.rotate(BABYLON.Axis.Y, -(Math.PI / 2), BABYLON.Space.WORLD);
mesh.rotate(BABYLON.Axis.X, -(Math.PI / 2), BABYLON.Space.WORLD);
camera.minZ = 0;
camera.wheelPrecision = 500;
});
// Move the light with the camera
scene.registerBeforeRender(function () {
light.position = camera.position;
});
// showAxis(10);
return scene;
}
var scene = createScene(); //Call the createScene function
// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function () {
scene.render();
});
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
engine.resize();
});
function showAxis(size) {
var makeTextPlane = function(text, color, size) {
var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", 50, scene, true);
dynamicTexture.hasAlpha = true;
dynamicTexture.drawText(text, 5, 40, "bold 36px Arial", color , "transparent", true);
var plane = BABYLON.Mesh.CreatePlane("TextPlane", size, scene, true);
plane.material = new BABYLON.StandardMaterial("TextPlaneMaterial", scene);
plane.material.backFaceCulling = false;
plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
plane.material.diffuseTexture = dynamicTexture;
return plane;
};
var axisX = BABYLON.Mesh.CreateLines("axisX", [
BABYLON.Vector3.Zero(), new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, 0.05 * size, 0),
new BABYLON.Vector3(size, 0, 0), new BABYLON.Vector3(size * 0.95, -0.05 * size, 0)
], scene);
axisX.color = new BABYLON.Color3(1, 0, 0);
var xChar = makeTextPlane("X", "red", size / 10);
xChar.position = new BABYLON.Vector3(0.9 * size, -0.05 * size, 0);
var axisY = BABYLON.Mesh.CreateLines("axisY", [
BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3( -0.05 * size, size * 0.95, 0),
new BABYLON.Vector3(0, size, 0), new BABYLON.Vector3( 0.05 * size, size * 0.95, 0)
], scene);
axisY.color = new BABYLON.Color3(0, 1, 0);
var yChar = makeTextPlane("Y", "green", size / 10);
yChar.position = new BABYLON.Vector3(0, 0.9 * size, -0.05 * size);
var axisZ = BABYLON.Mesh.CreateLines("axisZ", [
BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3( 0 , -0.05 * size, size * 0.95),
new BABYLON.Vector3(0, 0, size), new BABYLON.Vector3( 0, 0.05 * size, size * 0.95)
], scene);
axisZ.color = new BABYLON.Color3(0, 0, 1);
var zChar = makeTextPlane("Z", "blue", size / 10);
zChar.position = new BABYLON.Vector3(0, 0.05 * size, 0.9 * size);
};
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.min.js"></script>
<canvas id="renderCanvas" width=350 height=350>

How to get bounding box that contains all items in Paper.js?

How can we get the bounding Rectangle that contains all items in the project?
Currently I'm calculating them one by one:
calc-bounds = (scope) ->
fit = {}
for layer in scope.project.layers
for item in layer.children
for <[ top left ]>
if item.bounds[..] < fit[..] or not fit[..]?
fit[..] = item.bounds[..]
for <[ bottom right ]>
if item.bounds[..] > fit[..] or not fit[..]?
fit[..] = item.bounds[..]
#console.log "fit bounds: ", fit
top-left = new scope.Point fit.left, fit.top
bottom-right = new scope.Point fit.right, fit.bottom
new scope.Rectangle top-left, bottom-right
Rationale
A "Fit all" function that sets project.center and project.zoom will need this calculation.
You can just unite (merge) all the bounds from all elements.
This will return a Rectangle that tightly fits all the elements, a.k.a a Bounding Box.
Here's a Sketch.
And here's the code:
var items = [
new Path.Circle({
position: new Point(100, 200),
radius: 50,
fillColor: 'blue'
}),
new Path.Circle({
position: new Point(200, 70),
radius: 50,
fillColor: 'purple'
}),
new Path.Circle({
position: new Point(400, 100),
radius: 50,
fillColor: 'magenta'
})
]
// Unite all bounds from all items.
var unitedBounds = items.reduce((bbox, item) => {
return !bbox ? item.bounds : bbox.unite(item.bounds)
}, null)
// Draw the united bounds.
var bbox = new Path.Rectangle(unitedBounds)
bbox.strokeColor = 'black'
You can use the layer bounds or group the element you want to bound instead of doing the reduce trick from #nicholaswmin
Here is a sketch with both solutions
const items = [
new Path.Circle({
position: new Point(100, 200),
radius: 50,
fillColor: 'blue'
}),
new Path.Circle({
position: new Point(200, 70),
radius: 50,
fillColor: 'purple'
}),
new Path.Circle({
position: new Point(400, 100),
radius: 50,
fillColor: 'magenta'
})
]
// Use the layer bounds
const layerBounds = project.activeLayer.bounds
// Group all needed items and use the bounds
const groupBounds = (new Group(items)).bounds
// Draw the bounds.
const bbox = new Path.Rectangle(layerBounds)
const bbox2 = new Path.Rectangle(groupBounds)
bbox.strokeWidth = 3
bbox.strokeColor = 'blue'
bbox2.strokeWidth = 6
bbox2.strokeColor = 'red'
bbox2.dashArray = [10, 10]

clipping of MeshView scalafx/javafx

I have the following test code, where I try to clip a MeshView with a circle.
I also tried putting the meshView into a group then clipping that, but this result in a black circle.
Is there a way to clip a MeshView, preferably without putting it into a group?
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.image.Image
import scalafx.scene.paint.{Color, PhongMaterial}
import scalafx.scene.shape.{TriangleMesh, Circle, MeshView}
import scalafx.scene.{Group, PerspectiveCamera, Scene, SceneAntialiasing}
object Test4 extends JFXApp {
stage = new PrimaryStage {
scene = new Scene(500, 500, true, SceneAntialiasing.Balanced) {
fill = Color.LightGray
val clipCircle = Circle(150.0)
val meshView = new MeshView(new RectangleMesh(500,500)) {
// takes a while to load
material = new PhongMaterial(Color.White, new Image("https://peach.blender.org/wp-content/uploads/bbb-splash.png"), null, null, null)
}
// val meshGroup = new Group(meshView)
meshView.setClip(clipCircle)
root = new Group {children = meshView; translateX = 250.0; translateY = 250.0; translateZ = 560.0}
camera = new PerspectiveCamera(false)
}
}
}
class RectangleMesh(Width: Float, Height: Float) extends TriangleMesh {
points = Array(
-Width / 2, Height / 2, 0,
-Width / 2, -Height / 2, 0,
Width / 2, Height / 2, 0,
Width / 2, -Height / 2, 0
)
texCoords = Array(
1, 1,
1, 0,
0, 1,
0, 0
)
faces = Array(
2, 2, 1, 1, 0, 0,
2, 2, 3, 3, 1, 1
)
The clippling actually works fine over the MeshView wrapped around a Group.
If you check JavaDoc for setClip():
There is a known limitation of mixing Clip with a 3D Transform. Clipping is essentially a 2D image operation. The result of a Clip set on a Group node with 3D transformed children will cause its children to be rendered in order without Z-buffering applied between those children.
As a result of this:
Group meshGroup = new Group(meshView);
meshGroup.setClip(clipCircle);
you will have a 2D image, and it seems Material is not applied. However you can check there's a mesh, by seting this:
meshView.setDrawMode(DrawMode.LINE);
So in your case, adjusting dimensions:
#Override
public void start(Stage primaryStage) {
Circle clipCircle = new Circle(220.0);
MeshView meshView = new MeshView(new RectangleMesh(400,400));
meshView.setDrawMode(DrawMode.LINE);
Group meshGroup = new Group(meshView);
meshGroup.setClip(clipCircle);
PerspectiveCamera camera = new PerspectiveCamera(false);
StackPane root = new StackPane();
final Circle circle = new Circle(220.0);
circle.setFill(Color.TRANSPARENT);
circle.setStroke(Color.RED);
root.getChildren().addAll(meshGroup, circle);
Scene scene = new Scene(root, 500, 500, true, SceneAntialiasing.BALANCED);
scene.setCamera(camera);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
will give this:
In the end, clipping doesn't make sense with 3D shapes. For that you can use just 2D shape to get the result you want.
If you want 3D clipping have a look at CSG operations. Check this question for a JavaFX based solution.

Resources