/// <summary> /// Returns a sorted collection of DrawStubs /// </summary> /// <param name="transparentParts"></param> /// <param name="eye"></param> /// <returns></returns> private IEnumerable <PatchData> SortTransparentParts( ICollection <GlobalGeometryPartBlockNew> transparentParts, Camera eye) { var capacity = transparentParts.Sum(u => InstanceManager.GetInstanceCount(u)); var transparentDrawsSortedList = new SortedList <float, PatchData>(capacity, DistanceComparer); foreach (var part in transparentParts) { foreach (var instance in InstanceManager.GetInstancesOf(part)) { var scenePosition = Vector3.TransformPosition(part.Position, instance.worldMatrix); var distance = eye.DistanceOf(scenePosition); transparentDrawsSortedList.Add(distance, new PatchData(part, instance) { ShaderKey = _shaderDictionary[part] }); } } return(transparentDrawsSortedList.Select(u => u.Value)); }
/// <summary> /// Buffers array data and creates draw commands as needed for a given object /// </summary> /// <param name="eye">Viewer camera used to select detail level</param> /// <param name="objectBlock">Object to draw</param> /// <param name="instance">Instance data of object to draw</param> private void Dispatch(Camera eye, ObjectBlock objectBlock, IH2ObjectInstance instance) { CacheKey cacheKey; if (!objectBlock.TryGetCacheKey(out cacheKey)) { return; } var modelBlock = objectBlock.Model.Get <ModelBlock>(cacheKey); var renderBlock = modelBlock?.RenderModel.Get <RenderModelBlock>(cacheKey); if (renderBlock == null) { return; } BucketManager.UnpackVertexData(renderBlock); // TODO use bounding offset and bounding radius here x var distance = eye.DistanceOf(instance.ObjectDatum.Position); var detailLevel = GetDetailLevel(modelBlock, distance); var variant = StringIdent.Zero; var type = instance.GetType( ); if (!SupportsPermutations.ContainsKey(type)) { SupportsPermutations[type] = type.Field("PermutationData") != null; } var supportsPermutation = SupportsPermutations[type]; if (supportsPermutation) { var instanceVariant = StringIdent.Zero; var defaultModelVariant = objectBlock.DefaultModelVariant; // Select the instance variant if it exists, else select the default variant if it exists, // else default to zero variant = instanceVariant == StringIdent.Zero ? defaultModelVariant == StringIdent.Zero ? StringIdent.Zero : defaultModelVariant : instanceVariant; } var hasVariant = variant != StringIdent.Zero; var hasRegions = modelBlock.ModelRegionBlock.Length > 0; // Here sections are collected using the detail level and chosen variant (if it exists) RenderModelSectionBlock[] sections; if (hasVariant) { var variantBlock = modelBlock.Variants.Single(e => e.Name == variant); sections = ProcessVariant(variantBlock, renderBlock, detailLevel); } else if (hasRegions) { sections = ProcessRegions(modelBlock.ModelRegionBlock, renderBlock, detailLevel); } else { sections = renderBlock.Sections; } // Loop through all the sections and load the vertex data if needed and pass the part along // to the draw manager to handle sorting and grouping foreach (var renderModelSection in sections) { if (renderModelSection.SectionData.Length <= 0) { continue; } _bucketManager.BufferPartData(renderModelSection.SectionData[0].Section); foreach (var part in renderModelSection.SectionData[0].Section.Parts) { var materialBlock = renderBlock.Materials[part.Material]; // Create an instance for this part and assign a shader for it _drawManager.CreateInstance(part, instance, supportsPermutation); _drawManager.AssignShader(part, cacheKey, materialBlock.Shader.Ident); } } }