using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; //Uwaga! Mozna uogolnic kwadryki wprowadzajac rozne promienie w kierunku x i y przez skalowanie wspolrzednych z tablicy werteksow w metodzie ZbudujBuforWerteksow namespace MojaPierwszaGraXNA { enum TypKwadryki { ScietyStozek, Walec, Stozek, Dysk, Kolo, Sfera }; class Kwadryka { private TypKwadryki typKwadryki; private GraphicsDevice gd; private VertexBuffer buforWerteksow = null; private int iloscTrojkatowWPasmie; private int iloscPasm = 1; #region Metody statyczne static private VertexPositionNormalTextureTangentBinormal[] BudujTabliceWerteksowScietegoStozka(float promienDolny, float promienGorny, float polozeniePodstawy, float wysokosc,int iloscSekcji,Color kolor) { int iloscWerteksow = 2 * iloscSekcji; VertexPositionNormalTextureTangentBinormal[] tablicaWerteksow = new VertexPositionNormalTextureTangentBinormal[iloscWerteksow]; float przyrostKata = MathHelper.TwoPi / (iloscSekcji - 1.0f); for (int i = 0; i < iloscSekcji; i++) { float kat = i * przyrostKata; Vector3 kierunek = new Vector3((float)Math.Cos(kat), (float)Math.Sin(kat), 0); tablicaWerteksow[2 * i].Position = promienDolny * kierunek + polozeniePodstawy * Vector3.UnitZ; tablicaWerteksow[2 * i + 1].Position = promienGorny * kierunek + (polozeniePodstawy+wysokosc) * Vector3.UnitZ; //obliczanie normalnej float a=promienDolny-promienGorny; float c=(float)Math.Sqrt(a * a + wysokosc * wysokosc); float sinTheta = a / c; float cosTheta = wysokosc / c; Vector3 normalna = new Vector3((float)Math.Cos(kat)*cosTheta,(float)Math.Sin(kat)*cosTheta,sinTheta); tablicaWerteksow[2 * i].Normal = normalna; tablicaWerteksow[2 * i + 1].Normal = normalna; tablicaWerteksow[2 * i].Tangent = new Vector3(0,1,0); //głupie wartości tablicaWerteksow[2 * i + 1].Binormal = new Vector3(1, 0, 0); //głupie wartości //wspolrzedne teksturowania (dla bryl jednopasmowych) tablicaWerteksow[2 * i].TextureCoordinate = new Vector2(kat / MathHelper.TwoPi, 1); tablicaWerteksow[2 * i + 1].TextureCoordinate = new Vector2(kat / MathHelper.TwoPi, 0); } return tablicaWerteksow; } static private Kwadryka StworzKwadryke(GraphicsDevice gd, float promienDolny, float promienGorny, float polozeniePodstawy, float wysokosc, int iloscSekcji, Color kolor) { Kwadryka kwadryka = new Kwadryka(); kwadryka.gd = gd; kwadryka.iloscTrojkatowWPasmie = 2 * iloscSekcji; VertexPositionNormalTextureTangentBinormal[] tablicaWerteksow = Kwadryka.BudujTabliceWerteksowScietegoStozka(promienDolny, promienGorny, polozeniePodstawy, wysokosc, iloscSekcji, kolor); kwadryka.ZbudujBuforWerteksow(tablicaWerteksow); return kwadryka; } static public Kwadryka StworzScietyStozek(GraphicsDevice gd, float promienDolny, float promienGorny, float wysokosc, int iloscSekcji, Color kolor) { Kwadryka kwadryka = Kwadryka.StworzKwadryke(gd, promienDolny, promienGorny, 0, wysokosc, iloscSekcji, kolor); kwadryka.typKwadryki = TypKwadryki.ScietyStozek; return kwadryka; } static public Kwadryka StworzWalec(GraphicsDevice gd, float promien, float wysokosc, int iloscSekcji, Color kolor) { Kwadryka kwadryka = Kwadryka.StworzKwadryke(gd, promien, promien, 0, wysokosc, iloscSekcji, kolor); kwadryka.typKwadryki = TypKwadryki.Walec; return kwadryka; } static public Kwadryka StworzStozek(GraphicsDevice gd, float promien, float wysokosc, int iloscSekcji, Color kolor) { Kwadryka kwadryka = Kwadryka.StworzKwadryke(gd, promien, 0, 0, wysokosc, iloscSekcji, kolor); kwadryka.typKwadryki = TypKwadryki.Stozek; return kwadryka; } static public Kwadryka StworzDysk(GraphicsDevice gd, float promienWewnetrzny, float promienZewnetrzny, int iloscSekcji,Color kolor) { Kwadryka kwadryka = Kwadryka.StworzKwadryke(gd, promienZewnetrzny, promienWewnetrzny, 0, 0, iloscSekcji, kolor); kwadryka.typKwadryki = TypKwadryki.Dysk; return kwadryka; } static public Kwadryka StworzKolo(GraphicsDevice gd, float promien, int iloscSekcji, Color kolor) { Kwadryka kwadryka = Kwadryka.StworzKwadryke(gd, promien, 0, 0, 0, iloscSekcji, kolor); kwadryka.typKwadryki = TypKwadryki.Kolo; return kwadryka; } static public Kwadryka StworzSfere(GraphicsDevice gd, float promien, int iloscSekcjiNaRownoleznikach, int iloscSekcjiNaPoludnikach, Color kolor) { Kwadryka kwadryka = new Kwadryka(); kwadryka.gd = gd; kwadryka.typKwadryki = TypKwadryki.Sfera; kwadryka.iloscTrojkatowWPasmie = 2 * iloscSekcjiNaRownoleznikach; kwadryka.iloscPasm = iloscSekcjiNaPoludnikach; List listaWerteksow = new List(kwadryka.iloscPasm * kwadryka.iloscTrojkatowWPasmie * 2); double przyrostKataTheta = Math.PI / iloscSekcjiNaPoludnikach; for (int i = 0; i < iloscSekcjiNaPoludnikach; i++) { double katThetaGorny = i * przyrostKataTheta; double katThetaDolny = (i+1) * przyrostKataTheta; float wysokoscGorna = (float)(promien * Math.Cos(katThetaGorny)); float wysokoscDolna = (float)(promien * Math.Cos(katThetaDolny)); float promienGorny = (float)(promien * Math.Sin(katThetaGorny)); float promienDolny = (float)(promien * Math.Sin(katThetaDolny)); //listaWerteksow.AddRange(Kwadryka.BudujTabliceWerteksowScietegoStozka(promienDolny, promienGorny, wysokoscDolna, wysokoscGorna - wysokoscDolna, iloscSekcjiNaRownoleznikach, kolor)); VertexPositionNormalTextureTangentBinormal[] werteksyPasma = Kwadryka.BudujTabliceWerteksowScietegoStozka(promienDolny, promienGorny, wysokoscDolna, wysokoscGorna - wysokoscDolna, iloscSekcjiNaRownoleznikach, kolor); double przyrostKataPhi=2*Math.PI/iloscSekcjiNaRownoleznikach; for (int j = 0; j < iloscSekcjiNaRownoleznikach; j++) { double katPhi=j*przyrostKataPhi; werteksyPasma[2 * j].Normal.X = (float)(Math.Cos(katPhi) * Math.Sin(katThetaDolny)); werteksyPasma[2 * j].Normal.Y = (float)(Math.Sin(katPhi) * Math.Sin(katThetaDolny)); werteksyPasma[2 * j].Normal.Z = (float)(Math.Cos(katThetaDolny)); werteksyPasma[2 * j + 1].Normal.X = (float)(Math.Cos(katPhi) * Math.Sin(katThetaGorny)); werteksyPasma[2 * j + 1].Normal.Y = (float)(Math.Sin(katPhi) * Math.Sin(katThetaGorny)); werteksyPasma[2 * j + 1].Normal.Z = (float)(Math.Cos(katThetaGorny)); } przyrostKataPhi = 2 * Math.PI / (iloscSekcjiNaRownoleznikach - 1); for (int j = 0; j < iloscSekcjiNaRownoleznikach; j++) { double katPhi = j * przyrostKataPhi; werteksyPasma[2 * j].TextureCoordinate = new Vector2((float)katPhi / MathHelper.TwoPi, (float)katThetaDolny / MathHelper.Pi); werteksyPasma[2 * j + 1].TextureCoordinate = new Vector2((float)katPhi / MathHelper.TwoPi, (float)katThetaGorny / MathHelper.Pi); } listaWerteksow.AddRange(werteksyPasma); } kwadryka.ZbudujBuforWerteksow(listaWerteksow.ToArray()); return kwadryka; } #endregion private void ZbudujBuforWerteksow(VertexPositionNormalTextureTangentBinormal[] tablicaWerteksow) { buforWerteksow = new VertexBuffer(gd, VertexPositionNormalTextureTangentBinormal.VertexDeclaration, tablicaWerteksow.Count(), BufferUsage.WriteOnly); buforWerteksow.SetData(tablicaWerteksow); } #region Własności public TypKwadryki TypKwadryki { get { return typKwadryki; } } public VertexBuffer BuforWerteksow { get { return buforWerteksow; } } public int IloscTrojkatowWPasmie { get { return iloscTrojkatowWPasmie; } } public int IloscPasm { get { return iloscPasm; } } #endregion public void Rysuj(Effect efekt) { foreach (EffectPass pass in efekt.CurrentTechnique.Passes) { pass.Apply(); gd.SetVertexBuffer(buforWerteksow); for (int i = 0; i < iloscPasm; i++) { gd.DrawPrimitives(PrimitiveType.TriangleStrip, i * iloscTrojkatowWPasmie, iloscTrojkatowWPasmie); } } } } class Lampa { private GraphicsDevice gd; private Kwadryka zbiornik, abazurBok, abazurGora, podstawkaZarowki, zarowka; public Lampa(GraphicsDevice gd) { this.gd = gd; zbiornik = Kwadryka.StworzSfere(gd, 0.4f, 100, 100, Color.Green); podstawkaZarowki = Kwadryka.StworzWalec(gd, 0.05f, 0.1f, 100, Color.LimeGreen); zarowka = Kwadryka.StworzSfere(gd, 0.1f, 100, 100, Color.Yellow); Color kolorAbazura = Color.Lime; kolorAbazura.A = 230; abazurBok = Kwadryka.StworzScietyStozek(gd, 0.45f, 0.25f, 0.55f, 100, kolorAbazura); abazurGora = Kwadryka.StworzDysk(gd, 0.25f, 0.15f, 100, kolorAbazura); } public void Rysuj(BasicEffect efekt) { Matrix kopiaOryginalnejMacierzySwiata = efekt.World; efekt.World *= Matrix.CreateTranslation(0, -0.25f, 0); zbiornik.Rysuj(efekt); efekt.World = kopiaOryginalnejMacierzySwiata * Matrix.CreateRotationX(-MathHelper.PiOver2)*Matrix.CreateTranslation(0,0.15f,0); podstawkaZarowki.Rysuj(efekt); efekt.World *= Matrix.CreateTranslation(0, 0.15f, 0); zarowka.Rysuj(efekt); //polprzezroczysty abazur gd.BlendState = BlendState.NonPremultiplied; //gd.RenderState.AlphaBlendEnable = true; //gd.RenderState.SourceBlend = Blend.SourceAlpha; //gd.RenderState.DestinationBlend = Blend.DestinationAlpha; //gd.RenderState.BlendFunction = BlendFunction.Add; efekt.World = kopiaOryginalnejMacierzySwiata * Matrix.CreateRotationX(-MathHelper.PiOver2); abazurBok.Rysuj(efekt); efekt.World *= Matrix.CreateTranslation(0, 0.55f, 0); abazurGora.Rysuj(efekt); //gd.RenderState.AlphaBlendEnable = false; efekt.World = kopiaOryginalnejMacierzySwiata; } } }