The following code pen illustrates 50 cubes being generated directly in three.js and with A-Frame: https://codepen.io/ubermario/pen/XavVxY
What would be the A-Frame design pattern to duplicate the geometry reuse algorithm implemented when referencing three.js directly?
Code snippet:
//Re-use geometry if it was already instantiated;
try {
cubeGeom = uniqueGeom.filter(function(obj) { return obj.intDim == d.intDim})[0].geometry;
}
catch(err) {
cubeGeom = new THREE.CubeGeometry(d.intDim,d.intDim,d.intDim);
uniqueGeom.push({intDim:d.intDim, geometry:cubeGeom})
}
A-Frame hashes geometry properties to a string and places it inside a map.
e.g.,
{
'primitive:box;width:5': THREE.BoxBufferGeometry(),
'primitive:sphere;radius:2' THREE.SphereBufferGeometry()
}
Then when creating new geometry, create a hash using same function, and check the map.
Related
I wanted to load the spatial model using the gltfloader, and then create a collision with geometry data.
By the way, I’m trying to get help with a different result than I expected.
problem image
here is sample image
You can see that the collider is larger than the visible Mesh data.
Most of the spatial data has the above situation.
The example code used is as follows. (tsx on react)
function Space(props) {
const url = props.data?.spaceFileName ? `https://space-test.vrin.co.kr/files/${props.data.spaceFileName}` : null;
const model = useGLTF(url);
const clone = model.scene;
const getCollide = (child) => {
console.log(child);
const geometry = new Geometry().fromBufferGeometry(child.geometry);
const vertices = geometry.vertices.map((v) => new THREE.Vector3().copy(v));
const faces = geometry.faces.map((f) => [f.a, f.b, f.c]);
const normals = geometry.faces.map((f) => new THREE.Vector3().copy(f.normal));
return <Object key={child.uuid} clone={clone} args={[vertices, faces, normals]} model={model} />
};
const traverseObject = (child) => child.children.map((c) => {
if (c.type === 'Object3D' || c.type === 'Group') {
return traverseObject(c);
} if (c.type === 'Mesh') {
return getCollide(c);
}
});
const objects = traverseObject(model.scene)
return <group dispose={null}>{objects}</group>;
}
Some spatial data generate collisions properly, but some spatial data do not generate collisions properly.
make sample image
here is sample what i made on blender
As a result of watching the Blender program, it is expected that it does not seem to be able to properly load the Geometry layer at the top.
blender2
If you look at the collation in the image above, there is a group called Sketchfeb at the top.
If i erase that group layer,
blender2
It can be seen that it is very similar to the shape of the collision body shown in the first picture.
I don’t know if I wrote the recursive function incorrectly or if there is an internal problem with the module.
Does anyone know the solution?
I don’t know if I wrote the recursive function incorrectly or if there is an internal problem with the module.
Does anyone know the solution?
I'm trying to get a threeJS Mesh from Autodek Forge objects using the function
'viewer.impl.getRenderProxy(viewer.model, fragId)'.
The problem that I encounter is if I put this function in a loop routine to get Meshs of multiple objects, I get just a random Mesh.
To find out the problem's origin, I used a similar function that is :
'viewer.impl.getFragmentProxy(viewer.model, fragId)'
and it worked just fine.
Her is the routine code that I use and the result :
for(let i = 0, len = nodNamee.length; i < (len); i = i+3){
var instanceTree = viewer.model.getData().instanceTree;
var fragIds = [];
instanceTree.enumNodeFragments(nodNamee[i+1], function(fragId){
fragIds.push(fragId);
});
fragIds.forEach(function(fragId) {
var renderProxy = viewer.impl.getRenderProxy(viewer.model, fragId);
fragtoMesh.push(renderProxy);
//var fragmentproxy = viewer.impl.getFragmentProxy(viewer.model, fragId);
//fragtoProxy.push(fragmentproxy);
});
}
Result :
Arry of fragtoMesh
This is because the getFragmentProxy method always returns the same instance of THREE.Mesh, just with different properties. Basically, the method works like this under the hood:
let cachedMesh = new THREE.Mesh();
// ...
getRenderProxy(model, fragId) {
// Find the geometry, material, and other properties of the fragment
cachedMesh.geometry = fragGeometry;
cachedMesh.material = fragMaterial;
// ...
return cachedMesh;
}
// ...
Note that this is a performance optimization because if the getFragmentProxy (which is only meant for internal use) function returned a new instance every time it's called by other parts of Forge Viewer, it would cause a huge memory churn.
So in your case, if you really need to store all the THREE.Mesh instances in an array, you'll need to clone them or copy their individual properties into separate THREE.Mesh objects.
I want to add a route fence within the jxmap is it possible? like the picture above, with the feature of directly drawing a polyline in the map
Current version of JxMaps doesn't implement drawing tools.(https://developers.google.com/maps/documentation/javascript/examples/drawing-tools). This functionality will be included to one of next JxMaps releases.
But you can implement own logic using map events and polylines. For example you can add mouse click handler to the Map instance:
LatLng[] path = new LatLng[count];
map.addEventListener("click", new MapMouseEvent() {
#Override
public void onEvent(MouseEvent mouseEvent) {
path[current] = mouseEvent.latLng();
}
});
Using this handler you can collect positions and then write polyline with them:
Polyline polyline = new Polyline(map);
polyline.setPath(path);
When using a TextureAtlas to create a Sprite with the createSprite method, the LibGDX documentation says: This method uses string comparison to find the region and constructs a new sprite, so the result should be cached rather than calling this method multiple times.
How do I cache these results? Is it just a variable I create to store the created sprite? If so then how do I create different copies of the same sprite?
Each time you use the createSprite method, a new Sprite gets created. Usually you'd have one sprite per enemy for example. Let's say that you have a class Frog which is one of your enemies. It should look like this (pseudo-code):
public class Frog {
private Sprite sprite;
public Frog(TextureAtlas atlas) {
sprite = atlas.createSprite("frog");
}
public void update(float deltaTime) {
// update the sprite position
}
public void render(Batch batch) {
sprite.draw(batch);
}
}
Now each Frog would have its own Sprite. This is necessary, since all frogs can be in different places. The position will be configured via the Sprite. You will create the sprite just once in the constructor and all of those sprites share the same TextureRegion of the same TextureAtlas, which will result in a good performance, since there won't be many texture switches on the graphics card, when you render your frogs.
I'm trying to display a model created by SnappyTree/Proctree ( http://www.snappytree.com/ ).
Proctree is designed to work with GLGE, but I'm nearly there in using the library generated data in Three.js. Basically I construct a custom json object, add proctree data to it and use JSONLoader to generate the final geometry.
What I suspect is happening, the vertices (pointcloud) are imported correctly, but the array faces refer to wrong vertices or are otherwise interpreted wrong.
var tree = new Tree(json); // Proctree
// window.console.log(tree);
var model = { "metadata" : { "formatVersion" : 3.1, "generatedBy": "bb3d2proctree", "vertices": 0, "faces": 0, "description": "Autogenerated from proctree." },
"materials": [{ // just testing...
"diffuse": 20000
}],
"colors": [0xff00ff, 0xff0000] // just testing
};
model.vertices = Tree.flattenArray(tree.verts);
model.normals = Tree.flattenArray(tree.normals);
model.uvs = [Tree.flattenArray(tree.UV)];
model.faces = Tree.flattenArray(tree.faces);
var loader = new THREE.JSONLoader();
loader.createModel(model, function(geometry, materials) {
// cut out for brewity... see jsfiddle
}
It's almost working (haven't got into materials yet..) The tree looks kinda correct, however the faces are a bit messed up, and I'm sure there is some simple format difference, and it should be possible to modify the faces array so it works correctly with Three.js.
JSFiddle here: http://jsfiddle.net/nrZuS/
How could I import the data correctly into Three.js?
This is how it should look like: http://www.snappytree.com/#seed=861&segments=10&levels=5&vMultiplier=0.66&twigScale=0.47&initalBranchLength=0.5&lengthFalloffFactor=0.85&lengthFalloffPower=0.99&clumpMax=0.449&clumpMin=0.404&branchFactor=2.75&dropAmount=0.07&growAmount=-0.005&sweepAmount=0.01&maxRadius=0.269&climbRate=0.626&trunkKink=0.108&treeSteps=4&taperRate=0.876&radiusFalloffRate=0.66&twistRate=2.7&trunkLength=1.55&trunkMaterial=TrunkType2&twigMaterial=BranchType5 (except my code so far only tries to import the trunk without twigs, and without textures, so at this point I'm only worried about the trunk shape as can be seen in the jsfiddle)
Never mind, got it to work.
Instead of:
model.faces = Tree.flattenArray(tree.faces);
I do:
model.faces = [];
for (var i = 0; i < tree.faces.length; i++) {
var face = tree.faces[i];
model.faces.push(0);
model.faces.push(face[0]); // v1
model.faces.push(face[1]); // v2
model.faces.push(face[2]); // v3
}
Updated jsFiddle here: http://jsfiddle.net/KY7eq/