I'm facing a problem where I'm trying to instantiate an object inside the setup function of p5, using a callback to do so:
This is the part of sketch.js relevant to the problem:
var g; //for graph instance
var dropzone; //for the file dropping area
function setup() {
createCanvas(640, 480);
dropzone = select('#dropzone'); //selects the <p> element I'm using as dropzone
dropzone.drop(process_file, unhighlight); //unhighlight is just a function to make the drop area not-highlighted
}
function draw() {
background(200);
if (g) {
g.show();
}else{
msg = "Please, load a file by dropping it in the box above";
text(msg, width/2, height/2);
}
}
// callback being used to process the text file content
function process_file(file){
data = file.data; //gets file data(content)
lines = data.split('\n'); // split the lines
digraph = lines[0] == 1 ? true : false; // is it a digraph?
v = int(lines[1]);
g = Graph(digraph, v); //the class I"m using to instantiate the graph
console.log(g); // <-- says undefined
g.init_graph(); // initialize all vertices
for (var i = 2; i < lines.length; i++) {
edge = lines[i].split(' ');
g.add_edge(edge[0], edge[1], edge[2]);
}
}
I already checked using console.log() and the content of the file is being correctly loaded, and the values are correct in what I was expecting. the Graph() class is in another file, but it is being imported as well as the sketch.js. I also tried to put the script importing at the end of the page, but got the same result, the g is still saying undefined.
What I didn't try is to put the whole code of my Graph class into the sketch.js file, but I will need to put more 15 algorithms on the class later, so the sketch file will grow in a unneeded size. I thought the by declaring g as a global variable I would have no problems with it.
I'm fairly inexperienced with JavaScript, so this is probably a rookie mistake about some kind of loading order, so please, if you answer this question, show me the why it is not working as it is. If there's need of any other piece of code, please let me know.
Thanks in advance.
Looking at this line:
g = Graph(digraph, v);
I think you meant to do this:
g = new Graph(digraph, v);
This creates a new instance and stores a reference to that instance in the g variable.
Related
I have a problem adding a Bounding Box from an object in a different module. Right now, it is working fine as long as I write everything in my main function, but as soon as I create my function in a different file, and import in in the main file, it's not working anymore.
The error code I get :
Uncaught TypeError: Cannot read properties of undefined (reading 'updateWorldMatrix')
at Box3.expandByObject (three.module.js:4934:10)
at Box3.setFromObject (three.module.js:4852:15)
at camCollision (camColliders.js:68:37)
at HTMLDocument.<anonymous> (World.js:355:7)
camColliders.js being the file I'm trying to put the function in, and World.js my main file.
Here is the function :
function camCollision() {
const camBB = new Box3().setFromObject(camSphereDetector);
const boule1BB = new Box3().setFromObject(boule1Obj);
boule1BB.name = 'first';
const boule2BB = new Box3().setFromObject(boule2Obj);
boule2BB.name = 'second';
const boule3BB = new Box3().setFromObject(boule3Obj);
boule3BB.name = 'third';
const boulesBB = [boule1BB, boule2BB, boule3BB];
boulesBB.forEach((bbs) => {
if (bbs.intersectsBox(camBB)) {
console.log('got it');
}
});
}
document.addEventListener('mouseup', () => {
camCollision();
});
When I'm doing this in a separate file, i'm first importing the objects from another file and they are all Mesh.
I believe the problem is that I can't create the Bounding Boxes in a separate file, because it needs to be added to the scene first, and I'm only adding them in the scene in World.js. Yet, the error is leading me to line 68, the variable for 'boule1BB', which is weird because 'camBB' should have the problem first ?
Here is how I'm creating the Box3 (these are just copying some GLTF objects position and size, cause I can't manage to get a Box3 from it) :
const boule1Obj = new Mesh(
new SphereGeometry(2, 32, 16),
new MeshBasicMaterial({ color: 'red', transparent: true, opacity: 0 }),
);
boule1Obj.position.set(10, -3.5, 0);
Then, I would like to know, if I got the problem right : is there a way to create a Box3 in a different js file, from an object that is not added to the scene yet (even if it should when the function is being called) ? With a different way than 'setFromObject' maybe ? Or am I not understanding the real problem.
For a bit of context, the aim is to provide some informations about each model when the user clicks on it, and I'm planning on putting the informations as '.name' for each Mesh corresponding to a model. So I don't want to write all this stuff in the main file, but rather on a separate one.
I hope this is clear enough, and I've given enough content for a solution to be found. I couldn't find anyone else having this problem. If you need anything else, please tell me !
Thanks already for your help !
I believe the problem is that I can't create the Bounding Boxes in a separate file, because it needs to be added to the scene in World.js.
Not so. Since a constructed THREE.Mesh has a shape with extents (from its geometry) and a transform (by default, translated to the origin, with no scaling or rotation), Three.js can and will determine a bounding box from that information as though the mesh were in the scene. I've posted a demo of this on CodePen.
Nor should defining the object in one file and referencing it another make any difference, as long as the object is in scope and initialized at the time it's bound to.
Here, I suspect that you're assigning boule1Obj, boule2Obj, and boule3Obj in World.js. In that case, the imported function is being hoisted before the variables are assigned, and the function is seeingbinding to them as unassignedundefined.
Try changing camCollision() to accept the bouleXObjs as arguments.
function camCollision(...objs) {
const camBB = new Box3().setFromObject(camSphereDetector);
for(let i = 0; i < objs.length; i++) {
const objBB = new Box3().setFromGeometry(objs[i]);
objBB.name = `Bounding Box ${i + 1}`;
if(objBB.intersectsBox(camBB)) {
console.log("Got it!");
}
}
}
And then call it as
document.addEventListener("mouseup", () => {
camCollision(boule1Obj, boule2Obj, boule3Obj);
});
With p5.js in a first time I cannot draw gradually the Koch snowflake: when a click to perform I see the result of the drawing when the recursion is gone.
so I implemented it with worker thread
As I don't know how to share external var like a class or an array (because if a create a type="module" script it is not ok with the worker.js)
I can arrived to do it with difficulty
'Koch snowflake' is made in recursive mode.
The project is
index.html
main.js
worker.js that contain
(onmessage = function... , and the VonKoch class)
in worker.js it's like
onmessage = function(e) {
console.log('Worker: Message received from main script');
let depth = e.data.depth;
let f = new VonKoch(VonKoch);
};
class VonKoch {
constructor(depth) {
...
}
pencil_advance(){
...
postMessage([this.x, this.y, this.x + dx, this.y + dy, ]);
Surprising ! it can send message from/into the class which is out of onmessage
}
...
}
From the main.js it is like:
function setup() {
noLoop();
createCanvas(800, 400);
if (window.Worker) {
const myWorker = new Worker("worker.js");
let el = {profondeur:profondeur};
myWorker.postMessage(el);
let a=0;
a message has been received so with p5.js it draws a line
myWorker.onmessage = (e) => {
line(e.data[0],e.data[1],e.data[2],e.data[3]);
a++;
};
With that I can see the draws gradually.
Ok, but I want more simple and speed result with an external array[][] of pixel that I can redraw every setInterval( ...; redraw(), 500).
The "main.js" can recognize this array if it is declared and initialized in "worker.js" but when this array is modified in "worker.js" (with VonKoch class), the main.js will see the initial array class without modification. Maybe it is come from "new Worker("worker.js")?
And if I create this array class in the "main.js" it won't be recognized in "worker.js".
The only way to have a "array class" that is recognized in "main.js" is to put it in the "worker.js".
Thank you for your help
Solved.
With localStorage : not ok (see comment)
with indexedDB : not ok (see comment)
The solution is :
in the "worker.js" that perform Koch snowflake, when it does to draw there is a test of time. If the Date.now() is greater than 500 (ms) i send the matrix with post.
So the "main.js" while draw the matrix with p5.js after receiving the message comes from "worker.js".
It is fast
depth of 12
So I upgraded to Unity 5.3.2 last night, and now I can't drag a UI Text object into a script in the inspector. (Images below)
There are no compiler errors, except at runtime. I get this error every time:
NullReferenceException: Object reference not set to an instance of an object
Scoring.updateScores () (at Assets/Scripts/Scoring.js:21)
I have the javascript code below. The comments are things I have tried. Please ask for and needed clarification.
#pragma strict
var score : int;
//var scoreScore : GameObject;
//var highScore : GameObject;
var scoreScore : UnityEngine.UI.Text;
var highScore : UnityEngine.UI.Text;
function Start () {
//scoreScore = GameObject.Find("scoreScore").GetComponent.<UnityEngine.UI.Text>();
//highScore = GameObject.Find("highScore").GetComponent.<UnityEngine.UI.Text>();
score = 0;
updateScores();
}
function updateScores() {
if (score >= PlayerPrefs.GetInt("highScore")) {
PlayerPrefs.SetInt("highScore", score);
}
scoreScore.text = "" + score.ToString();
highScore.text = "" + PlayerPrefs.GetInt("highScore");
}
When you look at a script in the Inspector (by clicking on it within the Assets folder), you can set the default objects for that script. These objects can only be from your Sssets- it will not allow you to drag objects from within a certain scene. You can only drag objects from a scene to instances of scripts within that scene (e.g. a Scoring script attatched to a certain GameObject).
Try creating a GameObject, attaching the Scoring script to it, selecting that GameObject in the inspector, and the dragging the UIText elements to the instance of the script you attached to that GameObject.
Drag and drop those text objects to your project, make them prefab. Then you can assign them.
Background: For a university project I have been tasked with creating a Flappy Bird clone. Originally it worked fine, then as I began adding more images, they stopped loading within Chrome. Firefox was fine (unless I did a fresh reload, but every subsequent reload was fine).
I was making a new 'Sprite' object for each image and within that sprite object's initialiser I would create an Image object and assign the src. I eventually realised this was the problem, so I rearranged my structure like this:
var ent_player_img = new Image();
ent_player_img.onload = function()
{
window.ent_player = new Sprite(ent_player_img);
};
ent_player_img.src = "../images/ent_player.png";
I would assign ent_player.img to the new Image object within the constructor. However, this was throwing reference errors within my game loop.
To combat this I put all of the functions in my game loop that called these objects within an if statement.
if (typeof ent_player !== undefined)
{
//Draw image
}
And yet I was still getting the errors. Inside the if statement I used a console.log saying typeof ent_player which returned as undefined.
Very puzzled as to why this code was still running and causing issues, I used my debugger of choice (Firebug).
I put a breakpoint on the if statement, however, whenever I step through the code with the debugger it works perfectly. Correct outputs, etc. Then as soon as I try it again without the debugger, same issue.
Can anyone give me an idea as to why this is happening and how I can fix it?
Thank you very much.
Edit: Sprite constructor looks like this:
function Sprite(image)
{
this.img = image;
this.height = this.img.height;
this.width = this.img.width;
this.x = 0;
this.y = 0;
}
Simply i would like to pre-load contents with a bar or what ever really in my three.js project or JavaScript either way should be fine, im familiar with action-script to do this task but cant seem to manage this in javascript:
Heres the code:
var loader = new THREE.OBJMTLLoader();
loader.load( 'myobject.obj', 'myobject.mtl', function ( object ) {
for(k in object.children){
object.children[k].position.z =-5;
console.log("position Changed");
}
scene.add( object );
console.log("the item is loaded");
I have looked at the loader examples to do with three.js sample files but i really dont follow it to well, is there way to check the file size vs file bytes received and implement it with the above, i have tried but returns under-fine. Jquery is also welcomed
I have similar problem. I have created an Array to preload and store all the objects in there. Passed and returned the currentId, to be able to store them after that. In Objects3DListJson I put the info for the Paths
for (var curobj = 0; curobj < Objects3DListJson.length; curobj++) {
loaderMTL.load(curobj, ObjPath, mtlPath, function (object, currentID) {
var obj3D = new Obj3D(Objects3DListJson[currentID].ObjectName, object)
objects3D.push(obj3D);
}
}
Of course I changed OBJMTLLoader to return the Current ID. I hope this help you on some way.