The easiest thing to do instead of pasting the entire code here inconveniently is give a link to the Babylon.js playground..If you're not familiar with it, its basically an environment like jsfiddle but specifically for Babylon.js webGL rendering. It's got the canvas, engine, and render loop already initiated (term?)
http://www.babylonjs-playground.com/#LYEU3#0
I have created constructors for 3 different star types:YellowStar, WhiteStar, and RedStar. I have them pasted in the playground code, but locally, the 3 functions are in a separate file. You'll notice that YellowStar's emitting particles do not have the image rendered, which is fine as it doesn't relate to the question. The larger white spheres in the foreground are supposed to be an emissive red color(RedStar objects). The smaller white spheres in the background (WhiteStar objectcs) are white as they are supposed to be, but the emissive property isn't working on those either.
I know its a problem with the way I have them constructed. Because there aren't that many properties in common, I don't have set up to inherit from main Star constructor. Passing sphere and material parameters for the objects would sort of defeat the convenience of creating the constructors in the first place. But there is something I"m doing wrong, unaware of, or not considering that is making the .mat property not work, and the material therefore to not render. I'd like to have all my objects (including planets eventually), originating from one file.
Every time I have an issue I can't figure out, its usually related to scope. WhiteStar and RedStar's material properties are not being recognized. I dont get that because the scope of each .mat should be limited within its own function.
var YellowStar = function (position, size, scene) {
this.sphere = BABYLON.Mesh.CreateSphere("sphere1", 30, 30*size, scene);
this.mat = new BABYLON.StandardMaterial("white", scene);
this.mat.diffuseTexture = new BABYLON.Texture("textures/suntexture.jpg", scene);
this.mat.specularColor = new BABYLON.Color3(0, 0, 0);
this.sphere.material = this.mat;
this.sphere.position = position;
/*...this material works...*/
};
var WhiteStar = function(position, size, scene){
this.sphere = BABYLON.Mesh.CreateSphere("whiteStar", 20, 15*size, scene);
this.mat = new BABYLON.StandardMaterial("white", scene);
this.mat.emissiveColor = new BABYLON.Color3(1, 1, 1);
this.sphere.material = this.mat; /* doesn't work */
}
var RedStar = function (position, size, scene) {
this.sphere = BABYLON.Mesh.CreateSphere("redStar", 20, 30*size, scene);
this.mat = new BABYLON.StandardMaterial("red", scene);
this.mat.emissiveColor = new BABYLON.Color3(0.714, 0.239, 0.169);
this.sphere.material = this.mat; /*doesnt work*/
};
Babylon does have a community, but the questions relate more toward the engine, and I have more success getting general Javascript questions answered here. Thanks
After fiddling about with it, it looks like you have to explicitly add/define the diffuse colour before the emissive colour to work. I don't know why.
NB The white star emissive colour is full on white, so I'm unsure how you'd know whether it's working or not.
HTH
Related
I would like to build a parallax effect from a 2D image using a depth map, similar to this, or this but using three.js.
Question is, where should I start with? Using just a PlaneGeometry with a MeshStandardMaterial renders my 2D image without parallax occlusion. Once I add my depth map as displacementMap property I can see some sort of displacement, but it is very low-res. (Maybe, since displacement maps are not meant to be used for this?)
My first attempt
import * as THREE from "three";
import image from "./Resources/Images/image.jpg";
import depth from "./Resources/Images/depth.jpg";
[...]
const geometry = new THREE.PlaneGeometry(200, 200, 10, 10);
const material = new THREE.MeshStandardMaterial();
const spriteMap = new THREE.TextureLoader().load(image);
const depthMap = new THREE.TextureLoader().load(depth);
material.map = spriteMap;
material.displacementMap = depthMap;
material.displacementScale = 20;
const plane = new THREE.Mesh(geometry, material);
Or should I use a Sprite object, which face always points to the camera? But how to apply the depth map to it then?
I've set up a codesandbox with what I've got so far. It also contains event listener for mouse movement and rotates the camera on movement as it is work in progress.
Update 1
So I figured out, that I seem to need a custom ShaderMaterial for this. After looking at pixijs's implementation I've found out, that it is based on a custom shader.
Since I have access to the source, all I need to do is rewrite it to be compatible with threejs. But the big question is: HOW
Would be awesome if someone could point me into the right direction, thanks!
I'm new to PixiJS and I'm trying something simple like a painting application.
I'm having difficulty trying to capture a collection of shapes as a single grouping. I'm not interested in working code for this as I'd like to figure that out on my own; I'm simply interested in knowing whether I'm on the right track or if I need to explore some other PixiJS concepts to get what I need.
I have one canvas in which I can drag shapes such as rectangles, ellipse, and lines. These "strokes" are being stored as individual Graphics objects, for instance:
var shape = new PIXI.Graphics();
shape.position.set(...);
...
shape.lineStyle(...)
.beginFill(...)
.drawRect(...)
.endFill();
...
stage.addChild(shape);
...
renderer.render(stage);
I'm also holding onto these shapes in an array:
shapes.push(shape);
Now that I have these displayed as well as have the order of the strokes available, I'd like to be able to capture them somehow. Imagine maybe taking the drawing and saving it, or perhaps using it as a thumbnail in a gallery, or simply just storing it on the back-end in a database, preferably keeping all the raw strokes so that they can be scaled up or down as desired.
For now, I'm simply trying to take this collection of strokes and display them again by holding them, clearing the graphics from my canvas, and then plopping down what I have held.
Looking at this example, I've been able to get a texture that I can reliably reproduce wherever I click with the mouse:
http://jsfiddle.net/gzh14bcn/
This means I've been able to take the first part that creates the texture object, and I tweaked the second part to create and display the sprites when I click the mouse.
When I try to replace this example code with my own code to create the texture itself, I can't get that part to work.
So this example snippet works fine when I try to create a sprite from it:
var texture = new PIXI.RenderTexture(renderer, 16, 16);
var graphics = new PIXI.Graphics();
graphics.beginFill(0x44FFFF);
graphics.drawCircle(8, 8, 8);
graphics.endFill();
texture.render(graphics);
FYI to create sprites:
var sprite = new PIXI.Sprite(texture);
sprite.position.set(xPos, yPos);
stage.addChild(sprite);
Since I have my shapes in the shapes array or on the stage, what is the preferred way I proceed to capture this as a single grouping from which I can create one or more sprites?
So basicaly you've got how to make some PIXI.Graphics shape
var pixiRect = new PIXI.Graphics();
pixiRect.lineStyle(..);
pixiRect.beginFill(..);
pixiRect.drawRect(..);
pixiRect.endFill(..);
(You can draw as many rects/circles/shapes as you want into one PIXI.Graphics)
But to convert it to texture you must tell renderer to create it
var texture = renderer.generateTexture(pixiRect);
Then you can easily create PIXI.Sprite from this texture
var spr = new PIXI.Sprite(texture);
And the last thing is to add it to your stage or array, but you can also make some empty PIXI.Container and then addChild to that and you've got your array
option - add sprite (created from graphics) to stage
stage.addChild(spr);
option - push it to your array
shapes.push(spr);
option - if you have var shapes = new PIXI.Container(); you can make a container for your sprites
shapes.addChild(spr);
Working example : https://jsfiddle.net/co7Lrbq1/3/
EDIT:
to position your canvas above you have to addChild it later, it means first addChild has zIndex = 0 and every addChild adds a layer on top of last
I figured it out. My stage is a container:
var stage = new PIXI.Container();
var canvas = new PIXI.Graphics();
canvas.lineStyle(4, 0xffffff, 1);
canvas.beginFill(0xffffff);
canvas.drawRect(canvasStartX, canvasStartY, 500, 600);
canvas.endFill();
stage.addChild(canvas);
I changed this to the following:
var canvas = new PIXI.Container();
var canvasRect = new PIXI.Graphics();
canvasRect.lineStyle(4, 0xffffff, 1);
canvasRect.beginFill(0xffffff);
canvasRect.drawRect(canvasStartX, canvasStartY, 500, 600);
canvasRect.endFill();
canvas.addChild(canvasRect);
stage.addChild(canvas);
Then, I replaced stage with canvas where appropriate and canvas with canvasRect where appropriate.
Finally, I got my texture with:
var texture = canvas.generateTexture(renderer);
At the moment, this grabbed the entire width/height of the stage, but I think I just need to tweak a bit on how I create my canvas above and I should be fine.
I am trying to take any three.js geometry and subdivide its existing faces into smaller faces. This would essentially give the geometry a higher "resolution". There is a subdivision modifier tool in the examples of three.js that works great for what I'm trying to do, but it ends up changing and morphing the original shape of the geometry. I'd like to retain the original shape.
View the Subdivision Modifier Example
Example of how the current subdivision modifier behaves:
Rough example of how I'd like it to behave:
The subdivision modifier is applied like this:
let originalGeometry = new THREE.BoxGeometry(1, 1, 1);
let subdivisionModifier = new THREE.SubdivisionModifier(3);
let subdividedGeometry = originalGeometry.clone();
subdivisionModifier.modify(subdividedGeometry);
I attempted to dig around the source of the subdivision modifier, but I wasn't sure how to modify it to get the desired result.
Note: The subdivision should be able to be applied to any geometry. My example of the desired result might make it seem that a three.js PlaneGeometry with increased segments would work, but I need this to be applied to a variety of geometries.
Based on the suggestions in the comments by TheJim01, I was able to dig through the original source and modify the vertex weight, edge weight, and beta values to retain the original shape. My modifications should remove any averaging, and put all the weight toward the source shape.
There were three sections that had to be modified, so I went ahead and made it an option that can be passed into the constructor called retainShape, which defaults to false.
I made a gist with the modified code for SubdivisionGeometry.js.
View the modified SubdivisionGeometry.js Gist
Below is an example of a cube being subdivided with the option turned off, and turned on.
Left: new THREE.SubdivisionModifier(2, false);
Right: new THREE.SubdivisionModifier(2, true);
If anyone runs into any issues with this or has any questions, let me know!
The current version of three.js has optional parameters for PlaneGeometry that specify the number of segments for the width and height; both default to 1. In the example below I set both widthSegments and heightSegments to 128. This has a similar effect as using SubdivisionModifier. In fact, SubdivisionModifier distorts the shape, but specifying the segments does not distort the shape and works better for me.
var widthSegments = 128;
var heightSegments = 128;
var geometry = new THREE.PlaneGeometry(10, 10, widthSegments, heightSegments);
// var geometry = new THREE.PlaneGeoemtry(10,10); // segments default to 1
// var modifier = new THREE.SubdivisionModifier( 7 );
// geometry = modifier.modify(geometry);
https://threejs.org/docs/#api/en/geometries/PlaneGeometry
I am beginning to explore the HTML5 canvas, and I apologize in advance for the naivety of my question. Using Flash CC, I have generated a canvas with a rectangle on it:
(function (lib, img, cjs, ss) {
var p; // shortcut to reference prototypes
// library properties:
lib.properties = {
width: 550,
height: 400,
fps: 24,
color: "#FFFFFF",
manifest: []
};
// symbols:
// stage content:
(lib.canvas_test = function() {
this.initialize();
// Layer 1
this.shape = new cjs.Shape();
this.shape.graphics.beginFill().beginStroke("#669966")
.setStrokeStyle(1,1,1).moveTo(-94,-62).lineTo(94,-62).lineTo(94,62).lineTo(-94,62).closePath();
this.shape.setTransform(198,136);
this.shape_1 = new cjs.Shape();
this.shape_1.graphics.beginFill("#FF933C")
.beginStroke().moveTo(-94,62).lineTo(-94,-62).lineTo(94,-62).lineTo(94,62).closePath();
this.shape_1.setTransform(198,136);
this.addChild(this.shape_1,this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(378,273,190,126);
})(lib = lib||{}, images = images||{}, createjs = createjs||{}, ss = ss||{});
var lib, images, createjs, ss;
Now I am stuck. How can I retrieve (and change) the color of the rectangle using a Javascript function? I had hoped that the shapes would simply be children of the canvas, but this does not seem to be the case.
The earlier answers are correct about Canvas being basically a bitmap, but EaselJS gives you a retained graphics mode, so you can change properties and update the stage/canvas to reflect them.
You are using Flash export to generate your content, so you should be able to access your elements via the exportRoot, which is created in the HTML. This is essentially the Flash "stage", represented by an EaselJS container that is defined by canvas_test in your exported library.
exportRoot = new lib.canvas_test();
You can see in the canvas_test code, each "child" is defined. Any graphics are wrapped in EaselJS Shape instances. There are also classes for handling groups (Containers), Bitmaps, Text, and animations (MovieClips).
Here is your exported code above put added to the stage:
http://jsfiddle.net/lannymcnie/b5me4xa2/
It is easy to modify shapes once they are created, but you have to define them with that in mind. The Flash export doesn't really provide you this capability, since it just exports everything as a single, chained graphics instructions list. You can however introspect it fairly easily to find the commands you want to modify. Warning: This requires EaselJS 0.7.0+ in order to work. Earlier versions will not work with this approach
The demo you provided has a single Rectangle. Unfortunately there is a bug in the current version of Flash that exports it as 2 shapes, one for the stroke, and another for the fill. This example will modify the stroke.
var shape = exportRoot.shape; // Access the shape instance that has the stroke
var stroke = shape.graphics._stroke;
stroke.style = "#ff0000"; // Set to red.
To do the fill, you can do the same thing on shape_1, but affect the _fill instead. Here is an updated sample
You can also access any of the instructions, and affect their properties. You can see a full command list in the Graphics docs (see the sidebar for the full list). Here is a quick sample modifying the first moveTo command on the stroke:
var shape = exportRoot.shape;
shape.graphics._activeInstructions[0].x = -110;
You can see a sample of that code here: http://jsfiddle.net/lannymcnie/b5me4xa2/2/ -- You will have to modify both fill and stroke to move them both :)
Canvas is basically a bitmap, it has no children. An SVG works more like you're imagining but a canvas just has pixels. If you want to change a canvas you're either going to have to go through it and find the pixels, or create a javascript object representing your drawing object (the rectangle), keep it separate from your canvas background, and redraw the the background and object when there are any changes.
[Added]
I'm not familiar with Flash CC, but as pointed out in the comment, perhaps there is some capability there already to do what the commenter and myself are describing - I'm afraid I don't know.
I am currently working on a small project using the new Babylon.js framework. One of the issues I have run into is that I basically have two meshes. One of the meshes is supposed to be the background, and the other is supposed to follow the cursor to mark where on the other mesh you are targeting. The problem is that when I move the targeting mesh to the position of the cursor, it blocks the background mesh when I use scene.pick, resulting in the other mesh having its position set on its self.
Is there any way to ignore the targeting mesh when using scene.pick so that I only pick the background mesh or is there some other method I could use? If not, what would be the steps to implement this sort of feature to essentially raycast only through certain meshes?
If you need code samples or any other forms of description, let me know. Thanks!
Ok, it's easy.
So, we have two meshes. One is called "ground", the second "cursor". If you want to pick only on the ground you have two solutions :
First:
var ground = new BABYLON.Mesh("ground",scene);
ground.isPickable = true ;
var cursor = new BABYLON.Mesh("cursor", scene);
cursor.isPickable = false;
...
var p = scene.pick(event.clientX, event.clientY); // it return only "isPickable" meshes
...
Second:
var ground = new BABYLON.Mesh("ground",scene);
var cursor = new BABYLON.Mesh("cursor", scene);
...
var p = scene.pick(event.clientX, event.clientY, function(mesh) {
return mesh.name == "ground"; // so only ground will be pickable
});
...
regards.