1

This may be a three.js question but I think it is more likely that I still don't understand prototype inheritance properly. Here's my code - a little simplified:

    define( ["jquery", "three", "svgUtils", "views/walls", "floor", "scene", "furniture"], function ( $, THREE, SvgUtils, Walls, Floor, scene, Furniture ) {


    function Section (svgNode) {

        if (!(this instanceof Section)){
            throw new TypeError("Constructor cannot be called as a function");
        }

        this.svgNode = svgNode;
        this.name = svgNode.id.replace("section-", "");



        if (this.name == "first") {
            this.position.y = 100;
        }
    }

    Section.prototype = new THREE.Object3D();
    Section.prototype.constructor = Section;

    return Section;

});

This is a require.js module where I define a Section which is an Object3D. I then create two Sections using new Section(svgNode) - but although only one of them has a name "first", both of them have their y position set to 100. Why is this?

UPDATE

Thanks to HMR I'm now pretty sure that this is an inheritance problem. Here's how I create a section (ie a floor) of a building from xml data containing the walls and floor:

define( ["jquery", "three", "svgUtils", "views/walls", "floor", "scene", "furniture"], function ( $, THREE, SvgUtils, Walls, Floor, scene, Furniture ) {
    function Section (svgNode) {

        if (!(this instanceof Section)){
            throw new TypeError("Constructor cannot be called as a function");
        }

        THREE.Object3D.call(this);

        this.svgNode = svgNode;
        this.name = svgNode.id.replace("section-", "");
        this.wallsNode = $(svgNode).find('[id*="walls"]');
        if (this.wallsNode.length == 0) {
                throw new Error("Section missing walls node")
        }
        this.walls = new Walls(this.wallsNode);     
        this.add(this.walls);
        this.add(new Floor($(svgNode).find('[id*="floor"]')));

        if (this.name == "first") {
            this.position.y = 100;
        }

    }

    Section.prototype = Object.create(THREE.Object3D.prototype);
    Section.prototype.constructor = Section;

    return Section;

});

If I create the ground floor and add it to the scene like this:

sections[0] = new section(sectionsXml[0]); scene.add(sections[0]);

I get the ground floor added to the scene - which I what I expect.

However if I create both the first and second floor but add only the ground floor, like this:

sections[0] = new section(sectionsXml[0]); sections[1] = new section(sectionsXml[1]); scene.add(sections[0]);

The ground floor contains the walls for the first floor as well (apologies to the US - over here we call the floor above the ground floor the 'first' floor - it's a Europe thing).

It's like the constructor of sections[0] is being called when I new section(sectionsXml[1]); but I don't see how that can be.

wagster
  • 498
  • 4
  • 15

1 Answers1

3
 function Section (svgNode) {
   THREE.Object3D.call(this);
    ...
 Section.prototype = Object.create(THREE.Object3D.prototype);
 Section.prototype.constructor = Section;

More info about the role of prototype and constructor functions here: Prototypical inheritance - writing up

HMR
  • 37,593
  • 24
  • 91
  • 160
  • That great - and a really good article. using call(this) added all the properties of Object3D to my Section. However the inheritance issue has now become a three,js issue. I have two Sections occupying the same space, so I'm moving one above the other. I can see that I've set the y position on my second object 100 above the first object - when I inspect the two objects I can see that the first one has a position of (0, 0, 0) and the second one a position of (0, 100, 0). However both objects now move to (0, 100, 0). Why? – wagster Feb 12 '15 at 22:51
  • @wagster make sure you use Object.create to set the prototype part of inheritance – HMR Feb 13 '15 at 11:33
  • Thanks HMR. It took a long time to figure this out. It turns out that the problem was not within the Section as it appeared, but within the Walls. Walls was also using new instead of Object.create(). Once I updated Walls everything started working as it should. – wagster Feb 20 '15 at 23:12