- Forums Home
- >
- Revit Products Community
- >
- Revit API Forum
- >
- Re: Get translation and rotation for a FamilyInstance (Export)

Community

Revit API Forum

Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.

Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

This page has been translated for your convenience with an automatic translation service. This is not an official translation and may contain errors and inaccurate translations. Autodesk does not warrant, either expressly or implied, the accuracy, reliability or completeness of the information translated by the machine translation service and will not be liable for damages or losses caused by the trust placed in the translation service.
Translate

13 REPLIES 13

Topic Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

Message 1 of 14

Anonymous

2047 Views, 13 Replies

01-29-2020
12:53 PM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-29-2020
12:53 PM

Get translation and rotation for a FamilyInstance (Export)

Hello, I'm currently doing some code to export a model from to glTF.

For performance reasons, I need to export each kind of geometry only one time, so my code does that, but something is wrong with it:

ElementType elementType = CurrentDocument.GetElement(CurrentElement.GetTypeId()) as ElementType; string meshName = elementType.Name + "[" + elementType.Id + "]"; _mesh.Name = meshName; //Check if we already have the geometry Node node = _scene.FindNode(n => n.Mesh.Name == meshName); //No, it's new, so save it inside a node if (node == null) node = _scene.CreateNode(elementId.IntegerValue.ToString()).WithMesh(_model.CreateMeshes(_mesh)[0]); //We already have a mesh/geometry else { Transform currentTransform = (CurrentElement as FamilyInstance).GetTransform(); ElementId id = new ElementId(Convert.ToInt32(node.Name)); Element firstElementOfType = CurrentDocument.GetElement(id); FamilyInstance firstElementOfTypeFamilyInstance = firstElementOfType as FamilyInstance; Transform firstElementOfTypeTransform = firstElementOfTypeFamilyInstance.GetTransform(); var currentElementOriginPoint = new XYZ(currentTransform.Origin.Y, currentTransform.Origin.Z, currentTransform.Origin.X); var firstElementOfTypeOriginPoint = new XYZ(firstElementOfTypeTransform.Origin.Y, firstElementOfTypeTransform.Origin.Z, firstElementOfTypeTransform.Origin.X); var p = new XYZ(currentTransform.Origin.Y - firstElementOfTypeTransform.Origin.Y, currentTransform.Origin.Z - firstElementOfTypeTransform.Origin.Z, currentTransform.Origin.X - firstElementOfTypeTransform.Origin.X); _scene.CreateNode(elementId.IntegerValue.ToString()).WithMesh(node.Mesh).LocalTransform = new SharpGLTF.Transforms.AffineTransform() {

//TODO: Rotation //Rotation = new Vector3((float)(p.Y),(float)(p.X),(float)(p.Z)), Translation = new Vector3((float)(p.Z), (float)(p.X), (float)(p.Y)), Scale = new Vector3(1, 1, 1), }; }

I'm working on this very hard, It should be simple, can someone provide some tips?

Why is my translation vector wrong?

How can I get the Rotation.

13 REPLIES 13

Message 2 of 14

01-30-2020
12:15 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
12:15 AM

If your goal is to export the entire model, or the contents of a specific view, the easiest way to go (and the officially recommended way) is to use a custom exporter:

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.1

Arnošt Löbel's Custom Exporter to XML is the goto-reference sample for that functionality:

https://thebuildingcoder.typepad.com/blog/2013/07/graphics-pipeline-custom-exporter.html#4

If you wish to go down the other path of handling elements individually yourself, one reliable source of truth for the task is the Revit SDK sample ElementViewer.

You can also take a look at a current project of mine that does something similar:

https://github.com/jeremytammik/ExportSymbolInstanceGeo

A number of other samples on The Building Coder export geometry meshes to various targets and demonstrate various ways of handling family instances and their possibly nested transformations. Several of them are pointed out in the same article:

https://thebuildingcoder.typepad.com/blog/2013/07/graphics-pipeline-custom-exporter.html#3

Best regards,

Jeremy

Message 3 of 14

01-30-2020
03:51 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
03:51 AM

Hello Jeremy!

I'm already using the custom exporter.

The code I've posted is inside

public void OnPolymesh(PolymeshTopology polymesh)

I can't understand why you use 3 vectors for the rotation, for example:

Like this:

https://github.com/jeremytammik/ExportSymbolInstanceGeo

{ "rotation_matrix": [1,0,0,0,1,0,0,0,1], "translation": [1,2,3], ... }

Look at the rotation matrix, here we have 3 vectors.

On glTF format I only need ONE vector for the rotation, one for transformation and one for scaling.

I understand how the process works for one XYZ for rotation.

But 3 XYZ just for rotation? How does that works?

On other words, how can I make this 3 vectors:

Transform.BasisX,

Transform.BasisY and

Transform.BasisZ

into one? Should I multiply them? (I will try that now)

The translation on the code is just using Transform.Origin (It's one XYZ, good enough for me), but I've already used that without success. I will try again.

Probably this question is more math related than revit API, but asking for help doesn't hurt =P

Thanks for the help!

Edit:

Viewing the values for the BasisXYZ, they are aways 1... Now I'm more confused, It doesn't make any sense using these... But your code does =/

I don't think that code is relevant to my situation, It only exports ONE thing... I need to export all things.

I think that's why the Transformation is aways = basis on your code, it doesn't need any kind of positioning (because it's just one object...) Back to square one =/

Message 4 of 14

01-30-2020
06:04 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
06:04 AM

Please understand that the problem is not related with REVIT instances, but glTF mesh instancing.

I've written a response... But the sistem diagnosed as spam and deleted it... WHY JESUS WHY

Please, I have already read ALL of the topics you posted but one (https://github.com/jeremytammik/ExportSymbolInstanceGeo), and now I've read and that have no correlation with my problem. (I've explained in detail on my previous post, deleted by the system... You don't do a transformation based on a previous object, your code use XYZ.Basis... if I do that every object will be in the same place)

I don't know what to do, I'm working on this for weeks.

I'm already using the custom exporter, like the samples you provided.

Please, help, please... I'm desperate I don't know what else I can do. I tried EVERYTHING you posted...

Using the symbol tranformation, using instance transformation, using point location, multiplying transformations...

I will try to resume my point, please, please, please try to understand my problem, I don't know what else I can do, that's why I came to the forum to post (as you can see I don't do that much...)

Everything on the view will be exported, not just one object... (That's why I need the transformation).

1 - EXPORT GEOMETRY

1.1 - THE GEOMETRY IS ALREADY EXPORTED?

1.1.1 - NO - JUST EXPORT IT THEN. (This is what is done in all samples... there's nothing like 1.1 in any of the samples)

1.1.2 - YES - THEN USE THE ALREADY EXPORTED GEOMETRY AND APPLY THE TRANSFORM TO THE BASE GEOMETRY.

My problem is how do I get the correct transform.

I've tried everything, researched a lot about it but no success so far. I'm reading thebuildingcoder everyday trying different stuff but I've reached a dead end, I need some help =/

Please I'm begging, if there is anything is my code bad written I will do my best to explain, that was the nearest I've reached.

I'm really sorry for not being able to achieve the desired results with your content, I never worked so hard on any stuff to fail like this.

Sorry for the long text I really need help.

Message 5 of 14

01-30-2020
06:20 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
06:20 AM

The sample by Arnost that I pointed out above demonstrates exactly how to keep track of the required transformations.

Message 6 of 14

01-30-2020
08:58 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

Message 7 of 14

Anonymous

in reply to:
Anonymous

01-30-2020
09:29 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
09:29 AM

I thought that was the collada exporter, I did not see that XML one...

Anyway... Please correct me if I'm wrong, you mean this:

// applying the current transform to a collection of points public IList<XYZ> ApplyTransform( IList<XYZ> points ) { IList<XYZ> newPoints = new List<XYZ>( points.Count ); foreach( XYZ xyz in points ) { newPoints.Add( m_currentTransform.OfPoint( xyz ) ); } return newPoints; }

If is this what you meant, It does not help in my case.

I will try to ask with other words:

<MyFile>

<Nodes>

<Node Mesh="ChairMesh" Translation="10,10,10" Rotation="0,0,0">

<Node Mesh="ChairMesh" Translation="20,10,10" Rotation="0,0,0">>

<Node Mesh="ChairMesh" Translation="30,10,10" Rotation="0,0,0">>

</Nodes>

<Meshes>

<Mesh Name="ChairMesh">

(MeshPrimitives)

</Mesh>

</Meshes>

<MyFile>

I don't need to transform each point of the mesh to do that.

Am I missing something?

Message 8 of 14

Anonymous

in reply to:
Anonymous

01-30-2020
12:20 PM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

01-30-2020
12:20 PM

The translation I needed was correct all along!

We can update to a more "simple" way of subtract:

XYZ translation = (meshInstance.First() as GeometryInstance).Transform.Origin.Subtract((meshBase.First() as GeometryInstance).Transform.Origin)

I've changed the variable names to be a little more semantical.

Unfortunatelly my problems with the rotation remains.

I've tried to do the same thing with the rotation (using FacingOrientation), no luck so far.

Message 9 of 14

Anonymous

in reply to:
Anonymous

02-07-2020
04:06 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

02-07-2020
04:06 AM

Is there anyone who can help me on this?

I'm still trying to get that rotation quarternion...

Is there anywhere else where I can seek help on this?

Message 10 of 14

11-15-2021
08:55 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

11-15-2021
08:55 AM

Hi @Anonymous, have you figured that out? From what I have found Rotation of Node is a quaternion, so a vector4. Have you been able to get it somehow from Revit Transfrom?

Message 11 of 14

11-15-2021
10:34 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

11-15-2021
10:34 AM

Another example that is guaranteed to keep correct track of the transformation stack that I referred to above is the Revit SDK ElementViewer sample:

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open

Message 12 of 14

11-15-2021
01:45 PM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

11-15-2021
01:45 PM

For rotations, what you are trying to do is transform between two different representations of the 3d rotation group (aka the Special Orthogonal group of dimension 3, SO(3)). Revit provides rotations in the form of a 3x3 matrix whose three columns are the BasisX, BasisY, and BasisZ properties of Transform. This rotates vectors by standard matrix multiplication.

However, what you are using in SharpGLTF requires a quaternion. To be precise, it actually requires a *unit* quaternion, which is a quaternion of length 1. The equation for this is *x²+y²+z²+w²=1* (this is identical to the equation of the unit sphere in 4-dimensional space, known as the 3-sphere because its 'surface' is 3-dimensional). Furthermore, the product of two unit quaternions is also a unit quaternion. Unit quaternions rotate 3d vectors in a more mathematically complicated way that is actually faster to compute (I won't get into the details). A significant consequence of how unit quaternions are used to rotate vectors is that multiplying the unit quaternion by *-1* does not change how the vector is rotated. As such each 3d rotation can be represented by two different quaternions, *q*, and *-q*. As such, the group of unit quaternions is called a 'double cover' of SO(3).

Given an axis you wish to rotate about (as a unit vector, **v**) and the amount you wish to rotate, θ, (in radians), the process of constructing a unit quaternion for that rotation is straight forward. The x, y, and z components of the unit quaternion are the x, y, and z components of **v**, multiplied by *sin(θ/2**)* and the fourth component is *cos(θ/2**)*.

If you don't know the axis and angle but only have the rotation matrix (i.e. a Revit Transform), there are algorithms for converting from a 3d rotation matrix to a quaternion, though I won't go into any here. Alternatively, it looks like in the latest version of SharpGLTF, AffineTransform has a constructor that takes a 4x4 matrix. To make such a matrix from a Revit Transform, the first 3 columns should be the BasisX, BasisY, and BasisZ of the Transform, with the fourth member of the column being zero, and the last column should be the Transform's origin, with the fourth member of the column being one.

Message 13 of 14

11-23-2021
08:29 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

11-23-2021
08:29 AM

Quarternion functions added to the Revit api would be great. Quarternion explanations always seem very confusing, the best explanation (primer) video i found was this 10 mins GameDev tips - Quaternions - YouTube hope this helps

Message 14 of 14

11-23-2021
09:11 AM

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report

11-23-2021
09:11 AM

Thank you for the great pointer. I fully agree, and added both your and Matthew's explanation and pointer to The Building Coder for future reference and posterity:

https://thebuildingcoder.typepad.com/blog/2021/11/installer-asset-formit-and-quaterions.html#4

Many thanks to you both, @bnewcombe, @mhannonQ65N2 !

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page