How to integrate meshes with custom classes?

For clarification, I have the below code. Running it I get some very strange behavior.

Object.assign(window,BABYLON); //for convenience don't judge me 
Mesh.sizeOf = mesh => {
	const sizes = mesh.getHierarchyBoundingVectors();
  	return new Vector3(sizes.max.x - sizes.min.x,sizes.max.y - sizes.min.y,sizes.max.z - sizes.min.z)
};
const Entity = class {
	constructor(type,scene){
		Object.defineProperties(this,{
			entityType: {
				value: type
			}
		});
		scene.entities.push(this);
	}
}
const Star = class extends Entity{
	constructor(name, radius, scene){
		let star = Object.assign(super('star',scene), Mesh.CreateSphere(name, 256, radius, scene), {
			id: random.hex(32)
		})
		return star;
	}
}

Please ignore the random.hex(32) it is defined and generates a random hex string of n length.

Currently, I’m having issues with the order of things in Object.assign:

  • having super first cause the mesh not to render.
  • having Object.assign(this, ...) and calling super outside of Object.assign also produces the above
  • having Mesh.CreateSphere first causes (Star).entityType to be undefined, and (Scene).entities[n].id to be undefined
  • having super last also causes the above
  • All of the above cause Mesh.sizeOf((Scene).entities[n]) not to work (throws TypeError: (Scene).entities[n].getHierarchyBoundingVectors is not a function, even though (Scene).entities[n].position is fine).
  • The first two also cause (Star).getHierarchyBoundingVectors() to throw the TypeError.

How do I correctly assign things so that (Scene).entities[n] == (Star), with both having the id and entityType properties set and being able to call Mesh.sizeOf with both of them?

@Vortex would you mind creating a playground for it ?

So that we could all dig into it ?

Sure: https://playground.babylonjs.com/#Z2L247#1. See the console for the test info.

Here you are trying to merge types which can lead to plenty of unforeseen weird cases.

In your case, why not extends from Mesh whish is what you want create sphere vertexData and apply them to your mesh ?

1 Like

That could work, though I need to be able to check if it is an instance of the Entity class.

There is no multi inheritance in JS, probably for the best :slight_smile:

Sometimes I wish we had that. Just imagine:

class example extends other1 extends other2 extends other3...

It could be useful.
On the more serious hand, I thought of an easy solution to the class mixing:

class Example extends Entity{
	constructor(scene){
		super('example_type');
		Object.defineProperties(this,{
			id:{
				value: id
			}
		});
		Object.assign(this,Mesh.CreteSphere(...))
	}
}

Would this work?

1 Like

nope as they won t have both prototypes in the prototype chain so instanceof would fail. Also functions from mesh would not be available on Example only the properties data.

You should probably keep it simpler and rely on a behavior for instance or proxy.

1 Like

I tried @sebavan’s earlier suggestion to extend from Mesh and create the vertex data. Entity extends Mesh and then Entity’s Star subclasses create and apply the vertex data, that way your star object will be an Entity and a Mesh. And edited to create different meshes and simplify a bit. :slight_smile:

3 Likes

@sebavan - multiple inheritance constructor and prototype :wink: or am i missing something :wink:

function extend(toThisInstance,fromThisConstructor){
   fromThisConstructor.call(toThisInstance); 
  let c  = Object.assign(toThisInstance.constructor, fromThisConstructor.constructor);
   Object.assign(Object.getPrototypeOf(toThisInstance), fromThisConstructor.prototype);
   toThisInstance.constructor = c;
   
  
 }

var fruit = function(){
  this.nameFruit = "fruit"
  this.willOverride = "im number 1";
}
fruit.prototype = {
  fruitfunc: function(){
    return "im a fruit"
  }
}

var veg = function(){
   this.nameVeg = "veg"
  this.willOverride = "im number 2";
}
veg.prototype = {
  vegfunc: function(){
   return  "im a veg"
  }
}

var imaFruitANDaVeg = function(){
  extend(this,fruit);
  extend(this,veg);
     this.nameFruitANDVeg = "nameFruitANDVeg"
  this.willOverride = "im number 3";
}

imaFruitANDaVeg.prototype = {
  imaFruitANDaVegfunc: function(){
    return "im a fruit and a veg"
  }
}

var testMultipleInheritance = new imaFruitANDaVeg();

console.log(testMultipleInheritance);
console.log(testMultipleInheritance.fruitfunc())
console.log(testMultipleInheritance.vegfunc())
console.log(testMultipleInheritance.imaFruitANDaVegfunc())
  1. constructor: ƒ Object()

  2. nameFruit: “fruit”

  3. nameFruitANDVeg: “nameFruitANDVeg”

  4. nameVeg: “veg”

  5. willOverride: “im number 3”

  6. [[Prototype]]: Object

  7. fruitfunc: ƒ ()

  8. imaFruitANDaVegfunc: ƒ ()

  9. vegfunc: ƒ ()

here the prototype chain will look like imaFruitAndaVeg => veg => fruit like fruit would inherit from veg so any veg function would have precedence over the fruit one. It is asking for troubles :slight_smile:

agreed , i did put a variable in the constructor named override to show override happens , also no actual calling of super etc. So akin to a mixin.

Just thought to point it out here as it is sort of the idea of multiple inheritance :wink: sort of :wink:

1 Like

Wow! I was thinking of something like that but then disregarded the idea because I didn’t think I could properly implement it since other non-spheres also extended from Entity. Thank you so much!!!
image

1 Like