webGL unresponsive script with requestAnimationFrame - three.js

Hi, I have a problem with webgl and using requestAnimationFrame, if i continue in debug the animation is fine but as soon as i let the script run freely i get an unresponsive script error from the browser
here is my html :
<!DOCTYPE html>
<html>
<head>
<title>Earth to WebGL</title>
<script type="text/javascript" src="../Rec/three.min.js"></script>
<script type="text/javascript" src="../Rec/jquery-1.6.4.js"></script>
<script type="text/javascript" src="../Rec/RequestAnimationFrame.js"></script>
<script type="text/javascript" src="ex_loop.js"></script>
<script type="text/javascript" src="Earth.js"></script>
<script>
var loopProg = null;
var renderer = null;
var scene = null;
var camera = null;
var mesh = null;
var earth = null;
$(document).ready(
function() {
var container = document.getElementById("container");
renderer = new THREE.WebGLRenderer({ antialias: true } );
renderer.setSize(container.offsetWidth,container.offsetHeight);
container.appendChild(renderer.domElement)
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45,
container.offsetWidth / container.offsetHeight, 1, 4000 );
earth = new Earth();
scene.add(earth.getEarth);
camera.position.set( 0, 0, 3 );
loopProg = new loopProgram();
loopProg.add(function(){earth.update()});
loopProg.add(function(){renderer.render( scene, camera );});
loopProg.solarLoop();
}
);
</script>
my earth script file
function Earth()
{
this.getEarth = init();
function init()
{
var map = {map:THREE.ImageUtils.loadTexture("images/earth_surface_2048.jpg")};
var material = new THREE.MeshBasicMaterial(map);
var geometry = new THREE.SphereGeometry(1,32,32);
return new THREE.Mesh(geometry, material);
}
this.update = function()
{
this.getEarth.rotation.x += .01;
}
return this;
}
and the loop code :
function loopProgram()
{
this.functionsToRun = new Array();
this.solarLoop= function()
{
jQuery.each(this.functionsToRun, function(index,value)
{
value ? value() : null;
});
var loopRef = this;
requestAnimationFrame(loopRef.solarLoop());
}
this.add = function(func)
{
this.functionsToRun[this.functionsToRun.length] = func;
}
}

You're calling solarLoop recursively instead of passing just the callback function:
requestAnimationFrame(loopRef.solarLoop());
should be
requestAnimationFrame(loopRef.solarLoop);

Related

How to show a color-coded country map (with city boundaries) in Aframe

Following my previous question:Load json map into aframe by aframe-geo-projection-component created by earthlinginteractive
Now, I am trying to find a way to show different geometries (country or city) in AFrame each with a different color,
looking for something like this.
I do not mind which library or approach are used, Found this but not sure how to convert this D3.js to Aframe. However as the community bot asked me to provide more details, I have put the code that I am working on below. Not sure which part I need to modify to have such a color coded map but I am working on that. Again, any working example works for me even if someone can show what I need to modify in the below code.
<!-- https://github.com/EarthlingInteractive/aframe-geo-projection-component
https://earthlinginteractive.github.io/aframe-geo-projection-component/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>A-Frame Geo Projection Component - U.S. Population 2017 (est.)</title>
<meta name="description" content="Visualization of estimated U.S. population by state in 2017"></meta>
<script src="https://aframe.io/releases/0.7.1/aframe.min.js"></script>
<script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v3.12.4/dist/aframe-extras.min.js"></script>
<script src="https://unpkg.com/super-hands#2.1.0/dist/super-hands.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-queue.v3.js"></script>
<script src="https://earthlinginteractive.github.io/aframe-geo-projection-component/dist/aframe-geo-projection-component.min.js"></script>
</head>
<body>
<script>
AFRAME.registerComponent('geo-extrude-population-renderer', {
dependencies: ['geo-projection'],
schema: {
maxExtrudeHeight: {
default: 2
}
},
init: function () {
this.system = this.el.sceneEl.systems['geo-projection'];
this.geoProjectionComponent = this.el.components['geo-projection'];
this.geoJsonReady = this.geoJsonReady.bind(this);
// Wait for geoJson to finish loading to avoid race conditions
this.el.addEventListener('geo-src-loaded', this.geoJsonReady);
},
update: function (oldData) {
if (!this.geoProjectionComponent.geoJson) {
return;
}
if (this.data.maxExtrudeHeight !== oldData.maxExtrudeHeight) {
this.geoJsonReady();
}
},
geoJsonReady: function () {
// Now kick off loading the data
d3.queue()
.defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-population-2017.csv?v=1657704183925', function (d) {
return {
state: d.state,
population: +d.population
}
})
.defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-state-county-geocodes-v2016.csv?v=1657704190160')
.await(this.onDataLoaded.bind(this));
},
onDataLoaded: function(error, populationData, geocodes) {
if (error) throw error;
var stateFips = geocodes.filter(function (row) {
return row['Summary_Level'] === '040'
});
var maxPopulation = d3.max(populationData, function (d) {
return d.population;
});
var populationByFipsCode = populationData.reduce(function (accum, d) {
var fipsForState = stateFips.find(function (fipsRow) { return fipsRow['Area_Name'] === d.state; });
var fipsCode = fipsForState['State_Code_FIPS'];
accum[fipsCode] = d.population;
return accum;
}, {});
this.render(populationByFipsCode, maxPopulation, this.data.maxExtrudeHeight);
},
render: function (populationByFipsCode, maxPopulation, maxExtrudeHeight) {
if (!populationByFipsCode) return;
var material = [];
var extrudeGeometry = null;
var stateOutlineVertices = [];
// Split the geoJson into features and render each one individually so that we can set a different
// extrusion height for each based on the population.
this.geoProjectionComponent.geoJson.features.forEach(function (feature) {
var population = populationByFipsCode[feature.id];
var extrudeAmount = (population / maxPopulation) * maxExtrudeHeight;
var material="#999999";
const extrudeSettings = {
amount: extrudeAmount,
bevelEnabled: false
};
//Math.floor(Math.random()*16777215).toString(16);
var mapRenderContext = this.system.renderToContext(feature, this.geoProjectionComponent.projection);
const stateShapes = mapRenderContext.toShapes();
// Gather the outline of the state and set the height of the outline to the extrude level
// so that the top of the state is outlined
stateOutlineVertices = stateOutlineVertices.concat(mapRenderContext.toVertices(extrudeAmount));
// Merge all the extruded feature geometries together for better rendering performance
// Need to use ExtrudeGeometry here instead of ExtrudeBufferGeometry because the latter doesn't merge properly
// in this version of Three.js
var extrudedFeatureGeometry = new THREE.ExtrudeGeometry(stateShapes, extrudeSettings);
if (!extrudeGeometry) {
extrudeGeometry = extrudedFeatureGeometry;
} else {
extrudeGeometry.merge(extrudedFeatureGeometry);
}
}.bind(this));
// Convert the extrude geometry into a buffer geometry for better rendering performance
var extrudeBufferGeometry = new THREE.BufferGeometry();
extrudeBufferGeometry.fromGeometry(extrudeGeometry);
var sideMaterial = new THREE.MeshStandardMaterial( { color: 0xaaafff } );
var extrudedMap = new THREE.Mesh(extrudeBufferGeometry, [material, sideMaterial]);
this.el.setObject3D('map', extrudedMap);
var stateOutlineGeometry = new THREE.BufferGeometry();
stateOutlineGeometry.addAttribute('position', new THREE.Float32BufferAttribute(stateOutlineVertices, 3));
var stateOutlineMaterial = new THREE.LineBasicMaterial( { color: 0xcccaaa } );
var stateOutlines = new THREE.LineSegments(stateOutlineGeometry, stateOutlineMaterial);
this.el.setObject3D('lines', stateOutlines);
}
});
</script>
<a-scene>
<a-assets>
<a-asset-item id="json-us" src="https://unpkg.com/us-atlas#1/us/10m.json" />
</a-assets>
<a-sky color="#ECECEC"></a-sky>
<a-entity id="map"
rotation="-90 0 0"
material="color: #123456;"
topojson-loader="src: #json-us; topologyObject: states;"
geo-projection="
projection: geoIdentity;
height: 6;
width: 10;"
geo-extrude-population-renderer
>
</a-entity>
<a-locomotor>
<a-entity hand-controls="left" super-hands></a-entity>
<a-entity hand-controls="right" super-hands></a-entity>
</a-locomotor>
</a-scene>
</body>
</html>
<!--material="color: #123456;"-->
getting this error as well if I use aframe 1.3.0:
Uncaught TypeError: extrudeBufferGeometry.fromGeometry is not a function
at i.render ((index):104:29)
at i.onDataLoaded ((index):66:12)
at Queue._call (d3-queue.v3.js:43:54)
at maybeNotify (d3-queue.v3.js:120:7)
at d3-queue.v3.js:91:12
at Object.<anonymous> (d3.v4.js:11470:86)
at Dispatch.call (d3.v4.js:792:72)
at XMLHttpRequest.respond (d3.v4.js:11395:13)

Loading multiple textures from different url's fails

I am trying to render textures on planes loaded from different URL's. For some reason after 2nd or 3rd image I can see in browser that loading image is stuck and it is not being rendered.
Adding the code used:
function init() {
loadPicturesFromDirectUrl();
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
renderPicture(picture, texture);
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}
You may want to try to preload all the pictures in one function and store them in an array and render them only after all of them have been loaded. Like so:
var all_textures = [];
function init() {
loadPicturesFromDirectUrl();
for int (i = 0; i < all_picture.length; i++) {
renderPicture(data.pictures[i], all_textures[i])
}
}
function loadPicturesFromDirectUrl(currentPictureIndex) {
if (currentPictureIndex === undefined) {
currentPictureIndex = 0;
}
var picture = data.pictures[currentPictureIndex];
var loader = new THREE.TextureLoader();
loader.load(picture.url, function (texture) {
all_textures[currentPictureIndex] = texture
currentPictureIndex++;
if (currentPictureIndex > data.pictures.length - 1) {
return;
}
loadPicturesFromDirectUrl(currentPictureIndex);
}, null, function (e) {
console.log(e);
});
}
function renderPicture(picture, texture) {
var planeGeometry = new THREE.PlaneGeometry(picture.size.width, picture.size.height);
var planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.position.x = picture.location.x;
planeMesh.position.y = picture.location.y;
planeMesh.rotateY(myzeum.toRadians(180));
scene.add(planeMesh);
}

paper js display stop issue

I use paper.js and canvas to make web api, but when open web page , there is nothing until I move mouse on canvas. I don't know why.
code as follow, actually when I try to draw a box , it also like that.
<script language="javascript" type="text/javascript" canvas="canvas">
paper.install(window);
window.onload=function(){
var scope2 = new PaperScope();
paper = scope2.setup('controlpanel');
// var L_controlpanel = new Layer();
var bgshadoW = new Shape.Rectangle({
point:[10,10],
size:[200,360],
fillColor:'#f2f2f2',
shadowColor:'black',
shadowBlur: 12,
shadowOffset: [5, 5]
});
var colorfunC ;
var G_colorfunC = new Group();
var colorcontenT = ['#ffff66','#77ff33','#66b3ff','#f0aad9','#ffd486']
for (var i, i=0;i<5;i++){
colorfunC = new Path.Rectangle({
point:[20,20+30*i],
size:[15,15],
radius:5,
strokeColor: 'black',
strokeWidth: 1,
fillColor:'#f2f2f2',
data:{'click':0,'color':colorcontenT[i]}
});
G_colorfunC.addChild(colorfunC);
colorfunC.onClick = function(event){
G_colorfunC.fillColor='#f2f2f2';
this.fillColor=' #4dc3ff';
fillcolorshoT = this.data['color'];
}
fixdemO = new Path.Rectangle({
point:[60,20+30*i],
size:[50,15],
fillColor:colorcontenT[i]
});
}
var G_denVfunC = new Group();
var denVcontenT = [120,150,200,250,300]
for (var i, i=0;i<5;i++){
denVfunC = new Path.Rectangle({
point:[20,200+30*i],
size:[15,15],
radius:5,
strokeColor: 'black',
strokeWidth: 1,
fillColor:'#f2f2f2',
data:{'click':0,'denV':denVcontenT[i]}
});
G_denVfunC.addChild(denVfunC);
denVfunC.onClick = function(event){
G_denVfunC.fillColor='#f2f2f2';
this.fillColor='#4dffa6';
denV = this.data['denV'];
}
FixText = new PointText({
point:[60,212+30*i],
fontSize:14,
fillColor: 'black',
content:'DOMA density: '+denVcontenT[i]
});
}
}
</script>
found cause,just add
paper.view.update();

How to get Famo.us draggable modifier's render node

I am trying to get parent renderNode of a draggable modifier on 'end' event, is there any api to get a renderNode to which draggable belongs to? My code is as follows :
/*globals define*/
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require("famous/modifiers/Draggable");
var RenderNode = require('famous/core/RenderNode');
/*
* #name DragTest
* #constructor
* #description
*/
function DragTest() {
View.apply(this, arguments);
_createDragSurface.call(this);
}
DragTest.prototype = Object.create(View.prototype);
DragTest.prototype.constructor = DragTest;
DragTest.DEFAULT_OPTIONS = {
};
function _createDragSurface(){
var yOffset=0;
for(var i=0;i<2;i++){
var draggable = new Draggable({
xRange: [-220,0],
yRange: [0,0]
});
var dragSurface= new Surface({
content:'this is a drag surface',
size:[150,150],
properties:{
marginLeft: '10px',
backgroundColor:'grey'
}
});
var dragSurfaceModifier= new StateModifier({
align:[0.5,yOffset]
});
yOffset+=0.3;
dragSurface.pipe(draggable);
draggable.on('end',function(e){
this.setPosition([0,0,0], {
method: 'snap',
period: 300
});
});
var nodePlayer = new RenderNode(draggable);
nodePlayer.add(dragSurfaceModifier).add(dragSurface);
this.add(nodePlayer);
}
}
module.exports = DragTest;
});
On drag of a surface to the left, once it reaches threshold, I want to remove the renderNode i.e.,
draggable.on('end',function(e){
if(e.position[0]<-50){
renderNode.remove()//how to achieve this part of the code as I dont have an access to nodePlayer renderNode here.
}
else{
this.setPosition([0,0,0], {
method: 'snap',
period: 300
});
}
});
If I simply use the name of a renderNode i.e., nodePlayer it will remove the last surface no matter which surface is been dragged.Any input on this is much appreciated.
Best Regards.
There are a lot of ways to accomplish what you want to do.
Since you are using the end event on the draggable and using the position value from the custom event, let's bind the references to the needed items to be able to access them.
There is not a .remove() method on the RenderNode so the example shows a way you could remove a node from the view with a RenderController.
Remember: There is no need to remove nodes from the DOM. Famo.us will manage the renderables in the render tree.
define('main', function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Modifier = require('famous/core/Modifier');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require('famous/modifiers/Draggable');
var TransitionableTransform = require('famous/transitions/TransitionableTransform');
var DragTest = require('DragTest');
var mainContext = Engine.createContext();
var dragTest = new DragTest();
mainContext.add(dragTest);
dragTest.on('removed', function(e) {
console.log('removed ', e.removedNode);
});
});
define('DragTest', function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require("famous/modifiers/Draggable");
var RenderNode = require('famous/core/RenderNode');
var RenderController = require('famous/views/RenderController');
/*
* #name DragTest
* #constructor
* #description
*/
function DragTest() {
View.apply(this, arguments);
_createDragSurface.call(this);
}
DragTest.prototype = Object.create(View.prototype);
DragTest.prototype.constructor = DragTest;
DragTest.DEFAULT_OPTIONS = {};
function _endingDrag(e) {
console.log('end position', e.position, this);
if (e.position[0] < -180) {
this.renderController.hide(this.nodePlayer, function() {
this.surface.emit('removed', {
removedNode: this.nodePlayer
});
}.bind(this));
} else {
this.draggable.setPosition([0, 0, 0], {
duration: 300
});
}
}
function _updatingDrag(e) {
console.log('update position', e.position);
this.surface.setContent('Position ' + e.position);
}
function _createDragSurface() {
var yOffset = 0;
for (var i = 0; i < 2; i++) {
var dragSurface = new Surface({
content: 'this is a drag surface',
size: [150, 150],
properties: {
marginLeft: '10px',
backgroundColor: 'grey'
}
});
var dragSurfaceModifier = new StateModifier({
origin: [0, 0],
align: [0.5, yOffset]
});
yOffset += 0.3;
var draggable = new Draggable({
xRange: [-220, 0],
yRange: [0, 0]
});
var renderController = new RenderController();
this.add(renderController);
var nodePlayer = new RenderNode();
nodePlayer.add(dragSurfaceModifier).add(draggable).add(dragSurface);
renderController.show(nodePlayer)
draggable.on('end', _endingDrag.bind({
draggable: draggable,
renderController: renderController,
nodePlayer: nodePlayer,
surface: dragSurface
}));
draggable.on('update', _updatingDrag.bind({
surface: dragSurface
}));
draggable.subscribe(dragSurface);
dragSurface.pipe(this._eventOutput); // so we can emit a custom removed event to this widget
}
}
module.exports = DragTest;
});
require(['main']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>

Google Map V3: Loading Markers using AJAX+ASP/PHP and Reload on Ruquest or Event

Hi I've searched so many things and found many contents but didn't found what I required actually.
I can loading all markers but unable to Refresh it or Reload it please help me out here's the code:
$(document).ready(function() {
var myLatLng = new google.maps.LatLng(24.86802, 67.06416);
MYMAP.init('#map', myLatLng, 11);
$(document).ready(function(e){
MYMAP.placeMarkers('testasp.asp');
});
});
var curr_infw;
var MYMAP = {
map: null,
bounds: null,
infowindow:null
}
MYMAP.init = function(selector, latLng, zoom) {
var myOptions = {
zoom:zoom,
center: latLng,
mapTypeId: google.maps.MapTypeId.HYBRID
}
this.map = new google.maps.Map($(selector)[0], myOptions);
this.bounds = new google.maps.LatLngBounds();
}
MYMAP.placeMarkers = function(filename) {
$.get(filename, function(xml){
$(xml).find("marker").each(function(){
var name = $(this).find('name').text();
var address = $(this).find('address').text();
// create a new LatLng point for the marker
var lat = $(this).find('lat').text();
var lng = $(this).find('lng').text();
var point = new google.maps.LatLng(parseFloat(lat),parseFloat(lng));
var infowindow = null;
// extend the bounds to include the new point
MYMAP.bounds.extend(point);
var marker = new google.maps.Marker({
position: point,
map: MYMAP.map,
clickable: true,
icon: 'truck_green.png'
});
//var infowindow = null;
infoWindow = new google.maps.InfoWindow();
var html='<strong>'+name+'</strong.><br />'+address;
google.maps.event.addListener(marker, 'mouseover', function() {
infoWindow.setContent(html);
infoWindow.open(MYMAP.map, marker);
});
MYMAP.map.fitBounds(MYMAP.bounds);
});
});
}
If somebody help me out I want to refresh it using click event or settimeout function though.
Regards and looking forward to hear it here soon. thanks
Not an answer, but what's this meant to be?
$(document).ready(function() {
var myLatLng = new google.maps.LatLng(24.86802, 67.06416);
MYMAP.init('#map', myLatLng, 11);
$(document).ready(function(e){
MYMAP.placeMarkers('testasp.asp');
});
});
Why are you nesting document.ready? Just do
$(document).ready(function() {
var myLatLng = new google.maps.LatLng(24.86802, 67.06416);
MYMAP.init('#map', myLatLng, 11);
MYMAP.placeMarkers('testasp.asp');
});
For event use
google.maps.event.addListener([ mapObject ], 'bounds_changed', function() {
// [ update code here ]
});

Resources