Skip to content

Migration to A Frame

naraesk edited this page Mar 11, 2019 · 3 revisions

This Site documents the migration from X3D to A-Frame

Current state of migration

Feature State Priority Comments
ActionController done uses workarounds for click events
Application done might also be done without any 3d-framework specific code
CanvasManipulator done high
Events done
Model done
DefaultLogger done
CanvasFilter done
CanvasFlyTo done high
CanvasGrid To do low
CanvasHover done high
CanvasMark done
CanvasResetView done middle
CanvasSelect done high
Configuration done
Email done
Experiment done middle
Filter To do middle
InteractionLogger To do
IssueExplorer To do irrelevant
Legend done
Menu done
PackageExplorer done
PatternConnector To do irrelevant
PatternExplorer To do irrelevant
PatternTransparency To do irrelevant
RelationConnector done high
RelationHighlight done high
RelationTransparency done high
Search done
SourceCode done middle
Systeminfo done middle
VersionExplorer To do irrelevant

AframeActionController Workarounds

The problem with intercepting mouse events

In Aframe the appropriate way to react on users mouse interaction with the 3D content is to add the corresponding EventListeners to the a-scene via AFRAME.registerComponent. However this leads to three different event objects emitted by a single "mousedown" event. From those events the AframeActionController needs to extract the triggering mouse button as well as the clicked graphics object. While the second event object holds the clicked object, the triggering mouse button is only contained in the third one. The first event object holds none of the desired information. On this page possible solutions shall be gathered and discussed.

1. Storing the currently hovered entity (currently in use)

On every "mouseenter" event, save the target of the emerging event object. On "mousedown"/"mouseup" add the saved entity to the event object with the .which attribute (mouse button). Since there is no "mouseenter" event when leaving the 3D object and 'entering' the canvas the hoveredEntity variable is set to the canvas on every "mouseleave". In case a 3D object is entered while leaving another the "mouseleave" event is emitted first ultimately storing the correct object with the "mouseenter" event.

2. Saving a number of previous events

Since the structure of related event objects is always the same it's possible to store previous events and combine the desired information in the last one. This solution relies on being able to identify the last event object without having a real link to preceding event objects. (Which in case of "mousedown" is easy by checking for the .which attribute and adding the .target element of the preceding event object.)

3. Getting intersects of ray caster

Apart from just having one satisfying event object being sent out, this should be the cleanest solution. On each click event the first intersect of the ray caster is the clicked 3D object, which in turn is added to the one with the .which attribute.

Unfortunately I haven't been able to get this approach working...

AframeRelationConnectorController workarounds

fixPositionZ changed to fixPositionY

The original fixPositionZ parameter caused the z coordinate to be set true if itself was true leading to a 3D point (x, y, true) which makes no sense. For the city model I saw the purpose for this boolean in equating the height of related objects if it is true.

missing functions

sourceStart-/targetEndAtParentBorder The functions

function calculatePositionFromParent(sourcePosition, targetPosition, sourceParent)

and

function calculateSquarePositionFromParent(sourcePosition, targetPosition, sourceParent)

haven't been looked into because the circle function doesn't seem to work properly and the square function only says "// To implement..."

sourceStart-/targetEndAt(Parent)Border

The intersections of the connectors at the surface of objects are calculated by the following function:

function calculateBorderPosition(sourcePosition, targetPosition, entity)

It uses a raycasting algorithm starting at the 3d point sourcePosition heading in direction targetPosition-sourcePosition and checks for intersections with the entities mesh (document.getElementById(entity.id).object3DMap.mesh). The entity argument has the type of an entity from the model. This approach should apply to all kinds of shapes and can be used for all possible configs within this controller, given the entity is contained within the model.

The algorithm fails at calculating intersections with object surfaces for the Aframe RD Model since this contains 2D shapes as of yet.

Issues

Source map error occurs on start

Source map error: request failed with status 404
Resource URL: http://localhost:63342/ui/libs/aframe/aframev0.8.2.min.js
Source Map URL: aframe-v0.8.2.min.js.map

  • no problems with Linux, but seemingly causes Getaviz not to work on Windows.

Camera object

For properly manipulating the camera you need access to its member variables. Since I couldn't find the correct object anywhere in the DOM, I used the ugly solution: Creating a global reference to the object during it's init function.

AframeCanvasManipulator

  • problems might occur when flyToEntity() is called by the flyToController

AframeActionController

  • keyboard events not working

revisit click workaround

  • "mousedown"/"mouseup" event objects have either no 3Dobject or no mouse button
  • keeping track of hovered entity on every "mouseenter"/"mouseleave" event might not be optimal...

revisit cursor coordinate workaround

  • "mouseenter"/"mouseleave" event objects have no cursor coordinates (used in hoverController)
  • keeping track of those on every "mousemove" event might not be optimal...