Giter VIP home page Giter VIP logo

forgefader's Introduction

ForgeFader

ForgeFader is a Forge viewer extension app that calculates and displays signal attenuation caused by distance and obstacles in a building model with a floor plan containing walls.

It makes use of JavaScript and three.js to implement a functionality similar to the Revit C# .NET add-in RvtFader:

Given a source point, calculate the attenuation in a widening circle around it and display that as a heat map.

You can try it out for yourself in the forge-rcdb.autodesk.io Fader sample.

Two signal attenuation values in decibels are defined in the application settings:

  • Attenuation per metre in air
  • Attenuation by a wall

The extension expects an RVT model with a floor element. Two sample models are provided in the test subdirectory. You can translate them for Forge using your credentials and pass in the resulting URN to the viewer as described below.

Here is one of the models in Revit and the result of processing it using Forgefader:

Revit fader_test model Signal attenuation calculated and displayed by ForgeFader

The four-minute forgefader Autodesk Forge sample app YouTube video explains some of the background and shows this sample app live in action.

ForgeFader is based on Philippe Leefsma's Forge React boilerplate sample. Please refer to that for more details on the underlying architecture and components used.

Implementation

The ForgeFader implementation lives in Viewing.Extension.Fader.Core.js.

On loading, in onGeometryLoaded, it determines the Revit BIM wall fragments for subsequent ray tracing.

On picking a point on a floor in the model, in onSelection, it launches the attenuationCalculator function to do the work.

That determines the picked floor top face and adds a new mesh to the model on which to draw the attenuation map.

Once the mesh has been added, it in turn calls rayTraceToFindWalls to create a bitmap representing the signal attenuation to be displayed by a custom shader.

The following sections describing details of the implementation process have also been published by The Building Coder:

Adding Custom Geometry to the Forge Viewer

When debugging any kind of geometrical programming task, it is of utmost importance to be able to comfortably visualise the situation.

In this app, I add three different kinds of geometry dynamically to the model displayed by the Forge viewer:

  • Points and lines representing the top face of the floor and the picked source point.
  • A mesh representing the top face of the floor to be equipped with a custom shader and offset slightly above and away from the floor element surface.
  • Points and lines representing the raytracing rays.

Three example screen snapshots illustrate what I mean.

Display points and lines for debugging using drawVertex and drawLine:

Line and vertex debug markers

Create a mesh to represent the floor top face and offset it up slightly above the floor surface:

Floor top face mesh

A debug helper displaying lines in the model representing the ray tracing rays:

Ray tracing rays

Three.js Raytracing in the Forge Viewer

You cannot call the three.js Raycaster.intersectObjects directly on the Forge viewer fragments representing the Revit BIM walls.

One alternative approach is to analyse the Forge viewer fragments and generate new three.js mesh objects from them.

That is achieved by the getMeshFromRenderProxy function that successfully processes Revit BIM floors and walls.

It is called in onGeometryLoaded to generate meshes representing all walls in the model:

  this.wallMeshes = fragIds.map((fragId) => {
    return this.getMeshFromRenderProxy( 
      this.viewer.impl.getRenderProxy( 
        this.viewer.model, fragId ), null, null, null );
  })

These meshes are used to determine the number of walls between a given pair of source and target points by getWallCountBetween.

I raised a question with the Forge viewer development team before embarking on the research to implement the above. Unfortunately, due to time differences, they replied only after I had completed it:

[Q@14:19] How can I invoke Raycaster.intersectObjects with viewer fragments?

[Q@21:35] I solved my Raycaster.intersectObjects challenge by generating my own threejs mesh from the lmv original.

[A@21:39] Ok well, for the record, you can intersect the whole scene using viewer.impl.rayIntersect, or you can do it per model via model.rayIntersect, or per mesh via VBIntersector.rayCast. The first two approaches take advantage of the spatial index acceleration structure.

[Q@21:42] Thank you for the info! I assume these approaches would offer multiple advantages: (i) more efficient (ii) easier to set up and use (iii) more fool- and future-proof. Do you agree?

[A@21:43] Probably better to use the high level hit testing APIs instead of messing with internal mesh representation directly... i.e. avoid doing fragile stuff like this.viewer.impl.getRenderProxy(this.viewer.model, fragId).

In summary, you might be better off ignoring the interesting solution I present above and using the built-in viewer functionality instead.

Implementing a Custom Shader in the Forge Viewer

In the main commit of release 0.0.30, Cyrille Fauvel shows how a custom shader can be applied to a Forge viewer element, initially, for testing puurposes, as a radial gradient:

Radial gradient shader

In release 0.0.32 (cf. the diff) Cyrille replaces the hard-wired radial gradiant by the real thing, a testure map displaying the signal attenuation:

Signal attentiuation shader

Running the Sample

Configuration is controlled by NODE_ENV environment variable, make sure to set it properly to development or production, based on the configuration type you want to run.

In development, the client is dynamically built by the webpack-dev-middleware, so just run:

  • npm install (downloads project dependencies locally)

  • npm start (builds client on the fly and run server)

  • open http://localhost:3000 in your favourite browser

In production, the client requires a build step, so run:

  • npm install (not required if you already run at previous step)

  • npm run build-prod && npm start (builds client and run server)

  • open http://localhost:3000 in your favourite browser

Loading Custom Models in the Forge Viewer

To load a model into the Forge viewer for this extension to process, you first need to generate a viewable URN as documented in the Prepare a File for the Viewer tutorial.

One easy way to achieve this manually is to upload it to models.autodesk.io.

Using the same Forge ClientId & ClientSecret used to upload the model, populate environment variables used by the config files (in /config):

  • development:

    FORGE_DEV_CLIENT_ID

    FORGE_DEV_CLIENT_SECRET

  • production:

    FORGE_CLIENT_ID

    FORGE_CLIENT_SECRET

Restart the server; you can then directly load your model by specifying the resulting design URN as query parameter in the url of the viewer page, e.g.:

Deploy to Heroku

Using your Forge ClientId and ClientSecret obtained while Creating a new Forge App, press this button:

Deploy

More about the Autodesk Forge Platform and Web Applications of the Future

Check it out at autodesk-forge.github.io.

Look at the quickstarts guide to find the Forge SDK for the programming language of your choice.

Authors

License

This sample is licensed under the terms of the MIT License. Please see the LICENSE file for full details.

forgefader's People

Contributors

cyrillef avatar jeremytammik avatar

Stargazers

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

Watchers

 avatar  avatar  avatar

forgefader's Issues

Can't build releases 43-45

release 43 build fails with errors about "/Users/PrestoS/Documents/Dev/forgefader-0.0.43/node_modules/Viewing.Extension.Fader doesn't exist"

For release 45, after trying to manually npm install cross-env, rifraf and webpack, I knw get this error. This doesn't seem to be a very user friendly npm package.

Unhandled Rejection at: Promise Promise {
{ Error: Cannot find module 'inline-manifest-webpack-plugin'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/webpack/production.webpack.config.js:7:37)
at Module._compile (module.js:570:32)
at loader (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12) code: 'MODULE_NOT_FOUND' } } reason: { Error: Cannot find module 'inline-manifest-webpack-plugin'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/webpack/production.webpack.config.js:7:37)
at Module._compile (module.js:570:32)
at loader (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/PrestoS/Documents/Dev/forgefader-0.0.45/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12) code: 'MODULE_NOT_FOUND' }
<<

phil 3 activate/deactivate attenuation settings in setter

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

phil 6 higher resolution spheres

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

phil 5 fix load method

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

rays not showing

rays are not showing on some brwose
Chrome update 57 โ€“ was working in 56.

there is also issues on Firefox / opera
works fine on edge

phil 2: activate/deactivate raycasting rays upon modification in the setter

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

phil 4 provide a fancier RVT model

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

philippe 1 reactivate or remove show floor face

There are a few tweaks to do tho:

1/ I guess "Show floor face" is pretty useless now because the shader will overlay on it anyway

2/ Show raycasting works, but only i selecting again a point on the model. The fader core should activate/deactivate the rays upon modification in the setter.

3/ Same thing when changing the attenuation settings, they get applied only after the next selection

4/ your room model is ok for testing the code but honestly I find it a bit pitiful for a real demo. Can't we get a bit more fancy model to illustrate this cool code sample... Cyrille may have some better models. I tested the code with "urban house" but doesn't seem to work ...

5/ You should add this code/ replace the load method as follow. It will handle asynchronously both events for model loaded, and rename onGeometryLoaded into onModelLoaded

6/ the custom spheres to visualize raycasting have such a low resolution they almost look like squares :s it wont hurt to throw a few more vertices there

6/ dont mind the gradient, it's not yet finalized ...

Cheers
Philippe.

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.