123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047 |
- #include "pch.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // Mine Field Geo
- //
- //////////////////////////////////////////////////////////////////////////////
- class MineFieldGeoImpl : public MineFieldGeo {
- private:
- TRef<Surface> m_psurface;
- TVector<Vector> m_vposition;
- float m_radius;
- static int GetCount(float strength, float radius)
- {
- return 1 + int(strength * radius * radius / 100.0f);
- }
- public:
- MineFieldGeoImpl(Surface* psurface, float strength, float radius) :
- m_psurface(psurface),
- m_vposition(GetCount(strength, radius)),
- m_radius(radius)
- {
- for (int index = 0; index < m_vposition.GetCount(); index++) {
- m_vposition.Set(index, Vector::RandomPosition(radius));
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // MineFieldGeo methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void SetStrength(float strength)
- {
- int count = GetCount(strength, m_radius);
- ZAssert(count <= m_vposition.GetCount());
- m_vposition.SetCount(count);
- Changed();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Geo Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- float GetRadius(const Matrix& mat)
- {
- return m_radius;
- }
- void Render(Context* pcontext)
- {
- Vector vecEye = pcontext->TransformLocalToEye(Vector::GetZero());
- float bright = bound(100.0f / vecEye.Length(), 0.0f, 1.0f);
- if (bright > 0) {
- Color color(bright, bright, bright);
- int count = m_vposition.GetCount();
- for (int index = 0; index < count; index++) {
- pcontext->DrawDecal(
- m_psurface,
- color,
- m_vposition[index],
- Vector::GetZero(),
- Vector::GetZero(),
- 1,
- 0,
- BlendModeSource
- );
- }
- }
- }
- };
- TRef<MineFieldGeo> CreateMineFieldGeo(Surface* psurface, float strength, float radius)
- {
- return new MineFieldGeoImpl(psurface, strength, radius);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Build Effect Geo
- //
- //////////////////////////////////////////////////////////////////////////////
- const float c_ratio = 1.1f;
- class BuildEffectGeoImpl :
- public BuildEffectGeo,
- public IGeoCallback
- {
- private:
- Color m_colorInner;
- Color m_colorOuter;
- Color m_colorComplement;
- TRef<Geo> m_psphere;
-
- float m_time;
- float m_radius;
- float m_fOuter;
- Vector m_position;
- public:
- BuildEffectGeoImpl(
- Modeler* pmodeler,
- Number* ptime,
- const Color& color
- ) :
- BuildEffectGeo(ptime),
- m_colorOuter(color)
- {
- float h;
- float s;
- float b;
- m_colorOuter.GetHSB(h, s, b);
- m_colorComplement.SetHSBA(h + 0.5f, s, b);
- m_psphere = pmodeler->LoadGeo("build");
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // BuildEffectGeo Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- float GetRadius()
- {
- return m_radius;
- }
- void SetRadius(float f)
- {
- m_radius = f;
- }
- const Vector& GetPosition()
- {
- return m_position;
- }
- void SetPosition(const Vector& p)
- {
- m_position = p;
- }
- void SetColors(float aInner, float fInner, float fOuter)
- {
- m_colorInner = m_colorComplement * fInner;
- m_colorInner.SetAlpha(aInner);
- m_fOuter = fOuter;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Geo Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void Evaluate()
- {
- m_time = GetTime()->GetValue();
- }
- void Render(Context* pcontext)
- {
- pcontext->DrawCallbackGeo(this, true);
- }
- void RenderCallback(Context* pcontext)
- {
- //
- // Rendering modes
- //
- pcontext->SetBlendMode(BlendModeSourceAlpha);
- pcontext->SetShadeMode(ShadeModeGlobalColor);
- //
- //
- //
- pcontext->Translate(m_position);
- pcontext->Scale3(m_radius);
- //
- // inner sphere
- //
- pcontext->PushState();
- pcontext->Scale3(1.0f / c_ratio);
- pcontext->Rotate(Vector(0, 0, 1), m_time / pi);
- pcontext->Rotate(Vector(0, 1, 0), 0.5f * pi * m_time);
- pcontext->SetGlobalColor(m_colorInner);
- m_psphere->Render(pcontext);
- pcontext->PopState();
- //
- // outer sphere
- //
- pcontext->Rotate(Vector(1, 0, 0), m_time);
- pcontext->Rotate(Vector(0, 1, 0), pi * m_time);
- pcontext->SetBlendMode(BlendModeAdd);
- pcontext->SetGlobalColor(m_colorOuter * m_fOuter);
- m_psphere->Render(pcontext);
- }
- };
- TRef<BuildEffectGeo> CreateBuildEffectGeo(
- Modeler* pmodeler,
- Number* ptime,
- const Color& color
- ) {
- return
- new BuildEffectGeoImpl(
- pmodeler,
- ptime,
- color
- );
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // WireSphere
- //
- //////////////////////////////////////////////////////////////////////////////
- class WireSphereGeo : public Geo {
- private:
- TVector<VertexL> m_vertices;
- TVector<MeshIndex> m_indices;
- static const int vSegments;
- public:
- WireSphereGeo(float minDot, int hSegments) :
- m_vertices(
- hSegments * (vSegments - 1),
- hSegments * (vSegments - 1)
- ),
- m_indices(
- 2 * hSegments * (vSegments * 2 - 3),
- 2 * hSegments * (vSegments * 2 - 3)
- )
- {
- //
- // Create the vertex array
- //
- int vIndex;
- int hIndex;
- for (vIndex = 0; vIndex < vSegments - 1; vIndex++)
- {
- float vSin = minDot - float(vIndex) * 0.05f;
- float vCos = float(sqrt(1.0f - vSin * vSin));
- for (hIndex = 0; hIndex < hSegments; hIndex++)
- {
- int index = vIndex * hSegments + hIndex;
- float hAngle = (float)hIndex * 2.0f * pi / (float)hSegments;
- float x = cos(hAngle) * vCos;
- float y = sin(hAngle) * vCos;
- float z = -vSin;
- static const float intensity = 1.0f;
- m_vertices.Set(
- index,
- VertexL(
- 1000 * x,
- 1000 * y,
- 1000 * z,
- intensity,
- intensity,
- intensity,
- 1,
- 0,
- 0
- )
- );
- }
- }
- //
- // Vertical lines
- //
- int index = 0;
- for (vIndex = 0; vIndex < vSegments - 2; vIndex++) {
- for (hIndex = 0; hIndex < hSegments; hIndex++) {
- m_indices.Set(index , vIndex * hSegments + hIndex);
- m_indices.Set(index + 1, (vIndex + 1) * hSegments + hIndex);
- ZAssert(m_indices[index ] >= 0 && m_indices[index ] < m_vertices.GetCount());
- ZAssert(m_indices[index + 1] >= 0 && m_indices[index + 1] < m_vertices.GetCount());
- index += 2;
- }
- }
- //
- // Horizontal lines
- //
- for (vIndex = 0; vIndex < vSegments - 1; vIndex++) {
- for (hIndex = 0; hIndex < hSegments; hIndex++) {
- m_indices.Set(index, vIndex * hSegments + hIndex);
- m_indices.Set(index + 1,
- hIndex == hSegments - 1 ?
- vIndex * hSegments
- : vIndex * hSegments + hIndex + 1
- );
- ZAssert(m_indices[index ] >= 0 && m_indices[index ] < m_vertices.GetCount());
- ZAssert(m_indices[index + 1] >= 0 && m_indices[index + 1] < m_vertices.GetCount());
- index += 2;
- }
- }
- ZAssert(index == m_indices.GetCount());
- }
- void Render(Context* pcontext)
- {
- pcontext->DrawLines(m_vertices, m_indices);
- }
- //
- // Value members
- //
- ZString GetFunctionName() { return "WireSphereGeo"; }
- };
- const int WireSphereGeo::vSegments = 3;
- TRef<Geo> CreateWireSphereGeo(float minDot, int hSegments)
- {
- return new WireSphereGeo(minDot, hSegments);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Pulse Geo
- //
- //////////////////////////////////////////////////////////////////////////////
- class PulseGeoImpl :
- public PulseGeo,
- public IGeoCallback
- {
- protected:
- class WhiteSurfaceSite : public SurfaceSite {
- public:
- void UpdateSurface(Surface* psurface)
- {
- psurface->FillSurface(Color::White());
- }
- };
- struct PulseData : public IObject
- {
- float m_fRadius;
- Vector m_vecPosition;
- Color m_color;
- float m_fStartTime;
- float m_fExplodeTime;
- PulseData (float fStartTime, float fExplodeTime, float fRadius, const Vector& vecPosition, const Color& color)
- {
- m_fRadius = fRadius;
- m_vecPosition = vecPosition;
- m_color = color;
- m_fStartTime = fStartTime;
- m_fExplodeTime = fExplodeTime;
- }
- };
- TList<TRef<PulseData> > m_pulseData;
- float m_fTime;
- TRef<Geo> m_pSphere;
- TRef<Surface> m_pTexture;
- public:
- PulseGeoImpl (Modeler* pmodeler, Number* ptime) : PulseGeo (ptime)
- {
- m_pSphere = pmodeler->LoadGeo("aleph_sphere");
- m_pTexture = pmodeler->GetEngine ()->CreateSurface (WinPoint (16, 16), SurfaceType2D (), new WhiteSurfaceSite());
- }
- void AddPulse (float fExplodeTime, float fRadius, const Vector& vecPosition, const Color& color)
- {
- float fStartTime = GetTime()->GetValue();
- m_pulseData.PushFront (new PulseData (fStartTime, fExplodeTime, (fRadius / m_pSphere->GetRadius (Matrix::GetIdentity ())) * 0.5f, vecPosition, color));
- }
- void Evaluate()
- {
- m_fTime = GetTime()->GetValue();
- }
- void Render(Context* pcontext)
- {
- pcontext->DrawCallbackGeo(this, true);
- }
- void RenderCallback(Context* pcontext)
- {
- TList<TRef<PulseData> >::Iterator iter (m_pulseData);
- // Rendering modes
- pcontext->SetBlendMode (BlendModeAdd);
- pcontext->SetShadeMode (ShadeModeGlobalColor);
- pcontext->SetTexture (m_pTexture);
- while (! iter.End ())
- {
- TRef<PulseData> pGeo = iter.Value ();
- // compute the time
- float fTimeUntilExplosion = pGeo->m_fExplodeTime - (m_fTime - pGeo->m_fStartTime);
- float fEffectDuration = 0.5f;
- if (fTimeUntilExplosion <= fEffectDuration)
- {
- if (fTimeUntilExplosion <= -fEffectDuration)
- {
- // the effect has expired, so remove this node and move on to the next one
- iter.Remove ();
- }
- else
- {
- // compute the factor that gives us the growth and opacity of the effect
- float fEffectScale = 1.0f - fabsf (fTimeUntilExplosion / fEffectDuration);
- assert (fEffectScale <= 1.0f);
- fEffectScale *= fEffectScale;
- // transformations
- pcontext->Translate(pGeo->m_vecPosition);
- pcontext->Scale3(pGeo->m_fRadius * fEffectScale);
- // do the rendering
- pcontext->PushState ();
- pcontext->SetGlobalColor (Color (pGeo->m_color.R () * fEffectScale, pGeo->m_color.G () * fEffectScale, pGeo->m_color.B () * fEffectScale, fEffectScale));
- m_pSphere->Render (pcontext);
- pcontext->PopState ();
- // skip to the next node in the list
- iter.Next ();
- }
- }
- else
- {
- // skip to the next node in the list
- iter.Next ();
- }
- }
- }
- };
- TRef<PulseGeo> CreatePulseGeo(Modeler* pmodeler, Number* ptime)
- {
- return new PulseGeoImpl (pmodeler, ptime);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Trail Geo
- //
- //////////////////////////////////////////////////////////////////////////////
- const int maxSections = 16;
- const float timeDelta = 0.5f;
- class TrailGeo : public Geo, public IGeoCallback {
- private:
- TVector<VertexL> m_vertices;
- TVector<MeshIndex> m_indices;
- int m_section;
- float m_timeLast;
- Color m_color;
- TRef<Image> m_pimage;
- Vector m_vecRightLast;
- Number* GetTime() { return Number::Cast(GetChild(0)); }
- VectorValue* GetPosition() { return VectorValue::Cast(GetChild(1)); }
- VectorValue* GetRight() { return VectorValue::Cast(GetChild(2)); }
- Boolean* GetMoving() { return Boolean::Cast(GetChild(3)); }
- public:
- TrailGeo(
- Modeler* pmodeler,
- const Color& color,
- VectorValue* pvectorPosition,
- VectorValue* pvectorRight,
- Boolean* pbooleanMoving,
- Number* ptime
- ) :
- Geo(ptime, pvectorPosition, pvectorRight, pbooleanMoving),
- m_color(color),
- m_vecRightLast(pvectorRight->GetValue()),
- m_vertices((maxSections + 1) * 2, (maxSections + 1) * 2),
- m_indices(maxSections * 6, maxSections * 6),
- m_section(0),
- m_timeLast(-1)
- {
- m_pimage = pmodeler->LoadImage(AWF_EFFECT_TRAIL, true);
- int index;
- for(index = 0; index < maxSections; index ++) {
- int indexVertex = index * 2;
- int indexIndex = index * 6;
- m_indices.Set(indexIndex + 0, indexVertex + 0);
- m_indices.Set(indexIndex + 1, indexVertex + 2);
- m_indices.Set(indexIndex + 2, indexVertex + 3);
- m_indices.Set(indexIndex + 3, indexVertex + 0);
- m_indices.Set(indexIndex + 4, indexVertex + 3);
- m_indices.Set(indexIndex + 5, indexVertex + 1);
- }
- int count = m_vertices.GetCount();
- for(index = 0; index < count; index += 2) {
- m_vertices.Get(index ).SetTextureCoordinate(Point(0, 0));
- m_vertices.Get(index + 1).SetTextureCoordinate(Point(1, 0));
- }
- }
- void UpdateColors(float time)
- {
- if (m_section != 0) {
- float dtime = (time - m_timeLast) / (timeDelta * maxSections);
- float bright = 1 - dtime;
- float dbright = 1.0f / maxSections;
- for (int index = 0; index <= m_section; index++) {
- Color color = m_color * bright;
- bright -= dbright;
- if (bright < 0) {
- bright = 0;
- }
- m_vertices.Get(index * 2 ).SetColor(color);
- m_vertices.Get(index * 2 + 1).SetColor(color);
- }
- }
- }
- void Evaluate()
- {
- float time = GetTime()->GetValue();
- const Vector& vecPos = GetPosition()->GetValue();
- const Vector& vecRight = GetRight()->GetValue();
- bool bMoving = GetMoving()->GetValue();
- if (vecPos != Vector(0, 0, 0)) {
- if (m_timeLast == -1) {
- m_timeLast = time;
- } else {
- if (time - m_timeLast > timeDelta) {
- m_timeLast = time;
- if (m_section < maxSections) {
- m_section++;
- }
- for(int index = m_section * 2 + 1; index > 1; index--) {
- m_vertices.Set(index, m_vertices[index - 2]);
- }
- }
- }
- if (bMoving) {
- m_vecRightLast = vecRight;
- }
- m_vertices.Get(0).SetPosition(vecPos - m_vecRightLast);
- m_vertices.Get(1).SetPosition(vecPos + m_vecRightLast);
- UpdateColors(time);
- }
- }
- void Render(Context* pcontext)
- {
- pcontext->DrawCallbackGeo(this, true);
- }
- void RenderCallback(Context* pcontext)
- {
- pcontext->SetMaterial(NULL);
- pcontext->SetShadeMode(ShadeModeGouraud);
- pcontext->SetCullMode(CullModeNone);
- pcontext->SetBlendMode(BlendModeAdd);
- pcontext->SetZWrite(false);
- pcontext->SetTexture(m_pimage->GetSurface());
- if (m_section != 0) {
- pcontext->DrawTriangles(
- &m_vertices[0],
- (m_section + 1) * 2,
- &m_indices[0],
- m_section * 6
- );
- }
- }
- };
- TRef<Geo> CreateTrailGeo(
- Modeler* pmodeler,
- const Color& color,
- VectorValue* pvectorPosition,
- VectorValue* pvectorRight,
- Boolean* pbooleanMoving,
- Number* ptime
- ) {
- return new TrailGeo(pmodeler, color, pvectorPosition, pvectorRight, pbooleanMoving, ptime);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // HullHitGeo
- //
- //////////////////////////////////////////////////////////////////////////////
- class HullHitGeoImpl : public HullHitGeo {
- private:
- class HullHitData {
- public:
- Vector m_position;
- Vector m_normal;
- Vector m_forward;
- Vector m_right;
- float m_timeStart;
- };
- typedef TList<HullHitData, DefaultNoEquals> HullHitDataList;
- HullHitDataList m_listHullHitData;
- TRef<Surface> m_psurfaceNormal;
- TRef<Surface> m_psurfaceTangent;
- Number* GetTime() { return Number::Cast(GetChild(0)); }
- public:
- HullHitGeoImpl(Modeler* pmodeler, Number* ptime) :
- HullHitGeo(ptime)
- {
- m_psurfaceNormal = pmodeler->LoadSurface(AWF_EFFECT_NORMAL, true);
- m_psurfaceTangent = pmodeler->LoadSurface(AWF_EFFECT_TANGENT, true);
- }
- void AddHullHit(const Vector& vecPosition, const Vector& vecNormal)
- {
- m_listHullHitData.PushFront();
- HullHitData& data = m_listHullHitData.GetFront();
- data.m_position = vecPosition;
- data.m_normal = vecNormal;
- if (vecNormal == Vector(0, 0, 1)) {
- data.m_forward = CrossProduct(vecNormal, Vector(0, 1, 0)).Normalize();
- } else {
- data.m_forward = CrossProduct(vecNormal, Vector(0, 0, 1)).Normalize();
- }
- data.m_right = CrossProduct(data.m_forward, vecNormal);
- data.m_timeStart = GetTime()->GetValue();
- }
- void Render(Context* pcontext)
- {
- float timeCurrent = GetTime()->GetValue();
- HullHitDataList::Iterator iter(m_listHullHitData);
- while (!iter.End()) {
- HullHitData& data = iter.Value();
- Color color(1, 1, 1);
- float maxSize = 2.0f;
- float scale = 0.1f + maxSize * 5.0f * (timeCurrent - data.m_timeStart);
- if (scale > maxSize) {
- scale = maxSize;
- }
- //
- // draw the tangent decal
- //
- pcontext->DrawDecal(
- m_psurfaceTangent,
- color,
- data.m_position,
- scale * data.m_forward,
- scale * data.m_right,
- 1,
- 0
- );
- //
- // draw the normal decal
- //
- pcontext->DrawDecal(
- m_psurfaceNormal,
- color,
- data.m_position + scale * data.m_normal,
- scale * data.m_normal,
- Vector(0, 0, 0),
- 1,
- 0
- );
- //
- // Remove it if it's reached fullsize
- //
- if (scale == maxSize) {
- iter.Remove();
- } else {
- iter.Next();
- }
- }
- }
- };
- TRef<HullHitGeo> CreateHullHitGeo(Modeler* pmodeler, Number* ptime)
- {
- return new HullHitGeoImpl(pmodeler, ptime);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // BitsGeo
- //
- //////////////////////////////////////////////////////////////////////////////
- const int g_maxBits = 32;
- const int g_bitsLifeTime = 2;
- class BitsGeoImpl : public BitsGeo {
- private:
- typedef TRange<g_maxBits> BitsRange;
- class BitsData {
- public:
- Vector m_vecPosition;
- Vector m_dvecPosition;
- Vector m_axis;
- float m_speed;
- float m_time;
- float m_size;
- };
- BitsData m_data[g_maxBits];
- TRef<Geo> m_pgeo;
- BitsRange m_indexFirst;
- BitsRange m_indexLast;
- float m_time;
- Number* GetTime() { return Number::Cast(GetChild(0)); }
- public:
- BitsGeoImpl(Modeler* pmodeler, Number* ptime) :
- BitsGeo(ptime),
- m_indexFirst(0),
- m_indexLast(0),
- m_time(ptime->GetValue())
- {
- m_pgeo = pmodeler->LoadGeo(AWF_EFFECT_BIT);
- }
- void AddBit(
- const Vector& vecPosition,
- const Vector& dvecPosition,
- float size
- ) {
- --m_indexFirst;
- if (m_indexFirst == m_indexLast) {
- --m_indexLast;
- }
- m_data[m_indexFirst].m_time = m_time;
- m_data[m_indexFirst].m_vecPosition = vecPosition;
- m_data[m_indexFirst].m_dvecPosition = dvecPosition;
- m_data[m_indexFirst].m_axis = Vector::RandomDirection();
- m_data[m_indexFirst].m_speed = random(pi /2, 2 * pi);
- m_data[m_indexFirst].m_size = size;
- }
- void Evaluate()
- {
- m_time = GetTime()->GetValue();
- }
- void Render(Context* pcontext)
- {
- if (m_indexFirst != m_indexLast) {
- for(BitsRange index = m_indexFirst; index != m_indexLast; ++index) {
- BitsData& data = m_data[index];
- float dtime = m_time - data.m_time;
- if (dtime > g_bitsLifeTime) {
- m_indexLast = index;
- break;
- }
- Vector position = data.m_vecPosition + data.m_dvecPosition * dtime;
- pcontext->PushState();
- pcontext->Translate(position);
- pcontext->Scale3(data.m_size);
- pcontext->Rotate(data.m_axis, data.m_speed * dtime);
- m_pgeo->Render(pcontext);
- pcontext->PopState();
- }
- }
- }
- };
- TRef<BitsGeo> CreateBitsGeo(Modeler* pmodeler, Number* ptime)
- {
- return new BitsGeoImpl(pmodeler, ptime);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // BoltGeo
- //
- //////////////////////////////////////////////////////////////////////////////
- class BoltGeo : public Geo, IGeoCallback {
- private:
- TRef<Surface> m_psurface;
- float m_size;
- VectorValue* GetStart() { return VectorValue::Cast(GetChild(0)); }
- VectorValue* GetEnd() { return VectorValue::Cast(GetChild(1)); }
- public:
- BoltGeo(VectorValue* pstart, VectorValue* pend, float size, Surface* psurface) :
- Geo(pstart, pend),
- m_size(size),
- m_psurface(psurface)
- {
- }
- void Render(Context* pcontext)
- {
- pcontext->DrawCallbackGeo(this, false);
- }
- void RenderCallback(Context* pcontext)
- {
- int index;
- //
- // Find two orthogonal vectors
- //
- Vector vecStart = GetStart()->GetValue();
- Vector vecEnd = GetEnd()->GetValue();
- Vector vecForward = vecEnd - vecStart;
- Vector vecUp = vecForward.GetOrthogonalVector().Normalize();
- Vector vecRight = CrossProduct(vecForward, vecUp).Normalize();
- float length = vecForward.Length();
- float size = m_size * length;
- //
- // Calculate the level of detail
- //
- float lengthImage =
- max(
- pcontext->GetImageRadius(vecStart, size),
- pcontext->GetImageRadius(vecEnd, size)
- );
- int lcount;
- if (lengthImage > 128) {
- lcount = 6;
- } else if (lengthImage > 64) {
- lcount = 5;
- } else if (lengthImage > 32) {
- lcount = 4;
- } else {
- lcount = 3;
- }
- //
- // color is based on size
- //
- float bright = min(1.0f, lengthImage / 128);
- Color color(bright, bright, bright);
- //
- // allocate the vertex and index buffers
- //
- int vcount = (1 << lcount) + 1;
- VertexL* pvertex = pcontext->GetVertexLBuffer(vcount);
- for (index = 0; index < vcount; index++) {
- pvertex[index].SetColor(color);
- pvertex[index].SetTextureCoordinate(
- Point(
- (float)index / (float)(vcount - 1),
- 0
- )
- );
- }
- //
- // sub divide
- //
- pvertex[0].SetPosition(vecStart);
- pvertex[vcount - 1].SetPosition(vecEnd);
- for (int level = lcount; level > 0 ; level--) {
- int dbig = 1 << level;
- int dsmall = dbig / 2;
- for (index = dsmall; index < vcount; index += dbig) {
- float angle = random(0, 2 * pi);
- VertexL& vecFirst = pvertex[index - dsmall];
- VertexL& vecLast = pvertex[index + dsmall];
- Vector vecMiddle = 0.5f * (vecFirst.GetPosition() + vecLast.GetPosition());
- Vector vecRandom = size * (cos(angle) * vecUp + sin(angle) * vecRight);
- pvertex[index].SetPosition(vecMiddle + vecRandom);
- }
- size = size / 2;
- }
- //
- // draw it
- //
- pcontext->SetTexture(m_psurface);
- pcontext->SetLineWidth(4);
- pcontext->SetBlendMode(BlendModeAdd);
- pcontext->DrawLineStrip(pvertex, vcount);
- }
- };
- TRef<Geo> CreateBoltGeo(VectorValue* pstart, VectorValue* pend, float size, Surface* psurface)
- {
- return new BoltGeo(pstart, pend, size, psurface);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // CullGeo
- //
- //////////////////////////////////////////////////////////////////////////////
- class CullGeo : public WrapGeo {
- private:
- float m_radius;
- public:
- CullGeo(Geo* pgeo) :
- WrapGeo(pgeo)
- {
- m_radius = GetGeo()->GetRadius(Matrix::GetIdentity());
- }
- void Render(Context* pcontext)
- {
- bool bNoClipping;
- if (!pcontext->IsCulled(Vector::GetZero(), m_radius, bNoClipping)) {
- if (bNoClipping) {
- pcontext->SetClipping(false);
- }
- //float screenRadius = pcontext->GetScreenRadius(Vector::GetZero(), m_radius);
- //pcontext->SetLOD(screenRadius * max(m_lodBiasMin, s_lodBias));
- GetGeo()->Render(pcontext);
- if (bNoClipping) {
- pcontext->SetClipping(true);
- }
- }
- }
- };
- TRef<Geo> CreateCullGeo(Geo* pgeo)
- {
- return new CullGeo(pgeo);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // CopyModeGeo
- //
- //////////////////////////////////////////////////////////////////////////////
- class CopyModeGeo : public WrapGeo {
- public:
- CopyModeGeo(Geo* pgeo) :
- WrapGeo(pgeo)
- {
- }
- void Render(Context* pcontext)
- {
- #ifdef FixPermedia
- pcontext->SetShadeMode(ShadeModeGlobalColor);
- pcontext->SetColor(Color::White());
- #else
- pcontext->SetShadeMode(ShadeModeCopy);
- #endif
- GetGeo()->Render(pcontext);
- }
- };
- TRef<Geo> CreateCopyModeGeo(Geo* pgeo)
- {
- return new CopyModeGeo(pgeo);
- }
|