Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Common_glTF_Exporter/Common_glTF_Exporter.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Materials\AssetProperties.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Materials\BitmapsUtils.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Materials\MaterialProperties.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Materials\MaterialTextures.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Model\GlbComponents.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Model\Links.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Model\LoadContext.cs" />
Expand Down Expand Up @@ -69,9 +70,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Utils\GLTFBinaryDataUtils.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utils\SettingsConfig.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Utils\Theme.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UVs\CylindricalUv.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UVs\PlanarUv.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UVs\VertexUvs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Version\DownloadFile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Version\InternetConnection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Version\LatestVersion.cs" />
Expand Down
3 changes: 3 additions & 0 deletions Common_glTF_Exporter/Core/GLTFMaterial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class GLTFMaterial
[JsonIgnore]
public double Fadevalue { get; set; } = 1;

[JsonIgnore]
public Autodesk.Revit.DB.Color TintColour { get; set; }

[JsonIgnore]
public Autodesk.Revit.DB.Color BaseColor { get; set; }

Expand Down
7 changes: 6 additions & 1 deletion Common_glTF_Exporter/Core/GlTFExportContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ public void OnPolymesh(PolymeshTopology polymesh)
var geomItem = currentGeometry.CurrentItem;
var vertItem = currentVertices.CurrentItem;

IList<UV> uvs = polymesh.GetUVs();
IList<XYZ> pts = polymesh.GetPoints();
for (int i = 0; i < pts.Count; i++)
{
Expand All @@ -313,7 +314,11 @@ public void OnPolymesh(PolymeshTopology polymesh)
new PointIntObject(vertex), geomItem.Vertices);
geomItem.Faces.Add(vertexIndex);

VertexUvs.AddUvToVertex(vertex, geomItem, currentMaterial, preferences, currentFace);
if (preferences.materials == MaterialsEnum.textures && currentMaterial?.EmbeddedTexturePath != null)
{
UV uv = uvs[index];
geomItem.Uvs.Add(uv);
}
}
}

Expand Down
62 changes: 54 additions & 8 deletions Common_glTF_Exporter/Materials/AssetProperties.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Visual;
using System;
using System.Collections.Generic;
using System.IO;

namespace Common_glTF_Exporter.Materials
{
public static class AssetPropertiesUtils
{
private static readonly string[] DIFFUSE_NAMES = { "opaque_albedo", "generic_diffuse" };
private const string PATHPROPERTY = "unifiedbitmap_Bitmap";
private static readonly string[] DIFFUSE_NAMES = {
Autodesk.Revit.DB.Visual.AdvancedOpaque.OpaqueAlbedo,
Autodesk.Revit.DB.Visual.Generic.GenericDiffuse,
Autodesk.Revit.DB.Visual.AdvancedWood.WoodCurlyDistortionMap,
Autodesk.Revit.DB.Visual.Hardwood.HardwoodColor,
Autodesk.Revit.DB.Visual.AdvancedMetal.SurfaceAlbedo
};
private const string AUTODESKPATHTEXTURES = @"Autodesk Shared\Materials\Textures\";
private const string ROTATIONPROPERTY = "texture_WAngle";
private const string DIFUSSEDEFINITION = "generic_diffuse";

public static Asset GetDiffuseBitmap(Asset theAsset)
{
Expand All @@ -33,7 +37,7 @@ public static string GetTexturePath(Asset connectedAsset)
{
if (connectedAsset != null)
{
var bitmapPathProp = connectedAsset.FindByName(PATHPROPERTY) as AssetPropertyString;
var bitmapPathProp = connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap) as AssetPropertyString;

if (bitmapPathProp != null && !string.IsNullOrEmpty(bitmapPathProp.Value))
{
Expand All @@ -59,7 +63,7 @@ public static Autodesk.Revit.DB.Color GetAppearenceColor(Asset theAsset)
Autodesk.Revit.DB.Color appearenceColor = Autodesk.Revit.DB.Color.InvalidColorValue;

AssetPropertyDoubleArray4d colorProperty =
theAsset.FindByName(DIFUSSEDEFINITION) as AssetPropertyDoubleArray4d;
theAsset.FindByName(Generic.GenericDiffuse) as AssetPropertyDoubleArray4d;

if (colorProperty != null)
{
Expand All @@ -75,7 +79,8 @@ public static Autodesk.Revit.DB.Color GetAppearenceColor(Asset theAsset)

public static float GetRotationRadians(Asset connectedAsset)
{
AssetPropertyDouble rotation = connectedAsset.FindByName(ROTATIONPROPERTY) as AssetPropertyDouble;
AssetPropertyDouble rotation =
connectedAsset.FindByName(UnifiedBitmap.TextureWAngle) as AssetPropertyDouble;

if (rotation != null)
{
Expand All @@ -87,7 +92,8 @@ public static float GetRotationRadians(Asset connectedAsset)

public static float GetScale(Asset connectedAsset, string textureName)
{
AssetPropertyDistance scale = connectedAsset.FindByName(textureName) as AssetPropertyDistance;
AssetPropertyDistance scale =
connectedAsset.FindByName(textureName) as AssetPropertyDistance;

if (scale != null)
{
Expand All @@ -103,5 +109,45 @@ public static float GetScale(Asset connectedAsset, string textureName)

return 1;
}

public static Autodesk.Revit.DB.Color GetTint(Asset asset)
{
bool tintOn = true;

AssetProperty tintEnabledProp = asset.FindByName(Generic.CommonTintToggle);
if (tintEnabledProp is AssetPropertyBoolean apb)
{
tintOn = apb.Value;
}

if (tintOn)
{
AssetProperty tintProp = asset.FindByName(Generic.CommonTintColor);
if (tintProp is AssetPropertyDoubleArray4d tintArray4d)
{
IList<double> rgba = tintArray4d.GetValueAsDoubles();

byte r = (byte)(rgba[0] * 255.0);
byte g = (byte)(rgba[1] * 255.0);
byte b = (byte)(rgba[2] * 255.0);

return new Autodesk.Revit.DB.Color(r, g, b);
}
}

return null;
}

public static double GetFade(Asset asset)
{
AssetPropertyDouble fadeProp = asset.FindByName(Generic.GenericDiffuseImageFade) as AssetPropertyDouble;

if (fadeProp != null)
{
return fadeProp.Value;
}

return 1;
}
}
}
90 changes: 55 additions & 35 deletions Common_glTF_Exporter/Materials/BitmapsUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,68 +30,88 @@ public static (string, ImageFormat) GetMimeType(string path)
}

public static byte[] BlendImageWithColor(
byte[] imageBytes,
double fade,
Autodesk.Revit.DB.Color flatColor,
ImageFormat mimeType)
byte[] imageBytes,
double fade,
Autodesk.Revit.DB.Color flatColor,
ImageFormat mimeType,
Autodesk.Revit.DB.Color tintColor)
{
if (fade >= 1.0)
return imageBytes;
bool noFlatBlend = fade >= 1.0 || flatColor == null;
if (noFlatBlend && tintColor == null)
return imageBytes;

float fFade = Clamp((float)fade, 0f, 1f);
float fInv = 1f - fFade;

float lr = SrgbToLinear(flatColor.Red / 255f);
float lg = SrgbToLinear(flatColor.Green / 255f);
float lb = SrgbToLinear(flatColor.Blue / 255f);
float fFade = noFlatBlend ? 1f
: Clamp((float)fade, 0f, 1f);
float fInv = 1f - fFade; // 0 if no blend

byte[] resultBytes;
// face colour in linear space (0 if unused)
float lrFlat = 0f, lgFlat = 0f, lbFlat = 0f;
if (!noFlatBlend)
{
lrFlat = SrgbToLinear(flatColor.Red / 255f);
lgFlat = SrgbToLinear(flatColor.Green / 255f);
lbFlat = SrgbToLinear(flatColor.Blue / 255f);
}

using (MemoryStream inputMs = new MemoryStream(imageBytes))
using (Bitmap bitmap = new Bitmap(inputMs))
// tint factors (1,1,1 ⇒ no change)
float lrTint = 1f, lgTint = 1f, lbTint = 1f;
if (tintColor != null)
{
lrTint = SrgbToLinear(tintColor.Red / 255f);
lgTint = SrgbToLinear(tintColor.Green / 255f);
lbTint = SrgbToLinear(tintColor.Blue / 255f);
}

/* 3 ── PROCESS IMAGE ─────────────────────────────────────────── */
byte[] resultBytes;
using (var inputMs = new MemoryStream(imageBytes))
using (var bitmap = new Bitmap(inputMs))
{
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
BitmapData data = bitmap.LockBits(
rect,
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
BitmapData data = bitmap.LockBits(rect, ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);

int byteCount = Math.Abs(data.Stride) * bitmap.Height;
byte[] pixels = new byte[byteCount];
Marshal.Copy(data.Scan0, pixels, 0, byteCount);

for (int i = 0; i < byteCount; i += 4)
{
// bytes BGRA → float 0-1
/* -- BGRA → linear ------------------------------------------------ */
float sb = pixels[i + 0] / 255f;
float sg = pixels[i + 1] / 255f;
float sr = pixels[i + 2] / 255f;

// sRGB → lineal
float lbSrc = SrgbToLinear(sb);
float lgSrc = SrgbToLinear(sg);
float lrSrc = SrgbToLinear(sr);

// lineal interpolation
float lbMix = lbSrc * fFade + lb * fInv;
float lgMix = lgSrc * fFade + lg * fInv;
float lrMix = lrSrc * fFade + lr * fInv;

pixels[i + 0] = (byte)(Clamp(LinearToSrgb(lbMix), 0f, 1f) * 255f + 0.5f);
pixels[i + 1] = (byte)(Clamp(LinearToSrgb(lgMix), 0f, 1f) * 255f + 0.5f);
pixels[i + 2] = (byte)(Clamp(LinearToSrgb(lrMix), 0f, 1f) * 255f + 0.5f);
float lb = SrgbToLinear(sb);
float lg = SrgbToLinear(sg);
float lr = SrgbToLinear(sr);

/* -- BLEND WITH FLAT COLOUR (if any) ------------------------------ */
lb = lb * fFade + lbFlat * fInv;
lg = lg * fFade + lgFlat * fInv;
lr = lr * fFade + lrFlat * fInv;

/* -- APPLY TINT ---------------------------------------------------- */
lb *= lbTint;
lg *= lgTint;
lr *= lrTint;

/* -- linear → sRGB, write back ------------------------------------ */
pixels[i + 0] = (byte)(Clamp(LinearToSrgb(lb), 0f, 1f) * 255f + 0.5f);
pixels[i + 1] = (byte)(Clamp(LinearToSrgb(lg), 0f, 1f) * 255f + 0.5f);
pixels[i + 2] = (byte)(Clamp(LinearToSrgb(lr), 0f, 1f) * 255f + 0.5f);
// alpha (pixels[i+3]) untouched
}

Marshal.Copy(pixels, 0, data.Scan0, byteCount);
bitmap.UnlockBits(data);

using (MemoryStream outputMs = new MemoryStream())
using (var outputMs = new MemoryStream())
{
bitmap.Save(outputMs, mimeType);
resultBytes = outputMs.ToArray();
}
}

return resultBytes;
}

Expand Down
84 changes: 84 additions & 0 deletions Common_glTF_Exporter/Materials/MaterialTextures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Collections.Generic;
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Visual;
using Common_glTF_Exporter.Core;
using Common_glTF_Exporter.Windows.MainWindow;
using Revit_glTF_Exporter;
using Common_glTF_Exporter.Materials;
using Common_glTF_Exporter.Model;
using System.IO.Ports;
using System.Windows.Controls;
using System.Windows.Media.Media3D;
using Material = Autodesk.Revit.DB.Material;
using System;

namespace Common_glTF_Exporter.Materials
{
public static class MaterialTextures
{
public static GLTFMaterial SetMaterialTextures(Material material, GLTFMaterial gl_mat,
Document doc, float opacity)
{

ElementId appearanceId = material.AppearanceAssetId;
if (appearanceId == ElementId.InvalidElementId)
{
return gl_mat;
}

var appearanceElem = doc.GetElement(appearanceId) as AppearanceAssetElement;
if (appearanceElem == null)
{
return gl_mat;
}

Asset theAsset = appearanceElem.GetRenderingAsset();

Asset connectedAsset = AssetPropertiesUtils.GetDiffuseBitmap(theAsset);
string texturePath = AssetPropertiesUtils.GetTexturePath(connectedAsset);


if (!string.IsNullOrEmpty(texturePath) && File.Exists(texturePath))
{
SetTextureProperties(gl_mat, texturePath, connectedAsset, theAsset, opacity);
}

return gl_mat;
}

private static void SetTextureProperties(GLTFMaterial gl_mat, string texturePath, Asset connectedAsset,
Asset theAsset, float opacity)
{
gl_mat.EmbeddedTexturePath = texturePath;

float scaleX = AssetPropertiesUtils.GetScale(connectedAsset, UnifiedBitmap.TextureRealWorldScaleX);
float scaleY = AssetPropertiesUtils.GetScale(connectedAsset, UnifiedBitmap.TextureRealWorldScaleY);
float rotation = AssetPropertiesUtils.GetRotationRadians(connectedAsset);
gl_mat.Fadevalue = AssetPropertiesUtils.GetFade(theAsset);
gl_mat.TintColour = AssetPropertiesUtils.GetTint(theAsset);
gl_mat.BaseColor = AssetPropertiesUtils.GetAppearenceColor(theAsset);

gl_mat.pbrMetallicRoughness.baseColorFactor = new List<float>(4)
{
1,
1,
1,
opacity
};

gl_mat.pbrMetallicRoughness.baseColorTexture = new GLTFTextureInfo
{
index = -1,
extensions = new GLTFTextureExtensions
{
TextureTransform = new GLTFTextureTransform
{
scale = new float[] { 1f / scaleX, 1f / scaleY },
rotation = rotation
}
}
};
}
}
}
Loading