I would like to retrieve and display 3d attribute data using the Feature ID obtained from the ArcGISHitTestSample scene as a key.
In the Sample3DAttributesComponent class of the 3DAttributesSample scene, the material is changed when "AttributeType:BuildingName" matches a unique name.
I thought that if this matched the Feature ID obtained in the aforementioned hit test, the corresponding building would be considered to have been identified and the 3D attribute data (year of construction, building name, etc.) could be retrieved and displayed.
However, this does not work.
Is this possible?
Or is this a misguided attempt?
Code is here:Sample3DAttributesComponent.cs
(I first tried to debug output of the FID.
I can output it, but it seems to be different from the value output in the HitTestSample scene.)
private void Setup3DAttributes(ArcGIS3DObjectSceneLayer buildingLayer)
{
if (buildingLayer == null)
{
return;
}
if (layerAttribute == AttributeType.ConstructionYear)
{
Setup3DAttributesFloatAndIntegerType(buildingLayer);
}
else if (layerAttribute == AttributeType.BuildingName)
{
Setup3DAttributesOtherType(buildingLayer);
}
// Add a process to handle FIDs
else if (layerAttribute == AttributeType.FID)
{
var layerAttributes = ArcGISImmutableArray<String>.CreateBuilder();
layerAttributes.Add("FID");
var renderAttributeDescriptions = ArcGISImmutableArray<Esri.GameEngine.Attributes.ArcGISVisualizationAttributeDescription>.CreateBuilder();
renderAttributeDescriptions.Add(new Esri.GameEngine.Attributes.ArcGISVisualizationAttributeDescription("IsBuildingOfInterest", Esri.GameEngine.Attributes.ArcGISVisualizationAttributeType.Float32));
attributeProcessor = new Esri.GameEngine.Attributes.ArcGISAttributeProcessor();
attributeProcessor.ProcessEvent += (ArcGISImmutableArray<Esri.GameEngine.Attributes.ArcGISAttribute> layerNodeAttributes, ArcGISImmutableArray<Esri.GameEngine.Attributes.ArcGISVisualizationAttribute> renderNodeAttributes) =>
{
var fidAttribute = layerNodeAttributes.At(0);
var isBuildingOfInterestAttribute = renderNodeAttributes.At(0);
var isBuildingOfInterestBuffer = isBuildingOfInterestAttribute.Data;
var isBuildingOfInterestData = isBuildingOfInterestBuffer.Reinterpret<float>(sizeof(byte));
// FID Debug Output
ForEachInt64(fidAttribute, (long element, Int32 index) =>
{
Debug.Log("FID::" + element);
});
};
buildingLayer.SetAttributesToVisualize(layerAttributes.MoveToArray(), renderAttributeDescriptions.MoveToArray(), attributeProcessor);
}
}
// Add function
void ForEachInt64(Esri.GameEngine.Attributes.ArcGISAttribute attribute, Action<Int64, Int32> predicate)
{
unsafe
{
var buffer = attribute.Data;
var unsafePtr = NativeArrayUnsafeUtility.GetUnsafePtr(buffer);
var metadata = (int*)unsafePtr;
var count = metadata[0];
IntPtr intPtr = (IntPtr)unsafePtr + sizeof(int);
for (var i = 0; i < count; ++i)
{
Int64 element = *((Int64*)intPtr); // Rises NullReferenceException: Object reference not set to an instance of an object
predicate(element, i);
intPtr += sizeof(Int64);
}
}
}
runtime console:
Same question here, also the float value extraction, appreciated if some one can help 🙏
Editted on 7 Feb 23:
I found the data stored in 8 byte, this works for float... may be int as well
var buffer = attribute.Data;
var unsafePtr = NativeArrayUnsafeUtility.GetUnsafePtr(buffer);
var metadata = (double*)unsafePtr;
var count = attribute.Data.Length / 8;
for (var i = 0; i < count; ++i)
{
predicate((float)metadata[i], i);
}