1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 
4 #include "SmokeProjectile2.h"
5 
6 #include "Game/Camera.h"
7 #include "Game/GlobalUnsynced.h"
8 #include "Map/Ground.h"
9 #include "Rendering/GlobalRendering.h"
10 #include "Rendering/ProjectileDrawer.h"
11 #include "Rendering/GL/VertexArray.h"
12 #include "Rendering/Textures/TextureAtlas.h"
13 #include "Sim/Misc/Wind.h"
14 
15 CR_BIND_DERIVED(CSmokeProjectile2, CProjectile, )
16 
17 CR_REG_METADATA(CSmokeProjectile2,
18 (
19 	CR_MEMBER_BEGINFLAG(CM_Config),
20 		CR_MEMBER(color),
21 		CR_MEMBER(ageSpeed),
22 		CR_MEMBER(size),
23 		CR_MEMBER(startSize),
24 		CR_MEMBER(sizeExpansion),
25 		CR_MEMBER(wantedPos),
26 		CR_MEMBER(glowFalloff),
27 	CR_MEMBER_ENDFLAG(CM_Config),
28 	CR_MEMBER(age),
29 	CR_MEMBER(textureNum),
30 	CR_RESERVED(8)
31 ))
32 
33 //////////////////////////////////////////////////////////////////////
34 // Construction/Destruction
35 //////////////////////////////////////////////////////////////////////
36 
CSmokeProjectile2()37 CSmokeProjectile2::CSmokeProjectile2():
38 	CProjectile(),
39 	color(0.5f),
40 	age(0.0f),
41 	ageSpeed(1.0f),
42 	size(0.0f),
43 	startSize(0.0f),
44 	sizeExpansion(0.0f),
45 	textureNum(0),
46 	glowFalloff(0.0f)
47 {
48 	deleteMe = false;
49 	checkCol = false;
50 }
51 
CSmokeProjectile2(CUnit * owner,const float3 & pos,const float3 & wantedPos,const float3 & speed,float ttl,float startSize,float sizeExpansion,float color)52 CSmokeProjectile2::CSmokeProjectile2(
53 	CUnit* owner,
54 	const float3& pos,
55 	const float3& wantedPos,
56 	const float3& speed,
57 	float ttl,
58 	float startSize,
59 	float sizeExpansion,
60 	float color)
61 : CProjectile(pos, speed, owner, false, false, false),
62 	color(color),
63 	age(0),
64 	size(0),
65 	startSize(startSize),
66 	sizeExpansion(sizeExpansion),
67 	wantedPos(wantedPos)
68 {
69 	ageSpeed = 1 / ttl;
70 	checkCol = false;
71 	castShadow = true;
72 	if ((pos.y - CGround::GetApproximateHeight(pos.x, pos.z, false)) > 10) {
73 		useAirLos = true;
74 	}
75 	glowFalloff = 4.5f + gu->RandFloat() * 6;
76 	textureNum = (int)(gu->RandInt() % projectileDrawer->smoketex.size());
77 }
78 
79 
80 
Init(const CUnit * owner,const float3 & offset)81 void CSmokeProjectile2::Init(const CUnit* owner, const float3& offset)
82 {
83 	textureNum = (int) (gu->RandInt() % projectileDrawer->smoketex.size());
84 
85 	if (offset.y - CGround::GetApproximateHeight(offset.x, offset.z, false) > 10) {
86 		useAirLos = true;
87 	}
88 
89 	if (!owner) {
90 		alwaysVisible = true;
91 	}
92 
93 	wantedPos += offset;
94 
95 	CProjectile::Init(owner, offset);
96 }
97 
Update()98 void CSmokeProjectile2::Update()
99 {
100 	wantedPos += speed;
101 	wantedPos += wind.GetCurrentWind() * age * 0.05f;
102 
103 	pos.x += (wantedPos.x - pos.x) * 0.07f;
104 	pos.y += (wantedPos.y - pos.y) * 0.02f;
105 	pos.z += (wantedPos.z - pos.z) * 0.07f;
106 	age += ageSpeed;
107 	size += sizeExpansion;
108 	if (size < startSize) {
109 		size += (startSize - size) * 0.2f;
110 	}
111 	SetRadiusAndHeight(size, 0.0f);
112 	if (age > 1) {
113 		age = 1;
114 		deleteMe = true;
115 	}
116 }
117 
Draw()118 void CSmokeProjectile2::Draw()
119 {
120 	inArray = true;
121 	const float interAge = std::min(1.0f, age + ageSpeed * globalRendering->timeOffset);
122 	unsigned char col[4];
123 	unsigned char alpha;
124 	if (interAge < 0.05f) {
125 		alpha = (unsigned char) (interAge * 19 * 127);
126 	} else {
127 		alpha = (unsigned char) ((1 - interAge) * 127);
128 	}
129 	const float rglow = std::max(0.f, (1 - (interAge * glowFalloff))        * 127);
130 	const float gglow = std::max(0.f, (1 - (interAge * glowFalloff * 2.5f)) * 127);
131 	col[0] = (unsigned char) (color * alpha + rglow);
132 	col[1] = (unsigned char) (color * alpha + gglow);
133 	col[2] = (unsigned char) std::max(0.f, color * alpha - gglow * 0.5f);
134 	col[3] = alpha/*-alphaFalloff*globalRendering->timeOffset*/;
135 
136 	const float3 interPos = pos + (wantedPos + speed * globalRendering->timeOffset - pos) * 0.1f * globalRendering->timeOffset;
137 	const float interSize = size + sizeExpansion * globalRendering->timeOffset;
138 	const float3 pos1 ((camera->right - camera->up) * interSize);
139 	const float3 pos2 ((camera->right + camera->up) * interSize);
140 
141 	#define st projectileDrawer->smoketex[textureNum]
142 	va->AddVertexTC(interPos - pos2, st->xstart, st->ystart, col);
143 	va->AddVertexTC(interPos + pos1, st->xend,   st->ystart, col);
144 	va->AddVertexTC(interPos + pos2, st->xend,   st->yend,   col);
145 	va->AddVertexTC(interPos - pos1, st->xstart, st->yend,   col);
146 	#undef st
147 }
148