TubeRenderer

Лучший способ помочь другим, поделиться своими находками.

TubeRenderer

Сообщение Mr_Anderson 11 сен 2009, 15:57

Перевел на шарп TubeRenderer из вики http://www.unifycommunity.com/wiki/inde ... beRenderer (делает ломаную трубу по точкам, здесь пока без оптимизации перерисовки для теста). Работает, но криво... исходник на явескрипт тоже глючит... буду править, если кому интересно, можно довести до ума ;)
Задачки с визуализацией веревок никак не отпускают :)))))

Код: Выделить всё
using UnityEngine;
using System.Collections.Generic;
using System;
using System.Text;
using System.IO;


class TubeRenderer: MonoBehaviour
{
    class TubeVertex
    {
        public Vector3 point = Vector3.zero;
        public float radius = 1.0f;
        public Color color = Color.white;

        public TubeVertex(Vector3 pt, float r, Color c)
        {
            point = pt;
            radius = r;
            color = c;
        }
    }

    TubeVertex[] vertices;
    public Material material;

    int crossSegments = 30;
    private Vector3[] crossPoints;

    /*
    private Vector3 lastCameraPosition1;
    private Vector3 lastCameraPosition2;
    int movePixelsForRebuild = 6;
    float maxRebuildTime = 0.1f;
    private float lastRebuildTime = 0.00f;
    */

    void Reset()
    {
        vertices = new TubeVertex[2];
        vertices[0] = new TubeVertex(Vector3.zero, 1.0f, Color.white);
        vertices[1] = new TubeVertex(new Vector3(1f, 0f, 0f), 1.0f, Color.white);
    }

    void Start()
    {
        this.gameObject.AddComponent("MeshFilter");
        MeshRenderer mr = this.gameObject.AddComponent("MeshRenderer") as MeshRenderer;
        mr.material = material;

        crossPoints = new Vector3[crossSegments];
        float theta = 2.0f * Mathf.PI / crossSegments;
        for (int c = 0; c < crossSegments; c++)
            crossPoints[c] = new Vector3(Mathf.Cos(theta * c), Mathf.Sin(theta * c), 0);

        // начальные точки для ломаной "трубы"
        Vector3[] points = new Vector3[4];
        points[0] = new Vector3(1f, 1f, 1f);
        points[1] = new Vector3(1f, 1f, 10f);
        points[2] = new Vector3(10f, 10f, 10f);
        points[3] = new Vector3(1f, 10f, 10f);
        SetPoints(points, 1f, Color.cyan);
    }

    void Update()
    {
        if ((vertices == null) || (vertices.Length < 2))
        {
            renderer.enabled = false;
            return;
        }
        renderer.enabled = true;
        bool redraw = true; // !!! обновление рендера палюбасу (тест)

        /*
        float distFromMainCam;
        if (vertices.Length > 1)
        {
            Vector3 cur1 = Camera.main.WorldToScreenPoint(vertices[0].point);
            distFromMainCam = lastCameraPosition1.z;
            lastCameraPosition1.z = 0;
            Vector3 cur2 = Camera.main.WorldToScreenPoint(vertices[vertices.Length - 1].point);
            lastCameraPosition2.z = 0;

            float distance = (lastCameraPosition1 - cur1).magnitude;
            distance += (lastCameraPosition2 - cur2).magnitude;

            if (distance > movePixelsForRebuild || Time.time - lastRebuildTime > maxRebuildTime)
            {
                re = true;
                lastCameraPosition1 = cur1;
                lastCameraPosition2 = cur2;
            }
        }
        */

        if (redraw)
        {
            Vector3[] meshVertices = new Vector3[vertices.Length * crossSegments];
            Vector2[] uvs = new Vector2[vertices.Length * crossSegments];
            Color[] colors = new Color[vertices.Length * crossSegments];
            int[] tris = new int[vertices.Length * crossSegments * 6];
            int[] lastVertices = new int[crossSegments];
            int[] theseVertices = new int[crossSegments];
            Quaternion rotation;

            for (int p = 0; p < vertices.Length; p++)
            {
                if (p < vertices.Length - 1)
                    rotation = Quaternion.FromToRotation(Vector3.forward,
                        vertices[p + 1].point - vertices[p].point);

                for (int c = 0; c < crossSegments; c++)
                {
                    int vertexIndex = p * crossSegments + c;
                    meshVertices[vertexIndex] = vertices[p].point +
                        this.transform.rotation * crossPoints[c] * vertices[p].radius;
                    uvs[vertexIndex] = new Vector2((0.0f + c) / crossSegments, (0.0f + p) / vertices.Length);
                    colors[vertexIndex] = vertices[p].color;
                    lastVertices[c] = theseVertices[c];
                    theseVertices[c] = p * crossSegments + c;
                }
                if (p > 0)
                    for (int c = 0; c < crossSegments; c++)
                    {
                        int start = (p * crossSegments + c) * 6;
                        tris[start] = lastVertices[c];
                        tris[start + 1] = lastVertices[(c + 1) % crossSegments];
                        tris[start + 2] = theseVertices[c];
                        tris[start + 3] = tris[start + 2];
                        tris[start + 4] = tris[start + 1];
                        tris[start + 5] = theseVertices[(c + 1) % crossSegments];
                    }
            }

            Mesh mesh = new Mesh();
            mesh.vertices = meshVertices;
            mesh.triangles = tris;
            mesh.RecalculateNormals();
            mesh.uv = uvs;
            MeshFilter mf = this.GetComponent(typeof(MeshFilter)) as MeshFilter;
            mf.mesh = mesh;
        }
    }

    // Задание точек ломаной и ее свойств
    void SetPoints(Vector3[] points, float radius, Color col)
    {
        if (points.Length < 2)
            return;
        vertices = new TubeVertex[points.Length + 2];

        Vector3 v0offset = (points[0] - points[1]) * 0.01f;
        vertices[0] = new TubeVertex(v0offset + points[0], 0.0f, col);
        Vector3 v1offset = (points[points.Length - 1] - points[points.Length - 2]) * 0.01f;
        vertices[vertices.Length - 1] = new TubeVertex(v1offset + points[points.Length - 1], 0.0f, col);

        for (int p = 0; p < points.Length; p++)
            vertices[p + 1] = new TubeVertex(points[p], radius, col);
    }
}
Mr_Anderson
UNIт
 
Сообщения: 143
Зарегистрирован: 16 апр 2009, 13:32

Re: TubeRenderer

Сообщение gnoblin 11 сен 2009, 23:49

спс :-bd
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: TubeRenderer

Сообщение Robotron18 10 сен 2010, 19:32

Вот доведенный до ума TubeRenderer на C#. Тайлинг текстуры веревки чтобы тянулась по любой длине, бамп на текстуру и наконец - VBO не растет. К слову сказать, все равно отстойный метод в случае использования веревок в сцене массово.

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class TubeRenderer : MonoBehaviour
{
    class TubeVertex
    {
        public Vector3 point = Vector3.zero;
        public float radius = 1.0f;
        public Color color = Color.white;

        public TubeVertex(Vector3 pt, float r, Color c)
        {
            point = pt;
            radius = r;
            color = c;
        }
    }

    TubeVertex[] vertices;
    Material material;
    int crossSegments = 8;
    float ropeRadius = 0.03f;    //радиус веревки
    bool useMeshCollision = false;

    Vector3 lastCameraPosition1;
    Vector3 lastCameraPosition2;
    Vector3[] crossPoints;
    int lastCrossSegments;
    Mesh mesh;
    bool colliderExists = false;
    bool usingBumpmap = false;
    Quaternion rotation;
 
    viod Awake()
    {
        mesh = new Mesh();
        gameObject.AddComponent<MeshFilter>();
        MeshRenderer mr = gameObject.AddComponent<MeshRenderer>();
        mr.material = (Material)Resources.Load("maretial");    //накладываем материал на веревку

        if (material && material.GetTexture("_BumpMap"))
            usingBumpmap = true;

        Vector3[] points = new Vector3[2];
        points[0] = new Vector3(0f, 0f, 0f);

        //определяем тайлинг текстуры, чтобы не было растяжек текстуры при любой длине веревки
        renderer.material.mainTextureScale = new Vector2(1, Vector3.Distance(transform.position, endRope.position) * 8);
        SetPoints(points, ropeRadius, Color.white);

    }

    void LateUpdate()
    {
        if (vertices == null || vertices.Length <= 1)
        {
            renderer.enabled = false;
            return;
        }

        renderer.enabled = true;
        if (crossSegments != lastCrossSegments)
        {
            crossPoints = new Vector3[crossSegments];
            float theta = 2.0f * Mathf.PI / crossSegments;
            for (int c = 0; c < crossSegments; c++)
            {
                crossPoints[c] = new Vector3(Mathf.Cos(theta * c), Mathf.Sin(theta * c), 0);
            }
            lastCrossSegments = crossSegments;
        }

        Vector3[] meshVertices = new Vector3[vertices.Length * crossSegments];
        Vector2[] uvs = new Vector2[vertices.Length * crossSegments];
        Color[] colors = new Color[vertices.Length * crossSegments];
        int[] tris = new int[vertices.Length * crossSegments * 6];
        int[] lastVertices = new int[crossSegments];
        int[] theseVertices = new int[crossSegments];

        for (int p = 0; p < vertices.Length; p++)
        {
            if (p < vertices.Length - 1)
                rotation = Quaternion.FromToRotation(Vector3.forward, vertices[p + 1].point - vertices[p].point);

            for (int c = 0; c < crossSegments; c++)
            {
                int vertexIndex = p * crossSegments + c;
                meshVertices[vertexIndex] = vertices[p].point + rotation * crossPoints[c] * vertices[p].radius;
                uvs[vertexIndex] = new Vector2((0.0f + c) / crossSegments, (0.0f + p) / vertices.Length);
                colors[vertexIndex] = vertices[p].color;

                lastVertices[c] = theseVertices[c];
                theseVertices[c] = p * crossSegments + c;
            }

            //make triangles
            if (p > 0)
            {
                for (int c = 0; c < crossSegments; c++)
                {
                    int start = (p * crossSegments + c) * 6;
                    tris[start] = lastVertices[c];
                    tris[start + 1] = lastVertices[(c + 1) % crossSegments];
                    tris[start + 2] = theseVertices[c];
                    tris[start + 3] = tris[start + 2];
                    tris[start + 4] = tris[start + 1];
                    tris[start + 5] = theseVertices[(c + 1) % crossSegments];
                }
            }
        }

        //Clear mesh for new build  (jf)  
        mesh.Clear();
        mesh.vertices = meshVertices;
        mesh.triangles = tris;
        mesh.RecalculateNormals();
        if (usingBumpmap)
            mesh.tangents = CalculateTangents(meshVertices);
        mesh.uv = uvs;

        if (useMeshCollision)
            if (colliderExists)
            {
                gameObject.GetComponent<MeshCollider>().sharedMesh = mesh;
            }
            else
            {
                gameObject.AddComponent<MeshCollider>();
                colliderExists = true;
            }
        GetComponent<MeshFilter>().mesh = mesh;
    }



    Vector4[] CalculateTangents(Vector3[] verts)
    {
        Vector4[] tangents = new Vector4[verts.Length];

        for (int i = 0; i < tangents.Length; i++)
        {
            Vector4 vertex1 = i > 0 ? verts[i - 1] : verts[i];
            Vector4 vertex2 = i < tangents.Length - 1 ? verts[i + 1] : verts[i];
            Vector4 tan = (vertex1 - vertex2).normalized;
            tangents[i] = new Vector4(tan.x, tan.y, tan.z, 1.0f);
        }
        return tangents;
    }



    //sets all the points to points of a Vector3 array, as well as capping the ends.
    void SetPoints(Vector3[] points, float radius, Color col)
    {
        if (points.Length < 2)
            return;
        vertices = new TubeVertex[points.Length + 2];

        Vector3 v0offset = (points[0] - points[1]) * 0.01f;
        vertices[0] = new TubeVertex(v0offset + points[0], 0.0f, col);
        Vector3 v1offset = (points[points.Length - 1] - points[points.Length - 2]) * 0.001f; //здесь затыкаются мешем концы веревки
        vertices[vertices.Length - 1] = new TubeVertex(v1offset + points[points.Length - 1], 0.0f, col);

        for (int p = 0; p < points.Length; p++)
        {
            vertices[p + 1] = new TubeVertex(points[p], radius, col);
        }
    }
}
 
Robotron18
UNец
 
Сообщения: 40
Зарегистрирован: 25 июл 2010, 15:48

Re: TubeRenderer

Сообщение Neodrop 10 сен 2010, 19:46

Настоятельно советую научиться использовать тег syntax. (на первый раз поправил за вас)
А так же, встраивать в ответ плеер с демкой ;)
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: TubeRenderer

Сообщение Robotron18 10 сен 2010, 20:03

Тег понял. На плеер у меня времени нет. У кого вопросы или проблемы с использование скрипта - пишите в личку, отвечу.
Robotron18
UNец
 
Сообщения: 40
Зарегистрирован: 25 июл 2010, 15:48


Вернуться в Исходники (Копилка)

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

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