Рисование графиков

Программирование на Юнити.

Рисование графиков

Сообщение MediaMen 20 янв 2011, 04:36

Как программно нарисовать график функции, с возможностью динамического изменения параметров? 2d, 3d в какую сторону копать? Направьте, подскажите пожалуйста.
Аватара пользователя
MediaMen
UNIт
 
Сообщения: 85
Зарегистрирован: 13 апр 2009, 05:49

Re: Рисование графиков

Сообщение Paul Siberdt 20 янв 2011, 07:57

2D - работа с битмапами, GetPixel, SetPixel и прочее
3D - система частиц или Debug.Draw... или Gizmos, или TrailRenderer или...
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Рисование графиков

Сообщение MediaMen 20 янв 2011, 09:08

А DebugDraw и Gizmos только для редактора? или как то можно их визуализировать?
Аватара пользователя
MediaMen
UNIт
 
Сообщения: 85
Зарегистрирован: 13 апр 2009, 05:49

Re: Рисование графиков

Сообщение gnoblin 20 янв 2011, 09:12

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

Re: Рисование графиков

Сообщение MediaMen 20 янв 2011, 09:31

Господа, а можно ли Trail превратить в полигоны?
Аватара пользователя
MediaMen
UNIт
 
Сообщения: 85
Зарегистрирован: 13 апр 2009, 05:49

Re: Рисование графиков

Сообщение DbIMok 20 янв 2011, 12:20

почему бы тогда не LineRenderer
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Рисование графиков

Сообщение nazgul30 20 янв 2011, 16:07

Я вот пытался реализовать такую вещь: рисование синусоиды.
Объекты: сфера и камера, смотрящая на сферу. Сфера двигается по синусоиде.
Скрипт для рисования синусоиды:

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
//Класс, определяющий рисование графика.
public class DrawGraphic : MonoBehaviour {

        private Vector3 currentPos;
        private Vector3 nextPos;
        public Transform sphere;
       
        void Update(){
                currentPos = sphere.position;
                sphere.Translate(Vector3.right*Time.deltaTime);
                sphere.Translate(Vector3.up*Mathf.Sin(sphere.position.x)*Time.deltaTime);
                nextPos = sphere.position;
        }
       
        void OnPostRender() {
                CreateLineMaterial();
                lineMaterial.SetPass( 0 );
                GL.Begin(GL.LINES);
                GL.Vertex(currentPos);
                GL.Vertex(nextPos);
                GL.End();
                Debug.Log("Draw line");
        }
       
        private Material lineMaterial;

        void CreateLineMaterial() {
                if( !lineMaterial ) {
                        lineMaterial = new Material( "Shader \"Lines/Colored Blended\" {" +
                        "SubShader { Pass { " +
                        " Blend SrcAlpha OneMinusSrcAlpha " +
                        " ZWrite Off Cull Off Fog { Mode Off } " +
                        " BindChannels {" +
                        " Bind \"vertex\", vertex Bind \"color\", color }" +
                        "} } }" );
                        lineMaterial.hideFlags = HideFlags.HideAndDontSave;
                        lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
                }
        }
}

 


Почему синусоида не рисуется? В чем ошибка?
nazgul30
UNIт
 
Сообщения: 76
Зарегистрирован: 08 сен 2010, 18:10

Re: Рисование графиков

Сообщение Paul Siberdt 20 янв 2011, 16:17

DbIMok писал(а):почему бы тогда не LineRenderer

Мнэээ... ну, да, я его и имел в виду, пися про Trail ;;)

MediaMen писал(а):Господа, а можно ли Trail превратить в полигоны?

Это и есть полигоны :)

Если у вас есть массив последовательных координат графика функции, совсем не сложно растянуть по нему LineRenderer
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: Рисование графиков

Сообщение Steelclad 25 янв 2011, 01:35

Я недавно такое делал.
Рисование гистограммы, графика и 3d поверхности.

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

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

public class CreateMesh : MonoBehaviour {
       
public Color lineColor ;

private    Vector3[] linesArray  ;
private  Material lineMaterial ;
private  MeshRenderer meshRenderer;
private bool flag=false;       
       
       
public int vctW=2;
public int vctH=2;
public bool XZorXY=false;
public Color SurfaceColor=Color.red;
public Texture tex;

       
       
private    Vector3[] vert;
private int[] tri;     
private Mesh mesh;


void Awake()
{
       
gameObject.AddComponent("MeshFilter"); 
mesh = GetComponent<MeshFilter>().mesh;

       
       
       
meshRenderer = gameObject.GetComponent<MeshRenderer>();
if(meshRenderer==false)
{
        gameObject.AddComponent("MeshRenderer");       
        meshRenderer = gameObject.GetComponent<MeshRenderer>();
}
        mesh.Clear();  
       
//meshRenderer.material = new Material("Shader \"Lines/Background\" { Properties { _Color (\"Main Color\", Color) = (1,1,1,1) } SubShader { Pass {" + (ZWrite ? " ZWrite on " : " ZWrite off ") + (blend ? " Blend SrcAlpha OneMinusSrcAlpha" : " ") + (AWrite ? " Colormask RGBA " : " ") + "Lighting Off Offset 1, 1 Color[_Color] }}}");
lineMaterial = new Material("Shader \"Lines/Colored Blended\" { SubShader { Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Front Fog { Mode Off } } } }");
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave;
       
       

int i=0;
int j=0;       
       
//ОБЯЗАТЕЛЬНО создавать массивы а потом их присваивать ссылкам в объекте mesh, не создавать ссылку сразу на этот член

       
       
       
 vert=new Vector3[this.vctW*this.vctH];
        if(this.XZorXY==false)//В плоскости XY, Z - это высоты
        {
                for( i=0;i<this.vctH;i++)
                {
                        for( j=0;j<this.vctW;j++)
                        {
                                this.vert[i*this.vctW+j].x=j;//print("x="+vert[i*this.vctX+j].x);
                                this.vert[i*this.vctW+j].y=i; //print("y="+vert[i*this.vctX+j].y);
                                this.vert[i*this.vctW+j].z=0;// print("z=0");
                       
                               
                                }
                }
        }else
        {
                //В плоскости XZ, Y высоты
                for( i=0;i<this.vctH;i++)
                {
                        for( j=0;j<this.vctW;j++)
                        {
                                this.vert[i*this.vctW+j].x=j;//print("x="+vert[i*this.vctX+j].x);
                                this.vert[i*this.vctW+j].y=0; //print("y="+vert[i*this.vctX+j].y);
                                this.vert[i*this.vctW+j].z=i;// print("z=0");
                       
                               
                                }
                }      
                       
        }

       
        this.mesh.vertices=this.vert;
       
       
       

       
Vector2[] uvs = new Vector2[this.mesh.vertices.Length];
 i = 0;
while (i < uvs.Length) {
if(this.XZorXY==false) uvs[i] = new Vector2 (this.mesh.vertices[i].x, this.mesh.vertices[i].y);
        else uvs[i] =new  Vector2 (this.mesh.vertices[i].x, this.mesh.vertices[i].z);
i++;
}
this.mesh.uv = uvs;


this.tri = new int[((this.vctH-1)*(this.vctW-1))*6];
j=0;
int k=0;

for( i=0;i<this.mesh.vertices.Length; i++)
{
               
        if(i>=(this.mesh.vertices.Length-this.vctW-1)) break;//исключим верхние вертиксы крайние, что не образуют верхних треуг
       
       
        if(k==(this.vctW-1)){ k=0; continue;}//исключим правые вертиксы
//обход треугольника по часовой - иначе нормали будут в др сторону, если конечно это не обратная сторона
                this.tri [j++]=i; //print( i);
           this. tri [j++]=(i+1)+this.vctW;     //print( (i+1)+this.vctX);
                this.tri [j++]=i+1; //print( i+1);     
               

        this.tri [j++]=i; //print( i);
        this.tri [j++]=i+this.vctW; //print( i+this.vctX);
        this.tri [j++]=(i+1)+this.vctW; //print((i+1)+this.vctX);      
       
k++;
}


        //составим последовательность обрабатываемых вершин, для рисования линий сетки
 this.linesArray=new Vector3[this.tri.Length];
int kk=0;
        for (i = 0; i < this.tri.Length / 3; i++)
        {
               
         this.linesArray[kk++] =this.vert[this.tri[i * 3]];            
         this.linesArray[kk++ ]=this.vert[this.tri[i * 3 + 1]];        
         this.linesArray[kk++]=this.vert[this.tri[i * 3 + 2]] ;
        }
       
       

       
////////////////



this.mesh.triangles = this.tri;
this.mesh.RecalculateBounds();
this.mesh.RecalculateNormals();


renderer.material.color = this.SurfaceColor;
if( this.tex!=null) renderer.material.mainTexture = this.tex;
Shader shad=Shader.Find( "Diffuse" );
if(shad!=null) renderer.material.shader = shad;

//renderer.enabled = false;    

}

public void UpdateData(float[,] mdata)
        {
               

        this.vert = this.mesh.vertices;
                //Vector3[] normals = this.mesh.normals;
               
        if(this.XZorXY==false)//В плоскости XY, Z - это высоты
        {
                for(int  i=0;i<this.vctH;i++)
                {
                        for(int  j=0;j<this.vctW;j++)
                        {
                               
                                this.vert[i*this.vctW+j].z= mdata[i,j];//0.01F*Mathf.Sin((i+j)*Time.time);
                       
                               
                                }
                }
        }else
        {
                //В плоскости XZ, Y высоты
                for(int  i=0;i<this.vctH;i++)
                {
                        for(int  j=0;j<this.vctW;j++)
                        {
                               
                                this.vert[i*this.vctW+j].y=mdata[i,j];//0.01F*Mathf.Sin((i+j)*Time.time);
                       
                       
                               
                                }
                }      
                       
        }

                       
        this.mesh.vertices=this.vert;  

this.flag=true;
       
                //составим последовательность обрабатываемых вершин, для рисования линий сетки
 //this.linesArray=new Vector3[tri.Length];
int kk=0;
        for (int i = 0; i < this.tri.Length / 3; i++)
        {
               
         this.linesArray[kk++] =this.vert[this.tri[i * 3]];            
         this.linesArray[kk++ ]=this.vert[this.tri[i * 3 + 1]];        
         this.linesArray[kk++]=this.vert[this.tri[i * 3 + 2]] ;
        }
       
        this.flag=false;
       
                       
        }
       
        public void UpdateDataTest()
        {
               

        this.vert = this.mesh.vertices;
                //Vector3[] normals = this.mesh.normals;
               
        if(this.XZorXY==false)//В плоскости XY, Z - это высоты
        {
                for(int  i=0;i<this.vctH;i++)
                {
                        for(int  j=0;j<this.vctW;j++)
                        {
                               
                                this.vert[i*this.vctW+j].z+= 0.01F*Mathf.Sin((i+j)*Time.time);
                       
                               
                                }
                }
        }else
        {
                //В плоскости XZ, Y высоты
                for(int  i=0;i<this.vctH;i++)
                {
                        for(int  j=0;j<this.vctW;j++)
                        {
                               
                                this.vert[i*this.vctW+j].y+=0.01F*Mathf.Sin((i+j)*Time.time);
                       
                       
                               
                                }
                }      
                       
        }

                       
        this.mesh.vertices=this.vert;  

this.flag=true;
       
                //составим последовательность обрабатываемых вершин, для рисования линий сетки
 //this.linesArray=new Vector3[tri.Length];
int kk=0;
        for (int i = 0; i < this.tri.Length / 3; i++)
        {
               
         this.linesArray[kk++] =this.vert[this.tri[i * 3]];            
         this.linesArray[kk++ ]=this.vert[this.tri[i * 3 + 1]];        
         this.linesArray[kk++]=this.vert[this.tri[i * 3 + 2]] ;
        }
       
        this.flag=false;
       
                       
        }
        void Start()
        {
        //renderer.enabled = false;    
        }
       
        void Update()
        {

        this.UpdateDataTest();
                       
        }

       
       
        void  OnRenderObject()
{  
        if(this.flag==true) return;
               
    this.meshRenderer.material.color = this.SurfaceColor;
        this.lineMaterial.SetPass(0);
   
        GL.PushMatrix();
        GL.MultMatrix(transform.localToWorldMatrix);
        GL.Begin(GL.LINES);
        GL.Color(this.lineColor);
   
        for (int i = 0; i < this.linesArray.Length / 3; i++)
        {
                GL.Vertex(this.linesArray[i * 3]);
                GL.Vertex(this.linesArray[i * 3 + 1]);
               
                GL.Vertex(this.linesArray[i * 3 + 1]);
                GL.Vertex(this.linesArray[i * 3 + 2]);
               
                GL.Vertex(this.linesArray[i * 3 + 2]);
                GL.Vertex(this.linesArray[i * 3]);
        }
         
        GL.End();
        GL.PopMatrix();
}
       
}





Для гистограммы
Синтаксис:
Используется csharp

using UnityEngine;
using System.Collections;

public class Histo : MonoBehaviour {

       
       
public GameObject bar;
private GameObject[] bars;
public float distBetweenBars=1F;       
public Color c1 = Color.red;
public float widthBars=0.5F;
       
       
       
public int nGroup=10;
       
        void Awake()
        {
               
                this.bars=new GameObject[this.nGroup];
                for(int i=0;i<this.nGroup;i++)
                {
                        this.bars[i]=Instantiate (this.bar, transform.position, transform.rotation) as GameObject;
                        this.bars[i].transform.Translate(Vector3.right*(i*(this.widthBars+this.distBetweenBars) ));
                        this.bars[i].GetComponent<HistoColumn>().CreateBar(this.widthBars,this.c1, i, i+" Код");
                       
                        //bars[i].GetComponent<HistoColumn>().SetBar(i);
                        //bars[i].GetComponent<HistoColumn>().SetLegend(i+" Код");
                       
                }
                 
                 

        }

       
       
        public void UpdateBars(float[] barsHeight)
        {
                if(barsHeight.Length!=this.nGroup) print("Неверное число баров");
                for(int i=0;i<barsHeight.Length;i++) bars[i].GetComponent<HistoColumn>().SetBar(barsHeight[i]);
                               
        }
       
        void Update()
        {
               
        }
}


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

public class HistoColumn : MonoBehaviour {

       

private float BarWidth;
private LineRenderer bar;      
private TextMesh txt;
private TextMesh legend;       
       
        // Use this for initialization
        void Awake ()
        {
               
       
       
                this.bar = gameObject.AddComponent<LineRenderer>();            
                this.bar.useWorldSpace = false;
                this.bar.material = new Material(Shader.Find("Particles/Additive"));           
                this.bar.SetVertexCount(2);
               
        this.txt=gameObject.transform.Find("heightHisto").GetComponent<TextMesh>(); //получим компонетн текста у для обозначения высоты(настраивается из редактора, в перфабе)
        this.legend=gameObject.transform.Find("Legend").GetComponent<TextMesh>();
       
        }
       
       
        public void CreateBar(float Barwidth,Color c, float Barheight,string leg )
        {
                this.BarWidth=Barwidth;
                this.bar.SetColors(c, c);
                this.bar.SetWidth(Barwidth, Barwidth);
                this.bar.SetPosition(0,new Vector3(0,0,0) );
                this.bar.SetPosition(1,new Vector3(0,Barheight,0) );   
               
        this.txt.transform.Translate(Vector3.up*(Barheight+0.5F)-Vector3.right*(Barwidth/2.3F));
                this.txt.text=Barheight.ToString();            
               
                this.legend.transform.Translate(Vector3.up*(-0.2F)-Vector3.right*(Barwidth/2.3F));
                this.legend.text=leg;
               
        }
       
       
        public void SetBar(float height)
        {
               
                this.bar.SetPosition(1,new Vector3(0,height,0) );//установим значение бара
       
                this.txt.transform.Translate(Vector3.up*(height+0.5F)-Vector3.right*(this.BarWidth/2.3F));//переместим надпись на верх бара
                this.txt.text=height.ToString();
        }
       
        public void SetLegend(string leg)
        {
               
                this.legend.text=leg;
       
               
               
        }
       
       
}

 


Histo вешаешь на на пустой объект и настараиваешь параметры.
Создается Prefab со скриптом HistoColumn с дочерними текстовыми объектами для высоты и подписи бара.
MATRIX HAS YOU,...Knock,knock...
Аватара пользователя
Steelclad
UNец
 
Сообщения: 41
Зарегистрирован: 03 ноя 2010, 16:08

Re: Рисование графиков

Сообщение gnoblin 25 янв 2011, 02:56

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

Re: Рисование графиков

Сообщение Steelclad 25 янв 2011, 23:15

Здесь поверхность которая может быть с заданным разрешением сетки, цвета, цвета линий. Можно даже текстуру наложить )
Сейчас она прорисовывает какой-то sin, можно просто подавать на вход набор чисел, как в карте высот.

Гистограмма для примера отображает в колонках 0 -9 (первая колонка показывает 0, поэтому не видно бара).
Можно в любой момент менять высоту баров и соответственно подписей тоже.
Конечно код может быть еще сыроват, я его временно отложил. Но если кому поможет чем то это хорошо

HTML код для вашего блога :
Код: Выделить всё
<script language='javascript' type="text/javascript"> document.write("<iframe marginheight='0' src='http://unity3d.ru/distribution/player.php?url=http://cystatin.ru/un/WebPlayer.unity3d&w=800&h=600&t=true&preview=1' height='"+(600+30)+"' width='800' frameborder='0' scrolling='no'></iframe>"); </script>


Вот ссылка, если не что не так вбил в плейере
http://cystatin.ru/un/index.html
У вас нет доступа для просмотра вложений в этом сообщении.
MATRIX HAS YOU,...Knock,knock...
Аватара пользователя
Steelclad
UNец
 
Сообщения: 41
Зарегистрирован: 03 ноя 2010, 16:08


Вернуться в Скрипты

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

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