public static MeshGpuInstancing WithInstanceCustomAccessor(this MeshGpuInstancing instancing, string attribute, IReadOnlyList <Object> values) { Guard.NotNullOrEmpty(attribute, nameof(attribute)); attribute = attribute.ToUpperInvariant(); var expectedType = values.Where(item => item != null).FirstOrDefault()?.GetType(); if (expectedType == null) { return(instancing); } if (expectedType == typeof(int)) { var xValues = values.Select(item => item is int val ? val : 0).ToList(); return(instancing.WithInstanceAccessor(attribute, xValues)); } if (expectedType == typeof(Single)) { var xValues = values.Select(item => item is float val ? val : 0).ToList(); return(instancing.WithInstanceAccessor(attribute, xValues)); } throw new ArgumentException(expectedType.Name); }
public static MeshGpuInstancing WithInstanceAccessors(this MeshGpuInstancing instancing, IReadOnlyList <Transforms.AffineTransform> transforms) { Guard.NotNull(instancing, nameof(instancing)); Guard.NotNull(transforms, nameof(transforms)); var xfrms = transforms.Select(item => item.GetDecomposed()); var hasS = xfrms.Any(item => item.Scale != Vector3.One); var hasR = xfrms.Any(item => item.Rotation != Quaternion.Identity); var hasT = xfrms.Any(item => item.Translation != Vector3.Zero); if (hasS) { instancing.WithInstanceAccessor("SCALE", xfrms.Select(item => item.Scale).ToList()); } if (hasR) { instancing.WithInstanceAccessor("ROTATION", xfrms.Select(item => item.Rotation).ToList()); } if (hasT) { instancing.WithInstanceAccessor("TRANSLATION", xfrms.Select(item => item.Translation).ToList()); } return(instancing); }
public static MeshGpuInstancing WithInstanceCustomAccessors(this MeshGpuInstancing instancing, IReadOnlyList <IO.JsonContent> extras) { Guard.NotNull(instancing, nameof(instancing)); // gather attribute keys var keys = extras .Select(item => item.Content) .OfType <IReadOnlyDictionary <string, Object> >() .SelectMany(item => item.Keys) .Distinct() .Where(item => item.StartsWith("_", StringComparison.Ordinal)); foreach (var key in keys) { Object valueGetter(IO.JsonContent extra) { if (!(extra.Content is IReadOnlyDictionary <string, Object> dict)) { return(null); } return(dict.TryGetValue(key, out var val) ? val : null); } var values = extras.Select(valueGetter).ToList(); instancing.WithInstanceCustomAccessor(key, values); } return(instancing); }
public static unsafe MeshGpuInstancing WithInstanceAccessor <T>(this MeshGpuInstancing instancing, string attribute, IReadOnlyList <T> values) where T : unmanaged { Guard.NotNull(instancing, nameof(instancing)); Guard.NotNull(values, nameof(values)); var root = instancing.LogicalParent.LogicalParent; var view = root.CreateBufferView(values); var accessor = root.CreateAccessor(); if (typeof(T) == typeof(int)) { accessor.SetIndexData(view, 0, values.Count, IndexEncodingType.UNSIGNED_INT); } else { var dt = DimensionType.CUSTOM; if (typeof(T) == typeof(Single)) { dt = DimensionType.SCALAR; } if (typeof(T) == typeof(Vector2)) { dt = DimensionType.VEC2; } if (typeof(T) == typeof(Vector3)) { dt = DimensionType.VEC3; } if (typeof(T) == typeof(Vector4)) { dt = DimensionType.VEC4; } if (typeof(T) == typeof(Quaternion)) { dt = DimensionType.VEC4; } if (typeof(T) == typeof(Matrix4x4)) { dt = DimensionType.MAT4; } if (dt == DimensionType.CUSTOM) { throw new ArgumentException(typeof(T).Name); } accessor.SetVertexData(view, 0, values.Count, dt, EncodingType.FLOAT, false); } instancing.SetAccessor(attribute, accessor); return(instancing); }
public MeshGpuInstancing UseGpuInstancing() { var ext = GetGpuInstancing(); if (ext == null) { ext = new MeshGpuInstancing(this); this.SetExtension(ext); } return(ext); }