public void Clear()
 {
     placeholder = null;
     chunk       = null;
     voxelIndex  = -1;
     collider    = null;
 }
예제 #2
0
 /// <summary>
 /// Removes all existing voxels in this chunk.
 /// </summary>
 public void ClearVoxels(byte light)
 {
     if (lightSources != null)
     {
         int lightSourcesCount = lightSources.Count;
         for (int k = 0; k < lightSourcesCount; k++)
         {
             if (lightSources [k].gameObject != null)
             {
                 DestroyImmediate(lightSources [k].gameObject);
             }
         }
         lightSources.Clear();
     }
     if (placeholders != null)
     {
         int phCount = placeholders.Count;
         for (int k = 0; k < phCount; k++)
         {
             VoxelPlaceholder ph = placeholders [k];
             if (ph != null)
             {
                 DestroyImmediate(ph.gameObject);
             }
         }
         placeholders.Clear();
     }
     Voxel.Clear(voxels, light);
 }
        bool RayCastFast(Vector3 origin, Vector3 direction, out VoxelHitInfo hitInfo, float maxDistance = 0, bool createChunksIfNeeded = false, byte minOpaque = 0, ColliderTypes colliderTypes = ColliderTypes.AnyCollider)
        {
            bool voxelHit = RayCastFastVoxel(origin, direction, out hitInfo, maxDistance, createChunksIfNeeded, minOpaque);

            if ((colliderTypes & ColliderTypes.OnlyVoxels) != 0)
            {
                return(voxelHit);
            }

            if (voxelHit)
            {
                maxDistance = hitInfo.distance - 0.1f;
            }
            // Cast a normal raycast to detect normal gameobjects within ray
            RaycastHit hit;

            if (Physics.Raycast(origin + 0.3f * direction, direction, out hit, maxDistance - 0.3f))
            {
                hitInfo.distance = hit.distance;
                hitInfo.point    = hit.point;
                hitInfo.normal   = hit.normal;
                hitInfo.collider = hit.collider;

                // Check if gameobject is a dynamic voxel
                if (hit.collider != null)
                {
                    if ((colliderTypes & ColliderTypes.IgnorePlayer) != 0 && characterController != null && characterController.name.Equals(hit.collider.name))
                    {
                        return(false);
                    }
                    hitInfo.voxelIndex = -1;
                    VoxelPlaceholder placeholder = hit.collider.GetComponentInParent <VoxelPlaceholder> ();
                    if (placeholder != null)
                    {
                        hitInfo.chunk       = placeholder.chunk;
                        hitInfo.voxelIndex  = placeholder.voxelIndex;
                        hitInfo.voxel       = placeholder.chunk.voxels [placeholder.voxelIndex];
                        hitInfo.voxelCenter = placeholder.transform.position;
                        hitInfo.placeholder = placeholder;
                    }
                }
                return(true);
            }
            else
            {
                return(voxelHit);
            }
        }
예제 #4
0
        /// <summary>
        /// Adds a torch.
        /// </summary>
        GameObject TorchAttachInt(VoxelHitInfo hitInfo, ItemDefinition torchDefinition = null, bool refreshChunks = true)
        {
            // Make sure the voxel exists (has not been removed just before this call) and is solid
            if (hitInfo.chunk.voxels [hitInfo.voxelIndex].hasContent != 1 || hitInfo.chunk.voxels [hitInfo.voxelIndex].opaque < FULL_OPAQUE)
            {
                return(null);
            }

            // Placeholder for attaching the torch
            VoxelPlaceholder placeHolder = GetVoxelPlaceholder(hitInfo.chunk, hitInfo.voxelIndex, true);

            if (placeHolder == null)
            {
                return(null);
            }

            // Position of the voxel containing the "light" of the torch
            Vector3 voxelLightPosition = hitInfo.voxelCenter + hitInfo.normal;

            VoxelChunk chunk;
            int        voxelIndex;

            if (!GetVoxelIndex(voxelLightPosition, out chunk, out voxelIndex))
            {
                return(null);
            }

            //  Make sure it's empty where the light gameobject will be placed
            if (chunk.voxels[voxelIndex].opaque >= 2)
            {
                return(null);
            }

            // Updates current chunk
            if (chunk.lightSources != null)
            {
                foreach (var x in chunk.lightSources)
                {
                    if (x.voxelIndex == voxelIndex)
                    {
                        // Restriction 2: no second torch on the same voxel index
                        return(null);
                    }
                }
            }

            if (torchDefinition == null)
            {
                // Get an inventory item with name Torch
                int itemCount = allItems.Count;
                for (int k = 0; k < itemCount; k++)
                {
                    if (allItems [k].item.category == ItemCategory.Torch)
                    {
                        torchDefinition = allItems [k].item;
                        break;
                    }
                }
            }
            if (torchDefinition == null)
            {
                return(null);
            }

            // Instantiate torch prefab
            GameObject torch = Instantiate <GameObject> (torchDefinition.prefab);

            torch.name = TORCH_NAME;

            // Parent the torch gameobject to the voxel placeholder
            torch.transform.SetParent(placeHolder.transform, false);

            // Position torch on the wall
            torch.transform.position = hitInfo.chunk.transform.position + GetVoxelChunkPosition(hitInfo.voxelIndex) + hitInfo.normal * 0.5f;

            // Rotate torch according to wall normal
            if (hitInfo.normal.y == -1)               // downwards
            {
                torch.transform.Rotate(180f, 0, 0);
            }
            else if (hitInfo.normal.y == 0)                 // side wall
            {
                torch.transform.Rotate(hitInfo.normal.z * 40f, 0, hitInfo.normal.x * -40f);
            }

            Item itemInfo = torch.AddComponent <Item> ();

            itemInfo.itemDefinition    = torchDefinition;
            itemInfo.canPickOnApproach = false;
            itemInfo.canBeDestroyed    = true;
            itemInfo.itemChunk         = hitInfo.chunk;
            itemInfo.itemVoxelIndex    = hitInfo.voxelIndex;

            // Add light source to chunk
            LightSource lightSource = new LightSource();

            lightSource.gameObject     = torch;
            lightSource.voxelIndex     = voxelIndex;
            lightSource.itemDefinition = torchDefinition;
            lightSource.hitInfo        = hitInfo;
            lightSource.lightIntensity = torchDefinition.lightIntensity;
            chunk.AddLightSource(lightSource);
            chunk.modified = true;

            // Add script to remove light source from chunk when torch or voxel is destroyed
            LightSourceRemoval sr = torch.AddComponent <LightSourceRemoval> ();

            sr.env   = this;
            sr.chunk = chunk;

            Light pointLight = torch.GetComponentInChildren <Light> ();

            if (pointLight != null)
            {
                pointLight.enabled = true;
            }

            // Make torch collider ignore player's collider to avoid collisions
            if (characterControllerCollider != null)
            {
                Physics.IgnoreCollision(torch.GetComponent <Collider> (), characterControllerCollider);
            }

            // Recompute lightmap
            if (refreshChunks)
            {
                UpdateChunkRR(chunk);
            }

            // Trigger torch event
            if (!isLoadingGame && OnTorchAttached != null)
            {
                OnTorchAttached(chunk, lightSource);
            }

            return(torch);
        }
예제 #5
0
        void WriteChunkData_10(BinaryWriter bw, VoxelChunk chunk)
        {
            // Chunk position
            EncodeVector3Binary(bw, chunk.position);
            bw.Write(chunk.isAboveSurface ? (byte)1 : (byte)0);

            int             voxelDefinitionIndex = 0;
            VoxelDefinition prevVD = null;


            // Count voxels words
            int k        = 0;
            int numWords = 0;

            while (k < chunk.voxels.Length)
            {
                if (chunk.voxels [k].hasContent == 1)
                {
                    VoxelDefinition voxelDefinition = chunk.voxels [k].type;
                    if (voxelDefinition.isDynamic)
                    {
                        k++;
                        continue;
                    }
                    if (voxelDefinition != prevVD)
                    {
                        if (!saveVoxelDefinitionsDict.TryGetValue(voxelDefinition, out voxelDefinitionIndex))
                        {
                            k++;
                            continue;
                        }
                        prevVD = voxelDefinition;
                    }
                    Color32 tintColor = chunk.voxels [k].color;
                    int     flags     = 0;
                    if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                    {
                        flags = chunk.voxels [k].GetFlags();
                    }
                    k++;
                    while (k < chunk.voxels.Length && chunk.voxels [k].type == voxelDefinition && chunk.voxels [k].color.r == tintColor.r && chunk.voxels [k].color.g == tintColor.g && chunk.voxels [k].color.b == tintColor.b && voxelDefinition.renderType != RenderType.Custom && chunk.voxels [k].GetFlags() == flags)
                    {
                        k++;
                    }
                    numWords++;
                }
                else
                {
                    k++;
                }
            }
            bw.Write((Int16)numWords);

            // Write voxels
            k = 0;
            while (k < chunk.voxels.Length)
            {
                if (chunk.voxels [k].hasContent == 1)
                {
                    int             voxelIndex      = k;
                    VoxelDefinition voxelDefinition = chunk.voxels [k].type;
                    if (voxelDefinition.isDynamic)
                    {
                        k++;
                        continue;
                    }
                    if (voxelDefinition != prevVD)
                    {
                        if (!saveVoxelDefinitionsDict.TryGetValue(voxelDefinition, out voxelDefinitionIndex))
                        {
                            k++;
                            continue;
                        }
                        prevVD = voxelDefinition;
                    }
                    Color32 tintColor = chunk.voxels [k].color;
                    byte    flags     = 0;
                    if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                    {
                        flags = chunk.voxels [k].GetFlags();
                    }
                    int repetitions = 1;
                    k++;
                    while (k < chunk.voxels.Length && chunk.voxels [k].type == voxelDefinition && chunk.voxels [k].color.r == tintColor.r && chunk.voxels [k].color.g == tintColor.g && chunk.voxels [k].color.b == tintColor.b && voxelDefinition.renderType != RenderType.Custom && chunk.voxels [k].GetFlags() == flags)
                    {
                        repetitions++;
                        k++;
                    }
                    bw.Write((Int16)voxelDefinitionIndex);
                    bw.Write(tintColor.r);
                    bw.Write(tintColor.g);
                    bw.Write(tintColor.b);
                    bw.Write((Int16)voxelIndex);
                    bw.Write((Int16)repetitions);
                    bw.Write(flags);
                    if (voxelDefinition.renderType == RenderType.Custom)
                    {
                        // Check rotation
                        VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, voxelIndex, false);
                        if (placeholder != null)
                        {
                            Vector3 angles = placeholder.transform.eulerAngles;
                            if (angles.x != 0 || angles.y != 0 || angles.z != 0)
                            {
                                bw.Write((byte)1);  // has rotation
                                EncodeVector3Binary(bw, angles);
                            }
                            else
                            {
                                bw.Write((byte)0);
                            }
                        }
                        else
                        {
                            bw.Write((byte)0);
                        }
                    }
                    else
                    {
                        bw.Write((byte)0);
                    }
                }
                else
                {
                    k++;
                }
            }

            // Write number of light sources
            int lightCount = chunk.lightSources != null ? chunk.lightSources.Count : 0;

            bw.Write((Int16)lightCount);
            if (lightCount > 0)
            {
                for (k = 0; k < lightCount; k++)
                {
                    LightSource    lightSource = chunk.lightSources [k];
                    int            voxelIndex  = lightSource.hitInfo.voxelIndex;
                    Vector3        normal      = lightSource.hitInfo.normal;
                    int            itemIndex   = 0;
                    ItemDefinition id          = lightSource.itemDefinition;
                    if (id != null)
                    {
                        saveItemDefinitionsDict.TryGetValue(id, out itemIndex);
                    }
                    bw.Write((Int16)voxelIndex);
                    EncodeVector3Binary(bw, normal);
                    bw.Write((Int16)itemIndex);
                }
            }

            // Write number of items
            int itemCount = chunk.items != null ? chunk.items.count : 0;

            bw.Write((Int16)itemCount);
            if (itemCount > 0)
            {
                for (k = 0; k < itemCount; k++)
                {
                    Int16   itemIndex    = 0;
                    Int16   itemQuantity = 0;
                    Vector3 itemPosition = Misc.vector3zero;
                    Item    item         = chunk.items.values [k];
                    if (item != null && item.itemDefinition != null)
                    {
                        ItemDefinition id = item.itemDefinition;
                        int            idIndex;
                        if (saveItemDefinitionsDict.TryGetValue(id, out idIndex))
                        {
                            itemIndex    = ((Int16)idIndex);
                            itemPosition = item.transform.position;
                            bw.Write((Int16)item.quantity);
                        }
                    }
                    bw.Write(itemIndex);
                    EncodeVector3Binary(bw, itemPosition);
                    bw.Write(itemQuantity);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Clears chunk state before returning it to the pool. This method is called when this chunk is reused.
        /// </summary>
        public void PrepareForReuse(byte light)
        {
            isAboveSurface         = false;
            needsMeshRebuild       = false;
            isPopulated            = false;
            inqueue                = false;
            modified               = false;
            renderState            = ChunkRenderState.Pending;
            allowTrees             = true;
            lightmapSignature      = -1;
            frustumCheckIteration  = 0;
            navMesh                = null;
            navMeshSourceIndex     = -1;
            inconclusiveNeighbours = 0;
            renderingFrame         = -1;

            if (lightSources != null)
            {
                lightSources.Clear();
            }

            if (placeholders != null)
            {
                int count = placeholders.Count;
                for (int k = 0; k < count; k++)
                {
                    VoxelPlaceholder placeholder = placeholders [k];
                    if (placeholder != null && placeholder.gameObject != null)
                    {
                        DestroyImmediate(placeholder.gameObject);
                    }
                }
                placeholders.Clear();
            }

            if (items != null)
            {
                for (int k = 0; k < items.count; k++)
                {
                    Item item = items.values [k];
                    if (item != null && item.gameObject != null)
                    {
                        DestroyImmediate(item.gameObject);
                    }
                }
                items.Clear();
            }


            if (_left != null)
            {
                _left.right = null;
                _left       = null;
            }
            if (_right != null)
            {
                _right.left = null;
                _right      = null;
            }
            if (_forward != null)
            {
                _forward.back = null;
                _forward      = null;
            }
            if (_back != null)
            {
                _back.forward = null;
                _back         = null;
            }
            if (_top != null)
            {
                _top.bottom = null;
                _top        = null;
            }
            if (_bottom != null)
            {
                _bottom.top = null;
                _bottom     = null;
            }
            ClearVoxels(light);
            mr.enabled = false;
        }
        /// <summary>
        /// Performs the voxel damage.
        /// </summary>
        /// <returns>The actual damage taken by the voxe.</returns>
        /// <param name="hitInfo">Hit info.</param>
        /// <param name="damage">Damage.</param>
        /// <param name="addParticles">If set to <c>true</c> add particles.</param>
        int DamageVoxelFast(ref VoxelHitInfo hitInfo, int damage, bool addParticles, bool playSound, bool allowDamageEvent = true)
        {
            VoxelChunk chunk = hitInfo.chunk;

            if (hitInfo.voxel.typeIndex == 0)
            {
                return(0);
            }
            VoxelDefinition voxelType = hitInfo.voxel.type;
            byte            voxelTypeResistancePoints = voxelType.resistancePoints;

            if (buildMode)
            {
                if (damage > 0)
                {
                    damage = 255;
                }
            }
            else
            {
                if (voxelTypeResistancePoints == (byte)0)
                {
                    damage = 0;
                }
                else if (voxelTypeResistancePoints == (byte)255)
                {
                    if (playSound)
                    {
                        PlayImpactSound(hitInfo.voxel.type.impactSound, hitInfo.voxelCenter);
                    }
                    damage = 0;
                }
            }

            if (allowDamageEvent && OnVoxelDamaged != null)
            {
                OnVoxelDamaged(chunk, hitInfo.voxelIndex, ref damage);
            }

            if (damage == 0)
            {
                return(0);
            }

            // Gets ambient light near surface
            float voxelLight = GetVoxelLight(hitInfo.point + hitInfo.normal * 0.5f);

            // Get voxel damage indicator GO's name
            bool             destroyed            = voxelType.renderType == RenderType.CutoutCross;
            int              resistancePointsLeft = 0;
            VoxelPlaceholder placeholder          = null;

            if (!destroyed)
            {
                placeholder          = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                resistancePointsLeft = placeholder.resistancePointsLeft - damage;
                if (resistancePointsLeft < 0)
                {
                    resistancePointsLeft = 0;
                    destroyed            = true;
                }
                placeholder.resistancePointsLeft = resistancePointsLeft;
            }

            if (voxelType.renderType == RenderType.Empty)
            {
                addParticles = false;
            }

            int particlesAmount;

            if (destroyed)
            {
                // Add recoverable voxel on the scene (not for vegetation)
                if (voxelType.renderType != RenderType.Empty && voxelType.renderType != RenderType.CutoutCross && voxelType.canBeCollected && !buildMode)
                {
                    bool create = true;

                    if (OnVoxelBeforeDropItem != null)
                    {
                        OnVoxelBeforeDropItem(chunk, hitInfo, out create);
                    }
                    if (create)
                    {
                        CreateRecoverableVoxel(hitInfo.voxelCenter, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                    }
                }

                // Destroy the voxel
                VoxelDestroyFast(chunk, hitInfo.voxelIndex);

                // Check if grass is on top and remove it as well
                VoxelChunk topChunk;
                int        topIndex;
                if (GetVoxelIndex(hitInfo.voxelCenter + Misc.vector3up, out topChunk, out topIndex, false))
                {
                    if (topChunk.voxels [topIndex].typeIndex != 0 && voxelDefinitions [topChunk.voxels [topIndex].typeIndex].renderType == RenderType.CutoutCross)
                    {
                        byte light = topChunk.voxels [topIndex].lightMesh;
                        topChunk.voxels [topIndex].Clear(light);
                        topChunk.modified = true;
                    }
                }

                // Max particles
                particlesAmount = 20;

                if (playSound)
                {
                    PlayDestructionSound(voxelDefinitions [hitInfo.voxel.typeIndex].destructionSound, hitInfo.voxelCenter);
                }
            }
            else
            {
                // Add damage indicator
                if (placeholder == null)
                {
                    placeholder = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                }
                if (placeholder.damageIndicator == null)
                {
                    if (damagedVoxelPrefab == null)
                    {
                        damagedVoxelPrefab = Resources.Load <GameObject> ("VoxelPlay/Prefabs/DamagedVoxel");
                    }
                    GameObject g = Instantiate <GameObject> (damagedVoxelPrefab);
                    g.name = DAMAGE_INDICATOR;
                    Transform tDamageIndicator = g.transform;
                    placeholder.damageIndicator = tDamageIndicator.GetComponent <Renderer> ();
                    tDamageIndicator.SetParent(placeholder.transform, false);
                    tDamageIndicator.localPosition = placeholder.bounds.center;
                    tDamageIndicator.localScale    = placeholder.bounds.size * 1.001f;
                }

                int textureIndex = FastMath.FloorToInt((5f * resistancePointsLeft) / voxelTypeResistancePoints);
                if (world.voxelDamageTextures.Length > 0)
                {
                    if (textureIndex >= world.voxelDamageTextures.Length)
                    {
                        textureIndex = world.voxelDamageTextures.Length - 1;
                    }
                    Material mi = placeholder.damageIndicatorMaterial;                     // gets a copy of material the first time it's used
                    mi.mainTexture = world.voxelDamageTextures [textureIndex];
                    mi.SetFloat("_VoxelLight", voxelLight);
                    placeholder.damageIndicator.enabled = true;
                }

                // Particle amount depending of damage
                particlesAmount = (6 - textureIndex) + 3;

                // Sets health recovery for the voxel
                placeholder.StartHealthRecovery(chunk, hitInfo.voxelIndex, world.damageDuration);

                if (playSound)
                {
                    PlayImpactSound(voxelDefinitions [hitInfo.voxel.typeIndex].impactSound, hitInfo.voxelCenter);
                }
            }

            // Add random particles
            if (!addParticles)
            {
                particlesAmount = 0;
            }
            for (int k = 0; k < particlesAmount; k++)
            {
                int ppeIndex = GetParticleFromPool();
                if (ppeIndex < 0)
                {
                    continue;
                }

                // Scale of particle
                Renderer particleRenderer = particlePool [ppeIndex].renderer;
                if (destroyed)
                {
                    if (voxelType.renderType == RenderType.CutoutCross)                         // smaller particles for vegetation
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.04f);
                    }
                    else
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.04f, 0.1f);
                    }
                }
                else
                {
                    particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.06f);
                }

                // Set particle texture
                Material instanceMat = particleRenderer.sharedMaterial;
                SetParticleMaterialTextures(instanceMat, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                instanceMat.mainTextureOffset = new Vector2(Random.value, Random.value);
                instanceMat.mainTextureScale  = Misc.vector2one * 0.05f;
                instanceMat.SetFloat("_VoxelLight", voxelLight);
                instanceMat.SetFloat("_FlashDelay", 0);

                // Set position
                Rigidbody rb = particlePool [ppeIndex].rigidBody;
                if (destroyed)
                {
                    Vector3 expelDir = Random.insideUnitSphere;
                    Vector3 pos      = hitInfo.voxelCenter + expelDir;
                    particleRenderer.transform.position = pos;
                    rb.AddForce(expelDir * (Random.value * 125f));
                }
                else
                {
                    Vector3 pos = hitInfo.point;
                    Vector3 v1  = new Vector3(-hitInfo.normal.y, hitInfo.normal.z, hitInfo.normal.x);
                    Vector3 v2  = new Vector3(-hitInfo.normal.z, hitInfo.normal.x, hitInfo.normal.y);
                    Vector3 dx  = (Random.value - 0.5f) * 0.7f * v1;
                    Vector3 dy  = (Random.value - 0.5f) * 0.7f * v2;
                    particleRenderer.transform.position = pos + hitInfo.normal * 0.001f + dx + dy;
                    rb.AddForce(cameraMain.transform.forward * (Random.value * -125f));
                }
                rb.AddForce(Misc.vector3up * 25f);
                rb.AddTorque(Random.onUnitSphere * 100f);
                rb.useGravity = true;

                // Self-destruct
                particlePool [ppeIndex].destructionTime = Time.time + 2.5f + Random.value;
            }

            return(damage);
        }
        /// <summary>
        /// Converts a voxel into dynamic type
        /// </summary>
        /// <param name="chunk">Chunk.</param>
        /// <param name="voxelIndex">Voxel index.</param>
        GameObject VoxelSetDynamic(VoxelChunk chunk, int voxelIndex, bool addRigidbody, float duration)
        {
            if (chunk == null || chunk.voxels [voxelIndex].hasContent == 0)
            {
                return(null);
            }

            VoxelDefinition vd = voxelDefinitions [chunk.voxels [voxelIndex].typeIndex];

            if (!vd.renderType.supportsDynamic())
            {
                return(null);
            }

            VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, voxelIndex, true);

            if (placeholder == null)
            {
                return(null);
            }

            // Add rigid body
            if (addRigidbody)
            {
                Rigidbody rb = placeholder.GetComponent <Rigidbody> ();
                if (rb == null)
                {
                    placeholder.rb = placeholder.gameObject.AddComponent <Rigidbody> ();
                }
            }

            // If it's a custom model ignore it as it's already a gameobject
            if (placeholder.modelMeshFilter != null)
            {
                return(placeholder.gameObject);
            }

            VoxelDefinition vdDyn = vd.dynamicDefinition;

            if (vdDyn == null)
            {
                // Setup and save voxel definition
                vd.dynamicDefinition         = vdDyn = ScriptableObject.CreateInstance <VoxelDefinition> ();
                vdDyn.isDynamic              = true;
                vdDyn.doNotSave              = true;
                vdDyn.staticDefinition       = vd;
                vdDyn.renderType             = RenderType.Custom;
                vdDyn.textureIndexBottom     = vd.textureIndexBottom;
                vdDyn.textureIndexSide       = vd.textureIndexSide;
                vdDyn.textureIndexTop        = vd.textureIndexTop;
                vdDyn.textureThumbnailTop    = vd.textureThumbnailTop;
                vdDyn.textureThumbnailSide   = vd.textureThumbnailSide;
                vdDyn.textureThumbnailBottom = vd.textureThumbnailBottom;
                vdDyn.scale             = vd.scale;
                vdDyn.offset            = vd.offset;
                vdDyn.offsetRandomRange = vd.offsetRandomRange;
                vdDyn.rotation          = vd.rotation;
                vdDyn.rotationRandomY   = vd.rotationRandomY;
                vdDyn.sampleColor       = vd.sampleColor;
                vdDyn.promotesTo        = vd.promotesTo;
                vdDyn.playerDamageDelay = vd.playerDamageDelay;
                vdDyn.playerDamage      = vd.playerDamage;
                vdDyn.pickupSound       = vd.pickupSound;
                vdDyn.landingSound      = vd.landingSound;
                vdDyn.jumpSound         = vd.jumpSound;
                vdDyn.impactSound       = vd.impactSound;
                vdDyn.footfalls         = vd.footfalls;
                vdDyn.destructionSound  = vd.destructionSound;
                vdDyn.canBeCollected    = vd.canBeCollected;
                vdDyn.dropItem          = GetItemDefinition(ItemCategory.Voxel, vd);
                vdDyn.buildSound        = vd.buildSound;
                vdDyn.navigatable       = true;
                vdDyn.windAnimation     = false;
                vdDyn.model             = MakeDynamicCubeFromVoxel(chunk, voxelIndex);
                vdDyn.name = vd.name + " (Dynamic)";
                AddVoxelTextures(vdDyn);
            }

            // Clear any vegetation on top if voxel can be moved (has a rigidbody) to avoid floating grass block
            if (placeholder.rb != null)
            {
                VoxelChunk topChunk;
                int        topIndex;
                if (GetVoxelIndex(chunk, voxelIndex, 0, 1, 0, out topChunk, out topIndex))
                {
                    if (topChunk.voxels [topIndex].hasContent == 1 && voxelDefinitions [topChunk.voxels [topIndex].typeIndex].renderType == RenderType.CutoutCross)
                    {
                        VoxelDestroyFast(topChunk, topIndex);
                    }
                }
            }
            Color32 color = chunk.voxels [voxelIndex].color;

            chunk.voxels [voxelIndex].Set(vdDyn, color);

            if (duration > 0)
            {
                placeholder.SetCancelDynamic(duration);
            }

            // Refresh neighbours
            RebuildNeighbours(chunk, voxelIndex);

            return(placeholder.gameObject);
        }
        void RenderModelsInVoxels(VoxelChunk chunk, FastList <ModelInVoxel> mivs)
        {
            instancingManager.ClearChunk(chunk);
            Quaternion rotation = Misc.quaternionZero;
            Vector3    position;

            for (int k = 0; k < mivs.count; k++)
            {
                ModelInVoxel    miv             = mivs.values [k];
                VoxelDefinition voxelDefinition = miv.vd;

                bool createGO = voxelDefinition.createGameObject || !voxelDefinition.gpuInstancing;

                if (createGO)
                {
                    VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, miv.voxelIndex, true);
                    bool             createModel = true;
                    if (placeholder.modelInstance != null)
                    {
                        if (placeholder.modelTemplate != voxelDefinition.model)
                        {
                            DestroyImmediate(placeholder.modelInstance);
                        }
                        else
                        {
                            createModel = false;
                        }
                    }
                    MeshFilter mf;
                    Mesh       mesh = null;

                    if (createModel || placeholder.modelMeshFilter == null || placeholder.modelMeshFilter.sharedMesh == null || placeholder.modelMeshRenderer == null)
                    {
                        if (voxelDefinition.model == null)
                        {
                            continue;
                        }
                        placeholder.modelTemplate      = voxelDefinition.model;
                        placeholder.modelInstance      = Instantiate(voxelDefinition.model);
                        placeholder.modelInstance.name = "DynamicVoxelInstance";
                        // Note: placeHolder.modelInstance layer must be different from layerVoxels to allow dynamic voxels collide with terrain. So don't set its layer to layer voxels
                        placeholder.modelMeshRenderer = placeholder.modelInstance.GetComponent <MeshRenderer> ();
                        if (voxelDefinition.gpuInstancing)
                        {
                            if (placeholder.modelMeshRenderer != null)
                            {
                                placeholder.modelMeshRenderer.enabled = false;
                            }
                        }
                        else
                        {
                            mf = placeholder.modelMeshFilter = placeholder.modelInstance.GetComponent <MeshFilter> ();
                            if (mf != null)
                            {
                                mesh           = mf.sharedMesh = Instantiate <Mesh> (mf.sharedMesh);
                                mesh.hideFlags = HideFlags.DontSave;
                            }
                        }
                    }
                    else
                    {
                        mf = placeholder.modelMeshFilter;
                        if (mf != null)
                        {
                            mesh = mf.sharedMesh;
                        }
                    }

                    // Parent model to the placeholder
                    Transform tModel = placeholder.modelInstance.transform;
                    tModel.SetParent(placeholder.transform, false);
                    tModel.transform.localPosition = Misc.vector3zero;
                    tModel.transform.localScale    = voxelDefinition.scale;

                    if (voxelDefinition.gpuInstancing)
                    {
                        rotation = placeholder.transform.localRotation;
                    }
                    else
                    {
                        // Adjust lighting
                        if (effectiveGlobalIllumination || chunk.voxels [miv.voxelIndex].isColored)
                        {
                            // Update mesh colors
                            float   voxelLight = chunk.voxels [miv.voxelIndex].lightMesh / 15f;
                            Color32 color      = chunk.voxels [miv.voxelIndex].color;
                            color.r = (byte)(color.r * voxelLight);
                            color.g = (byte)(color.g * voxelLight);
                            color.b = (byte)(color.b * voxelLight);
                            modelMeshColors.Clear();
                            for (int c = 0; c < mesh.vertexCount; c++)
                            {
                                modelMeshColors.Add(color);
                            }
                            mesh.SetColors(modelMeshColors);
                            mesh.UploadMeshData(false);
                        }
                    }
                    if (!tModel.gameObject.activeSelf)
                    {
                        tModel.gameObject.SetActive(true);
                    }
                    position = placeholder.transform.position;
                }
                else
                {
                    // pure gpu instancing, no gameobject

                    position = GetVoxelPosition(chunk, miv.voxelIndex);

                    rotation = voxelDefinition.GetRotation(position);                      // deterministic rotation
                    // User rotation
                    float rot = chunk.voxels [miv.voxelIndex].GetTextureRotationDegrees();
                    if (rot != 0)
                    {
                        rotation *= Quaternion.Euler(0, rot, 0);
                    }

                    // Custom position
                    position = position + rotation * voxelDefinition.GetOffset(position);
                }

                if (voxelDefinition.gpuInstancing)
                {
                    instancingManager.AddVoxel(chunk, miv.voxelIndex, position, rotation, voxelDefinition.scale);
                }
            }
        }
예제 #10
0
        void RenderModelsInVoxels(VoxelChunk chunk, FastList <ModelInVoxel> mivs)
        {
            instancedRenderer.ClearChunk(chunk);

            // deactivate all models in this chunk
            // we need to iterate the placeholders list entirely to address the case when the voxel is not using GPU instancing. In this case the gameobject renderer needs to be disabled
            // and we need to do this way because mivs won't contain the custom voxel since it may be termporarily converted to a transparent voxels due to see-through effect
            if (chunk.placeholders != null)
            {
                int count = chunk.placeholders.Count;
                for (int k = 0; k < count; k++)
                {
                    if (chunk.placeholders.entries [k].key >= 0)
                    {
                        VoxelPlaceholder placeHolder = chunk.placeholders.entries [k].value;
                        if (placeHolder != null)
                        {
                            placeHolder.ToggleRenderers(false);
                        }
                    }
                }
            }

            Quaternion rotation = Misc.quaternionZero;
            Vector3    position;

            for (int k = 0; k < mivs.count; k++)
            {
                ModelInVoxel    miv             = mivs.values [k];
                VoxelDefinition voxelDefinition = miv.vd;

                bool createGO = voxelDefinition.createGameObject || !voxelDefinition.gpuInstancing;

                if (VoxelIsHidden(chunk, miv.voxelIndex))
                {
                    continue;
                }

                if (createGO)
                {
                    VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, miv.voxelIndex, true);
                    bool             createModel = true;
                    if (placeholder.modelInstance != null)
                    {
                        if (placeholder.modelTemplate != voxelDefinition.prefab)
                        {
                            DestroyImmediate(placeholder.modelInstance);
                            placeholder.originalMeshColors32 = null;
                            placeholder.lastMivTintColor     = Misc.color32White;
                        }
                        else
                        {
                            createModel = false;
                        }
                    }

                    if (createModel || placeholder.modelInstance == null)
                    {
                        if (voxelDefinition.prefab == null)
                        {
                            continue;
                        }
                        placeholder.modelTemplate      = voxelDefinition.prefab;
                        placeholder.modelInstance      = Instantiate(voxelDefinition.prefab);
                        placeholder.modelInstance.name = "DynamicVoxelInstance";
                        // Note: placeHolder.modelInstance layer must be different from layerVoxels to allow dynamic voxels collide with terrain. So don't set its layer to layer voxels
                        placeholder.modelMeshRenderers = placeholder.modelInstance.GetComponentsInChildren <MeshRenderer> ();
                        if (voxelDefinition.gpuInstancing)
                        {
                            placeholder.ToggleRenderers(false);
                        }
                        else
                        {
                            placeholder.modelMeshFilter = placeholder.modelInstance.GetComponentInChildren <MeshFilter> (true);
                        }

                        // Parent model to the placeholder
                        Transform tModel = placeholder.modelInstance.transform;
                        tModel.SetParent(placeholder.transform, false);
                        tModel.transform.localPosition = Misc.vector3zero;
                        tModel.transform.localScale    = voxelDefinition.scale;
                    }
                    else
                    {
                        placeholder.ToggleRenderers(true);
                    }

                    if (voxelDefinition.gpuInstancing)
                    {
                        rotation = placeholder.transform.localRotation;
                    }
                    else
                    {
                        // Adjust lighting
                        if (effectiveGlobalIllumination || chunk.voxels [miv.voxelIndex].isColored)
                        {
                            // Update mesh colors
                            MeshFilter mf = placeholder.modelMeshFilter;
                            if (mf != null)
                            {
                                Mesh mesh = mf.sharedMesh;
                                if (mesh != null)
                                {
                                    Color32 tintColor = chunk.voxels [miv.voxelIndex].color;
                                    tintColor.a = (byte)(chunk.voxels[miv.voxelIndex].lightMesh + (chunk.voxels[miv.voxelIndex].torchLight << 4));
                                    if (placeholder.lastMivTintColor.a != tintColor.a || placeholder.lastMivTintColor.r != tintColor.r || placeholder.lastMivTintColor.g != tintColor.g || placeholder.lastMivTintColor.b != tintColor.b)
                                    {
                                        mf.sharedMesh = BakeMeshLighting(mf, tintColor);
                                        placeholder.lastMivTintColor = tintColor;
                                    }
                                }
                            }
                        }
                    }
                    if (!placeholder.modelInstance.gameObject.activeSelf)
                    {
                        placeholder.modelInstance.gameObject.SetActive(true);
                    }
                    position = placeholder.transform.position;
                }
                else
                {
                    // pure gpu instancing, no gameobject

                    position = GetVoxelPosition(chunk, miv.voxelIndex);

                    rotation = voxelDefinition.GetRotation(position);  // deterministic rotation
                                                                       // User rotation
                    float rot = chunk.voxels [miv.voxelIndex].GetTextureRotationDegrees();
                    if (rot != 0)
                    {
                        rotation *= Quaternion.Euler(0, rot, 0);
                    }

                    // Custom position
                    position += rotation * voxelDefinition.GetOffset(position);
                }

                if (voxelDefinition.gpuInstancing)
                {
                    instancedRenderer.AddVoxel(chunk, miv.voxelIndex, position, rotation, voxelDefinition.scale);
                }
            }
        }