public PackedLists <VertexDelta> ConvertToVertexDeltas(int vertexCount, bool[] channelsToInclude) { List <List <VertexDelta> > vertexDeltas = Enumerable.Range(0, vertexCount) .Select(idx => new List <VertexDelta>()) .ToList(); int morphCount = Morphs.Count; for (int morphIdx = 0; morphIdx < morphCount; ++morphIdx) { Morph morph = morphs[morphIdx]; if (channelsToInclude != null && !channelsToInclude[morph.Channel.Index]) { continue; } foreach (var delta in morph.Deltas) { vertexDeltas[delta.VertexIdx].Add(new VertexDelta(morphIdx, delta.PositionOffset)); } } return(PackedLists <VertexDelta> .Pack(vertexDeltas)); }
public ArraySegment Add(ImporterOcclusionSurrogate surrogate) { int dummyVertexCount = surrogate.SampleCount; var dummyMesh = new SubdivisionMesh( 0, new QuadTopology(dummyVertexCount, new Quad[0]), PackedLists <WeightedIndexWithDerivatives> .MakeEmptyLists(dummyVertexCount)); var dummyFaceTransparencies = new float[0]; var segment = Add(dummyMesh, dummyFaceTransparencies); //apply mask int maskIdx = nextMaskIdx++; uint mask = 1u << maskIdx; for (int i = 0; i < segment.Count; ++i) { int vertexIdx = i + segment.Offset; vertexMasks[vertexIdx] |= mask; } foreach (int faceIdx in surrogate.AttachedFaces) { faceMasks[faceIdx] |= mask; } return(segment); }
private PackedLists <WeightedIndex> CalculateFormFactorsForColorComponent( ScatteringFormFactorCalculator formFactorCalculator, IMaterialSettings[] materialSettingsArray, int componentIdx) { var profiles = materialSettingsArray .Select(baseMaterialSettings => { UberMaterialSettings materialSettings = baseMaterialSettings as UberMaterialSettings; if (materialSettings is null) { return(null); } if (materialSettings.thinWalled) { return(null); } var volumeSettings = new VolumeParameters( materialSettings.transmittedMeasurementDistance, materialSettings.transmittedColor[componentIdx], materialSettings.scatteringMeasurementDistance, materialSettings.sssAmount, materialSettings.sssDirection); ScatteringProfile profile = new ScatteringProfile( volumeSettings.SurfaceAlbedo, volumeSettings.MeanFreePathLength); return(profile); }) .ToArray(); PackedLists <WeightedIndex> formFactors = formFactorCalculator.Calculate(profiles); return(formFactors); }
private void Dump() { FileInfo formFactorSegmentsFile = targetDirectory.File(Scatterer.FormFactorSegmentsFilename); FileInfo formFactorElementsFile = targetDirectory.File(Scatterer.FormFactoryElementsFilename); if (formFactorElementsFile.Exists && formFactorSegmentsFile.Exists) { return; } Console.WriteLine("Dumping scattering form-factors..."); ScatteringFormFactorCalculator formFactorCalculator = ScatteringFormFactorCalculator.Make(figure.Geometry); //Note on units: // Daz uses units of cm for its "distance of measurement" volume parameters // Therefore, the calculted MeanFreePathLength is also in cm // And therefore, the radius and distance values passed to the scattering calculator must also be in cm PackedLists <WeightedIndex> redFormFactors = CalculateFormFactorsForColorComponent(formFactorCalculator, materialSettingsArray, 0); PackedLists <WeightedIndex> greenFormFactors = CalculateFormFactorsForColorComponent(formFactorCalculator, materialSettingsArray, 1); PackedLists <WeightedIndex> blueFormFactors = CalculateFormFactorsForColorComponent(formFactorCalculator, materialSettingsArray, 2); var formFactors = Vector3WeightedIndex.Merge(redFormFactors, greenFormFactors, blueFormFactors); targetDirectory.CreateWithParents(); formFactorSegmentsFile.WriteArray(formFactors.Segments); formFactorElementsFile.WriteArray(formFactors.Elems); }
public static AutomorpherRecipe Make(Geometry parentGeometry, Geometry childGeometry) { var parentLimit0Stencils = parentGeometry.MakeStencils(StencilKind.LimitStencils, 0); var subdivider = new Subdivider(parentLimit0Stencils); var parentLimit0VertexPositions = subdivider.Refine(parentGeometry.VertexPositions, new Vector3Operators()); List <(List <WeightedIndex>, Vector3)> resultPairs = Enumerable.Range(0, childGeometry.VertexCount) .AsParallel().AsOrdered() .Select(childVertexIdx => { Vector3 graftVertex = childGeometry.VertexPositions[childVertexIdx]; ClosestPoint.PointOnMesh closestPointOnBaseMesh = ClosestPoint.FindClosestPointOnMesh(parentGeometry.Faces, parentLimit0VertexPositions, graftVertex); var merger = new WeightedIndexMerger(); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxA), closestPointOnBaseMesh.BarycentricWeights.X); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxB), closestPointOnBaseMesh.BarycentricWeights.Y); merger.Merge(parentLimit0Stencils.GetElements(closestPointOnBaseMesh.VertexIdxC), closestPointOnBaseMesh.BarycentricWeights.Z); var cloestPointAsVector = closestPointOnBaseMesh.AsPosition(parentLimit0VertexPositions); return(merger.GetResult(), cloestPointAsVector); }) .ToList(); List <List <WeightedIndex> > baseDeltaWeights = resultPairs.Select(t => t.Item1).ToList(); Vector3[] parentSurfacePositions = resultPairs.Select(t => t.Item2).ToArray(); var packedBaseDeltaWeights = PackedLists <WeightedIndex> .Pack(baseDeltaWeights); return(new AutomorpherRecipe(packedBaseDeltaWeights, parentSurfacePositions)); }
public void Run() { int controlVertexCount = 6; Quad[] controlFaces = new [] { new Quad(0, 1, 2, 3), new Quad(1, 4, 5, 2) }; QuadTopology controlTopology = new QuadTopology(controlVertexCount, controlFaces); int refinementLevel = 1; using (Refinement refinement = new Refinement(controlTopology, refinementLevel)) { QuadTopology topology = refinement.GetTopology(); int[] faceMap = refinement.GetFaceMap(); for (int faceIdx = 0; faceIdx < topology.Faces.Length; ++faceIdx) { Console.WriteLine(topology.Faces[faceIdx] + " -> " + faceMap[faceIdx]); } Console.WriteLine(); PackedLists <WeightedIndex> stencils = refinement.GetStencils(StencilKind.LimitStencils); Console.WriteLine("stencils: "); for (int vertexIdx = 0; vertexIdx < stencils.Count; ++vertexIdx) { Console.WriteLine(vertexIdx + ":"); foreach (WeightedIndex weightedIndex in stencils.GetElements(vertexIdx)) { Console.WriteLine("\t" + weightedIndex.Index + " -> " + weightedIndex.Weight); } } } }
public static SkinBindingRecipe Merge(FigureRecipeMerger.Reindexer reindexer, SkinBindingRecipe parentSkinBinding, SkinBindingRecipe[] childSkinBindings) { List <string> mergedBones = new List <string>(parentSkinBinding.BoneNames); Dictionary <string, int> mergedBonesIndicesByName = Enumerable.Range(0, mergedBones.Count) .ToDictionary(idx => mergedBones[idx], idx => idx); PackedLists <BoneWeight> mergedBoneWeights = parentSkinBinding.BoneWeights; foreach (SkinBindingRecipe childSkinBinding in childSkinBindings) { var remappedChildBoneWeights = childSkinBinding.BoneWeights .Map(boneWeight => { string boneName = childSkinBinding.BoneNames[boneWeight.Index]; if (!mergedBonesIndicesByName.TryGetValue(boneName, out int mergedBoneIdx)) { mergedBoneIdx = mergedBones.Count; mergedBonesIndicesByName[boneName] = mergedBoneIdx; mergedBones.Add(boneName); } return(new BoneWeight(mergedBoneIdx, boneWeight.Weight)); }); mergedBoneWeights = PackedLists <BoneWeight> .Concat(mergedBoneWeights, remappedChildBoneWeights); } return(new SkinBindingRecipe { BoneNames = mergedBones.ToArray(), BoneWeights = mergedBoneWeights, FaceGroupToNodeMap = parentSkinBinding.FaceGroupToNodeMap }); }
public BasicVertexRefiner(Device device, ShaderCache shaderCache, PackedLists <WeightedIndexWithDerivatives> stencils) { this.refinedVertexCount = stencils.Count; this.refinerShader = shaderCache.GetComputeShader <BasicVertexRefiner>("subdivision/BasicVertexRefiner"); this.stencilSegmentsView = BufferUtilities.ToStructuredBufferView(device, stencils.Segments); this.stencilElemsView = BufferUtilities.ToStructuredBufferView(device, stencils.Elems); }
private PackedLists <WeightedIndex> NormalizeAndPackFormFactors(double[][] rawFormFactors) { List <List <WeightedIndex> > weightsByReceiver = new List <List <WeightedIndex> >(); for (int receiverIdx = 0; receiverIdx < vertexCount; receiverIdx++) { double[] formFactorsForReceiver = rawFormFactors[receiverIdx]; double total = 0; for (int transmitterIdx = 0; transmitterIdx < vertexCount; transmitterIdx++) { total += formFactorsForReceiver[transmitterIdx]; } if (total == 0) { weightsByReceiver.Add(new List <WeightedIndex>()); continue; } List <WeightedIndex> sortedWeights = Enumerable.Range(0, vertexCount) .Select(transmitterIdx => new WeightedIndex(transmitterIdx, (float)(formFactorsForReceiver[transmitterIdx] / total))) .Where(weightedIndex => weightedIndex.Weight != 0) .OrderByDescending(weightedIndex => weightedIndex.Weight) .ToList(); List <WeightedIndex> topWeights = new List <WeightedIndex>(); double accumulatedWeight = 0; foreach (WeightedIndex weightedIndex in sortedWeights) { topWeights.Add(weightedIndex); accumulatedWeight += weightedIndex.Weight; if (accumulatedWeight > 0.995) { break; } } if (topWeights.Count > 5000) { throw new InvalidOperationException("too many contributing vertices"); } weightsByReceiver.Add(topWeights); if (receiverIdx % 1000 == 0) { Console.WriteLine(receiverIdx + ": " + topWeights.Count); } } var packedWeightsByReceiver = PackedLists <WeightedIndex> .Pack(weightsByReceiver); return(packedWeightsByReceiver); }
public SubdivisionTopologyInfo(PackedLists <int> adjacentVertices, VertexRule[] vertexRules) { if (adjacentVertices.Count != vertexRules.Length) { throw new ArgumentException("count mismatch"); } AdjacentVertices = adjacentVertices; VertexRules = vertexRules; }
public SubdivisionMesh(int controlVertexCount, QuadTopology topology, PackedLists <WeightedIndexWithDerivatives> stencils) { if (stencils.Count != topology.VertexCount) { throw new ArgumentException("vertex count mismatch"); } ControlVertexCount = controlVertexCount; Topology = topology; Stencils = stencils; }
public static SubdivisionMesh Combine(SubdivisionMesh meshA, SubdivisionMesh meshB) { int offset = meshA.ControlVertexCount; return(new SubdivisionMesh( meshA.ControlVertexCount + meshB.ControlVertexCount, QuadTopology.Combine(meshA.Topology, meshB.Topology), PackedLists <WeightedIndexWithDerivatives> .Concat( meshA.Stencils, meshB.Stencils.Map(w => w.Reindex(offset))))); }
public static SubdivisionTopologyInfo Combine(SubdivisionTopologyInfo infoA, SubdivisionTopologyInfo infoB) { int offset = infoA.VertexRules.Length; PackedLists <int> combinedAdjancentVertices = PackedLists <int> .Concat( infoA.AdjacentVertices, infoB.AdjacentVertices.Map(neighbourIdx => neighbourIdx + offset)); VertexRule[] combinedVertexRules = Enumerable.Concat(infoA.VertexRules, infoB.VertexRules).ToArray(); return(new SubdivisionTopologyInfo(combinedAdjancentVertices, combinedVertexRules)); }
public static Scatterer Load(Device device, ShaderCache shaderCache, IArchiveDirectory figureDir, String materialSetName) { var l0GeometryDir = figureDir.Subdirectory("refinement").Subdirectory("level-0"); SubdivisionMesh level0Mesh = SubdivisionMeshPersistance.Load(l0GeometryDir); var scatteringDir = figureDir.Subdirectory("scattering").Subdirectory(materialSetName); var formFactorSegments = scatteringDir.File(FormFactorSegmentsFilename).ReadArray <ArraySegment>(); var formFactorElements = scatteringDir.File(FormFactoryElementsFilename).ReadArray <Vector3WeightedIndex>(); var formFactors = new PackedLists <Vector3WeightedIndex>(formFactorSegments, formFactorElements); return(new Scatterer(device, shaderCache, level0Mesh, formFactors)); }
public static SubdivisionMesh Load(IArchiveDirectory directory) { var stencilSegments = directory.File(StencilSegmentsFilename).ReadArray <ArraySegment>(); var stencilElements = directory.File(StencilElementsFilename).ReadArray <WeightedIndexWithDerivatives>(); var faces = directory.File(StencilFacesFilename).ReadArray <Quad>(); var stencils = new PackedLists <WeightedIndexWithDerivatives>(stencilSegments, stencilElements); int vertexCount = stencils.Count; var topology = new QuadTopology(vertexCount, faces); return(new SubdivisionMesh(0, topology, stencils)); }
public Scatterer(Device device, ShaderCache shaderCache, SubdivisionMesh mesh, PackedLists <Vector3WeightedIndex> formFactors) { vertexCount = mesh.Stencils.Count; stencilSegments = BufferUtilities.ToStructuredBufferView(device, mesh.Stencils.Segments); stencilElems = BufferUtilities.ToStructuredBufferView(device, mesh.Stencils.Elems); formFactorSegments = BufferUtilities.ToStructuredBufferView(device, formFactors.Segments); formFactorElements = BufferUtilities.ToStructuredBufferView(device, formFactors.Elems); samplingShader = shaderCache.GetComputeShader <Scatterer>("figure/scattering/SampleVertexIrradiances"); scatteringShader = shaderCache.GetComputeShader <Scatterer>("figure/scattering/ScatterIrradiances"); sampledIrrandiancesBufferManager = new InOutStructuredBufferManager <Vector3>(device, vertexCount); scatteredIrrandiancesBufferManager = new InOutStructuredBufferManager <Vector3>(device, vertexCount); }
public static RefinementResult Make(QuadTopology controlTopology, int[] controlSurfaceMap, int refinementLevel, bool derivativesOnly) { if (controlTopology.Faces.Length == 0 && controlTopology.VertexCount == 0) { return(RefinementResult.Empty); } PackedLists <WeightedIndex> limitStencils, limitDuStencils, limitDvStencils; QuadTopology refinedTopology; SubdivisionTopologyInfo refinedTopologyInfo; int[] controlFaceMap; using (var refinement = new Refinement(controlTopology, refinementLevel)) { limitStencils = refinement.GetStencils(StencilKind.LimitStencils); limitDuStencils = refinement.GetStencils(StencilKind.LimitDuStencils); limitDvStencils = refinement.GetStencils(StencilKind.LimitDvStencils); refinedTopology = refinement.GetTopology(); var adjacentVertices = refinement.GetAdjacentVertices(); var rules = refinement.GetVertexRules(); refinedTopologyInfo = new SubdivisionTopologyInfo(adjacentVertices, rules); controlFaceMap = refinement.GetFaceMap(); } if (derivativesOnly) { if (refinementLevel != 0) { throw new InvalidOperationException("derivatives-only mode can only be used at refinement level 0"); } limitStencils = PackedLists <WeightedIndex> .Pack(Enumerable.Range(0, controlTopology.VertexCount) .Select(vertexIdx => { var selfWeight = new WeightedIndex(vertexIdx, 1); return(new List <WeightedIndex> { selfWeight }); }).ToList()); } PackedLists <WeightedIndexWithDerivatives> stencils = WeightedIndexWithDerivatives.Merge(limitStencils, limitDuStencils, limitDvStencils); var refinedMesh = new SubdivisionMesh(controlTopology.VertexCount, refinedTopology, stencils); return(new RefinementResult(refinedMesh, refinedTopologyInfo, controlFaceMap)); }
public OccluderParameters CalculateOccluderParameters() { var baseInputs = MakePosedShapeInputs(); var baseOutputs = figure.Evaluate(null, baseInputs); var baseOcclusionInfos = CalculateOcclusion(baseOutputs); List <Channel> channels = new List <Channel>(); List <List <OcclusionDelta> > perVertexDeltas = new List <List <OcclusionDelta> >(); for (int i = 0; i < baseOcclusionInfos.Length; ++i) { perVertexDeltas.Add(new List <OcclusionDelta>()); } foreach (var channel in GetChannelsForOcclusionSystem()) { Console.WriteLine($"\t{channel.Name}..."); int occlusionChannelIdx = channels.Count; channels.Add(channel); var inputs = new ChannelInputs(baseInputs); channel.SetValue(inputs, 1); var outputs = figure.Evaluate(null, inputs); var occlusionInfos = CalculateOcclusion(outputs); for (int vertexIdx = 0; vertexIdx < occlusionInfos.Length; ++vertexIdx) { if (Math.Abs(occlusionInfos[vertexIdx].Front - baseOcclusionInfos[vertexIdx].Front) > OcclusionDifferenceThreshold) { var delta = new OcclusionDelta(occlusionChannelIdx, OcclusionInfo.Pack(occlusionInfos[vertexIdx])); perVertexDeltas[vertexIdx].Add(delta); } } } var parameters = new OccluderParameters( OcclusionInfo.PackArray(baseOcclusionInfos), channels.Select(channel => channel.Name).ToList(), PackedLists <OcclusionDelta> .Pack(perVertexDeltas)); return(parameters); }
public static PackedLists <WeightedIndexWithDerivatives> Merge( PackedLists <WeightedIndex> valueStencils, PackedLists <WeightedIndex> duStencils, PackedLists <WeightedIndex> dvStencils) { int segmentCount = valueStencils.Count; if (duStencils.Count != segmentCount) { throw new InvalidOperationException("expected du segment count to match"); } if (dvStencils.Count != segmentCount) { throw new InvalidOperationException("expected dv segment count to match"); } var combinedStencils = new List <List <WeightedIndexWithDerivatives> >(segmentCount); for (int segmentIdx = 0; segmentIdx < segmentCount; ++segmentIdx) { IEnumerable <WeightedIndexWithDerivatives> values = valueStencils.GetElements(segmentIdx) .Select(w => new WeightedIndexWithDerivatives(w.Index, w.Weight, 0, 0)); IEnumerable <WeightedIndexWithDerivatives> dvs = duStencils.GetElements(segmentIdx) .Select(w => new WeightedIndexWithDerivatives(w.Index, 0, w.Weight, 0)); IEnumerable <WeightedIndexWithDerivatives> dus = dvStencils.GetElements(segmentIdx) .Select(w => new WeightedIndexWithDerivatives(w.Index, 0, 0, w.Weight)); List <WeightedIndexWithDerivatives> combinedWeightedIndices = values.Concat(dvs).Concat(dus).GroupBy(w => w.Index).Select(group => { float sumWeight = group.Sum(w => w.Weight); float sumDuWeight = group.Sum(w => w.DuWeight); float sumDvWeight = group.Sum(w => w.DvWeight); return(new WeightedIndexWithDerivatives(group.Key, sumWeight, sumDuWeight, sumDvWeight)); }).ToList(); combinedStencils.Add(combinedWeightedIndices); } return(PackedLists <WeightedIndexWithDerivatives> .Pack(combinedStencils)); }
public static PackedLists <Vector3WeightedIndex> Merge( PackedLists <WeightedIndex> values0, PackedLists <WeightedIndex> values1, PackedLists <WeightedIndex> values2) { int segmentCount = values0.Count; if (values1.Count != segmentCount) { throw new InvalidOperationException("expected values1 count to match"); } if (values2.Count != segmentCount) { throw new InvalidOperationException("expected values2 count to match"); } var combined = new List <List <Vector3WeightedIndex> >(segmentCount); for (int segmentIdx = 0; segmentIdx < segmentCount; ++segmentIdx) { IEnumerable <Vector3WeightedIndex> v0s = values0.GetElements(segmentIdx) .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(w.Weight, 0, 0))); IEnumerable <Vector3WeightedIndex> v1s = values1.GetElements(segmentIdx) .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(0, w.Weight, 0))); IEnumerable <Vector3WeightedIndex> v2s = values2.GetElements(segmentIdx) .Select(w => new Vector3WeightedIndex(w.Index, new Vector3(0, 0, w.Weight))); List <Vector3WeightedIndex> combinedWeightedIndices = v0s.Concat(v1s).Concat(v2s).GroupBy(w => w.Index).Select(group => { float sum0 = group.Sum(w => w.Weight[0]); float sum1 = group.Sum(w => w.Weight[1]); float sum2 = group.Sum(w => w.Weight[2]); return(new Vector3WeightedIndex(group.Key, new Vector3(sum0, sum1, sum2))); }).ToList(); combined.Add(combinedWeightedIndices); } return(PackedLists <Vector3WeightedIndex> .Pack(combined)); }
public ShaperParameters( Vector3[] initialPositions, int morphCount, int[] morphChannelIndices, PackedLists <VertexDelta> morphDeltas, PackedLists <WeightedIndex> baseDeltaWeights, int boneCount, int[] boneIndices, PackedLists <BoneWeight> boneWeights, int[] occlusionSurrogateMap, OcclusionSurrogateParameters[] occlusionSurrogateParameters) { InitialPositions = initialPositions; MorphCount = morphCount; MorphChannelIndices = morphChannelIndices; MorphDeltas = morphDeltas; BaseDeltaWeights = baseDeltaWeights; BoneCount = boneCount; BoneIndices = boneIndices; BoneWeights = boneWeights; OcclusionSurrogateMap = occlusionSurrogateMap; OcclusionSurrogateParameters = occlusionSurrogateParameters ?? new OcclusionSurrogateParameters[0]; }
public Automorpher(PackedLists <WeightedIndex> baseDeltaWeights) { this.baseDeltaWeights = baseDeltaWeights; }
public Subdivider(PackedLists <WeightedIndex> stencils) { this.stencils = stencils; }
public SkinBinding(List <Bone> bones, PackedLists <BoneWeight> boneWeights, Dictionary <string, string> faceGroupToNodeMap) { this.bones = bones; this.boneWeights = boneWeights; this.faceGroupToNodeMap = faceGroupToNodeMap; }
public void Import(DsonTypes.SkinBinding skinBinding) { int vertexCount = skinBinding.vertex_count; List <List <BoneWeight> > boneWeightsByVertex = new List <List <BoneWeight> >(vertexCount); for (int i = 0; i < vertexCount; ++i) { boneWeightsByVertex.Add(new List <BoneWeight>()); } DsonTypes.WeightedJoint[] joints = skinBinding.joints; string[] boneNames = new string[joints.Length]; for (int boneIdx = 0; boneIdx < joints.Length; ++boneIdx) { DsonTypes.WeightedJoint joint = joints[boneIdx]; if (joint.node_weights == null) { throw new InvalidOperationException("expected scale_weights to be non-null"); } if (joint.scale_weights != null) { throw new InvalidOperationException("expected scale_weights to be null"); } if (joint.local_weights != null) { throw new InvalidOperationException("expected local_weights to be null"); } if (joint.bulge_weights != null) { throw new InvalidOperationException("expected bulge_weights to be null"); } DsonTypes.Node jointNode = joint.node.ReferencedObject; boneNames[boneIdx] = jointNode.name; foreach (DsonTypes.IndexedFloat elem in joint.node_weights.values) { boneWeightsByVertex[elem.index].Add(new BoneWeight(boneIdx, (float)elem.value)); } } Dictionary <string, string> faceGroupToNodeMap = new Dictionary <string, string>(); if (skinBinding.selection_map.Length != 1) { throw new InvalidOperationException("expected only one face-group-to-node map"); } foreach (DsonTypes.StringPair pair in skinBinding.selection_map[0].mappings) { faceGroupToNodeMap.Add(pair.from, pair.to); } SkinBindingRecipe recipe = new SkinBindingRecipe { BoneNames = boneNames, BoneWeights = PackedLists <BoneWeight> .Pack(boneWeightsByVertex), FaceGroupToNodeMap = faceGroupToNodeMap }; recipes.Add(recipe); }
public AutomorpherRecipe(PackedLists <WeightedIndex> baseDeltaWeights, Vector3[] parentSurfacePositions) { BaseDeltaWeights = baseDeltaWeights; ParentSurfacePositions = parentSurfacePositions; }
public OccluderParameters(uint[] baseOcclusion, List <string> channelNames, PackedLists <OcclusionDelta> deltas) { BaseOcclusion = baseOcclusion; ChannelNames = channelNames; Deltas = deltas; }