absence_thelab

view src/3deng/objects.cpp @ 0:1cffe3409164

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 23 Oct 2014 01:46:07 +0300
parents
children
line source
1 #include "objects.h"
2 #include "3dengine.h"
3 #include "objectgen.h"
5 Object::Object(GraphicsContext *gc, byte DetailLevels) {
6 this->gc = gc;
8 mesh = new TriMesh(DetailLevels, gc);
10 SetShadingMode(GouraudShading);
11 SetVertexProgram(FixedFunction);
12 SetPixelProgram(0);
13 rendp.Billboarded = false;
14 rendp.SourceBlendFactor = BLEND_SRCALPHA;
15 rendp.DestBlendFactor = BLEND_INVSRCALPHA;
16 rendp.ZWrite = true;
17 ShadowCount = 0;
18 UseTextureMatrix = false;
20 ShadowVolumes = 0;
21 CastShadows = false;
23 AutoSetZWrite = true;
24 }
26 Object::~Object() {
27 delete mesh;
28 if(rendp.VertexProgram != FixedFunction) gc->DestroyVertexProgram(rendp.VertexProgram);
29 }
31 TriMesh *Object::GetTriMesh() {
32 return mesh;
33 }
36 // Reset Transformation Matrices
37 void Object::ResetTransform() {
38 TransMat.ResetIdentity();
39 RotMat.ResetIdentity();
40 GRotMat.ResetIdentity();
41 ScaleMat.ResetIdentity();
42 }
44 void Object::ResetTranslation() {
45 TransMat.ResetIdentity();
46 }
48 void Object::ResetRotation() {
49 RotMat.ResetIdentity();
50 }
52 void Object::ResetGlobalRotation() {
53 GRotMat.ResetIdentity();
54 }
56 void Object::ResetScaling() {
57 ScaleMat.ResetIdentity();
58 }
60 // Concatenate additional transformations
61 void Object::Translate(float tx, float ty, float tz) {
62 TransMat.Translate(tx, ty, tz);
63 }
65 void Object::Rotate(float rx, float ry, float rz) {
66 RotMat.Rotate(rx, ry, rz);
67 }
69 void Object::Rotate(const Vector3 &axis, float angle) {
70 RotMat.Rotate(axis, angle);
71 }
73 void Object::Rotate(const Matrix4x4 &rot) {
74 RotMat *= rot;
75 }
77 void Object::GlobalRotate(float rx, float ry, float rz) {
78 GRotMat.Rotate(rx, ry, rz);
79 }
81 void Object::GlobalRotate(const Vector3 &axis, float angle) {
82 GRotMat.Rotate(axis, angle);
83 }
85 void Object::GlobalRotate(const Matrix4x4 &rot) {
86 GRotMat *= rot;
87 }
89 void Object::Scale(float sx, float sy, float sz) {
90 ScaleMat.Scale(sx, sy, sz);
91 }
93 void Object::SetTranslation(float tx, float ty, float tz) {
94 TransMat.SetTranslation(tx, ty, tz);
95 }
97 void Object::SetRotation(float rx, float ry, float rz) {
98 RotMat.Rotate(rx, ry, rz);
99 }
101 void Object::SetRotation(const Vector3 &axis, float angle) {
102 RotMat.Rotate(axis, angle);
103 }
105 void Object::SetRotation(const Matrix4x4 &rot) {
106 RotMat = rot;
107 }
109 void Object::SetGlobalRotation(float rx, float ry, float rz) {
110 GRotMat.Rotate(rx, ry, rz);
111 }
113 void Object::SetGlobalRotation(const Vector3 &axis, float angle) {
114 GRotMat.Rotate(axis, angle);
115 }
117 void Object::SetGlobalRotation(const Matrix4x4 &rot) {
118 GRotMat = rot;
119 }
121 void Object::SetScaling(float sx, float sy, float sz) {
122 ScaleMat.Scale(sx, sy, sz);
123 }
125 const Matrix4x4 Object::GetWorldTransform() const {
126 return ScaleMat * RotMat * TransMat * GRotMat;
127 }
129 void Object::SetTextureMatrix(Matrix4x4 mat) {
130 UseTextureMatrix = true;
131 TextureMatrix = mat;
132 }
134 Matrix4x4 Object::GetTextureMatrix() const {
135 return TextureMatrix;
136 }
138 void Object::SetVertexProgram(dword VertexProgram) {
139 rendp.VertexProgram = VertexProgram;
140 }
142 void Object::SetPixelProgram(dword PixelProgram) {
143 rendp.PixelProgram = PixelProgram;
144 }
146 void Object::SetShadingMode(ShadeMode smode) {
147 rendp.Shading = smode;
148 }
150 void Object::SetWriteZBuffer(bool enable) {
151 rendp.ZWrite = enable;
152 AutoSetZWrite = false;
153 }
155 void Object::SetBlendFunc(BlendingFactor src, BlendingFactor dest) {
156 rendp.SourceBlendFactor = src;
157 rendp.DestBlendFactor = dest;
158 }
160 void Object::GetBlendFunc(BlendingFactor *src, BlendingFactor *dest) {
161 *src = rendp.SourceBlendFactor;
162 *dest = rendp.DestBlendFactor;
163 }
165 void Object::CalculateShadows(const Light **lights, int LightCount) {
166 if(ShadowVolumes) {
167 for(int i=0; i<ShadowCount; i++) {
168 delete ShadowVolumes[i];
169 }
170 delete ShadowVolumes;
171 }
173 ShadowVolumes = new TriMesh*[LightCount];
174 for(int i=0; i<LightCount; i++) {
175 ShadowVolumes[i] = CreateShadowVolume(*mesh, lights[i], GetWorldTransform());
176 }
178 ShadowCount = LightCount;
179 }
181 TriMesh *Object::GetShadowVolume(int light) {
182 if(light >= ShadowCount) return 0;
183 return ShadowVolumes[light];
184 }
186 void Object::SetShadowCasting(bool enable) {
187 CastShadows = enable;
188 }
190 bool Object::GetShadowCasting() const {
191 return CastShadows;
192 }
194 ///////////////////////////
196 void Object::SetRenderStates() {
197 gc->SetWorldMatrix(GetWorldTransform());
199 gc->SetMaterial(material);
200 if(AutoSetZWrite && material.Alpha < 0.991f) rendp.ZWrite = false;
201 gc->SetSpecular(material.SpecularEnable);
203 gc->SetVertexProgram(rendp.VertexProgram);
204 gc->SetPixelProgram(rendp.PixelProgram);
205 gc->SetShadingMode(rendp.Shading);
206 }
208 void Object::Render() {
209 int TexUnits = gc->GetTextureStageNumber();
211 if(TexUnits < 4) {
212 Render2TexUnits();
213 } else if(TexUnits < 8) {
214 Render4TexUnits();
215 } else {
216 Render8TexUnits();
217 }
218 }
220 void Object::Render2TexUnits() {
222 SetRenderStates();
224 VertexBuffer *vb = const_cast<VertexBuffer*>(mesh->GetVertexBuffer());
225 IndexBuffer *ib = const_cast<IndexBuffer*>(mesh->GetIndexBuffer());
227 Material mat = material;
229 int TexCount = 0;
230 for(int i=0; i<NumberOfTextureTypes; i++) {
231 if(mat.Maps[i]) TexCount++;
232 }
234 if(!rendp.ZWrite) gc->SetZWrite(false);
236 if(!TexCount) {
237 // render without any texture
238 gc->SetTexture(0, 0);
239 gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgDiffuseColor, TexArgTexture);
240 if(mat.Alpha < 1.0f) {
241 gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32());
242 gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgFactor, TexArgDiffuseColor);
243 } else {
244 gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
245 }
246 gc->DisableTextureStage(1);
248 gc->SetAlphaBlending(true);
249 gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor);
250 gc->Draw(vb, ib);
251 gc->SetAlphaBlending(false);
252 } else {
254 ////////// pass 1 (texture & env) ///////////
255 int stage = 0;
256 if(mat.Maps[TextureMap]) {
257 if(UseTextureMatrix) gc->SetTextureMatrix(TextureMatrix, 0);
258 gc->SetTexture(stage, mat.Maps[TextureMap]);
259 gc->SetTextureStageColor(stage, TexBlendModulate, TexArgCurrent, TexArgTexture);
260 if(mat.Alpha < 1.0f) {
261 gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32());
262 gc->SetTextureStageAlpha(stage, TexBlendModulate, TexArgTexture, TexArgFactor);
263 } else {
264 gc->SetTextureStageAlpha(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture);
265 }
266 gc->SetTextureCoordIndex(stage, 0);
267 stage++;
268 }
270 if(mat.Maps[EnvironmentMap]) {
271 gc->SetTexture(stage, mat.Maps[EnvironmentMap]);
272 gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture);
273 gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
274 Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f);
275 gc->SetTextureMatrix(TexMat, stage);
276 gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
277 gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
278 stage++;
279 }
281 gc->SetTexture(stage, 0);
282 gc->DisableTextureStage(stage);
284 if(stage > 0) {
285 gc->SetAlphaBlending(true);
286 gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor);
287 gc->Draw(vb, ib);
288 gc->SetAlphaBlending(false);
290 gc->SetTextureMatrix(Matrix4x4(), 0);
291 gc->SetTextureMatrix(Matrix4x4(), 1);
292 }
294 ////////// pass 2 (Bump & Lightmap) //////////
295 if(stage > 0) { // did a first pass
296 gc->SetAlphaBlending(true);
297 gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); // mult blend
298 mat.Emissive = Color(1.0f); // do not recalculate lighting
299 }
301 stage = 0;
302 if(mat.Maps[LightMap]) {
303 gc->SetTexture(stage, mat.Maps[LightMap]);
304 gc->SetTextureStageColor(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture);
305 gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
306 gc->SetTextureCoordIndex(stage, 1);
307 stage++;
308 }
310 if(mat.Maps[BumpMap]) {
311 // re-implementation due
312 }
314 gc->SetTexture(stage, 0);
315 gc->DisableTextureStage(stage);
317 if(stage > 0) gc->Draw(vb, ib);
319 gc->SetAlphaBlending(false);
320 }
322 if(!rendp.ZWrite) gc->SetZWrite(true);
323 }
326 void Object::Render4TexUnits() {
327 SetRenderStates();
329 VertexBuffer *vb = const_cast<VertexBuffer*>(mesh->GetVertexBuffer());
330 IndexBuffer *ib = const_cast<IndexBuffer*>(mesh->GetIndexBuffer());
332 Material mat = material;
334 int TexCount = 0;
335 for(int i=0; i<NumberOfTextureTypes; i++) {
336 if(mat.Maps[i]) TexCount++;
337 }
339 if(!rendp.ZWrite) gc->SetZWrite(false);
341 if(!TexCount) {
342 // render without any texture
343 gc->SetTexture(0, 0);
344 gc->SetTextureStageColor(0, TexBlendSelectArg1, TexArgDiffuseColor, TexArgTexture);
345 if(mat.Alpha < 1.0f) {
346 gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32());
347 gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgFactor, TexArgDiffuseColor);
348 } else {
349 gc->SetTextureStageAlpha(0, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
350 }
351 gc->DisableTextureStage(1);
353 gc->SetAlphaBlending(true);
354 gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor);
355 gc->Draw(vb, ib);
356 gc->SetAlphaBlending(false);
357 } else {
359 ////////// pass 1 (texture, detail, env, bump) ///////////
360 int stage = 0;
361 if(mat.Maps[TextureMap]) {
362 if(UseTextureMatrix) gc->SetTextureMatrix(TextureMatrix, 0);
363 gc->SetTexture(stage, mat.Maps[TextureMap]);
364 gc->SetTextureStageColor(stage, TexBlendModulate, TexArgCurrent, TexArgTexture);
365 if(mat.Alpha < 1.0f) {
366 gc->SetTextureFactor(Color(mat.Alpha, mat.Alpha, mat.Alpha, mat.Alpha).GetPacked32());
367 gc->SetTextureStageAlpha(stage, TexBlendModulate, TexArgTexture, TexArgFactor);
368 } else {
369 gc->SetTextureStageAlpha(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture);
370 }
371 gc->SetTextureCoordIndex(stage, 0);
372 stage++;
373 }
375 if(mat.Maps[DetailMap]) {
376 gc->SetTexture(stage, mat.Maps[DetailMap]);
377 gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture);
378 gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
379 gc->SetTextureCoordIndex(stage, 1);
380 stage++;
381 }
383 if(mat.Maps[EnvironmentMap]) {
384 gc->SetTexture(stage, mat.Maps[EnvironmentMap]);
385 gc->SetTextureStageColor(stage, TexBlendAdd, TexArgCurrent, TexArgTexture);
386 gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
387 Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 1.0f);
388 gc->SetTextureMatrix(TexMat, stage);
389 gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
390 gc->D3DDevice->SetTextureStageState(stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
391 stage++;
392 }
394 if(mat.Maps[BumpMap]) {
395 // re-implementation due
396 }
398 gc->SetTexture(stage, 0);
399 gc->DisableTextureStage(stage);
401 if(stage > 0) {
402 gc->SetAlphaBlending(true);
403 gc->SetBlendFunc(rendp.SourceBlendFactor, rendp.DestBlendFactor);
404 gc->Draw(vb, ib);
405 gc->SetAlphaBlending(false);
407 gc->SetTextureMatrix(Matrix4x4(), 0);
408 gc->SetTextureMatrix(Matrix4x4(), 1);
409 gc->SetTextureMatrix(Matrix4x4(), 2);
410 }
412 ////////// pass 2 (Bump & Lightmap) //////////
413 if(stage > 0) { // did a first pass
414 gc->SetAlphaBlending(true);
415 gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO); // mult blend
416 mat.Emissive = Color(1.0f); // do not recalculate lighting
417 }
419 stage = 0;
420 if(mat.Maps[LightMap]) {
421 gc->SetTexture(stage, mat.Maps[LightMap]);
422 gc->SetTextureStageColor(stage, TexBlendSelectArg2, TexArgCurrent, TexArgTexture);
423 gc->SetTextureStageAlpha(stage, TexBlendSelectArg1, TexArgCurrent, TexArgTexture);
424 gc->SetTextureCoordIndex(stage, 1);
425 stage++;
426 }
428 gc->SetTexture(stage, 0);
429 gc->DisableTextureStage(stage);
431 if(stage > 0) gc->Draw(vb, ib);
433 gc->SetAlphaBlending(false);
434 }
436 if(!rendp.ZWrite) gc->SetZWrite(false);
437 }
440 void Object::Render8TexUnits() {Render4TexUnits();}
444 /*
445 void Object::Render() {
447 SetRenderStates();
449 VertexBuffer *vb = const_cast<VertexBuffer*>(mesh->GetVertexBuffer());
450 IndexBuffer *ib = const_cast<IndexBuffer*>(mesh->GetIndexBuffer());
452 Material mat = material;
453 int MapsCount = 0, ActiveTex = 0;
454 for(int i=0; i<NumberOfTextureTypes; i++) {
455 if(mat.Maps[i]) MapsCount++;
456 }
458 if(!MapsCount) {
459 gc->SetTexture(0, 0);
460 gc->DisableTextureStage(0);
461 gc->Draw(vb, ib);
462 } else {
463 int pass = 1;
464 TextureType PassFirstTexture;
465 while(MapsCount) {
467 if(mat.Maps[BumpMap]) {
468 gc->SetTexture(ActiveTex, mat.Maps[BumpMap]);
469 //gc->SetTextureFactor() TODO
470 gc->SetTextureStageColor(ActiveTex, TexBlendDotProduct, TexArgFactor, TexArgTexture);
471 mat.Maps[BumpMap] = 0;
472 if(!ActiveTex) PassFirstTexture = BumpMap;
473 } else if(mat.Maps[TextureMap]) {
474 gc->SetTexture(ActiveTex, mat.Maps[TextureMap]);
475 gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgTexture);
476 //gc->SetTextureStageColor(ActiveTex, TexBlendSelectArg2, TexArgCurrent, TexArgTexture);
477 gc->SetTextureCoordIndex(ActiveTex, 0);
478 mat.Maps[TextureMap] = 0;
479 if(!ActiveTex) PassFirstTexture = TextureMap;
480 } else if(mat.Maps[DetailMap]) {
481 gc->SetTexture(ActiveTex, mat.Maps[DetailMap]);
482 gc->SetTextureStageColor(ActiveTex, TexBlendAdd, TexArgCurrent, TexArgTexture);
483 gc->SetTextureCoordIndex(ActiveTex, 1);
484 mat.Maps[DetailMap] = 0;
485 if(!ActiveTex) PassFirstTexture = DetailMap;
486 } else if(mat.Maps[EnvironmentMap]) {
487 gc->SetTexture(ActiveTex, mat.Maps[EnvironmentMap]);
488 gc->SetTextureStageColor(ActiveTex, TexBlendAdd, TexArgCurrent, TexArgTexture);
490 //gc->SetTextureCoordGenerator(TexGenSpherical); TODO
491 Matrix4x4 TexMat = Matrix4x4(0.5f, 0.0f, 0.0f, 0.0f,
492 0.0f, -0.5f, 0.0f, 0.0f,
493 0.0f, 0.0f, 1.0f, 0.0f,
494 0.5f, 0.5f, 0.0f, 1.0f );
495 gc->SetTextureMatrix(TexMat, ActiveTex);
496 gc->D3DDevice->SetTextureStageState(ActiveTex, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
497 gc->D3DDevice->SetTextureStageState(ActiveTex, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
499 mat.Maps[EnvironmentMap] = 0;
500 if(!ActiveTex) PassFirstTexture = EnvironmentMap;
501 } else if(mat.Maps[LightMap]) {
502 gc->SetTexture(ActiveTex, mat.Maps[LightMap]);
503 gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgTexture);
504 gc->SetTextureCoordIndex(ActiveTex, 2);
505 mat.Maps[LightMap] = 0;
506 if(!ActiveTex) PassFirstTexture = LightMap;
507 }
509 MapsCount--;
510 ActiveTex++;
512 if(!MapsCount) {
513 gc->SetTextureStageColor(ActiveTex, TexBlendModulate, TexArgCurrent, TexArgDiffuseColor);
514 }
516 if(ActiveTex >= gc->GetTextureStageNumber() || !MapsCount) {
517 if(pass++ > 1) {
518 gc->SetAlphaBlending(true);
519 if(PassFirstTexture == DetailMap || PassFirstTexture == EnvironmentMap) {
520 gc->SetBlendFunc(BLEND_ONE, BLEND_ONE);
521 } else {
522 gc->SetBlendFunc(BLEND_DESTCOLOR, BLEND_ZERO);
523 }
524 gc->Draw(vb, ib);
525 gc->SetAlphaBlending(false);
526 } else {
527 gc->Draw(vb, ib);
528 }
529 ActiveTex = 0;
530 for(int i=0; i<gc->GetTextureStageNumber(); i++) {
531 gc->SetTextureMatrix(Matrix4x4(), i);
532 }
533 }
534 }
535 }
537 if(material.SpecularEnable) gc->SetSpecular(false);
538 }
539 */
543 void Object::RenderBare() {
544 VertexBuffer *vb = const_cast<VertexBuffer*>(mesh->GetVertexBuffer());
545 IndexBuffer *ib = const_cast<IndexBuffer*>(mesh->GetIndexBuffer());
546 gc->Draw(vb, ib);
547 }
550 // generate geometry
551 void Object::CreatePlane(float size, dword subdivisions) {
552 ObjGen::CreatePlane(gc, size, subdivisions, &mesh, mesh->GetLevelCount());
553 }
555 void Object::CreateCube(float size) {
556 ObjGen::CreateCube(gc, size, &mesh, mesh->GetLevelCount());
557 }