Integrate a 3d editor in a meteor js application

Hi,
I am working on a real time multi user 3d-editor which I have to integrate in an open source video conferencing app. So the aim is to work on 3d Models while conferencing. I am new in react-meteor so i have some difficulties understanding the pub/sub pattern. Actually my aim is to be able to launch a 3d Scene on all clients at the same time. So i need to insert the 3d Scene from the browser to the server by sending a message to other clients to load the scene. But i get undefined from my fetching container (ThreeDContainer) after inserting in ThreeDComponent. The Scene is created and rendered in the ThreeDComponent using babylon js Here the code:
I then create my collection on the server side ‚Äėimports/api/three-dimension/index.js‚Äô

import { Meteor } from 'meteor/meteor';

const Three = new Mongo.Collection('three-d');

if (Meteor.isServer) {
  Three.allow({
    'insert': function (userId,doc){
      return true;
    }
  })

  Three._ensureIndex({  id: 1 });
}

export default Three;

I now created the scene and all its options(light,camera,engine), which i then render localy, but since i want it to be launched on other clients at the same time i inserted it into my ‚ÄúThree‚ÄĚ collection as shown below

import React, { Component } from "react";
import Three from '/imports/api/three-dimension';
import * as BABYLON from "babylonjs";
import Auth from '/imports/ui/services/auth';`


.....I create the Scene with all needed options...


 //Inserting Scene after conversion in binary data
  sceneHandler = ()=> {
    var blob = new Blob ( [ this.canvas ], { type : "octet/stream" } );
      var scene = this.blob;
      try{
        Three.insert({Three: scene});
      } catch(e){
        console.log('no data inserted');
      }  
               
    }


render() {
let {width,height, ...rest} = this.props;
return (
  <canvas
    style={{ width: window.innerWidth/2, height: window.innerHeight/2 }}
    ref={canvas => {
      this.canvas = canvas;
    }}
  />
);
}
}
export default ThreeDComponent;

which i then publish in ‚Äėimports/api/three-dimension/server/publisher.js‚Äô

import { Meteor } from 'meteor/meteor';
import Three from '/imports/api/three-dimension';
import Logger from '/imports/startup/server/logger';
import { extractCredentials } from '/imports/api/common/server/helpers';

function threeD() {

  const { meetingId, requesterUserId } = extractCredentials(this.userId);

  Logger.debug(`Publishing ThreeD for ${meetingId} ${requesterUserId}`);

  return Three.find({userId: {$exists: false}
  },{
    fields: Three
  });
}

function publish(...args) {
  const boundThreeD = threeD.bind(this);
  return boundThreeD(...args);
}

Meteor.publish('three-d', publish);

Then in ThreeDContainer ‚Äėimports/ui/components/three-dimension/container‚Äô I subscribe and fetch the data then try rendering it there but i get the error ‚ÄúContainer is undefined‚ÄĚ

import React from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import ThreeDComponent from './component';
import Users from '/imports/api/users';
import Three from '/imports/api/three-dimension';
import Auth from '/imports/ui/services/auth';

class ThreeDContainer extends Component {
  render(){
    return (
    <canvas width={400} height={300} render={this.threed} />

    );
  }
}
 
export default withTracker(() => {
    const sceneHandle = Meteor.subscribe('three-d');
    const threed = Three.find({}).fetch();
    return {
      threed,
      
    };
  })(ThreeDContainer);

I then call the ThreeDComponent in the App Component below, where I added a Button to launch the Scene in App I added the following to ‚Äėimports/ui/components/app/component‚Äô

import Button from '/imports/ui/components/button/component';
import ThreeDComponent from '/imports/ui/components/three-dimension/component';
const propTypes = {
  show3d: PropTypes.bool,
};
class App extends Component {
  constructor() {
    super();
    this.state = {
      show3d: false,};
    this._3dButtonClick = this._3dButtonClick.bind(this);
  }
 _3dButtonClick(){
    this.setState({
      show3d: true,
    });
  }

  render3d() {
    return (
      MediaService.toggleSwapLayout(),
      <div>
        <Button onClick={this._3dButtonClick}>Start 3d Model</Button>
          {this.state.show3d ?
            <ThreeDComponent /> :
            null
          }
        </div>
    );

  }
  render() {
 
    return (
            <div>

               {this.render3d()}
          </div>
    );
  }
}

Please guys let me know what i am missing…

1 Like

Hi,

if you add a console.log(threed) after the find({}).fetch does it contain the document from the DB.

The subscription will move data into your client side mini mongo, so you could also open a js console and explore what is in ‚ÄėMongo‚Äô (minimongo) on the client.

remember that subscribe takes some time to move data from server to client and you might be just trying to find the data before it arrived.

you could add a onReady call back to the subscribe as described here… https://docs.meteor.com/api/pubsub.html#Meteor-subscribe

@annie I did use onReady and now i can see the data in my js console (minimongo), but i need the data to be published on all logged clients to the webpage. Any idea how to do that?

since you’ve published the data on the server, every logged in user should be able to subscribe to it.