I'm trying to make a little scene for viewing 3D models.
I modified the GLGE Collada example to add a .dae model from code.
http://goleztrol.nl/SO/GLGE/01/
What I've got
So far it works. The camera is rotated using an animation.
Using the buttons 'Add' and 'Remove' the model is added and removed from the scene, using the following code (Don't mind 'duck'. It was a duck in the original example.)
var duck = null;
function addDuck()
{
if (duck) return;
duck = new GLGE.Collada();
doc.getElement("mainscene").addCollada(duck);
duck.setId("duck");
duck.setDocument("amyrose.dae");
duck.setLocY(-15);
duck.setRotX(1);
duck.setScale(2);
}
function removeDuck()
{
if (!duck) return;
doc.getElement("mainscene").removeChild(duck);
duck = null;
}
Problem
Now the model is lying down, while it should stand up. The various methods of the element seem to work. The location is set, and the scale is set, but the call to setRotX seems to be ignored. I tried various others methods from the api, but setRotY, setRot, setQuatX and setDRotX all seem to fail. I don't get any errors (well not about this method). I tried values of 1.57 (which should be about 90 degrees), but other values as well, ranging from 1 to 180.
I can't find out what I'm doing wrong. Of course I could rotate the model itself in Blender, but I'd like to do it using the GLGE API.
Update
When I load the demo-model, seymourplane_triangulate.dae, the rotation works. Apparently my model differs in that it cannot be rotated. I just don't understand why. I figured it may be because the model is built of various separate meshes, but I don't understand why scaling and moving does work.
Does anyone know what's wrong with this model, and what I could do to fix it (maybe using Blender)?
Setting an initial rotation in the XML file that contains the scene does work. Setting rotation on another element (like the whole scene) works as well.
You need to rotate it after it has been loaded.
You can do this in the callback to setDocument
duck.setDocument("amyrose.dae", null, function() {
duck.setLocY(-15);
duck.setScale(2);
duck.setRotX(0);
duck.setRotY(0);
duck.setRotZ(3);
});
Related
I recently started working on a configurator tool, and I need a reflective surface on the ground to reflect the object we want to showcase and create a studio-like appearance.
The problem is that Three.js has a version of reflector, but its a 1:1 reflection and it looks weird since its too reflective. The question is if anyone knows how I can make that reflected image slightly more blurry. I'm not that well versed in shaders...
Alternatively, if there are better ways I am open to changing my approach. I am looking for the most performant way of getting a similar result to a car showcase. Image for reference
https://comps.canstockphoto.com/3d-red-hot-rod-drawing_csp0608954.jpg
Link to the file I am using.
https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Reflector.js
and the code I use to place it in the scene:
var mirrorGeometry = new THREE.CircleGeometry(200, 200);
var groundMirror = new Reflector(mirrorGeometry, {
clipBias: 0.05,
textureWidth: window.innerWidth * window.devicePixelRatio,
textureHeight: window.innerHeight * window.devicePixelRatio,
color: 0x777777,
recursion: 1
});
scene.add(groundMirror);
tl;dr: Object is placed on a mirror, causing an identical reflection. Which looks weird for a showcase model. I am asking for information on how to blur it, but a different approach would also work for me.
Edit: Apparently the Reflector object can also not receive shadows (though I need to look into this first. This is also a factor in the final render)
I'm exporting a simple scene from blender to three. Aside from the texture not showing up (which I'm also fighting with), I have a weird problem with the positions of objects. Here's how it looks in blender:
and this is how it renders in three
as you can see, elements are stacked up on each other (and the skybox texture is missing, even though it's referenced properly in the json, embedded as a base64 image). I'm using Three.js exporter v 1.5.0, three.js v84 and blender v 2.77
this is my configuration:
here's the code loading the scene:
var loader = new THREE.ObjectLoader();
loader.load(
'../dist/landscape.json',
function ( obj ) {
scene.add(obj)
}
);
now, I do realise that this way I'm adding a scene to a scene but for some reason, if I try to extract children from it like this:
loader.load(
'../dist/landscape.json',
function ( obj ) {
obj.children.forEach(function(elem) {
scene.add(elem)
}
}
)
I only get half of the objects. No idea why. Besides the objects are still stacked up on each other. I checked the positions in the result versus the original values in blender, and aside from the standard y/z swap x values are reversed (though that's not the cause of the problem), and rotation is removed from the bridge which causes it to render upside down. I'm completely lost
Also, here are the .blend and .json files:
http://www.filehosting.org/file/details/653174/landscape.blend
http://www.filehosting.org/file/details/653175/landscape.json
EDIT:
Partial solution: Scale was set to 10 in exporter, caused the objects to look as if they were misplaced. The thing is, they are still rotated and there's still some mismatch compared to the original. picture here:
I've just come across this issue for myself once again. Having the scale setting at 1 didn't fix it. The issue was that I hadn't applied object transformations in Blender.
Select all problematic objects in your blender file (or just all with A)
Press CTRL+A
Select Rotation & Scale
Repeat for Location if necessary
I am testing Cesiumjs to see if it can reflect a near-real-time expreience - for example: position of airplanes.
For that, I need to draw billboards and make them move - which I know is possible with cesium, just not sure how.
The code looks like this:
var billboards = scene.primitives.add(new Cesium.BillboardCollection());
var billboard = {
image : '/path/to/logo.png',
position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)
};
billboards.add(billboard);
My question is how do I change the position of the billboard. I couldn't find ant documentation that would explain.
I thought doing:
billboard.position = ... //new position
but how will cesium know that I've changed the position attribute unless it somehow turns that reference into a observable object.
So how do I update the location?
Thanks.
Cesium does indeed listen for changes to billboard.position
(source code here), so it is correct behavior for apps to simply write a new position.
Note that you must write the whole position at once, meaning you may not write to billboard.position.x. Instead, keep a "scratch" Cartesian3 around (don't create a new one every animation frame at 60fps), write to the x,y,z properties of your scratch variable, and then assign your scratch variable to billboard.position. You can see in the source that the assigned value will be cloned into another pre-existing Cartesian3, so you may immediately reuse the scratch variable.
Here's an example:
// Just once at app startup. Don't call "new" at 60fps.
var scratchCartesian3 = new Cesium.Cartesian3();
var ellipsoid = viewer.scene.mapProjection.ellipsoid;
function onTick() {
// This is safe to call at 60fps.
billboard.position = Cesium.Cartesian3.fromDegrees(
lon, lat, alt, ellipsoid, scratchCartesian3);
}
Also note that your question and the above answer are focused on the "Graphics Primitive" layer of the Cesium API. Cesium has one higher layer, called the "Entity" API, that you can use if you want Cesium to handle the concept of user-selectable objects with pop-up descriptions etc. Here's a Sandcastle demo showing how to add a billboard as a property of an entity, instead of as a primitive. This allows you to add other properties to the same entity, for example a name, description, label, 3D model, etc, and have them all be controlled from the same position property, and have Cesium take care of popup descriptions. The position property is more complex for entities than for primitives, for example it can be constant or sampled. This allows entities to change position over time when the timeline is shown.
I have tried following the suggestions given as answer to this questions but I still can't figure out how the "rendering flow" of a WebGL program really works.
I am simply trying to draw two triangles on a canvas, and it works in a rather non-deterministic way: sometimes both triangles are rendered, sometimes only the second one (second as in the last one drawn) is rendered.
(it appears to depend on rendering time: strangely enough, the longer it takes, the better the odds of ending up with both triangles rendered). EDIT: not true, tried refreshing over and over and the two triangles sometimes show up on very rapid renders (~55ms), sometimes on longer-running ones (~120ms). What does seem to be a recurring pattern is that on the very first time the page is rendered, the two triangles show, and on subsequent repeated refreshes the red one either shows for good or for a very short lapse of time, then flickers away.
Apparently I'm missing something here, let me explain my program's flow in pseudo-code (can include the real code if need be) to see if I'm doing something wrong:
var canvas = new Canvas(/*...*/);
var redTriangle = new Shape(/* vertex positions & colors */);
var blueTriangle = new Shape(/* vertex positions & colors */);
canvas.add(redTriangle, blueTriangle);
canvas.init(); //compiles and links shaders, calls gl.enableVertexAttribArray()
//for vertex attributes "position" and "color"
for(shape in canvas) {
for(bufferType in [PositionBuffer, ColorBuffer]) {
shape.bindBuffer(bufferType); //calls gl.bindBuffer() and gl.bufferData()
//This is equivalent to the initBuffers()
//function in the tutorial
}
}
for(shape in canvas) {
shape.draw();
//calls:
//-gl.bindBuffer() and gl.vertexAttribPointer() for each buffer (position & color),
//-setMatrixUniforms()
//-drawArrays()
//This is equivalent to the drawScene() function in the tutorial
}
Despite the fact I've wrapped the instructions inside object methods in my attempt to make the use of WebGLs slightly more OO, it seems to me I have fully complied to the instructions on this lesson (comparing the lesson's source and my own code), hence I cannot figure out what I'm doing wrong.
I've even tried to use only one for(shape in canvas) loop, as so:
for(shape in canvas) {
for(bufferType in [PositionBuffer, ColorBuffer]) {
shape.bindBuffer(bufferType); //calls gl.bindBuffer() and gl.bufferData()
//This is equivalent to the initBuffers()
//function in the tutorial
}
shape.draw();
//calls:
//-gl.bindBuffer() and gl.vertexAttribPointer() for each buffer (position & color),
//-setMatrixUniforms()
//-drawArrays()
//This is equivalent to the drawScene() function in the tutorial
}
but it doesn't seem to have any effect.
Any clues?
I'm guessing the issue is that by default WebGL canvases are cleared everytime they are composited
Try changing your WebGL context creation to
var gl = someCanvas.getContext("webgl", { preserveDrawingBuffer: true });
I'm just guessing your app is doing things asynchronously which means each triangle is drawn in response to some event? So, if both events happen to come in quick enough (between a single composite) then you get both triangles. If they come on different composites then you'll only see the second one.
preserveDrawingBuffer: true says "don't clear after each composite". Clearing is the default because it allows certain optimizations for certain devices, specifically iOS, and the majority of WebGL apps clear at the beginning of each draw operation. Those few apps that don't clear can set preserveDrawingBuffer: true
In your particular case line 21 of angulargl-canvas.js
options = {alpha: false, premultipliedAlpha: false};
try changing it to
options = {alpha: false, premultipliedAlpha: false, preserveDrawingBuffer: true};
I'm quite new to both Snap & svg, trying to get savvy. I have an external SVG file that I'm loading as a fragment, then appending to a paper object. Then I want to scale the entire paper object.
The following code executes; the external file loads, the shadow is applied, it is visibly appended to the paper object. The transform, however, doesn't do anything. As far as I can tell, I've replicated the same essential effect as seen in this tutorial. Unfortunately, the official documentation, at least to me, is more or less useless due to it's ambiguity-via-concision appraoch. Anyone?
var logo
$.ajax({
url:"img/logo.svg",
data: null,
complete: function(resp) {
logo = Snap.parse(resp.responseText);
logo = logo.selectAll("g");
var logoPaper = Snap(app.sl.svg.splash.logo.svg).append(logo);
logoPaper.select("#logo-full-mask")
.attr({filter:logoPaper.filter(Snap.filter.shadow(0,0,5, "rgba(0,0,0,.3)"))})
var t = Snap.matrix().scale(1.4);
var trans = logoPaper.transform(t.toTransformString());
}
});
Well after a little fooling around I solved this on my own, but since it wasn't clear to me that this answer would be obvious to anyone who, like me, was new, I chose to post it.
I was trying to scale the paper object itself, which doesn't work (or else works in some unintended way that wasn't useful). Instead, elements of the object needed to be scaled; for my case, the easiest thing to do was create a group of all my paths and scale that, so:
var t = Snap.matrix().scale(1.4);
logoPaper.group(logoPaper.selectAll("path")).transform(t);