1.2.2 • Published 14 days ago

architwin v1.2.2

Weekly downloads
-
License
ISC
Repository
-
Last release
14 days ago

Architwin Library

ArchiTwin Library

Table of Contents


Installation

Install Using NPM

To install the latest ArchiTwin package:

npm i architwin

Getting Started

Prerequisites

Before you start coding your architwin powered app, there are a few things you need to have ready to ensure that you are able to run the app properly without interruptions. For a seamless development experience, make sure to have the following ready:

  • appKey: your appKey is used to authenticate your connection when loading the 3D showcase. For security purposes, the appKey can only be used by a domain (e.g. awesomesite.com) it is associated with. This key is important especially when you launch your app in production and utilize your own site domain. Please contact us to request your appKey
  • apiKey: not to be confused with the appKey, the apiKey is used to authenticate all API requests sent to our servers including user authentication and fetching object data connected to a showcase. Please contact us to request your apiKey
  • apiURL: an optional key in the auth object which if set, will point all internal API calls to the api endpoint or base URL you assign. If this is not set, all api calls will be directed to the proxy address set in the vite.config.ts file during local development. Example: apiURL: "apps.awesomesite.com/api" will resolve internally to apps.awesomesite.com/api/cas/tickets?someparams or apps.awesomesite.com/api/v1/showcase/id/1. It is important to add /api to the base url of your custom apiURL to ensure the api requests are properly sent. There is no need to add a forward slash at the end of our custom apiURL. Please take note that you may have to setup a proxy server to bypass CORS issues when you deploy your application on your production servers
  • Username and password: User credentials used to authenticate the user. Please contact us to request your username and password

Define an iFrame as target for the Showcase

This example uses Vue's ref attribute to reference the target iFrame. Please consult the official documentation of your preferred framework of choice on how to reference a target component.

<template>
  <div class="at_showcase_container" id="showcase-container">
    <iframe id="mp-showcase" class="showcase" scrolling="no" width="100%" height="700" frameborder="0" allow="xr-spatial-tracking" allowfullscreen></iframe>
    <div class="at_map_container">
      <div id="at-map">
      </div>
    </div>
  </div>
</template>

Import the library

<script lang="ts">
import * as atwin from 'architwin';
//We also support default imports using import * as atwin from 'architwin';
import type { IMPConfig, IUser } from 'architwin/lib/types'; //for typescript projects
import { onMounted, ref } from 'vue';

const mpIframe = ref<HTMLIFrameElement>()

// replace with your api key and user
const apiKey = "YOUR-API-KEY" 
const authUser = {
  email: "su@email.com",
  password: "su123"
} as IUser

....
</script>

Setup your proxy

In your vite.config.ts, add the followig block of code. This will allow your app in your development environment to send API request to our servers and circumvent CORS issues. If you are not using vite as your build tool, please refer on the official documentation of your build tool of choice on how to setup the proxy.

You may have to change the VITE_PROXY value if you intend to direct your api requests on another server during development.

During production deployment you may need to setup proxy settings using your web or proxy server (ie: nginx, apache).

import { fileURLToPath, URL } from "node:url";

import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue"; //for Vue projects
import { svelte } from '@sveltejs/vite-plugin-svelte' //for Svelte projects
import react from '@vitejs/plugin-react' //for React projects
import dotenv from "dotenv";

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd(), "");
  console.log("=== env ===", mode, JSON.stringify(env));

  const VITE_PROXY = "https://basic-dev.rev-kitten.com";

  return {
    env: env,
    plugins: [
      vue(), //for vue projects,
      svelte(), //for svelte projects,
      react(), //for react projects
      ],
    server: {
      host: true,
      port: 5173,
      proxy: {
        "/api": {
          target: VITE_PROXY,
          secure: false,
          changeOrigin: true,
        },
        "/admin": { target: VITE_PROXY, secure: false, changeOrigin: true },
        "/default": { target: VITE_PROXY, secure: false, changeOrigin: true },


      },
    },
    devServer: {
      host: true,
      port: 5173,
      proxy: {
        "/api": { target: VITE_PROXY, secure: false, changeOrigin: true},
        "/admin": { target: VITE_PROXY, secure: false, 
          changeOrigin: true },
        "/default": { target: VITE_PROXY, true: false, changeOrigin: true },
      },
    },
    
    resolve: {
      alias: {
        "@": fileURLToPath(new URL("./src", import.meta.url)),
      },
    },
    //@ts-ignore
    test: {
      globals: true,
      environment: "jsdom",
    }
  };
});

Connect to a Space

In order to connect to space you may use connectSpace() method.

<script lang="ts">

  ...
  onMounted( async() => {

  // set spaceUrl
  const spaceUrl = "https://basic-dev.rev-kitten.com/showcase/model3d_public/1?token=e707880f-0fc5-48a6-b3f6-643a19f81464";

  // space url can also be a matterport url 
  // ex: const spaceUrl = "https://my.matterport.com/show/?m=qSGGhhjTYbN";

  const auth = {
    apiURL: 'YOUR-API-URL'
    apiKey: apiKey,
    user: authUser
  }

  const config: IMPConfig = {
    iframeId: 'mp-showcase',
    bundlePath: "path/to/bundle/", // optional. Iframe src should be something like this: <bundlePath>/showcase.html?
    appKey: 'YOUR-APP-KEY'
    play: 1,
  }

  // more config options as explain later
  await atwin.connectSpace(spaceUrl, auth, config)
  
  // after connected to space, the following objects should be available
  // tags - an array of tag objects found in the space
  // sweeps - an array of sweep objects found in the space
  ...

})

</script>

Once connected, the interactive Space will be rendered in the target iFrame.
A Space generally contains Tags, 3D objects, Video Screens , Slideshow Screens and Sweeps.
You should be able to move around the Space using keyboard and mouse.

Or programmatically using methods defined in this library.

Executing methods on specific App Phases

WARNING: This feature is deprecated, subscribe using Space Events instead

Your application may need to execute certain methods during the initialization of your 3D space. For example, you may want to useaddObjectToSpace() method to render a model to your 3D space the moment the 3D space becomes interactive. While you can always just invoke the function after the connectSpace() method there may be times where this will cause an error as the connectSpace() method which is an async method, may have not finished initializing the necessary internal variables that allow other methods to work properly. When you invoke the connectSpace() method, the library does some internal validation and then goes to several phases to render your 3D space and make it interactive. These phases are the following:

ARCHTWIN APP PHASES

  • LOADING: Initial fetch request to matterport. This is where the bundle downloads the 3D space from matterport and starts rendering it
  • STARTING: Matterport begins the transition to the start location
  • PLAYING The 3D space is now ready for user interaction

You can also view the technical diagram of how this work below:

To invoke a function from your application during one of the phases. Simply pass the function name as a parameter in the connectSpace() method. Make sure to not add a parenthesis to your function name when you pass it as a parameter to avoid invoking the function prematurely.

Example:

//Your application side function
async function runThisOnPlayState(){
const tags = await axios.get('my-custom-endpoint')

//Keep in mind that you should map the data from your endpoint into an object structure that the library supports

await atwin.showTags(tags)
}

await atwin.connectSpace(spaceUrl, auth, config,{onPlay:runThisOnPlayState})

In this example, the method named runThisOnPlayState is passed as a value to the onPlay key of an object. This will invoke the function during the PLAYING phase of the library. To invoke your function in a different phase, simply pass it to a different key in the object. You can pass your functions to onLoad,onStart, and onPlay. Async and synchronous functions are valid. Refer to the table below for more information

parametertyperequireddefaultvalues
onLoadFunctionnononeasync or non-async function
onStartFunctionnononeasync or non-async function
onPlayFunctionnononeasync or non-async function

Space Overview

Space - Space is an immersive and realistic Digital Twin model of a physical space, with virtual custom objects like animated 3D objects, Video Screens, Slideshow Screens and Tags, co-existing and enhancing the real objects.

A user should be able to navigate around using PC or devices (keyboard and mouse), measure real object dimensions and interact with the virtual objects as if you are actually visiting the physical space.

Sweeps - Space have static sweep markers (white circles on floor) which serves as primary navigation points. Users can go to sweeps (or click), stand and look around.

Tags - Space also have tags which are virtual markers attached to Objects or Locations in space. Tags can be clicked which will render and display relevant contents like web pages, videos, images or text descriptions. It is possible to go directly to any specifig tag (gotoTag) from anywhere in Space.

It can be used as quick way to navigate around the space.

3D Objects - Space usually contains 3D objects or three-dimentional models. Some 3D objects may have some simple animations.

Video Screens - Another interesting objects that can be found inside the space are Video Screens. They practially look like TV screens placed at selected locations. The Video screens will automatically play when a User is nearby (2 meters). And automatically turns off when the User leaves.

Slideshow Screens - Space can also contain Image Slideshow Screens. This is similar to the Video Screen, but uses static images. Clicking on the right section of the current slide image will display the next slide. Clicking on the the left section will display the previous slide.

The slideshow can be auto played in whole by clicking the lower-right corner.

Note: We use the word Space and Showcase interchangeably.

Subscribing to Space Events

Your 3D space allows your users to move around and interact with objects loaded into that space. Interactions such as clicking and dragging 3D objects in a space are events that your app may need to listen to and subsequently trigger the appropriate function for such an event.

You can subscribe to a particular event and pass callback method or methods to trigger when a subscribed event is fired using the subscribeSpaceEvent() method.

The method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | callback | Function or Array of Functions | yes | none | function or async function |

Subscribing a method to an event

To subscribe to an event, simpley call the subscribeSpaceEvent() and pass the event you want to subscribe to and the method you want to trigger. Subscribing to an event will also return to you the data of an object if you are interacting with one. Said object data will implement the IShowcaseObject interface.

Example:

function myFunction(objectData){
  console.log("I will run during a DRAG_END event",objectData)
}

atwin.subscribeSpaceEvent('DRAG_END',myFunction)

You can subscribe your method to more than one event. Currently, we support subscribing only the following events but we are working to add more events in the future.

SUPPORTED EVENTS

  • CLICK
  • DRAG_END
  • LOADING_PHASE
  • STARTING_PHASE
  • PLAYING_PHASE

For more information regarding the loading,starting, and playing phase events. Please refer to this section

Subscribing multiple methods to an event

If you wish to subscribe multiple methods to an event. You can use the folliwing methods listed below

Method 1: Subscribing each method one at a time

function myFunction(objectData){
  console.log("Function 1")
}

function myFunction2(objectData){
  console.log("Function 2")
}

atwin.subscribeSpaceEvent('DRAG_END',myFunction)
atwin.subscribeSpaceEvent('DRAG_END',myFunction2)

Method 2: Placing multiple methods in a parent method and passing it to the subscribeSpaceEvent method

function myFunction(){
  console.log("Function 1")
}

function myFunction2(){
  console.log("Function 2")
}

function parentFunction(objectData) {
  myFunction()
  myFunction2()
}

atwin.subscribeSpaceEvent('DRAG_END',parentFunction)

Method 3: Inserting multiple methods into an array and passing it to the subscribeSpaceEvent method.

function myFunction(){
  console.log("Function 1")
}

function myFunction2(){
  console.log("Function 2")
}

const functionArray = [myFunction,myFunction2]

atwin.subscribeSpaceEvent('DRAG_END',functionArray)

Keep in mind that the library's event system utilizes an FIFO algorithm. Your functions will always be executed in chronological order meaning functions that were subscribed first will be executed first.

Unsubscribing a method from an event

If you wish to unsubscribe your method from a subscribed event, simply call the unsubscribeSpaceEvent() method to so. The method accepts the following parameters:

The method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | callback | Function or Array of Functions | yes | none | function or async function |

Example:

function myFunction(){
  console.log("I will be unsubscribed and no longer trigger during the next DRAG_END event")
}

atwin.unsubscribeSpaceEvent('DRAG_END',myFunction)

If you used Method 3 in subscribing multiple methods. You can pass the same array to the unsubscribeSpaceEvent() method and they will all be unsubscribed from the event.

const functionArray = [myFunction,myFunction2]

atwin.unsubscribeSpaceEvent('DRAG_END',functionArray)

Creating Custom Events

The library has a list of default event types you can subscribe to but you may at times need to create your own event type to use for a specific task. You can easily create and subscribe to your own custom event by using registerCustomSpaceEvent() and subscribeSpaceEvent() respectively. Here is how to do it.

IMPORTANT: Your custom event type name must not be the same as an existing custom event type or a default event type. Doing so will return an error and the registration will fail.

STEP 1: Register your event type name. As a convention, the name of your event type should be in uppercase and use snake_case (e.g. FOO_BAR). It is important to register you custom event type first before subscribing a method to it. You can register one or multiple events using the method.

//Register one custom event type
atwin.registerCustomSpaceEvent('MY_EVENT')

//Register multiple custom events
const newEvents = ['FOO','BAR','MY_EVENT']
atwin.registerCustomSpaceEvent(newEvents)

STEP 2: Subscribe to your custom event

function myFunction(objectData){
  console.log("Function 1")
}

atwin.subscribeSpaceEvent('MY_EVENT',myFunction)

To trigger your custom event, you can use the dispatchSpaceEvent() in your app. You can also optionally pass a data payload with said event. Just make sure that you have done steps 1 and 2 before doing so.

The dispatchSpaceEvent() method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | payload | any | no | none | any |

const someData = {
  //some data here
}

atwin.dispatchSpaceEvent('MY_EVENT',someData)

Points of Interest

Tags are primarily use to mark locations or objects in space for quick and direct navigation. Tags usually contain additional content that will be rendered when hovered. Contents can be web pages, text descriptions, videos, or images.

You may use the getTags() method in order to get a list of Tags found in the space.

You may use the goToTag() method in order to navigate to specific Tag

You may use the getSweeps() method in order get a list of Sweeps found in the Space.

You may use the moveToSweep() method in order to move to a specific Sweep

parametertyperequireddefaultvalues
sweepIdstringyesId of the sweep
import * as atwin from 'architwin';

...

const spaceUrl = "https://basic-dev.rev-kitten.com/showcase/model3d_public/1?token=e707880f-0fc5-48a6-b3f6-643a19f81464"

const ispace = {
  id: 1;
  name: "mySpace";
  space_url: spaceUrl;
  tagpin_image: null;
} as ISpace

const tagId = "5"
const sweepId = "10"

// returns a list of Tags found in the Space
await atwin.getTags(ispace)

// to navigate to specific Tag and accepts a Tag's ID
await atwin.goToTag(tagId)

// returns a list of Sweeps found in the Space
await atwin.getSweeps()

// to move to a specific Sweep
await atwin.moveToSweep(sweepId)

...

More Examples:

import * as atwin from 'architwin';

...

// get current sweep data
await atwin.getCurrentSweep()

...

Adding, removing and customizing Tags

Tags are interactive elements that can be added to a 3D Space. Tags are essentially clickable anotations or markers that can be placed within the 3D model of a space, typically linking to additional information or media. They enhance the user experience by providing context and additional details about specific features or objects within the Space.

To render a tag in the Space, you can use renderTag() method. The renderTag() method accepts payload input.

Example

import * as atwin from 'architwin'

const payload = {
  tag: { /* Define your tag descriptor here */ },
  relocate: true,
  attachments: ['attachment1.png', 'attachment2.png'],
  icon: 'icon.png'
};

try {
  const renderedTag = await atwin.renderTag(payload);
  console.log('Rendered Tag:', renderedTag);
} catch (error) {
  console.error('Error rendering tag:', error);
}

You can define your tag descriptor like this:

const tag = {
  id?: string;
  anchorPosition: Vector3;
  stemVector: Vector3;
  stemVisible?: boolean;
  label?: string;
  description?: string;
  color?: Color;
  opacity?: number;
  iconId?: string;
  attachments?: string[];
};

To remove a tag in the Space, you can use disposeTags(). The disposeTags() has no parameter.

Example

import * as atwin from 'architwin'

// Example usage of the disposeTags function
async function removeTagsFromSpace() {
  try {
    console.log("Removing Mattertags from space...");
    await atwin.disposeTags();
    console.log("Mattertags removed successfully.");
  } catch (error) {
    console.error("Error removing Mattertags:", error);
  }
}

// Call the function to remove Mattertags from the space
removeTagsFromSpace();

Removing a specific tag in the Space, the disposeTag is the right method to use.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
};

try {
  await atwin.disposeTag(payload);
  console.log('Tag disposed successfully.');
} catch (error) {
  console.error('Error disposing the tag:', error);
}

Tags are customizables, you customize tag labels, description, stem, icon and its color.

editTagLabel() is the right method to change or edit the label of a specific tag.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  label: 'New Label' // Specify the new label for the tag
};

try {
  await atwin.editTagLabel(payload);
  console.log('Tag label edited successfully.');
} catch (error) {
  console.error('Error editing the tag label:', error);
}

To edit or change the description of a tag, the editTagDescription() is the method you can use.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  description: 'New Description' // Specify the new description for the tag
};

try {
  await atwin.editTagDescription(payload);
  console.log('Tag description edited successfully.');
} catch (error) {
  console.error('Error editing the tag description:', error);
}

You can also choose not show or hide the tag stem by invoking editTagStem().

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  stemVisible: true // Specify the new stem visibility value
};

try {
  await atwin.editTagStem(payload);
  console.log('Tag stem visibility edited successfully.');
} catch (error) {
  console.error('Error editing the tag stem visibility:', error);
}

Tag icon also editable, you can utilize the editTagIcon() method for this.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  icon: 'new-icon.png', // Specify the new icon file path or reference (optional)
  color: 'blue' // Specify the new color for the tag
};

try {
  await atwin.editTagIcon(payload);
  console.log('Tag icon and color edited successfully.');
} catch (error) {
  console.error('Error editing the tag icon and color:', error);
}

You can also change the color of the tag itself, just use the editTagColor() method.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  color: { r: 255, g: 0, b: 0 } // Specify the new color (RGB format)
};

try {
  await atwin.editTagColor(payload);
  console.log('Tag color edited successfully.');
} catch (error) {
  console.error('Error editing the tag color:', error);
}

Ataching media to a tag is also possible, you can utilize the attachTagMedia() method.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  attachments: ['media1.jpg', 'media2.jpg'] // Specify the media file paths
};

try {
  await atwin.attachTagMedia(payload);
  console.log('Media attached to the tag successfully.');
} catch (error) {
  console.error('Error attaching media to the tag:', error);
}

You can also remove the attached media, just call the detachTagMedia() method.

Example

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  attachmentIds: ['attachment1', 'attachment2'] // Specify the attachment IDs to detach
};

try {
  await atwin.detachTagMedia(payload);
  console.log('Media detached from the tag successfully.');
} catch (error) {
  console.error('Error detaching media from the tag:', error);
}

Please explore the Tags related function to learn more what you can do with tags.

Accessing List of Rendered Objects and Object Structure

Objects that have been loaded and rendered into the 3D space are stored in an array called _3DXObjects which you can access by doing calling it this way

atwin._3DXObjects

All the elements in this array implement the IObjectData interface. Each element in the array contains all the data you would need manipulate the object.

interface used (TS)

interface IObjectData {
  collider?: any
  object: IShowcaseObject
  component: Scene.IComponent
  node: Scene.INode
  type?: string
}

Each object element inside atwin._3DXObjects contains the value keys:

collider - Collider components define the shape of an 3D/2D object for the purposes of physical collisions. A collider, which is invisible, does not need to be the exact same shape as the GameObject’s mesh.

object - The object key is an object that implements the IShowcaseObject interface. This is one of the most important values as the object contains all the information about an object such as its id,name,position,rotation,scale,amazon_uri link, and etc. You can look at the interface below to view the full makeup of the object key.

interface used (TS)

export interface IShowcaseObject {
  id: number;
  showcase_id: number;
  object_id: number;
  user_id: number;
  object_position: {
    x: number;
    y: number;
    z: number;
  };
  object_rotation: {
    x: number;
    y: number;
    z: number;
  };
  object_scale: {
    x: number;
    y: number;
    z: number;
  };
  autoplay: boolean;
  autoplay_distance: number;
  offset_position: number;
  offset_rotation: number;
  position_unit: string;
  showcase_object_name: string;
  is_deleted: boolean;
  is_read: boolean;
  is_new: boolean;
  object_data: I3DObject;
}

component: This objects contains functions and variables responsible for intializing, updating, and destroying a rendered objects mesh, texture, etc. This object also contains the three.js instance. Since the 3D space is rendered with Three.js under the hood. You can use this instance to invoke methods made available by three.js. This gives you a lot of flexibility and control provided you know how to use it. This documentation will not cover Three.js specific methods. Visit their official website if you want to learn more about it.

node: The node is responsible for managing the lifecycle of a 3D/2D objects. The node can be used to start() and stop() a rendered model. Invoking start() will render the model into the scene while stop() will destroy it and remove it from the scene.

type: A string that states the file or object type of a 3D/2D object. The file type could be any of the following

Valid Types

typecontextdescription
GLB3D modelA 3D model with or without animation
FBX3D modelA 3D model with or without animation
FRAMEMedia ScreenA customizable media screen
ZIPslideshowA zip file rendered as a image slideshow

The atwin.selectedObject variable is an example of a variable that implements this interfacea and contains this data.

Transforming Objects

Transformation such as translate, scale, and rotate are actions used to manipulate objects in a 3D space. These transformations allow you to change an object's position, size, and orientation respectively.

NOTE: Please be aware that transform controls are disabled when viewMode in the config object you pass into connectSpace is undefined or is set to public. To enable transform controls in your 3D space. Make sure to set viewMode to 'interactive'.

Translate - Translation refers to moving an object from one position to another in space. It involves shifting the object's entire coordinate system without altering its orientation.

Scale - Scaling is the process of changing the size of an object by uniformly increasing or decreasing its dimensions along each axis. It can make an object larger (scaling up) or smaller (scaling down).

Rotate - Rotation involves changing the orientation or angle of an object around a specified point or axis. It rotates the object clockwise or counterclockwise by a certain angle.

There are several methods that allows you to transform an object. Let's go through each one

Transforming Object by clicking it

Clicking on any object in the space will attach the axis controls to it. By default, clicking on an object will show axis controls for translating the object. You can then use your mouse cursor to click and drag the object to modify its position,rotation, and scale in however way that pleases you. See screenshot for reference

You can switch the transform mode on the currently selected object by using the setTransformMode() method.

Please take note that transform controls can only be attached to one object at a time. Clicking on another object will remove the transform controls in the previous object and add it the currently selected object. It is impractical to attach multiple transform controls on more than one object. If you wish to programmatically transform multiple methods, then the next method offers a solution.

If you wish the to access the object data of the object that has been clicked on. You can do so by calling the atwin.selectedObject variable which returns an object implementing the IObjectData interface containing all the necessary data you need. Know more about the structure of an object by going to this section

import * as atwin from 'architwin';

...

console.log("Selected object data", atwin.selectedObject)

...

Switching Transform Modes

If you wish switch transformation mode, you can pass either 'translate' or 'scale' or 'rotate' as parameters to the setTransformMode() method. This will switch the transform controls on the currently selected object

parametertyperequireddefaultvalues
modestringyes'translate' or 'scale' or 'rotate'
import * as atwin from 'architwin';

...

// set the transform mode into translate
atwin.setTransformMode('translate')

// set the transform mode into scale
atwin.setTransformMode('scale')

// set the transform mode into rotate
atwin.setTransformMode('rotate')

...

Programmatically transforming objects

If you need to transform the position,rotation, and scale of one or more objects without having to use the mouse then the setObjectTransformation() method will allow you to do so. The method accepts the following parameters

parametertyperequireddefaultvalues
nodeScene.INodeyesnoneThe node of the object
transformObject3DPositionyesObject containing object position,rotation,scale. More information below

The transform object contains the following key-value pairs. These values when set will be applied to your target object

parametertyperequireddefaultvalues
object_positionVector3yesnoneValid x,y,z coordinates
object_rotationVector3yesnoneValid x,y,z coordinates
object_scaleVector3yesnoneValid x,y,z coordinates

In this example, we will get a random 3D model from the array of rendered objects stored in atwin._3DXObjects and manipulate it using the method. The object we will be manipulating in this example is a 3D model with a file type of GLB (You can also transform other object types such as a media screen). This will return a javascript object that contains the rendered object's data which implement the IObjectData interface. You can know more about that by going to this section

import * as atwin from 'architwin';

...

const targetObject = atwin._3DXObjects.find(obj => obj.object.object_data.object_type == 'GLB')

const transform = {
  object_position: {
    x: 12.345435,
    y: 0,
    z: 4.54754732
  },
  object_rotation: {x:0,y:12,z:8},
  object_scale: {x:2,y:2,z:2}
}

atwin.setObjectTransformation(targetObject.node,transform)

...

NOTE: You can also mirror an object by knowing the center position first then add and subtract (depending whether you want to mirror it to the left or to the right) values on either x, y, or z in the object_position.

import * as atwin from 'architwin';

...

const centerPosition:Vector3 = {x:6, y:6,z:6}

// add 5 values in either x, y, or z in the object_position to the mediaScreen to be positioned in the left
const mediaScreen = ArrayOfMediaScreen.value[0]
const newObjectPosition = {
    object_position: {x:centerPosition.x+5, y:centerPosition.y, z:centerPosition.z},
    object_rotation: {x:0, y:0, z:0},
    object_scale: {x:4, y:4, z:1} 
  } as Object3DPosition;

atwin.setObjectTransformation(mediaScreen.node, newObjectPosition)

// subtract 5 values in either x, y, or z in the object_position to the mediaScreen to be positioned in the right
const mirrorMediaScreen = ArrayOfMediaScreen.value[1]
const mirrorObjectPosition = {
    object_position: {x:centerPosition.x-5, y:centerPosition.y, z:centerPosition.z},
    object_rotation: {x:0, y:0, z:0},
    object_scale: {x:4, y:4, z:1} 
  } as Object3DPosition;

atwin.setObjectTransformation(mirrorMediaScreen.node, mirrorObjectPosition)

...

If done correctly, you should see your target object(s) display or reposition to your intended position, rotation, and scale. Please take note that the transform controls UI will not be attached to the object if you use this method

Undoing and Redoing Transformation Changes

Redo and undo are actions that allow you to revert or replay previous transformations performed on an object. They provide a way to navigate through the history of transformations and make adjustments or restore previous states.

Assuming that you have already selected an object and already performed different transformation actions. You can use the methods in the library to redo and undo the changes.

In order to do this, you may use the revertTransform() method to revert changes. By default, the action is set to 'undo'.

import * as atwin from 'architwin';

...

atwin.revertTransform()

...

If you want to redo a tranformation, change the parameter to 'redo'.

import * as atwin from 'architwin';

...

atwin.revertTransform('redo')

...

Adding Objects To Your Space

Adding an object to your space refers to the process of incorporating a pre-existing 2D or 3D object from the database into the 3D space. It allows for the creation of visualizations, simulations, and interactive experiences in your space.

In order to add an object, you may use the addObjectToSpace() method.

parametertyperequireddefaultvalues
objectUrlstringyesnonevalid url to media/object
objectTypestringyesnonevalid supported file type (GLB,FBX)
configObjectConfigyesvalid config object

There are two ways you can use the addObjectToSpace() method. We will go through each one

Method 1: Adding Programmatically

If you wish to add new object to your space to a pre-defined position, you can use the addObjectToSpace() method and pass the objectConfig along.

import * as atwin from 'architwin';

...

let objectUrl:string = "https://example.s3.amazonaws.com/filename.GLB";
let objectType:string = "GLB"

const yourTargetPosition = {
  x: 12.345435,
  y: 0,
  z: 4.54754732
}
const objScale = {x:1,y:1,z:1}
const objRotation = {x:0,y:0,z:0}

let objectConfig = {
  position: yourTargetPosition,
  scale: objScale,
  rotation: objRotation,
} as ObjectConfig;

atwin.addObjectToSpace(objectUrl,objectType, objectConfig)

...

Method 2: Adding with click method using getTargetPosition

The library has several helper methods that provide a range of commmon functionalities to help you achieve certain actions easier. If for example, you do not have your intended position coordinates stored in the database or in a local area and wish to click a specific area of the 3D space and get that the coordinates of the area you clicked, you may do some by using the getTargetPosition() helper method in tangent with the addObjectToSpace() method to do so. You can click here to know more about the getTargetPosition() method

Here is an example of how you can use the two methods together. This is just one example, it is up to you on how you wish to combine different methods provided by the library

import * as atwin from 'architwin';

...

function myCallbackFunction(clickedPosition){
  let objectUrl:string = "https://example.s3.amazonaws.com/filename.GLB";
  let objectType:string = "GLB"

  const objRotation = {x:0,y:0,z:0}
  const objScale = {x:1,y:1,z:1}

  let objectConfig = {
    position: clickedPosition,
    scale: objScale,
    rotation: objRotation,
  } as ObjectConfig;

  await atwin.addObjectToSpace(objectUrl,objectType, objectConfig)
}

atwin.getTargetPosition(myCallbackFunction)

...

Creating a Customizable Media Screen

A Media Screen is

1.2.2

14 days ago

1.2.1

1 month ago

1.1.9

1 month ago

1.1.8

1 month ago

1.1.7

1 month ago

1.1.6

1 month ago

1.1.5

1 month ago

1.1.4

2 months ago

1.1.1

2 months ago

1.1.3

2 months ago

1.1.2

2 months ago

1.0.98

2 months ago

1.0.97

2 months ago

1.0.96

2 months ago

1.0.95

2 months ago

1.0.94

2 months ago

1.0.93

2 months ago

1.0.92

2 months ago

1.0.91

2 months ago

1.0.90

3 months ago

1.0.89

3 months ago

1.0.88

3 months ago

1.0.87

3 months ago

1.0.86

3 months ago

1.0.85

3 months ago

1.0.84

4 months ago

1.0.83

4 months ago

1.0.82

4 months ago

1.0.81

4 months ago

1.0.80

4 months ago

1.0.79

4 months ago

1.0.78

4 months ago

1.0.77

5 months ago

1.0.76

5 months ago

1.0.75

5 months ago

1.0.74

5 months ago

1.0.73

5 months ago

1.0.72

5 months ago

1.0.62

7 months ago

1.0.60

8 months ago

1.0.66

6 months ago

1.0.65

6 months ago

1.0.64

7 months ago

1.0.63

7 months ago

1.0.69

6 months ago

1.0.67

6 months ago

1.0.71

6 months ago

1.0.70

6 months ago

1.0.33

9 months ago

1.0.32

9 months ago

1.0.31

10 months ago

1.0.37

9 months ago

1.0.36

9 months ago

1.0.39

9 months ago

1.0.38

9 months ago

1.0.40

9 months ago

1.0.44

9 months ago

1.0.43

9 months ago

1.0.42

9 months ago

1.0.41

9 months ago

1.0.48

9 months ago

1.0.47

9 months ago

1.0.46

9 months ago

1.0.45

9 months ago

1.0.49

9 months ago

1.0.51

9 months ago

1.0.50

9 months ago

1.0.54

8 months ago

1.0.53

8 months ago

1.0.52

8 months ago

1.0.59

8 months ago

1.0.57

8 months ago

1.0.56

8 months ago

1.0.22

11 months ago

1.0.21

11 months ago

1.0.20

11 months ago

1.0.26

11 months ago

1.0.25

11 months ago

1.0.24

11 months ago

1.0.23

11 months ago

1.0.29

11 months ago

1.0.28

11 months ago

1.0.27

11 months ago

1.0.30

10 months ago

1.0.19

11 months ago

1.0.18

11 months ago

1.0.17

11 months ago

1.0.16

11 months ago

1.0.15

11 months ago

1.0.14

11 months ago

1.0.13

11 months ago

1.0.12

11 months ago

1.0.11

11 months ago

1.0.10

11 months ago

1.0.9

11 months ago

1.0.8

11 months ago

1.0.7

11 months ago

1.0.6

11 months ago

1.0.5

11 months ago

1.0.4

11 months ago

1.0.3

11 months ago

1.0.2

11 months ago

1.0.1

11 months ago

1.0.0

11 months ago