Creating a reusable function for loaders in three.js - javascript

I am trying to find a way how to create a reusable function that prevents me from repeating the same loader code over and over again. An example can be seen below:
one = new THREE.Group();
var loader1 = new THREE.TextureLoader();
loader1.crossOrigin = '';
loader1.load('',
function (texture) {
this.geo = new THREE.BoxGeometry(10,10,10);
this.mat = new THREE.MeshBasicMaterial({color:'white'});
this.mesh = new THREE.Mesh(this.geo, this.mat);
one.add(mesh)
}
);
twp = new THREE.Group();
var loader2 = new THREE.TextureLoader();
loader2.crossOrigin = '';
loader2.load('',
function (texture) {
this.geo = new THREE.BoxGeometry(10,10,10);
this.mat = new THREE.MeshBasicMaterial({color:'white'});
this.mesh = new THREE.Mesh(this.geo, this.mat);
two.add(mesh)
}
);
My attempt was as follows:
example = new THREE.Group();
function reuse(obj) {
this.loader = new THREE.TextureLoader();
this.loader.crossOrigin = '';
this.loader.load('',
function (texture) {
this.geo = new THREE.BoxGeometry(10,10,10);
this.mat = new THREE.MeshBasicMaterial({color:'white'});
this.mesh = new THREE.Mesh(this.geo, this.mat);
obj.name.add(mesh)
}
)
};
var test = new reuse({name: 'example'});
I also tried pushing the mesh in an array within the function:
arr.push(mesh);
arr.mesh[0].position.x
etc.
I also tried returning it.
What exactly is the best and working method to avoid such disaster?

when dealing with duplicate code the most common and easiest way is to create a simple function
example with your code:
function getTexturedCube(path){
var geometry = new THREE.BoxGeometry(10,10,10);
var loader = new THREE.TextureLoader();
//you dont have to put onLoad function in,
//the texture returned will automatically update when it is loaded
var texture = loader.load(path);
var material = new THREE.MeshBasicMaterial({map:texture});
return new THREE.Mesh(geometry, material)
}
var group = new THREE.Group();
var cube1 = getTexturedCube("/path/to/image");
var cube2 = getTexturedCube("/path/to/other/image");
group.add(cube1);
group.add(cube2);
var anotherGroup = new THREE.Group();
var cube3 = getTexturedCube("/path/to/yet/another/image")
anotherGroup.add(cube3);
you can also pass the function a reference to your group and make it push the object into it
function addTexturedCube(path, object){
var geometry = new THREE.BoxGeometry(10,10,10);
var loader = new THREE.TextureLoader();
var texture = loader.load(path);
var material = new THREE.MeshBasicMaterial({map:texture});
object.add(new THREE.Mesh(geometry, material));
}
var group = new THREE.Group();
addTexturedCube("/path/to/image", group);
addTexturedCube("/path/to/other/image", group);

Related

Problem to do an arrays exercise. Beginner inside

I'm learning Javascript, and I have a problem with arrays in Javascript, and I have to do a class called TV Show with title, thematicand and actors (actors with array) Then, I have to do a function to grab a specific actor and classify it as "favorite" randomly.
Once done, I get an "empty" array.
This is my code.
class TVShow {
constructor (title, thematic, principalActors){
var arrayActors = new Array();
this.title=title;
this.thematic=thematic;
principalActors=[];
this.generateFavActor = function(){
var long = principalActors.lenght;
let calc = Math.floor(Math.random()*(long));
arrayActors = principalActors[calc];
}
console.log(arrayActors);
}
}
var show01= new TVShow("The Revolution", "Accion",["Hello","Hello2"]);
show01.generateFavActor();
var show02 = new TVShow("Peaky Blinders", "Drama",["Hello","Hello2", "Hello3"] );
show02.generateFavActor();
var show03 = new TVShow ("Stranger Things", "Accion", ["Hello","Hello2", "Hello3", "Hello4"]);
show03.generateFavActor();
Thanks!!
that ? ( using Destructuring assignment )
class TVShow
{
constructor (title, thematic, principalActors)
{
this.title = title
this.thematic = thematic
this.actors = [...principalActors]
}
generateFavActor()
{
console.log( this.actors[ Math.floor(Math.random()*this.actors.length ) ])
}
}
var show01 = new TVShow('The Revolution', 'Accion', ['Hello','Hello2'])
, show02 = new TVShow('Peaky Blinders', 'Drama', ['Hello','Hello2', 'Hello3'] )
, show03 = new TVShow('Stranger Things', 'Accion', ['Hello','Hello2', 'Hello3', 'Hello4'])
;
show01.generateFavActor()
show02.generateFavActor()
show03.generateFavActor()
I think you want something like this:
class TVShow {
constructor (title, thematic, principalActors){
this.title=title;
this.thematic=thematic;
this.arrayActors = principalActors;
this.generateFavActor = function(){
var size = principalActors.length;
let calc = Math.floor(Math.random()*(size));
return principalActors[calc];
}
this.favoriteActor = this.generateFavActor();
}
}
var show01 = new TVShow("The Revolution", "Accion",["Hello","Hello2"]);
var fav01 = show01.favoriteActor;
var show02 = new TVShow("Peaky Blinders", "Drama",["Hello","Hello2", "Hello3"] );
var fav02 = show02.favoriteActor;
var show03 = new TVShow ("Stranger Things", "Accion", ["Hello","Hello2", "Hello3", "Hello4"]);
var fav03 = show03.favoriteActor;
console.log(fav01);
console.log(fav02);
console.log(fav03);
first correct the principalActors.length not principalActors.lenght
Second don't set principalActors as an empty array Next Just put console.log inside the function... it will give you the right answer...right now it is showing the value which is just assigned to an empty array var arrayActors = new Array() Hope it will be HelpFul :-) and I think arrayActors don'nt need to be an an array
class TVShow {
constructor (title, thematic, principalActors){
var arrayActors = new Array();
this.title=title;
this.thematic=thematic;
this.generateFavActor = function(){
var long = principalActors.length;
let calc = Math.floor(Math.random()*(long));
arrayActors = principalActors[calc];
console.log(arrayActors);
}
}
}
var show01= new TVShow("The Revolution", "Accion",["Hello","Hello2"]);
show01.generateFavActor();
var show02 = new TVShow("Peaky Blinders", "Drama",["Hello","Hello2", "Hello3"] );
show02.generateFavActor();
var show03 = new TVShow ("Stranger Things", "Accion", ["Hello","Hello2", "Hello3", "Hello4"]);
show03.generateFavActor();

creating holes in three.js

This is actually taken from THREEJS: add hole to rendered Shape . But it's still not working.
The error is
three.js:34206 Uncaught TypeError: Cannot read property 'concat' of undefined
var plane, vertices = [], planeShape;
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xC0C0C0});
vertices.push(
new THREE.Vector3(-room_width/2,room_depth/2,0),
new THREE.Vector3(room_width/2,room_depth/2,0),
new THREE.Vector3(room_width/2,-room_depth/2,0),
new THREE.Vector3(-room_width/2,-room_depth/2,0)
);
planeShape = new THREE.Shape(vertices);
plane = new THREE.Mesh( new THREE.ShapeGeometry(planeShape), planeMaterial);
scene.add(plane);
var holes = [
new THREE.Vector3(-room_width/4,room_depth/4,0),
new THREE.Vector3(room_width/4,room_depth/4,0),
new THREE.Vector3(room_width/4,-room_depth/4,0),
new THREE.Vector3(-room_width/4,-room_depth/4,0)
],
hole = new THREE.Path();
hole.fromPoints(holes);
var shape = new THREE.Shape(plane.geometry.vertices);
shape.holes = [hole];
var points = shape.extractPoints();
plane.geometry.faces = [];
var triangles = THREE.ShapeUtils.triangulateShape ( points.vertices, points.holes );
for( var i = 0; i < triangles.length; i++ ){
plane.geometry.faces.push( new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2] ));
}
edit::: ANS
var plane, vertices = [], planeShape;
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xC0C0C0});
vertices.push(
new THREE.Vector3(-150,-150,0),
new THREE.Vector3(150,-150,0),
new THREE.Vector3(150,150,0),
new THREE.Vector3(-150,150,0)
);
planeShape = new THREE.Shape(vertices);
plane = new THREE.Mesh( new THREE.ShapeGeometry(planeShape), planeMaterial);
scene.add(plane);
var holes = [
new THREE.Vector3(-75,-75,0),
new THREE.Vector3(75,-75,0),
new THREE.Vector3(75,75,0),
new THREE.Vector3(-75,75,0)
],
hole = new THREE.Path();
hole.fromPoints(holes);
var shape = new THREE.Shape(plane.geometry.vertices);
shape.holes = [hole];
var points = shape.extractPoints();
plane.geometry.faces = [];
var triangles = THREE.ShapeUtils.triangulateShape ( points.shape, points.holes );
plane.geometry.vertices.push(
new THREE.Vector3(-75,-75,0),
new THREE.Vector3(75,-75,0),
new THREE.Vector3(75,75,0),
new THREE.Vector3(-75,75,0)
);
for( var i = 0; i < triangles.length; i++ ){
plane.geometry.faces.push( new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2] ));
}
For anyone stumbling onto this, there is now a much simpler way to work with holes compared to the old "THREE.ShapeUtils.triangulateShape" and constructing the triangles yourself.
//vertices is the main shape/contour/exterior, a "ring" as a list of THREE.Vector2 instances
//holes is a list of THREE.Path instances, created from THREE.Vector2
//If you pass THREE.Vector3 then the Z property is ignored.
var shape = new THREE.Shape(vertices);
shape.holes = holes;
var geometry = new THREE.ShapeBufferGeometry( shape );
...

How can I detect a specific 3d model collision three.js

I am trying to make clickable 3d objects with Leap Motion. I have two 3D models, IronMan helmet and a Hammer of Thor. If one of those two object is selected, then will change color. For the Iron Man will be green and for the Hammer will be white. But when I am selecting the Hammer, it changes to green instead of white. I use a cube as a pointer to select the object. Can you help?
This is the code to insert 3d models:
var colladaMeshlist = [];
model = new THREE.Object3D()
var object;
var skin;
var objectScale = 1.5;
rotX=0, rotY=0, rotZ=0;
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'models/IronMan.dae', function (collada) {
object = collada.scene;
object.scale.x = object.scale.y = object.scale.z = objectScale;
object.position.x= 20;
object.position.y= -40;
object.position.z= 0;
object.rotation.x= rotX;
object.rotation.y= rotY;
object.rotation.z= rotZ;
object.name="IronMan";
colladaMeshlist.push(object);
model.add(object);
});
scene.add(model);
model2 = new THREE.Object3D()
var object2;
var skin2;
var objectScale2 = 1;
posX=0, posY=-40, posZ=0;
rotX=0, rotY=0, rotZ=0;
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'models/Hammer.dae', function (collada) {
object2 = collada.scene;
object2.scale.x = object2.scale.y = object2.scale.z = objectScale2;
object2.position.x= -20;
object2.position.y= -20;
object2.position.z= posZ;
object2.rotation.x= rotX;
object2.rotation.y= rotY;
object2.rotation.z= rotZ;
object2.name="Hammer";
colladaMeshlist.push(object2);
model2.add(object2);
});
scene.add(model2);
This is the code for selecting the objects:
var originPoint = cube.position.clone();
for(var vertexIndex = 0; vertexIndex < cube.geometry.vertices.length; vertexIndex++)
{
var localVertex = cube.geometry.vertices[vertexIndex].clone();
var globalVertex = localVertex.applyMatrix4( cube.matrix );
var directionVector = globalVertex.sub( cube.position );
var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
var collisionResults = ray.intersectObjects(colladaMeshlist, true);
if(collisionResults.length > 0 && collisionResults[0].distance < directionVector.length())
{
collisionResults[0].object.material.color.setHex(0x4CAF50);
}
else if (collisionResults.length > 0 && collisionResults[1].distance < directionVector.length())
{
collisionResults[1].object.material.color.setHex(0xffffff);
}
}

Open layers label not working

I've been trying to get the openlayers label feature to work and produced the following example:
<html>
<head>
<title>OpenLayers Example</title>
<script src="http://openlayers.org/api/OpenLayers.js"></script>
</head>
<body>
<div style="width:100%; height:100%" id="map"></div>
<script>
var map = new OpenLayers.Map('map');
var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
map.addLayer(wms);
// Default polygon style
var polygonStyle =
OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
polygonStyle.strokeColor = "#800000";
polygonStyle.fillColor = "#800080";
polygonStyle.fillOpacity = 0.2;
polygonStyle.strokeWidth = 1;
polygonStyle.label = "Label:${label}";
polygonStyle.labelOutlineColor = "white";
polygonStyle.labelOutlineWidth = 3;
var smap = new OpenLayers.StyleMap({"default": polygonStyle});
var veclayer = new OpenLayers.Layer.Vector("Survey Locations", {"styleMap": smap});
map.addLayer(veclayer);
var data = {"type":"Polygon","coordinates":[[
[-2.07362131225228,52.0329916851734],
[-2.07096056091493,52.0228522264397],
[-2.05061868774548,52.0156687188299],
[-2.04280809509186,52.0210036398637],
[-2.02804521667506,52.0231163039992],
[-2.01748804200037,52.0300345805213],
[-2.01645807373352,52.0464545997404],
[-2.02589944946666,52.0529998067114],
[-2.04194978821027,52.0554276235705],
[-2.06023172485491,52.0455044093648],
[-2.07362131225228,52.0329916851734]]]};
var gson = new OpenLayers.Format.GeoJSON();
var GEO = gson.read(data, "Geometry");
var EPSG4326 = new OpenLayers.Projection("EPSG:4326");
GEO = GEO.transform(EPSG4326, map.getProjectionObject());
var locname="First label";
var FEA = new OpenLayers.Feature.Vector(GEO, {"label":locname}, polygonStyle);
veclayer.addFeatures([FEA]);
map.zoomToExtent(GEO.getBounds(),false);
data= {"type":"Polygon","coordinates":[[[-2.04514962074064,52.0403793945411],
[-2.03057040393828,52.0403841112724],
[-2.03057659173109,52.0493747022699],
[-2.04515873420745,52.049369984023],
[-2.04514962074064,52.0403793945411]]]}
var GEO = gson.read(data, "Geometry");
var EPSG4326 = new OpenLayers.Projection("EPSG:4326");
GEO = GEO.transform(EPSG4326, map.getProjectionObject());
var locname="Second label";
var FEA = new OpenLayers.Feature.Vector(GEO, {"label":locname}, polygonStyle);
veclayer.addFeatures([FEA]);
</script>
</body>
</html>
The code works but the label on the polygons displays as Label:${Label} rather than interpreting the variable to read Label: First label etc.
When this is integrated into a larger application the first label is not interpreted correctly but the second is. I suspect that it may be a layer initialisation problem but have no idea how to get over this.
Any help would be appreciated!!
Have you tried to add attributes as object after declaring the feature for example:
FEA.attributes = {
label:locname
}
It worked this way see, the changes below:
<html>
<head>
<title>OpenLayers Example</title>
<script src="http://openlayers.org/api/OpenLayers.js"></script>
</head>
<body>
<div style="width:100%; height:100%" id="map"></div>
<script>
var map = new OpenLayers.Map('map');
var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
map.addLayer(wms);
// Default polygon style
var polygonStyle =
OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
polygonStyle.strokeColor = "#800000";
polygonStyle.fillColor = "#800080";
polygonStyle.fillOpacity = 0.2;
polygonStyle.strokeWidth = 1;
polygonStyle.label = "Label:${label}";
polygonStyle.labelOutlineColor = "white";
polygonStyle.labelOutlineWidth = 3;
var smap = new OpenLayers.StyleMap({"default": polygonStyle});
var veclayer = new OpenLayers.Layer.Vector("Survey Locations", {"styleMap": smap});
map.addLayer(veclayer);
var data = {"type":"Polygon","coordinates":[[
[-2.07362131225228,52.0329916851734],
[-2.07096056091493,52.0228522264397],
[-2.05061868774548,52.0156687188299],
[-2.04280809509186,52.0210036398637],
[-2.02804521667506,52.0231163039992],
[-2.01748804200037,52.0300345805213],
[-2.01645807373352,52.0464545997404],
[-2.02589944946666,52.0529998067114],
[-2.04194978821027,52.0554276235705],
[-2.06023172485491,52.0455044093648],
[-2.07362131225228,52.0329916851734]]]};
var gson = new OpenLayers.Format.GeoJSON();
var GEO = gson.read(data, "Geometry");
var EPSG4326 = new OpenLayers.Projection("EPSG:4326");
GEO = GEO.transform(EPSG4326, map.getProjectionObject());
var locname="First label";
var FEA = new OpenLayers.Feature.Vector(GEO);
FEA.attributes = {
label:locname
}
veclayer.addFeatures([FEA]);
map.zoomToExtent(GEO.getBounds(),false);
data= {"type":"Polygon","coordinates":[[[-2.04514962074064,52.0403793945411],
[-2.03057040393828,52.0403841112724],
[-2.03057659173109,52.0493747022699],
[-2.04515873420745,52.049369984023],
[-2.04514962074064,52.0403793945411]]]}
var GEO = gson.read(data, "Geometry");
var EPSG4326 = new OpenLayers.Projection("EPSG:4326");
GEO = GEO.transform(EPSG4326, map.getProjectionObject());
var locname="Second label";
var FEA = new OpenLayers.Feature.Vector(GEO);
FEA.attributes = {
label: locname
}
veclayer.addFeatures([FEA]);
</script>
</body>
</html>

problems with a popup in openlayes

I need to make permanent popup but only managed to make it show when a mouse event, i found an example but nothing to adapt achievement: http://openlayers.org/dev/examples/osm-marker-popup.html
anyone can help me to make permanent the popup, Thanks.
var mapa;
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.ImgPath = "/openlayers/img/"
mapa = new OpenLayers.Map('map',{
controls: [
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
],
theme: null
});
var osm = new OpenLayers.Layer.OSM( " Open Street Map" );
var markers = new OpenLayers.Layer.Markers( "Ruta" );
$.each(info, function(i, data){
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon('/openlayers/img/data.png',size,offset);
var lonlat = new OpenLayers.LonLat(parseFloat(data.long),parseFloat(data.lat));
var proj_1 = new OpenLayers.Projection("EPSG:4326");
var proj_2 = new OpenLayers.Projection("EPSG:900913");
var EPSG = lonlat.transform(proj_1,proj_2);
var marker = new OpenLayers.Marker(EPSG, icon);
markers.addMarker(marker);
// popup
marker.events.register("click", marker, function(e){
var popup = new OpenLayers.Popup.FramedCloud(data.idunidad,
marker.lonlat,
new OpenLayers.Size(200,200),
'<p>info in the popup, mouse event</p>',
null,true);
popup.idunidad = data.idunidad;
mapa.addPopup(popup);
arrPopup.push(popup);
});
});
var lonlat = new OpenLayers.LonLat(-74.075833,4.598056);
var proj_1 = new OpenLayers.Projection("EPSG:4326");
var proj_2 = new OpenLayers.Projection("EPSG:900913");
var centrar = lonlat.transform(proj_1,proj_2);
mapa.addLayers([osm,markers]);
mapa.setCenter(centrar, 5);
mapa.addControl(new OpenLayers.Control.LayerSwitcher());
Why not use vector layers, you know this example?
http://openlayers.org/dev/examples/dynamic-text-layer.html

Categories

Resources