Using different material on each face of a tessellated shape

Using different material on each face of a tessellated shape

Anonymous
Not applicable
1,483 Views
10 Replies
Message 1 of 11

Using different material on each face of a tessellated shape

Anonymous
Not applicable

I am creating a complex tessellated shape, in which I am trying to use more than one material (essentially - I am trying to paint each face with its own color).

 

However, the end result seems to use just one material for the entire shape (I think it's the material that I've used for the first face). 

 

Is it possible to assign different materials to each face?

0 Likes
1,484 Views
10 Replies
Replies (10)
Message 2 of 11

jeremy_tammik
Alumni
Alumni

Can you achieve the desired effect manually in the end user interface? How? If not, the API may not support it either.

 

I do not think you can assign a material to a face alone, since real-world materials only come with volumes, and a face has none.

 

You might be able to paint individual faces, though.

 

Plus, you might be able to assign sub-categories to faces, and they can have different materials.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 11

Anonymous
Not applicable

The API allows me to specify the material id on a face level - the TesselatedFace constructor accepts the vertices and the material.

 

I am actually trying to paint each face with a different color and the only way to specify the color of the face that I've found was through creating a new material...

 

Is there a more straightforward way to paint the face of a tessellated shape?

 

thanks,

0 Likes
Message 4 of 11

jeremy_tammik
Alumni
Alumni

So you now have a working solution?

 

Congratulations on that!

 

I suspect the approach you describe is the only way to go.

 

Cheers,

 

Jeremy

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 11

Anonymous
Not applicable

I only have a very dirty workaround: I need to create a separate shape from faces in each color. 

 

Doing it the way I would expect - just assigning different materials / colors to faces within one shape does not work - all faces get colored in one color (although I assign different materials to them).

 

0 Likes
Message 6 of 11

Anonymous
Not applicable

So when I say "The API allows me to specify the material id on a face level" I only mean that the API has such method (but it doesn't work as expected in my case)

0 Likes
Message 7 of 11

jeremy_tammik
Alumni
Alumni

Can you provide a minimal reproducible case assigning different materials to the faces within one shape to demonstrate your exact approach, proving it does not work and enabling the development team to analyse the issue and possibly explain what might be done to make it work in the desired manner?

 

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

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 8 of 11

RPTHOMAS108
Mentor
Mentor

I don't see the same issue in Revit 2022:

 

210816a.PNG

Private Function Obj_210816c(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData,
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result

        Dim UIDoc As UIDocument = commandData.Application.ActiveUIDocument
        If UIDoc Is Nothing Then Return Result.Cancelled Else
        Dim IntDoc As Document = UIDoc.Document

        Dim Mats As New List(Of String)
        Mats.Add("RT_Red,255,0,0")
        Mats.Add("RT_Green,0,255,0")
        Mats.Add("RT_Blue,0,0,255")
        Mats.Add("RT_Cyan,0,255,255")

        Dim FEC As New FilteredElementCollector(IntDoc)
        Dim ECF As New ElementClassFilter(GetType(Material))
        Dim MatsFound As List(Of Element) = FEC.WherePasses(ECF).ToElements.Where(Function(n) n.Name.StartsWith("RT_")).ToList
        Dim NewMats As ElementId() = New ElementId(3) {}

        Using tx As New Transaction(IntDoc, "Add materials")
            If tx.Start = TransactionStatus.Started Then
                Dim Commit As Boolean = False
                Dim Ix As Integer = 0
                For Each item As String In Mats
                    Dim Str As String() = item.Split(New Char() {","}, StringSplitOptions.None)
                    Dim M As Element = MatsFound.FirstOrDefault(Function(x) x.Name = Str(0))
                    If M Is Nothing Then
                        NewMats(Ix) = Material.Create(IntDoc, Str(0))
                        Commit = True

                        IntDoc.Regenerate()
                        Dim M1 As Material = IntDoc.GetElement(NewMats(Ix))
                        M1.Color = New Color(CByte(Str(1)), CByte(Str(2)), CByte(Str(3)))
                    Else
                        NewMats(Ix) = M.Id
                    End If

                    Ix += 1
                Next
                If Commit Then
                    tx.Commit()
                Else
                    tx.RollBack()
                End If
            End If
        End Using

        Dim Size As Double = 1
        Dim v1 As New XYZ((8 / 9) ^ 0.5, 0, -1 / 3)
        Dim v2 As New XYZ(-(2 / 9) ^ 0.5, (2 / 3) ^ 0.5, -1 / 3)
        Dim v3 As New XYZ(-(2 / 9) ^ 0.5, -(2 / 3) ^ 0.5, -1 / 3)
        Dim v4 As New XYZ(0, 0, 1)

        v1 *= Size
        v2 *= Size
        v3 *= Size
        v4 *= Size

        Dim F As XYZ(,) = New XYZ(3, 2) {{v4, v1, v2}, {v4, v2, v3}, {v4, v3, v1}, {v1, v2, v3}}

        Dim TSB As New TessellatedShapeBuilder()
        TSB.OpenConnectedFaceSet(True)
        For i = 0 To 3
            Dim EID As ElementId = NewMats(i)
            TSB.AddFace(New TessellatedFace({F(i, 0), F(i, 1), F(i, 2)}.ToList, EID))
        Next
        TSB.CloseConnectedFaceSet()
        TSB.Build()

        Using tx As New Transaction(IntDoc, "Tetrahedron")
            If tx.Start = TransactionStatus.Started Then
                Dim DS As DirectShape = DirectShape.CreateElement(IntDoc, New ElementId(BuiltInCategory.OST_GenericModel))
                DS.AppendShape(TSB)

                tx.Commit()
            End If
        End Using
        Return Result.Succeeded


    End Function

TessellatedShapeBuilder.GraphicsStyleId will be set for whole shape i.e. can have Category with Material

0 Likes
Message 9 of 11

Archigrafix_Norge
Advocate
Advocate

Hi @Anonymous 

Testing on Revit 2022 and facing the same issue. Have you found a solution for setting a material to each face? 

 

 

TessellatedFace tessellatedFaceobj = new TessellatedFace(ptsxobj, materialId); 
builderobj.AddFace(tessellatedFaceobj);

 

 

I find very strange that a materialId must be be indicated for each face, if the shape can only contain 1 material on all faces.

 

@jeremy_tammik  @RPTHOMAS108 

 

 


Luis Santos

archi systems as

0 Likes
Message 10 of 11

RPTHOMAS108
Mentor
Mentor

The above code I posted was originally for 2022 (setting a material per face) and still works in 2023 version.

 

In realistic visual style the colour is taken from the Appearance Asset Colour which has not be set for the four materials created above (this can be changed via the assets of the material). However each face is set to a different material (which can also be seen in RevitLookup).

 

So you have to probably include some code highlighting what you are trying to do that isn't working because it seems to me that it is.

 

220815a.PNG220815b.PNG

 

 

0 Likes
Message 11 of 11

jeremy_tammik
Alumni
Alumni

Many thanks for the sample code and explanation! Preserved here for posterity:

  

https://thebuildingcoder.typepad.com/blog/2022/09/point-clouds-coloured-triangles-and-faces.html#2

  

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