public SystemDumper(Figure figure, SurfaceProperties surfaceProperties, bool[] channelsToInclude, DirectoryInfo figureDestDir)
 {
     this.figure            = figure;
     this.surfaceProperties = surfaceProperties;
     this.channelsToInclude = channelsToInclude;
     this.figureDestDir     = figureDestDir;
 }
Beispiel #2
0
    public FigureRenderer Load(IArchiveDirectory figureDir, MaterialSetAndVariantOption materialSetOption)
    {
        SurfaceProperties surfaceProperties = Persistance.Load <SurfaceProperties>(figureDir.File("surface-properties.dat"));

        var refinementDirectory = figureDir.Subdirectory("refinement");

        var controlMeshDirectory = refinementDirectory.Subdirectory("control");

        int[] surfaceMap = controlMeshDirectory.File("surface-map.array").ReadArray <int>();

        var             refinedMeshDirectory = refinementDirectory.Subdirectory("level-" + surfaceProperties.SubdivisionLevel);
        SubdivisionMesh mesh = SubdivisionMeshPersistance.Load(refinedMeshDirectory);

        int[] controlFaceMap = refinedMeshDirectory.File("control-face-map.array").ReadArray <int>();

        var materialSet = MaterialSet.LoadActive(device, shaderCache, textureCache, dataDir, figureDir, materialSetOption, surfaceProperties);
        var materials   = materialSet.Materials;

        Scatterer scatterer = surfaceProperties.PrecomputeScattering ? Scatterer.Load(device, shaderCache, figureDir, materialSetOption.MaterialSet.Label) : null;

        var uvSetName = materials[0].UvSet;
        IArchiveDirectory uvSetDirectory = figureDir.Subdirectory("uv-sets").Subdirectory(uvSetName);

        var texturedVertexInfos = uvSetDirectory.File("textured-vertex-infos.array").ReadArray <TexturedVertexInfo>();

        Quad[] texturedFaces = uvSetDirectory.File("textured-faces.array").ReadArray <Quad>();

        var vertexRefiner = new VertexRefiner(device, shaderCache, mesh, texturedVertexInfos);

        FigureSurface[] surfaces = FigureSurface.MakeSurfaces(device, materials.Length, texturedFaces, controlFaceMap, surfaceMap, materialSet.FaceTransparencies);

        HashSet <int> visitedSurfaceIndices = new HashSet <int>();
        List <int>    surfaceOrder          = new List <int>(surfaces.Length);

        bool[] areUnorderedTransparent = new bool[surfaces.Length];

        //first add surfaces with an explicity-set render order
        foreach (int surfaceIdx in surfaceProperties.RenderOrder)
        {
            visitedSurfaceIndices.Add(surfaceIdx);
            surfaceOrder.Add(surfaceIdx);
            areUnorderedTransparent[surfaceIdx] = false;
        }

        //then add any remaining surfaces
        for (int surfaceIdx = 0; surfaceIdx < surfaces.Length; ++surfaceIdx)
        {
            if (visitedSurfaceIndices.Contains(surfaceIdx))
            {
                continue;
            }
            surfaceOrder.Add(surfaceIdx);
            areUnorderedTransparent[surfaceIdx] = true;
        }

        var isOneSided = figureDir.Name == "genesis-3-female";         //hack

        return(new FigureRenderer(device, shaderCache, scatterer, vertexRefiner, materialSet, surfaces, isOneSided, surfaceOrder.ToArray(), areUnorderedTransparent));
    }
Beispiel #3
0
    public static void DumpFigure(Figure figure, SurfaceProperties surfaceProperties, DirectoryInfo figureDestDir)
    {
        var refinementDirectory = figureDestDir.Subdirectory("refinement");

        GeometryDumper dumper = new GeometryDumper(figure, surfaceProperties, refinementDirectory);

        dumper.DumpRefinement();
    }
 public UVSetDumper(
     Figure figure,
     SurfaceProperties surfaceProperties,
     DirectoryInfo uvSetsDirectory)
 {
     this.figure            = figure;
     this.surfaceProperties = surfaceProperties;
     this.uvSetsDirectory   = uvSetsDirectory;
 }
Beispiel #5
0
    public static void Dump(Figure figure, SurfaceProperties surfaceProperties, IMaterialSettings[] materialSettingsArray, DirectoryInfo figureDestDir, string materialSetName)
    {
        if (!surfaceProperties.PrecomputeScattering)
        {
            return;
        }

        new ScatteringDumper(figure, materialSettingsArray, figureDestDir, materialSetName).Dump();
    }
 public ShapeDumper(ContentFileLocator fileLocator, Device device, ShaderCache shaderCache, Figure parentFigure, float[] parentFaceTransparencies, Figure figure, SurfaceProperties surfaceProperties, ShapeImportConfiguration baseConfiguration)
 {
     this.fileLocator              = fileLocator;
     this.device                   = device;
     this.shaderCache              = shaderCache;
     this.parentFigure             = parentFigure;
     this.parentFaceTransparencies = parentFaceTransparencies;
     this.figure                   = figure;
     this.surfaceProperties        = surfaceProperties;
     this.baseConfiguration        = baseConfiguration;
 }
    public static void DumpFigure(Figure figure, SurfaceProperties surfaceProperties, DirectoryInfo figureDestDir)
    {
        DirectoryInfo uvSetsDirectory = figureDestDir.Subdirectory("uv-sets");
        UVSetDumper   dumper          = new UVSetDumper(figure, surfaceProperties, uvSetsDirectory);

        dumper.DumpShared();
        foreach (var pair in figure.UvSets)
        {
            dumper.Dump(pair.Key, pair.Value);
        }
    }
Beispiel #8
0
 public UVSetDumper(
     Figure figure,
     SurfaceProperties surfaceProperties,
     DirectoryInfo uvSetsDirectory,
     Quad[] spatialFaces, SubdivisionTopologyInfo spatialTopologyInfo)
 {
     this.figure              = figure;
     this.surfaceProperties   = surfaceProperties;
     this.uvSetsDirectory     = uvSetsDirectory;
     this.spatialFaces        = spatialFaces;
     this.spatialTopologyInfo = spatialTopologyInfo;
 }
Beispiel #9
0
 public FigureDumper(ContentFileLocator fileLocator, DsonObjectLocator objectLocator, Device device, ShaderCache shaderCache, Figure parentFigure, Figure figure, SurfaceProperties surfaceProperties, MaterialSetImportConfiguration baseMaterialSetImportConfiguration, ShapeImportConfiguration baseShapeImportConfiguration, ShapeDumper shapeDumper)
 {
     this.device            = device;
     this.shaderCache       = shaderCache;
     this.fileLocator       = fileLocator;
     this.objectLocator     = objectLocator;
     this.parentFigure      = parentFigure;
     this.figure            = figure;
     this.surfaceProperties = surfaceProperties;
     this.baseMaterialSetImportConfiguration = baseMaterialSetImportConfiguration;
     this.baseShapeImportConfiguration       = baseShapeImportConfiguration;
     this.shapeDumper = shapeDumper;
 }
Beispiel #10
0
        public bool isVisualOnly;    // if 0 has collision

        public void Read(Stream stream)
        {
            using BinaryReader reader = new BinaryReader(stream);
            idx             = reader.ReadUInt32();
            filename        = reader.ReadZString();
            pos             = reader.ReadVector3();
            rot             = reader.ReadVector3();
            surfaceProps    = SurfaceProperties.ReadNew(reader);
            color           = IColor.ReadNew(reader);
            useCachedModels = reader.ReadBoolean();
            wiggleAmpl      = reader.ReadInt32();
            isVisualOnly    = reader.ReadBoolean();
        }
Beispiel #11
0
    public static float[] For(Figure figure, SurfaceProperties surfaceProperties, DirectoryInfo figureDestDir)
    {
        if (surfaceProperties.MaterialSetForOpacities != null)
        {
            var materialSetDir     = figureDestDir.Subdirectory("material-sets").Subdirectory(surfaceProperties.MaterialSetForOpacities);
            var transparenciesFile = materialSetDir.File("face-transparencies.array");
            return(transparenciesFile.ReadArray <float>());
        }

        var surfaceMap = figure.Geometry.SurfaceMap;

        return(surfaceMap
               .Select(surfaceIdx => 1 - surfaceProperties.Opacities[surfaceIdx])
               .ToArray());
    }
Beispiel #12
0
    public FigureDumper LoadDumper(string figureName)
    {
        var figure = figureName == parentFigure.Name ?
                     parentFigure :
                     figureRecipeLoader.LoadFigureRecipe(figureName, parentFigureRecipe).Bake(parentFigure);

        var figureConfDir = pathManager.GetConfDirForFigure(figure.Name);
        MaterialSetImportConfiguration baseMaterialSetConfiguration = MaterialSetImportConfiguration.Load(figureConfDir).Single(conf => conf.name == "Base");
        ShapeImportConfiguration       baseShapeImportConfiguration = ShapeImportConfiguration.Load(figureConfDir).SingleOrDefault(conf => conf.name == "Base");
        SurfaceProperties surfaceProperties = SurfacePropertiesJson.Load(pathManager, figure);

        ShapeDumper shapeDumper = new ShapeDumper(fileLocator, device, shaderCache, parentFigure, parentFaceTransparencies, figure, surfaceProperties, baseShapeImportConfiguration);

        return(new FigureDumper(fileLocator, objectLocator, device, shaderCache, parentFigure, figure, surfaceProperties, baseMaterialSetConfiguration, baseShapeImportConfiguration, shapeDumper));
    }
Beispiel #13
0
    public static void DumpFigure(Figure figure, SurfaceProperties surfaceProperties, DirectoryInfo figureDestDir)
    {
        DirectoryInfo refinementDirectory = figureDestDir.Subdirectory("refinement").Subdirectory("level-" + surfaceProperties.SubdivisionLevel);

        Quad[] spatialFaces = refinementDirectory.File("faces.array").ReadArray <Quad>();
        SubdivisionTopologyInfo spatialTopologyInfo = Persistance.Load <SubdivisionTopologyInfo>(UnpackedArchiveFile.Make(refinementDirectory.File("topology-info.dat")));

        DirectoryInfo uvSetsDirectory = figureDestDir.Subdirectory("uv-sets");
        UVSetDumper   dumper          = new UVSetDumper(figure, surfaceProperties, uvSetsDirectory, spatialFaces, spatialTopologyInfo);

        foreach (var pair in figure.UvSets)
        {
            dumper.Dump(pair.Key, pair.Value);
        }
    }
Beispiel #14
0
 public void Read(Stream stream)
 {
     using BinaryReader reader = new BinaryReader(stream);
     idx              = reader.ReadUInt32();
     filename         = reader.ReadZString();
     pos              = reader.ReadVector3();
     rot              = reader.ReadVector3();
     fadeOutMin       = reader.ReadSingle();
     fadeOutMax       = reader.ReadSingle();
     surfaceProps     = SurfaceProperties.ReadNew(reader);
     color            = IColor.ReadNew(reader);
     worldDetailLevel = reader.ReadByte();
     unused           = reader.ReadByte();
     renderType       = EnumUtils.intToEnum <FOModelRenderType>(reader.ReadInt32());
     useCachedModels  = reader.ReadBoolean();
     wiggleAmpl       = reader.ReadInt32();
 }
Beispiel #15
0
        private SurfaceProperties CastToCollider(float GroundOffset, Vector3 fromPos, Vector3 forward, float minDistance, float maxDistance)
        {
            SurfaceProperties oSurf;

            if (!StickToGround)
            {
                oSurf          = new SurfaceProperties();
                oSurf.Position = fromPos;
                oSurf.Normal   = new Vector3(0, 1f, 0);
                return(oSurf);
            }

            Vector3 NodePosition = fromPos;
            Vector3 NodeNormal   = new Vector3(0, 1f, 0);

            RaycastHit hit;
            Ray        ray  = new Ray(fromPos, forward);
            bool       flag = false;

            if (maxDistance > 0f)
            {
                flag = Physics.SphereCast(ray, this.ColliRadius, out hit, maxDistance);
            }
            else
            {
                flag = Physics.SphereCast(ray, this.ColliRadius, out hit);
            }

            if (flag)
            {
                NodePosition = hit.point;
                NodeNormal   = hit.normal;
                //NodePosition += ((Vector3)(Vector3.up.normalized * GroundOffset));
            }
            else if (minDistance > 0f)
            {
                NodePosition  = fromPos + ((Vector3)(forward.normalized * minDistance));
                NodePosition += ((Vector3)(Vector3.up.normalized * GroundOffset));
            }

            oSurf          = new SurfaceProperties();
            oSurf.Position = NodePosition;
            oSurf.Normal   = NodeNormal;
            return(oSurf);
        }
Beispiel #16
0
        public void CreateRacingLine()
        {
            CheckIfMeshAlreadyCreated();

            Transform[] trans = GetTransforms();
            if (trans.Length < 2)
            {
                return;
            }

            if (MeshResolution < 16)
            {
                MeshResolution     = 16;
                LineSoftnessFactor = MeshResolution - 2;
                return;
            }
            LineSoftnessFactor = MeshResolution - 2;

            SplineInterpolator interp = GetComponent(typeof(SplineInterpolator)) as SplineInterpolator;

            SetupSplineInterpolator(interp, trans);

            interp.StartInterpolation(null, false, eWrapMode.ONCE);

            Vector3 prevPos = trans[0].position;


            for (int c = 0; c <= LineSoftnessFactor; c++)
            {
                float   currTime = c * Duration / LineSoftnessFactor;
                Vector3 currPos  = interp.GetHermiteAtTime(currTime);

                SurfaceProperties oSurf = CastToCollider(GroundOffset, currPos, new Vector3(0f, -1f, 0f), 0, 1);

                lastindex = AddLineNode(oSurf.Position, oSurf.Normal, 1f, lastindex);
                prevPos   = currPos;
            }

            UpdateMeshFilter();
            lastindex = -1;
            numMarks  = 0;
        }
Beispiel #17
0
 private void _read()
 {
     _format          = m_io.ReadU4le();
     _numTriangles    = m_io.ReadU4le();
     _numVertices     = m_io.ReadU4le();
     _numMorphTargets = m_io.ReadU4le();
     if (M_Parent.Version < 212992)
     {
         _surfProp = new SurfaceProperties(m_io, this, m_root);
     }
     if (!(IsNative))
     {
         _geometry = new GeometryNonNative(m_io, this, m_root);
     }
     _morphTargets = new List <MorphTarget>();
     for (var i = 0; i < NumMorphTargets; i++)
     {
         _morphTargets.Add(new MorphTarget(m_io, this, m_root));
     }
 }
Beispiel #18
0
    public FigureDumperLoader(ContentFileLocator fileLocator, DsonObjectLocator objectLocator, ImporterPathManager pathManager, Device device, ShaderCache shaderCache)
    {
        this.fileLocator   = fileLocator;
        this.objectLocator = objectLocator;
        this.pathManager   = pathManager;
        this.device        = device;
        this.shaderCache   = shaderCache;

        figureRecipeLoader = new FigureRecipeLoader(objectLocator, pathManager);

        FigureRecipe      genesis3FemaleRecipe = figureRecipeLoader.LoadFigureRecipe("genesis-3-female", null);
        FigureRecipe      genitaliaRecipe      = figureRecipeLoader.LoadFigureRecipe("genesis-3-female-genitalia", genesis3FemaleRecipe);
        FigureRecipe      genesis3FemaleWithGenitaliaRecipe = new FigureRecipeMerger(genesis3FemaleRecipe, genitaliaRecipe).Merge();
        Figure            genesis3FemaleWithGenitalia       = genesis3FemaleWithGenitaliaRecipe.Bake(null);
        SurfaceProperties genesis3FemaleSurfaceProperties   = SurfacePropertiesJson.Load(pathManager, genesis3FemaleWithGenitalia);

        float[] genesis3FemaleFaceTransparencies = FaceTransparencies.For(genesis3FemaleWithGenitalia, genesis3FemaleSurfaceProperties, null);

        parentFigureRecipe       = genesis3FemaleRecipe;
        parentFigure             = genesis3FemaleWithGenitalia;
        parentFaceTransparencies = genesis3FemaleFaceTransparencies;
    }
    public FaceTransparencyProcessor(Device device, ShaderCache shaderCache, Figure figure, SurfaceProperties surfaceProperties)
    {
        this.device            = device;
        this.figure            = figure;
        this.surfaceProperties = surfaceProperties;

        faceCount          = figure.Geometry.Faces.Length;
        faceTransparencies = new float[faceCount];

        var vertexShaderAndBytecode = shaderCache.GetVertexShader <TextureMaskRenderer>("occlusion/facetransparency/TransparencyCounting");

        inputLayout  = new InputLayout(device, vertexShaderAndBytecode.Bytecode, MeshBuffers.InputElements);
        vertexShader = vertexShaderAndBytecode;

        addingPixelShader = shaderCache.GetPixelShader <TextureMaskRenderer>("occlusion/facetransparency/TransparencyCounting_Add");
        maxingPixelShader = shaderCache.GetPixelShader <TextureMaskRenderer>("occlusion/facetransparency/TransparencyCounting_Max");

        var statesDesc = StateDescriptions.Default();

        statesDesc.rasterizer.CullMode = CullMode.None;
        states = new States(device, statesDesc);
    }
Beispiel #20
0
    public static MaterialSet LoadActive(Device device, ShaderCache shaderCache, TextureCache textureCache, IArchiveDirectory dataDir, IArchiveDirectory figureDir, string materialSetName, SurfaceProperties surfaceProperties)
    {
        var materialsDirectory = figureDir
                                 .Subdirectory("material-sets")
                                 .Subdirectory(materialSetName);

        var texturesDirectory = surfaceProperties.ShareTextures != null?
                                dataDir.Subdirectory("textures").Subdirectory(surfaceProperties.ShareTextures) :
                                    materialsDirectory;

        var textureLoader         = new TextureLoader(device, textureCache, texturesDirectory);
        var multiMaterialSettings = Persistance.Load <MultiMaterialSettings>(materialsDirectory.File("material-settings.dat"));
        var materials             = multiMaterialSettings.PerMaterialSettings.Select(settings => settings.Load(device, shaderCache, textureLoader)).ToArray();

        float[] faceTransparencies = materialsDirectory.File("face-transparencies.array").ReadArray <float>();

        return(new MaterialSet(textureLoader, materials, faceTransparencies));
    }
    public static MaterialSet LoadActive(Device device, ShaderCache shaderCache, TextureCache textureCache, IArchiveDirectory dataDir, IArchiveDirectory figureDir, MaterialSetAndVariantOption materialSetOption, SurfaceProperties surfaceProperties)
    {
        var materialSetDirectory = materialSetOption.MaterialSet.Directory;

        var texturesDirectory = dataDir.Subdirectory("textures");

        var textureLoader = new TextureLoader(device, textureCache, texturesDirectory);

        var materialSettingsBySurface = materialSetOption.PerSurfaceSettings;
        var materials = materialSettingsBySurface.Select(settings => settings.Load(device, shaderCache, textureLoader)).ToArray();

        float[] faceTransparencies = materialSetDirectory.File("face-transparencies.array").ReadArray <float>();

        return(new MaterialSet(textureLoader, materials, faceTransparencies));
    }
Beispiel #22
0
 private GeometryDumper(Figure figure, SurfaceProperties surfaceProperties, DirectoryInfo refinementDirectory)
 {
     this.figure              = figure;
     this.surfaceProperties   = surfaceProperties;
     this.refinementDirectory = refinementDirectory;
 }
    private static MultiMaterialSettings DumpMaterialSet(ImportSettings settings, Device device, ShaderCache shaderCache, ContentFileLocator fileLocator, DsonObjectLocator objectLocator, Figure figure, SurfaceProperties surfaceProperties, MaterialSetImportConfiguration baseConfiguration, DirectoryInfo figureDestDir, MaterialSetImportConfiguration configuration, TextureProcessor textureProcessor)
    {
        DirectoryInfo materialsSetsDirectory     = figureDestDir.Subdirectory("material-sets");
        DirectoryInfo materialSetDirectory       = materialsSetsDirectory.Subdirectory(configuration.name);
        FileInfo      materialSettingsFileInfo   = materialSetDirectory.File("material-settings.dat");
        FileInfo      faceTransparenciesFileInfo = materialSetDirectory.File("face-transparencies.array");

        if (materialSettingsFileInfo.Exists && faceTransparenciesFileInfo.Exists)
        {
            return(Persistance.Load <MultiMaterialSettings>(UnpackedArchiveFile.Make(materialSettingsFileInfo)));
        }

        var aggregator = new DsonMaterialAggregator(fileLocator, objectLocator);
        IEnumerable <string> dufPaths = Enumerable.Concat(baseConfiguration.materialsDufPaths, configuration.materialsDufPaths);

        foreach (string path in dufPaths)
        {
            DsonTypes.DsonDocument doc = objectLocator.LocateRoot(path);
            aggregator.IncludeDuf(doc.Root);
        }

        var faceTransparencyProcessor = new FaceTransparencyProcessor(device, shaderCache, figure, surfaceProperties);

        IMaterialImporter materialImporter;

        if (figure.Name.EndsWith("-hair"))
        {
            materialImporter = new HairMaterialImporter(figure, textureProcessor, faceTransparencyProcessor);
        }
        else
        {
            materialImporter = new UberMaterialImporter(figure, textureProcessor, faceTransparencyProcessor);
        }

        string[] surfaceNames = figure.Geometry.SurfaceNames;
        Dictionary <string, int> surfaceNameToIdx = Enumerable.Range(0, surfaceNames.Length)
                                                    .ToDictionary(idx => surfaceNames[idx], idx => idx);

        var perMaterialSettings = Enumerable.Range(0, figure.Geometry.SurfaceCount)
                                  .Select(surfaceIdx => {
            string surfaceName   = figure.Geometry.SurfaceNames[surfaceIdx];
            var bag              = aggregator.GetBag(surfaceName);
            var materialSettings = materialImporter.Import(surfaceIdx, bag);
            return(materialSettings);
        })
                                  .ToArray();

        var variantCategories = configuration.variantCategories
                                .Select(variantCategoryConf => {
            int[] surfaceIdxs = variantCategoryConf.surfaces
                                .Select(surfaceName => surfaceNameToIdx[surfaceName])
                                .ToArray();

            var variants = variantCategoryConf.variants
                           .Select(variantConf => {
                var variantAggregator = aggregator.Branch();
                foreach (string path in variantConf.materialsDufPaths)
                {
                    DsonTypes.DsonDocument doc = objectLocator.LocateRoot(path);
                    variantAggregator.IncludeDuf(doc.Root);
                }

                var settingsBySurface = variantCategoryConf.surfaces
                                        .Select(surfaceName => {
                    int surfaceIdx       = surfaceNameToIdx[surfaceName];
                    var bag              = variantAggregator.GetBag(surfaceName);
                    var materialSettings = materialImporter.Import(surfaceIdx, bag);
                    return(materialSettings);
                })
                                        .ToArray();

                return(new MultiMaterialSettings.Variant(variantConf.name, settingsBySurface));
            })
                           .ToArray();

            return(new MultiMaterialSettings.VariantCategory(variantCategoryConf.name, surfaceIdxs, variants));
        })
                                .ToArray();

        var multiMaterialSettings = new MultiMaterialSettings(perMaterialSettings, variantCategories);

        materialSetDirectory.CreateWithParents();

        textureProcessor.RegisterAction(() => {
            Persistance.Save(materialSettingsFileInfo, multiMaterialSettings);
        });

        var faceTranparencies = faceTransparencyProcessor.FaceTransparencies;

        faceTransparenciesFileInfo.WriteArray(faceTranparencies);

        faceTransparencyProcessor.Dispose();

        return(multiMaterialSettings);
    }
    public static void DumpMaterialSetAndScattering(ImportSettings settings, Device device, ShaderCache shaderCache, ContentFileLocator fileLocator, DsonObjectLocator objectLocator, Figure figure, SurfaceProperties surfaceProperties,
                                                    MaterialSetImportConfiguration baseConfiguration, TextureProcessor sharedTextureProcessor, DirectoryInfo figureDestDir, MaterialSetImportConfiguration configuration)
    {
        var materialSettings = DumpMaterialSet(settings, device, shaderCache, fileLocator, objectLocator, figure, surfaceProperties, baseConfiguration, figureDestDir, configuration, sharedTextureProcessor);

        ScatteringDumper.Dump(figure, surfaceProperties, materialSettings.PerMaterialSettings, figureDestDir, configuration.name);
    }
 public static void DumpFigure(Figure figure, SurfaceProperties surfaceProperties, bool[] channelsToInclude, DirectoryInfo figureDestDir)
 {
     new SystemDumper(figure, surfaceProperties, channelsToInclude, figureDestDir).DumpAll();
 }
        /**
         * All mighty method for computing material, surface position and surface parameters in a single pass.
         * 
         * If material and surface position are required this is the best way to obtain that information.
         * 
         * When using the coefficient cache be sure to have it properly set up. (MyPlanetShapeProvider.PrepareCache())
         */
        public void ComputeCombinedMaterialAndSurface(Vector3 position, bool useCache, out SurfaceProperties props)
        {
            if (Closed)
            {
                Debug.Fail("Storage closed!");
                props = new SurfaceProperties();
                return;
            }

            byte occl = 0;

            MyPlanetMaterialProvider.MaterialSampleParams pars;

            position -= Shape.Center();

            float distance = position.Length();

            pars.Gravity = position / distance;

            // Latitude
            props.Latitude = pars.Gravity.Y;

            Vector2 lon = new Vector2(-pars.Gravity.X, -pars.Gravity.Z);
            lon.Normalize();

            props.Longitude = lon.Y;
            if (-pars.Gravity.X > 0)
            {
                props.Longitude = 2 - props.Longitude;
            }

            // Height and slope
            int face;
            Vector2 pos;
            MyCubemapHelpers.CalculateSampleTexcoord(ref position, out face, out pos);

            float value;
            if(!useCache)
                value = Shape.GetValueForPosition(face, ref pos, out props.Normal);
            else
                value = Shape.GetValueForPositionWithCache(face, ref pos, out props.Normal);

            pars.SampledHeight = value;
            pars.SurfaceDepth = 0;
            pars.Texcoord = pos;
            pars.LodSize = 1.0f;
            pars.Latitude = props.Latitude;
            pars.Longitude = props.Longitude;
            pars.Face = face;
            pars.Normal = props.Normal;

            props.Position = pars.Gravity * (Radius + value) + Shape.Center();

            props.Gravity = pars.Gravity = -pars.Gravity;

            pars.DistanceToCenter = props.Position.Length();

            var rule = Material.GetLayeredMaterialForPosition(ref pars, out props.Biome, ref occl);

            props.Material = rule.FirstOrDefault;
            if (props.Material == null) props.Material = MyDefinitionManager.Static.GetVoxelMaterialDefinition(0);

            //props.Altitude = value;

            props.Slope = pars.Normal.Z;

            props.HeightRatio = Shape.AltitudeToRatio(value);
        }