Revit 2021.1 and Normalising Custom Export UV

The hottest news for today is the Revit update release, seasoned with other titbits of interest:

Before we get to those, another nice quote of the week, courtesy of Quincy Larson:

Programming is the only job I can think of where I get to be both an engineer and an artist. There's an incredible, rigorous, technical element to it, which I like because you have to do very precise thinking. On the other hand, it has a wildly creative side where the boundaries of imagination are the only real limitation.

– Andy Hertzfeld

The Revit 2021.1 Update

The long-awaited Revit 2021.1 update release is now available.

Check out the top experts' and product managers' detailed report on What’s new in Revit 2021.1.

Here are the top highlights from their release run-down, grouping features into four benefit categories: Automation and Computation, Interoperability and Data Exchange, Productivity and Ease of Use, and Coordination and Collaboration.

Normalising UVs in Custom Exporter

Sunsflower (sic) shared a nice explanation in the Revit API discussion forum thread on IExportContext converting UV to the range (0,1):

Question: I'm writing an exporter for Revit and encountered with a problem when exporting UV.

When I call PolymeshTopology.GetUV, the coordinates given are often larger than 1.

My questions are:

To give a concrete example:

Say I have a texture of size 4096x4096, the corresponding UV data I read in IExportContext is around 25, and the RealWorldScale from the UnifiedBitmapAsset is about 141.

I cannot seem to be able to discern a formula or anything...

Answer: Maybe this background information on faces and their coordinates in the Revit API will help?

Response: That post explains UV as two variables that parametrise a face, but as far as I can see they are related to the structure of the face in 3d space, not how each vertex of the face are mapped to the bitmap.

How can I convert the UV coordinates returned by PolymeshTopology.GetUV to pixel coordinates on the image or in the range (0,1).

I found the discussion on PolymeshTopology UVs to be relevant, but the answer given is not detailed enough for me to actually solve the problem.

Later: Okay, I think I've figured it out and I'll list the solution found just in case someone else also has this problem...

The PolymeshTopology.GetUV method returns a UV coordinate, which corresponds to the parameters of a face.

Therefore, I guess they are related to the dimension of the face that they parameterize.

These UV coordinates can be converted to display units via UnitUtils.ConvertFromInternalUnits (which is probably deprecated now, but anyway...). My add-in uses centimetres. So far, we have the UV in centimetres.

The next step is to obtain the size of the bitmap. This is given by the properties with name UnifiedBitmap.TextureRealWorldScaleX/Y. These values are actually given in inches, so you can call UnitUtils.Convert from DisplayUnitType.DUT_DECIMAL_INCHES to DisplayUnitType.DUT_CENTIMETERS to convert them. In fact, I've found DisplayUnitType.DUT_FRACTIONAL_INCHES gives the same result. I don't know what the difference is... maybe someone could elaborate on that.

After that, the UV coordinates can be scaled to the range [0,1] or whatever.

Correction: the AssetPropertyDistance class actually has a DisplayUnitType property, which should be used instead of the DUT_DECIMAL_INCHES.

Many thanks to Sunsflower for this useful research and helpful documentation!


Set up your own Free VPN Server

I have not tried this myself yet, but the detailed steps sound perfectly simple, sound and doable in the 5 minute read on how to set up your own VPN server at home for free using Linux and WireGuard:

This is a great way to boost your own privacy and security without needing to share your data with a paid VPN service.