И снова дыры в террейне

Speed Tree : Terrain & Trees.

И снова дыры в террейне

Сообщение netner 17 фев 2012, 19:05

Наткнулся на забавное решение данной темы. Особенность скрипта в создании меш-"маски" для дыры на основе имеющегося тиррейна. Разобрал скрипт, все должно работать, однако не работает.
Источник: http://www.smokymonkeys.com/kyrill/index.asp?direct=22

Синтаксис:
Используется javascript
var sizeX:int = 2;
var sizeY:int = 2;
var terrain:Terrain;

private var myRenderer:Renderer;
private var mf:MeshFilter;

function Start() {
    makePoly(false);
   
    myRenderer = renderer;
    if (!myRenderer) {
        myRenderer = gameObject.AddComponent(MeshRenderer);
        myRenderer.hideFlags = HideFlags.HideAndDontSave;
    }
    mf = GetComponent(MeshFilter);
}


function OnDrawGizmosSelected() {
    makePoly(true);
}


private var verts:Array = new Array();
private var uvs:Array = new Array();
private var inds:Array = new Array();
private var nmls:Array = new Array();
private function makePoly(isEdit_:boolean) {
    if (!terrain) {return;}

    var w:int = terrain.terrainData.heightmapWidth;
    var h:int = terrain.terrainData.heightmapHeight;
    var meshScale:Vector3 = terrain.terrainData.size;
   
    var tData = terrain.terrainData.GetHeights(0, 0, w, h);
    meshScale = Vector3(meshScale.x/(w-1), meshScale.y, meshScale.z/(h-1));
   
    var stX:int = Mathf.Floor(transform.position.z /meshScale.z);
    var stY:int = Mathf.Floor(transform.position.x /meshScale.x);

    var vCountW:int = sizeX +1;
    var vCountH:int = sizeY +1;
   
    var ii:int = 0;
    var xi:int = 0;
    var yi:int = 0;
    verts.Clear();
    uvs.Clear();
    inds.Clear();
    nmls.Clear();
    for (var y:int = stY; y < stY +vCountH; y++) {
        for (var x:int = stX; x < stX +vCountW; x++) {
            verts.Add(Vector3.Scale(meshScale, Vector3(y, tData[x,y], x)) -transform.position);
            uvs.Add(Vector2(1.0 /(vCountW -1) *xi, 1.0 /(vCountH -1) *yi));
            nmls.Add(terrain.terrainData.GetInterpolatedNormal(x/(w -0.0), y/(h -0.0)));
            if ((x < stX +vCountW -1) && (y < stY +vCountH -1)) {
                inds.Add(ii);
                inds.Add(ii +1);
                inds.Add(ii +1 +vCountW);
                inds.Add(ii);
                inds.Add(ii +1 +vCountW);
                inds.Add(ii +vCountW);
            }
            ii++;
            xi++;
        }
        yi++;
        xi = 0;
    }

    if (!isEdit_) {
        if (!mf) {
            mf = gameObject.AddComponent(MeshFilter);
            mf.hideFlags = HideFlags.HideAndDontSave;
        }

        mf.mesh.Clear();
        mf.mesh.vertices = verts.ToBuiltin(Vector3);
        mf.mesh.uv = uvs.ToBuiltin(Vector2);
        mf.mesh.normals = nmls.ToBuiltin(Vector3);
        mf.mesh.triangles = inds.ToBuiltin(int);
    } else {
        for (var i:int = 0; i < inds.length; i += 3) {
            Gizmos.color = Color(1.0, 0.7, 0.0, 0.5);
            Gizmos.DrawLine(verts[inds[i]] +transform.position, verts[inds[i+1]] +transform.position);
            Gizmos.DrawLine(verts[inds[i+1]] +transform.position, verts[inds[i+2]] +transform.position);
            Gizmos.DrawLine(verts[inds[i+2]] +transform.position, verts[inds[i]] +transform.position);
        }
    }
}


По каким-то причинам массив tData постоянно вываливается в out of range. Обращение к массиву tData заменил на terrain.terrainData.GetHeight(x,y), скрипт заработал, но значение по Y в 2000 раз превысило фактическое. Добавил в рассчет Scale деление для Y на 2000, над терейном появилась сеточка маски, но она зависла на высоте 1450,955 и не меняет ее независимо от рельефа ландшафта. Такое ощущение что функции TerrainData.GetHeights и TerrainData.GetHeight не "чуствуют" террейн.
Я вполне допускаю что я что-то проглядел, но после 2х суток втыкания в скрипт так ни к чему и не пришел. Может кто подсказать, в чем тут проблема?
Последний раз редактировалось netner 18 фев 2012, 19:47, всего редактировалось 1 раз.
netner
UNец
 
Сообщения: 14
Зарегистрирован: 10 июн 2009, 21:00

Re: И снова дыры в террейне

Сообщение netner 18 фев 2012, 19:46

Все, разобрался - оказалось скрипт рассчитан на работу с тиррейнами находящимися в позиции 0,0,0. Внес корректировки координат на основе положения тиррейна - заработало.

Правда теперь проблема со вторым скриптом, который должен скрывать фрагмент тиррейна, он не видит созданный первым скриптом меш. Когда камера наводится на объект, должна срабатывать функция OnWillRenderObject, но этого не происходит. Пробовал в ручную задать материал объекту, функция срабатывает в режиме редактирования, но в режиме воспроизведения не работает. Пробовал привязать второй скрипт к стандартному объекту plane - все отлично работает. Никто не сталкивался с похожей проблемой?

Код второго скрипта:
Синтаксис:
Используется javascript
@script ExecuteInEditMode

var disablePixelLights:boolean = true;
var textureSize:int = 1024;
var renderingLayers:LayerMask = ~20;

private var camCount:int = 0;
private var isVisible:boolean = true;

private var filteredCameras:Hashtable = new Hashtable();
private var layerFilterTexture:RenderTexture = null;
private var oldLayerFilterTextureSize:int = 0;
private var myRenderer:Renderer;
private var myTransform:Transform;
private var shaderMat:Material;


private var renderProjectionShaderStr:String =
    "Shader \"FX/Render Projector\" {" +
    " Properties {" +
    "  _MainTex (\"Texture\", 2D) = \"white\" { TexGen ObjectLinear }" +
    " }" +
    " Subshader {" +
    "  Pass {" +
    "   Tags { \"Queue\" = \"Geometry+10\" }" +
    "   Offset -32,-32" +
    "   Cull Back" +
   
    "   SetTexture[_MainTex] {" +
    "    matrix[_ProjMatrix] combine texture" +
    "   }" +
    "  }" +
    " }" +
    "}";


function Awake() {
    myTransform = transform;
}

function Start() {
    if (renderer) {
        renderer.castShadows = false;
        renderer.receiveShadows = false;
    }

}

function OnBecameVisible() {
    isVisible = true;
       
}
function OnBecameInvisible() {
    isVisible = false;
}


function OnWillRenderObject() {
    if (!enabled || !renderer || !renderer.enabled || !isVisible) {return;}

    var cam:Camera = Camera.current;
   
    if (!cam) {return;}
   
    var filteringCamera:Camera = CreateCameraObjects(cam);
    var oldPixelLightCount:int = QualitySettings.pixelLightCount;
    if (disablePixelLights) {QualitySettings.pixelLightCount = 0;}
    UpdateCameraModes(cam, filteringCamera);
    filteringCamera.Render();

    if (!shaderMat) {
 
        shaderMat = Material(renderProjectionShaderStr);
        shaderMat.hideFlags = HideFlags.HideAndDontSave;
        shaderMat.mainTexture =  layerFilterTexture;

        Debug.Log(shaderMat.mainTexture);
       
        renderer.castShadows = false;
        renderer.receiveShadows = false;
    }
    shaderMat.SetMatrix("_ProjMatrix", createProjectionMatrix(cam));
    renderer.sharedMaterial  = shaderMat;


    if (disablePixelLights) {
        QualitySettings.pixelLightCount = oldPixelLightCount;
    }      
}

function OnDisable() {
    shaderMat = null;
    if (layerFilterTexture) {
        DestroyImmediate(layerFilterTexture);
        layerFilterTexture = null;
    }
    for (var item in filteredCameras) {
        DestroyImmediate((item.Value as Camera).gameObject);
    }
    filteredCameras.Clear();
}


private function createProjectionMatrix(camera_:Camera):Matrix4x4 {
    var scaleOffset:Matrix4x4 = Matrix4x4.TRS(Vector3(0.5, 0.5, 0.5), Quaternion.identity, Vector3(0.5, 0.5, 0.5));
    var mtx:Matrix4x4 = Matrix4x4.Scale(Vector3(1.0/myTransform.lossyScale.x, 1.0/myTransform.lossyScale.y, 1.0/myTransform.lossyScale.z));
    return scaleOffset * camera_.projectionMatrix *camera_.worldToCameraMatrix *myTransform.localToWorldMatrix * mtx;
}

private function UpdateCameraModes(src:Camera, dest:Camera):void {
    if (dest == null) {return;}

    dest.clearFlags = src.clearFlags;
    dest.backgroundColor = src.backgroundColor;      
    if (src.clearFlags == CameraClearFlags.Skybox) {
        var sky:Skybox = src.GetComponent(Skybox);
        var mysky:Skybox = dest.GetComponent(Skybox);
        if (!sky || !sky.material) {
            mysky.enabled = false;
        } else {
            mysky.enabled = true;
            mysky.material = sky.material;
        }
    }
    dest.farClipPlane = src.farClipPlane;
    dest.nearClipPlane = src.nearClipPlane;
    dest.orthographic = src.orthographic;
    dest.fieldOfView = src.fieldOfView;
    dest.aspect = src.aspect;
    dest.orthographicSize = src.orthographicSize;
   
    dest.worldToCameraMatrix = src.worldToCameraMatrix;
    dest.cullingMask = renderingLayers.value;
    dest.targetTexture = layerFilterTexture;
}


private function CreateCameraObjects(currentCamera:Camera):Camera {
    var filteringCamera:Camera = null;
   
    if (!layerFilterTexture || oldLayerFilterTextureSize != textureSize) {
        if (layerFilterTexture) {DestroyImmediate(layerFilterTexture);}
        layerFilterTexture = RenderTexture(textureSize, textureSize, 16);
        layerFilterTexture.name = "__LayerFilteredTexture" +GetInstanceID();
        layerFilterTexture.isPowerOfTwo = true;
        layerFilterTexture.hideFlags = HideFlags.DontSave;
        oldLayerFilterTextureSize = textureSize;
    }
   
    filteringCamera = filteredCameras[currentCamera] as Camera;
    if (!filteringCamera) {
        var go:GameObject = new GameObject("Layer Filtering Camera id" +GetInstanceID() +" for " +currentCamera.GetInstanceID(), Camera, Skybox);
        filteringCamera = go.camera;
        filteringCamera.enabled = false;
        filteringCamera.transform.position = myTransform.position;
        filteringCamera.transform.rotation = myTransform.rotation;
        filteringCamera.gameObject.AddComponent("FlareLayer");
        go.hideFlags = HideFlags.HideAndDontSave;
        filteredCameras[currentCamera] = filteringCamera;
        camCount++;
    }
    return filteringCamera;
}
netner
UNец
 
Сообщения: 14
Зарегистрирован: 10 июн 2009, 21:00

Re: И снова дыры в террейне

Сообщение waruiyume 18 фев 2012, 22:34

Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: И снова дыры в террейне

Сообщение netner 21 фев 2012, 11:10

Не помогло. :(
Юнити по прежнему не считает объект попавшим в поле зрения камеры.
netner
UNец
 
Сообщения: 14
Зарегистрирован: 10 июн 2009, 21:00

Re: И снова дыры в террейне

Сообщение netner 21 фев 2012, 20:21

Все, разобрался. У обоих проблем была одна причина, скрипт создания меша был рассчитан на террейн размещенный в нулевых координатах. Если кому нужны скрипты после моей редакции пишите. На самом деле довольно простой и удобный способ делать дырки в террейне.
netner
UNец
 
Сообщения: 14
Зарегистрирован: 10 июн 2009, 21:00

Re: И снова дыры в террейне

Сообщение Ingvarson 08 апр 2012, 09:03

если можно,то очень интересно было бы эти скрипты увидеть)))
Аватара пользователя
Ingvarson
UNIт
 
Сообщения: 59
Зарегистрирован: 01 фев 2011, 18:42
Откуда: Россия, Москва

Re: И снова дыры в террейне

Сообщение ThierryH 01 сен 2014, 07:24

netner писал(а):Все, разобрался. У обоих проблем была одна причина, скрипт создания меша был рассчитан на террейн размещенный в нулевых координатах. Если кому нужны скрипты после моей редакции пишите. На самом деле довольно простой и удобный способ делать дырки в террейне.


Добрый день, вот спустя 2года наткнулся на эту тему)
Большая просьба к вам, не могли бы вы скинуть скрипт.
ThierryH
UNец
 
Сообщения: 18
Зарегистрирован: 01 июл 2014, 08:02

Re: И снова дыры в террейне

Сообщение Zodjeks 19 апр 2015, 20:18

netner писал(а):Все, разобрался. У обоих проблем была одна причина, скрипт создания меша был рассчитан на террейн размещенный в нулевых координатах. Если кому нужны скрипты после моей редакции пишите. На самом деле довольно простой и удобный способ делать дырки в террейне.

не могли бы вы педелиться скриптами?
The Underground Get out alive - computer game in the genre of first-person shooter with elements of survival horror.
Zodjeks
UNец
 
Сообщения: 33
Зарегистрирован: 19 апр 2015, 20:11

Re: И снова дыры в террейне

Сообщение HukpoFuJl 24 июл 2015, 20:09

Имя пользователя:netner
Последнее посещение:27 мар 2012, 19:56

Думаю стоит проделать то же что проделал netner самим, т.к. он тут не появляется давно уже... И вообще не понимаю людей, пишущих подобное:
netner писал(а):Если кому нужны скрипты после моей редакции пишите.

Предлагаешь - публикуй сразу... Мало ли когда твой скрипт пригодится =((
HukpoFuJl
UNец
 
Сообщения: 1
Зарегистрирован: 21 июл 2015, 12:39


Вернуться в Земля и деревья.

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1