GithubHelp home page GithubHelp logo

troisjs / trois Goto Github PK

View Code? Open in Web Editor NEW
4.1K 47.0 299.0 9.91 MB

✨ ThreeJS + VueJS 3 + ViteJS ⚡

Home Page: https://troisjs.github.io

License: MIT License

JavaScript 31.70% HTML 0.14% Vue 6.48% TypeScript 61.68%
vuejs3 vitejs threejs webgl vuejs three-js 3d

trois's Introduction

✨ ThreeJS + VueJS 3 + ViteJS ⚡

NPM Package Build Size NPM Downloads Twitter Twitter

I wanted to code something similar to react-three-fiber but for VueJS.

I started from scratch, I will rewrite some of my WebGL demos to see if this little toy can do the job.

Feel free to contact me if you need a ThreeJS developer ^^

Trois is a french word, it means Three.

Sponsors (Thanks 💙 !!!)

Contributors (Thanks 💙 !!!)

Usage (CDN)

TroisJS is really simple and easy to use :

<div id="app">
  <renderer ref="renderer" antialias orbit-ctrl resize="window">
    <camera :position="{ z: 10 }"></camera>
    <scene>
      <point-light :position="{ y: 50, z: 50 }"></point-light>
      <box ref="box" :rotation="{ y: Math.PI / 4, z: Math.PI / 4 }">
        <lambert-material></lambert-material>
      </box>
    </scene>
  </renderer>
</div>

<script type="module">
  import { createApp } from 'https://unpkg.com/[email protected]/build/trois.module.cdn.min.js';
  createApp({
    mounted() {
      const renderer = this.$refs.renderer;
      const box = this.$refs.box.mesh;
      renderer.onBeforeRender(() => {
        box.rotation.x += 0.01;
      });
    }
  }).mount('#app');
</script>

Read more on https://troisjs.github.io/guide/

trois's People

Contributors

1albertchen avatar estebanfuentealba avatar kartsims avatar klevron avatar psoglav avatar safrmo avatar schelmo avatar semleti-sfeir avatar xcchcaptain avatar xewl avatar yoanngueny avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

trois's Issues

Install error

Absolutely love the idea of this repo, really excited to learn more about it! I'm running into this error when running yarn && yarn dev:

% yarn dev
yarn run v1.22.10
$ vite
error when starting dev server:
Error: The following dependencies are imported but could not be resolved:

  index.3540f44e.js (imported by /[...]/trois/docs/index.html)

Are they installed?
    at optimizeDeps (/[...]/trois/node_modules/vite/dist/node/chunks/dep-d13406fa.js:67493:15)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async runOptimize (/[...]/trois/node_modules/vite/dist/node/chunks/dep-d13406fa.js:68030:48)
    at async Server.httpServer.listen (/[...]/trois/node_modules/vite/dist/node/chunks/dep-d13406fa.js:68044:17)
error Command failed with exit code 1.

Any thoughts on what the issue might be? Thanks so much!

scene.remove not work

i'm writing another demo with troisjs recently with three.sprite(not using trois sprite component because the sprite is not supported while coding this demo lol) & scene and i find out that $refs.sceneInstance.remove doesnt work. i've checked the sprites' parent is the scene's reference and $refs.sceneInstance.scene.remove doesn't work as well(but .add() api works fine ,curious)
`
//so this part of code do not work
// debugger;
// activatedNodeInstanceList.forEach(node=>{
// this.$refs.sceneInstance.remove(node);
// })

    debugger;
    //directly use removeFromParent api works fine
    activatedNodeInstanceList.forEach(node=>{
      node.removeFromParent();
    })

`
trois version:0.3.2 three:0.129.0
original src code file
besides i see the doc installation is still using ^0.127 which is not support the removeFromParent api , but i check the trois Object3D sourcecode to find out it has already supported removeFromParent api :P

Add postprocessing

React Three Fiber includes easy ways to implement postprocessing - I'd like to see how straightforward it would be to create a custom effect pass in the EffectComposer using these methods. Will self-assign and keep this thread updated!

canvas height cut off

Hi - I'm experimenting with your slider examples and everything works except for some reason the canvas height is cut off at 153px. I can't figure out how to change it, any idea whats going on?

Much thanks for this great project.

Screen Shot 2021-05-11 at 4 13 12 PM

<template>
  <Slider :images="images" />
</template>

<script>
import { default as Slider } from "/node_modules/troisjs/src/components/sliders/Slider1.vue";
export default {
  components: { Slider },
  data() {
    return {
      images: [{ src: "/assets/images/screen1.png" }, { src: "/assets/images/screen2.png" }, { src: "/assets/images/screen1.png" }, { src: "/assets/images/screen2.png" }],
    };
  },
};
</script>

Materials refactoring

Instead duplicating properties from three materials, it should be easier to use a generic props prop, e.g. :

<BasicMaterial color="#ffffff" :props="{ transparent: true, opacity: 0.2 }">

But keeping a color prop is useful.

I think this design pattern will be used for other components.
I will keep some props (geometries is a good example) to have a good ts/ide support.

Groups

I use groups a lot when organizing my Three.js scenes and would love to use them here as well with a <Group> component:

<!-- A road with a car -->
<Scene>
  <Plane ref="road">...</Plane>
  
  <Group id="car-1>
    <Box ref="car1_body">...</Box>
    <Torus ref="car1_wheel_front_l>...</Torus>
    <Torus ref="car1_wheel_front_r>...</Torus>
    <Torus ref="car1_wheel_back_l>...</Torus>
    <Torus ref="car1_wheel_back_r>...</Torus>
  </Group>
</Scene>

(Eventually I'd love to be able to place a group into a self-contained component - so for example:

[app.vue]
<Scene>
  <Plane ref="road">...</Plane>
  
  <Car id="car-1"/>
  <Car id="car-2"/>
</Scene

[car.vue]
<Group>
  <Box ref="car_body">...</Box>
  <Torus ref="car_wheel_front_l>...</Torus>
  [...]
</Group>

but that can be a later goal!)

Happy to take this on if you'd like, I just wanted to make sure this wasn't already in the works or anything. Thanks so much!

Type inference when using custom defineComponent

Example : https://github.com/troisjs/trois/blob/typescript/src/geometries/BoxGeometry.ts
Type inference don't work as expected.

It works with :

export default defineComponent({
  extends: Geometry,
  props,
  methods: {
    createGeometry() {
      this.geometry = createGeometry(this)
    },
  },
})

But only in generated .d.ts file, not in vs code (with vetur extension).
Strange because it works with props: { ...props }, but not for parent props...

image

I think I will have to use a custom defineComponent type (not easy, I tried) :
https://github.com/vuejs/vue-next/blob/master/packages/runtime-core/src/apiDefineComponent.ts

Or refactor geometries and meshes...

Object3D lifecycle

A lot of components extends Object3D (Group, Light, Mesh, InstancedMesh...), we have to find a nice way to handle life cycle (#25, #26).

Events could be :

Do we have to handle something like onSetGeometry, onSetMaterial ?

Thanks @SaFrMo for the help

TransformControls directive

One of the most time-consuming parts of creating a new scene from scratch is placing items in the scene, so I'd love to add in an optional directive (v-transform-control or similar) to allow easy placement, rotation, scaling, and copying items directly from the scene using TransformControls. I'll take a look at this when I have some more time - let me know if there are any other features you'd like to see!

Raycaster does not detect click on GltfModel

Great library!

When I use Raycaster it does not detect clicks on loaded Gltf-Models.
When I activate the option intersectRecursive and then console log the click event, the intersectObjects list only contains meshes with a direct parent of scene and no loaded models.
Is there a hidden attribute that has to be set in the Gltf-Model loading process?

ShaderMaterial and Stats components not working

I tried to use ShaderMaterial but I am getting this error :

TypeError: Cannot set property 'texture1' of undefined at Proxy.initTexture (Texture.ts:48) at Proxy.refreshTexture (Texture.ts:54) at Proxy.created (Texture.ts:28)

Here is my template :

<Plane :width="ratio"
       :height="1"
       :widthSegments="50"
       :heightSegments="50">
	<ShaderMaterial :props="{vertexShader, uniforms, fragmentShader}">
		<Texture src="/@assets/images/4.jpg"
		         uniform="texture1"
		         ref="texture"
		         :onLoad="onTextureLoaded" />
	</ShaderMaterial>
</Plane>

It works well with a BasicMaterial, like so :

<Plane :width="ratio"
       :height="1"
       :widthSegments="50"
       :heightSegments="50">
	<BasicMaterial>
		<Texture src="/@assets/images/4.jpg" />
	</BasicMaterial>
</Plane>

I also tried with the default vertexShader and fragmentShader but it didn't work either. I am thinking that this might be related to this commit.

Also, the Stats component didn't work, getting this error : Failed to resolve import "stats.js" from "node_modules/troisjs/src/components/misc/Stats.js". Does the file exist?. I copy pasted the import from the doc : import Stats from 'troisjs/src/components/misc/Stats' (using vitejs for development).

Suggestions: about usability & visual quality

🎉🎉 Thank you for such amazing library! A great piece for vue x three community.

For me (heavy threejs + raf oriented user) this is already perfect!
but looking at react-three-fibers, I've got 1-2 suggestions for contributors to consider.

  1. Better visual quality by default
    (I can see we already have postprocessing & efforts put in visual quality, thus raising this visual-oriented suggestion could be relevant)
    we may provide nice default value + expose options around:

_dpi: Auto DPI scaling (setPixelRatio)
_toneMapping: ACES ToneMapping
_shadows: PCSS & VSM Shadow
_colors: this might be a bit involved (trois/src/materials/Texture.js), could we auto-fix encoding for all textures (also on colors : convertSRGBToLinear when possible, don't know how to proceed though)?

  1. Usability add-ons

for ordinary vue-users, layout in the 3D world can be tough.. this is a heavy one too, but libs like Yoga could be used to provide layout 'containers'.

Please consider this as my own to-do too, I'll try to do something in next-proj if any of those sounds useful.

Reactivity to update troisjs components

The note on the Render loop page warns against using Vue reactivity to update troisjs components, but I'm wondering if there's any possible way to make reactive data a reliable source of truth. Curious if you have any thoughts on this - I'm happy to look into it if that's not something you've already researched. Thank you!

Renderer before/after render...

I don't know yet if it is a good idea but we could add events to Renderer :

  • @before/after render
  • @after-resize

This implies we don't need anymore to add a ref to renderer to animate things.
And we could use renderer.$onBeforeRender... to add multiple callbacks.

troisjs is still early stage, I don't think it will be a problem if we change this now.

Bundle Size improvements?

Hi! First thanks for the work and it's great to have some sort of React-Three-Fiber for Vue 🔥

I was trying it and I'm a bit concerned about the size. With the demo from the README I'm getting a 925kb size.
I believe that Trois is importing every component form Three.js, so it makes a very large bundle.

I was comparing the size and package distributions to React-three-fiber:

Bundle size for Trois Comparassion Bundle Size for React-three-fiber
Screenshot_2021-03-02 BundlePhobia Screenshot_2021-03-02 BundlePhobia(1)

Would it be technically possible to not import Three like React-three-fiber does, or only import the components that are being used by the user?

Thanks a lot!

GLTFViewer import

Hi!

Is it possible to use the GLTFViewer component? What is the proper way to import it in my Vue component?

Thanks for this amazing project!

/CN

Raycast and pointer enter/leave handling

While working with #30, I was wondering if there's a cleaner way to handle raycasting and pointer events. I'm thinking of a two-step approach, raycaster-first and object-first.

Raycaster-first

Sometimes I want to raycast against everything in a crowded scene - in this case, I'd rather write a single raycaster's pointerEnter and pointerLeave functions than those of all the objects in the scene. To accomplish this, we could add a Raycaster component:

<Camera>
  <Raycaster @pointerEnter="onEnter" @pointerLeave="onLeave"/>
</Camera>
export default {
  methods: {
    onEnter(intersections) {
      console.log(intersections)
    },
    onLeave(inactiveIntersections){ 
      console.log(inactiveIntersections)
    }
  }
}

This would raycast against everything (raycaster.intersectObjects(scene.children)) and fire appropriate callbacks when pointer interactions start and end. We could also include an optional prop targetObjects if the user wants to specify which objects to target if they don't want all of them.

Object-first

I'm finding the <Renderer mouse-over> and mesh :onHover prop a little confusing - maybe we could do something like this:

  • Add pointerEnter and pointerLeave props to all Meshes
  • In a mesh's initialization, if either pointerEnter or pointerLeave are defined, check for this.three.raycaster.
    • If one is defined, add the mesh to the list of target objects the raycaster can intersect.
    • If one is not defined, tell this.three to create one (a new method like this.three.initializeRaycaster()), then add the mesh to the list of target objects.

From there, three.raycaster can handle calling events on meshes when the pointer enters or leaves them. This way we don't need any Renderer-level awareness of raycasting and the pointerEnter/pointerLeave events more closely match the Raycast component above (plus they're more clearly named for handling non-mouse inputs).

Happy to add this in the next couple days if it sounds worthwhile - let me know any thoughts @klevron !

Existing VueJS 3 project

Looks like there is some issue with using Trois in projects that already exist. I tried both the import and declare in main process as well as the direct import in the component and I get the same error both ways. I did download the starter app and that worked but I'm more interested in including Trois in my own bundle. I looked up the error in the source and it apparently has something to do with the intersect function. I did try adding Vite and ViteJS plugin-vue to no effect. The error says something about not having a proper loader but I'm not sure that is what the issue is since I tried Vite and it seems the start app is a pretty barebones implementation.

error  in ./node_modules/troisjs/build/trois.module.js

Module parse failed: Unexpected token (128:34)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|           onIntersectOver(overEvent);
|           onIntersectEnter(enterEvent);
>           component.onPointerOver?.(overEvent);
|           component.onPointerEnter?.(enterEvent);
|         }

 @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/router/views/Home.vue?vue&type=script&lang=js 3:0-84 9:9-12 10:12-18 11:21-36 12:16-26 13:14-22 14:11-16
 @ ./src/router/views/Home.vue?vue&type=script&lang=js
 @ ./src/router/views/Home.vue
 @ ./src/router/index.js
 @ ./src/main.js
 @ multi (webpack)-dev-server/client?http://192.168.1.113:8080&sockPath=/sockjs-node (webpack)/hot/dev-server.js ./src/main.js

onBeforeRender from component

Actually it is not so easy to modify render loop from a component...
We could use the same design pattern as in R3F (or something similar) : the useFrame hook
Open to suggestions :)

individually color faces of an instanced cube

Thanks for this great package and the beautiful demos. I've had great fun playing with it over the past week.

Is it possible to individually shade the faces of an instanced cube? In a regular threejs project, I use the method described here: https://stackoverflow.com/questions/44828713/paint-cube-faces-as-a-whole-not-the-triangles-that-make-up-the-face-three-js/44836160#44836160. It seems the geometry is tied together with the material. I'm not sure how to do that with the vue component design paradigm. Thanks for any guidance or suggestions.

Resize canvas when DOM parent changes size

Hello,

I am wondering if there is an easy way to resize the canvas when the DOM parent of the canvas is changed. As it is now, a "resize" listener is set on the windows and the "onResize()" method is not exposed.

What would be the cleanest way to do it?

Thanks,

/CN

Access to OrbitCtrls

I would like to be able to active/deactivate OrbitCtrls at runtime.

Is there a reason why this is only called at createRenderer()?

trois/src/core/useThree.ts

Lines 128 to 138 in 6f9251a

if (config.orbitCtrl) {
const cameraCtrl = new OrbitControls(obj.camera, obj.renderer.domElement)
if (config.orbitCtrl instanceof Object) {
Object.entries(config.orbitCtrl).forEach(([key, value]) => {
// @ts-ignore
cameraCtrl[key] = value
})
}
onBeforeRender(() => { cameraCtrl.update() })
obj.cameraCtrl = cameraCtrl
}

How can I do this dynamically?
I don't see any controls object exported for outside usage either, activating/deactivating this would be ideal.
Or simply accessing it to give it a new target

The underlying issue is that I would like to switch the camera target at runtime with orbitctrls attached. As you can see in this live example on glitch once the ctrls is attached I can not influence camera.target via code anymore and orbitctrls target is not accessible either.

UPDATE:
I can access orbit controls via this.$refs.renderer.three.cameraCtrl to some degree. I will leave this open to remind me to document this feature.

Composition / Options API ?

For the moment I think it is still handy to use composition and options API.

Using only composition api => code more verbose, may be I'm wrong
But using both => more typescript tweaks...

Raycaster not working on sphere

First of all, thank you for an amazing library. It feels so easy to use yet pretty much customisable!
I'm still new to three.js so I'm not sure if my issue is related to this library. Appoligies if it's not the case.

I'm trying to raycasting sphere to add some click points on it, but if I place a 2d object with particular position set, the raycaster doesn't recoginise the object. I had some research and I found some hints on the web and wanted to add recursive parameter true to intersectObjects of the raycaster instance. However, looking into your code, there is no way to add this option using your library (correct me if I'm wrong). I wonder if that's unnecessary or it's simply not added at this moment or I'm doing something completely wrong.

The code bellow is the minimum part of what I'm trying to add. If I remove this position prop and render it in a default position, this onclick event works

const position = {
 x: radius * Math.sin(phi) * Math.cos(theta),
 y: 1,
 z: radius * Math.cos(phi),
};

<box :position="position" :scale="scale" @click="onClick">
 <basicMaterial color="#fff" />
</box>

Thank you in advance.

shaderMaterial uniforms prop not work

in version 0.2.3 the material props work well like the code below
<ShaderMaterial :vertexShader="curlNoiseVertexShader" :uniforms="curNoiseUniforms" :fragmentShader="curlNoiseFragmentShader" />
but after updated to 0.3 the uniforms cannot be passed to the instance with the same code. I checked the ref instance to find out the vertexShader & fragmentShader work well, but uniforms appers to be the inital empty object. i also get a vue warning like this:
[Vue warn]: Extraneous non-props attributes (vertexShader, uniforms, fragmentShader) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

so is there anything should be changed in this usage?

Nuxt.js Add in

I am having this error after setting up the trios js

@/plugins/trois-js.js

import Vue from 'vue';

import {
    TroisJSVuePlugin
} from 'troisjs';

if (process.browser) {
    Vue.use(TroisJSVuePlugin);
}

@/pages/customize.vue

<template>
    <Renderer ref="renderer">
        <Camera :position="{ z: 100 }"></Camera>
        <LambertMaterial id="material"></LambertMaterial>
        <Scene>
            <PointLight :position="{ y: 50, z: 50 }"></PointLight>
            <Box ref="box" :size="10" :rotation="{ y: Math.PI / 4, z: Math.PI / 4 }" material="material"></Box>
        </Scene>
    </Renderer>
</template>

<script>
    export default {
        mounted() {
            const renderer = this.$refs.renderer;
            const box = this.$refs.box.mesh;

            renderer.onBeforeRender(() => {
                box.rotation.x += 0.01;
            });
        },
    };
</script> 

Error:
Uncaught SyntaxError: The requested module '/@fs/run/media/monster/Backup/manjaro/app/x-3D/frontend/node_modules/deepmerge/dist/cjs.js' does not provide an export named 'default'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.