Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrbitControls #100

Open
johnny-human opened this issue Jan 11, 2018 · 11 comments
Open

OrbitControls #100

johnny-human opened this issue Jan 11, 2018 · 11 comments
Labels

Comments

@johnny-human
Copy link

Thanks for a really good and extendable repository. I have a question. I have created a custom GridSystem that extends the VglObject3D. It works as expected. Now I would like to add OrbitControls. How would you do it? So far I have created a new vue component that import THREE.OrbitControls. But how would you instantiate the OrbitControls component with a camera attached?

@johnny-human
Copy link
Author

I wrote a component like this:

<script>
  import {validatePropString} from "vue-gl/src//utils"
  import * as VueGL from 'vue-gl'
  import OrbitControls from 'orbit-controls-es6'

  export default {
    mixins: [VueGL.VglObject3d],
    name: 'OrbitControls',
    inject: ["vglCameras"],
    props: {
      camera: validatePropString
    },

    computed: {
      inst () {
        const cmr = this.vglCameras.forGet[this.camera]
        return new OrbitControls(cmr)
      }
    }
  }
</script>

But when I give the camera a name and point it to the OrbitControls, the scene get black.

<vgl-perspective-camera name="pCamera" orbit-position="200 1 0.5"></vgl-perspective-camera>
<orbit-controls camera="pCamera"></orbit-controls>

@h-ikeda
Copy link
Member

h-ikeda commented Jan 12, 2018

I was on the assumption that the user would change orbit-position property manually by handling mouse event... I guess it should be enable instantly in the future (like by adding directive).

So far, the following code should work.

export default {
  inject: ['vglCameras'],
  props: {
    camera: validatePropString
  },
  computed: {
    cmr () {
      return this.vglCameras.forGet[this.camera]
    }
  },
  watch: {
    cmr: {
      handler(cmr) {
        const controls = new OrbitControls(cmr)
        controls.addEventListener('change', () => {
          cmr.dispatchEvent({type:'update'})
        })
      },
      immediate: true
    }
  }
}

I don't know why your scene got black. (Getting some error?)

You need to inform the renderer when the position of camera changes. We can use THREE's event dispatcher. VglRenderer listens update event of scene and camera, and THREE.OrbitControls dispatches change event.

You don't have to mixin VglObject3d because THREE.OrbitControls does not inherit the THREE.Object3D.

I hope it will help you :)

@Wazabiii
Copy link

Hello,
I had the same issue when I set name="pCamera" on the "vgl-perspective-camera" component.
I solved the black screen by setting the camera properties on vgl-renderer component.

But I had error when I use the OrbitControls component.

@h-ikeda
Copy link
Member

h-ikeda commented Sep 22, 2018

Internal namespace and rendering flow are changed.
Now the code below will work.

import { string } from 'vue-gl/src/validators.js'
import OrbitControls from 'orbit-controls-es6'

export default {
  inject: ['vglNamespace'],
  props: {
    camera: string,
  },
  computed: {
    cmr () {
      return this.vglNamespace.cameras[this.camera];
    }
  },
  watch: {
    cmr: {
      handler(cmr) {
        const controls = new OrbitControls(cmr)
        controls.addEventListener('change', () => {
          this.vglNamespace.update();
        });
      },
      immediate: true,
    }
  },
  render(h) {
    return h('div');
  },
});

example:
https://jsfiddle.net/qwu7v0ms/39/

Injected namespaces are gathered in injected vglNamespace property.
To render scenes at nextTick, call vglNamespace.update() function.

@anthony-chaudhary
Copy link

anthony-chaudhary commented Feb 20, 2019

Thanks for putting this all together!

When using inject: ['vglNamespace'] it errors with: "Injection "vglNamespace" not found"
However, this.$children[0].vglNamespace (within other functions) does work.

I'm using this within <template> tags, not sure if that maybe is part of the issue?
Am I missing some step here?

Update
Calling the following method on mounted() appears to work

 orbit_controls: function () {
      let cmr = this.$children[0].vglNamespace.cameras["cmr1"]
      const controls = new OrbitControls(cmr)
      controls.addEventListener('change', () => {
        this.$children[0].vglNamespace.update();
      });
    }

Not saying that's a good or right way to do it - just that it does appear to work.

@h-ikeda
Copy link
Member

h-ikeda commented Feb 24, 2019

@swirlingsand Don't you put components outside VglNamespace? VglNamespace just provides a namespace object for its children.

@Sharlaan
Copy link

Sharlaan commented May 17, 2019

@h-ikeda how do you constrain the controls to the domElement only ?
ie the line const controls = new OrbitControls(cmr, domElement), should be initialized with a reference to the canvas container, so it does not interfere with other mouse control in the external UI.

EDIT: just fixed with :

handler(cmr) {
    const domElement = this.vglNamespace.renderers[0].inst.domElement;
    const controls = new THREE.OrbitControls(cmr, domElement);
    controls.addEventListener('change', () => this.vglNamespace.update());
},

@notchris
Copy link

With the new update, I had trouble accessing properties. So I just do this in my app and it seems to work nicely.

    this.controls = new OrbitControls(this.$refs.camera.inst, document.querySelector('.renderer'));
    this.controls.addEventListener('change', () => {
      this.$refs.renderer.requestRender()
    })

@fraguada
Copy link

I'm testing this out and have run into issues with the samples on this page. My setup is similar https://codesandbox.io/s/qlpy3, but I'm getting some errors with recent versions of vue-gl (0.21.0):

[Vue warn]: Error in callback for immediate watcher "cmr": "TypeError: this.object is undefined"
found in
---> <OrbitControls>

and

TypeError: "this.object is undefined"
    OrbitControls OrbitControls.js:98
    handler main.js:38

this.object refers to the camera object used in OrbitControls.js. I am referencing ObjectControls directly from import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

So it seems the camera isn't being passed properly to the component.

You can see similar errors in the example posted by @h-ikeda

https://jsfiddle.net/qwu7v0ms/39/

Any ideas how to resolve this?

@notchris
Copy link

@fraguada I was able to solve it by doing this:

Vue.component('OrbitControls', {
  inject: ['vglNamespace'],
  props: ['camera'],
  computed: {
    cmr () {
      return this.vglNamespace.cameras.hash.c
    }
  },
  watch: {
    cmr: {
      handler(cmr) {
      	Vue.nextTick(() => {
           const controls = new OrbitControls(cmr, this.$parent.$el)
           controls.addEventListener('change', () => {
             this.$parent.requestRender()
           })
        })
      },
      immediate: true,
    }
  },
  render(h) {
    return h('div');
  },
});

jsfiddle

@fraguada
Copy link

Thanks @notchris. That did it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants