3 #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
4 #define ECERE_NOTRUETYPE
12 import "DisplaySystem"
15 import "BitmapResource"
17 import "LFBDisplayDriver"
19 // TOFIX: Temporary until we pass Display instead of DisplaySystem to FontExtent
20 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
21 import "GDIDisplayDriver"
24 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
34 #if (!defined(ECERE_VANILLA) && !defined(ECERE_ONEDRIVER))
35 import "OpenGLDisplayDriver"
44 public class GLCapabilities : uint
47 // Expect reloading graphics
52 bool legacyFormats :1;
53 bool nonPow2Textures :1;
54 bool vertexPointer :1;
56 // Should be able to toggle without reloading
59 bool fixedFunction :1;
70 public enum RenderState { fillMode = 1, depthTest, depthWrite, fogDensity, fogColor, blend, ambient, alphaWrite, antiAlias, vSync };
72 public union RenderStateFloat { float f; uint ui; };
74 public enum FillModeValue { solid, wireframe };
76 public class DisplayFlags
78 public bool fullScreen:1, flipping:1, alpha:1, memBackBuffer:1, text:1, scrolling:1, printer:1;
80 public class FontFlags
82 public bool bold:1, italic:1, underline:1;
85 __attribute__((unused)) static void DummyFunction()
90 public class DisplayDriver
93 class_data const char * name;
94 class_data bool textMode;
95 class_data bool printer;
96 class_data DisplaySystem displaySystem;
98 class_property DisplaySystem displaySystem
100 set { class_data(displaySystem) = value; }
101 get { return class_data(displaySystem); }
104 class_property const char * name
106 set { class_data(name) = value; }
107 get { return class_data(name); }
110 class_property bool printer
112 set { class_data(printer) = value; }
113 get { return class_data(printer); }
116 // Constructor / Destructor
117 virtual bool ::CreateDisplaySystem(DisplaySystem);
118 virtual void ::DestroyDisplaySystem(DisplaySystem);
120 virtual bool ::CreateDisplay(Display);
121 virtual void ::DestroyDisplay(Display);
123 // Display Position and Size
124 virtual bool ::DisplaySize(Display, int, int);
125 virtual void ::DisplayPosition(Display, int, int);
128 virtual void ::SetPalette(Display, ColorAlpha *, bool);
129 virtual void ::RestorePalette(Display);
131 // Display the back buffer content
132 virtual void ::StartUpdate(Display);
133 virtual void ::Scroll(Display, Box, int, int, Extent);
134 virtual void ::Update(Display, Box);
135 virtual void ::EndUpdate(Display);
137 // Allocate/free a bitmap
138 virtual bool ::AllocateBitmap(DisplaySystem, Bitmap, int, int, int, PixelFormat, bool);
139 virtual void ::FreeBitmap(DisplaySystem, Bitmap);
142 virtual bool ::LockSystem(DisplaySystem displaySystem);
143 virtual void ::UnlockSystem(DisplaySystem displaySystem);
145 virtual bool ::Lock(Display);
146 virtual void ::Unlock(Display);
148 // Get/release a surface
149 virtual bool ::GetSurface(Display, Surface surface, int,int,Box);
150 virtual bool ::GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int,int,Box);
151 virtual void ::ReleaseSurface(Display this, Surface);
154 virtual void ::Clip(Display, Surface, Box);
156 // Grab from the screen
157 virtual bool ::GrabScreen(Display, Bitmap, int, int, unsigned int, unsigned int);
159 // Converts a bitmap format
160 virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *);
162 // Converts an LFB bitmap into an offscreen bitmap for this device
163 virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool mipMaps, int cubeMapFace);
166 virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade);
167 virtual void ::UnloadFont(DisplaySystem, Font);
170 virtual void ::SetForeground(Display, Surface, ColorAlpha);
171 virtual void ::SetBackground(Display, Surface, ColorAlpha);
172 virtual void ::LineStipple(Display, Surface, uint pattern);
173 virtual ColorAlpha ::GetPixel(Display, Surface, int x, int y);
174 virtual void ::PutPixel(Display, Surface, int x, int y);
175 virtual void ::DrawLine(Display, Surface, int x1, int y1, int x2, int y2);
176 virtual void ::Rectangle(Display, Surface, int x1, int y1, int x2, int y2);
177 virtual void ::Area(Display, Surface, int x1, int y1, int x2, int y2);
178 virtual void ::Clear(Display, Surface, ClearType);
179 virtual void ::Blit(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h);
180 virtual void ::Stretch(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh);
181 virtual void ::Filter(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh);
182 virtual void ::BlitDI(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h);
183 virtual void ::StretchDI(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh);
184 virtual void ::FilterDI(Display, Surface, Bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh);
185 virtual void ::TextFont(Display, Surface, Font);
186 virtual void ::TextOpacity(Display, Surface, bool);
187 virtual void ::WriteText(Display, Surface, int x, int y, const String text, int len, int prevGlyph, int * rPrevGlyph);
188 virtual void ::TextExtent(Display, Surface, const String text, int len, int * tw, int * th, int prevGlyph, int * rPrevGlyph, int * overHang);
189 virtual void ::FontExtent(DisplaySystem, Font, const String text, int len, int * tw, int * th, int prevGlyph, int * rPrevGlyph, int * overHang);
190 virtual void ::DrawingChar(Display, Surface, char ch);
191 virtual void ::NextPage(Display);
192 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
194 virtual void ::SetRenderState(Display, RenderState, uint);
195 virtual void ::SetLight(Display, int, Light);
196 virtual void ::SetCamera(Display, Surface, Camera);
197 virtual bool ::AllocateMesh(DisplaySystem, Mesh, MeshFeatures, int nVertices);
198 virtual void ::FreeMesh(DisplaySystem, Mesh);
199 virtual bool ::LockMesh(DisplaySystem, Mesh, MeshFeatures flags);
200 virtual void ::UnlockMesh(DisplaySystem, Mesh, MeshFeatures flags);
201 virtual void * ::AllocateIndices(DisplaySystem, int nIndices, bool indices32bit);
202 virtual void ::FreeIndices(DisplaySystem, void * indices);
203 virtual uint16 * ::LockIndices(DisplaySystem, void * indices);
204 virtual void ::UnlockIndices(DisplaySystem, void * indices, bool indices32bit, int nIndices);
205 virtual void ::SelectMesh(Display, Mesh);
206 virtual void ::ApplyMaterial(Display, Material, Mesh);
207 virtual void ::DrawPrimitives(Display, PrimitiveSingle *, Mesh mesh);
208 virtual void ::PushMatrix(Display);
209 virtual void ::PopMatrix(Display, bool);
210 virtual void ::SetTransform(Display, Matrix, bool, bool);
212 virtual void ::SetBlitTint(Display, Surface, ColorAlpha);
215 public enum Alignment { left, right, center };
216 public enum ClearType { colorBuffer, depthBuffer, colorAndDepth };
218 subclass(DisplayDriver) GetDisplayDriver(const char * driverName)
223 for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
225 subclass(DisplayDriver) displayDriver = link.data;
226 if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
227 return displayDriver;
233 DisplaySystem GetDisplaySystem(const char * driverName)
235 subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
236 return displayDriver ? displayDriver.displaySystem : null;
239 define textCellW = 8;
240 define textCellH = 16;
242 public enum PixelFormat // : byte MESSES UP GuiApplication
244 pixelFormat4, pixelFormat8, pixelFormat444, pixelFormat555, pixelFormat565, pixelFormat888, pixelFormatAlpha, pixelFormatText, pixelFormatRGBA
246 public enum Resolution : int
248 resText80x25, res320x200, res320x240, res320x400, res360x480, res400x256, res400x300, res512x256, res512x384,
249 res640x200, res640x350, res640x400, res640x480, res720x348, res800x600, res856x480, res960x720, res1024x768,
250 res1152x864, res1280x1024, res1600x1200, res768x480
253 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
254 public class LightFlags
256 public bool off:1, spot:1, omni:1, attenuation:1;
266 Quaternion orientation;
279 public define NumberOfLights = 8;
281 // Painter's algorithm
283 public class HitRecord : struct
286 HitRecord prev, next;
290 void * tags[1]; // More tags may follow
292 int Compare(HitRecord recordB, void * unused)
294 if(center.z > recordB.center.z)
296 else if(center.z < recordB.center.z)
298 else if(pos > recordB.pos)
300 else if(pos < recordB.pos)
307 #define EPSILON 0.00001
311 PrimitiveSingle * triangle;
318 int Compare(SortPrimitive primitive2)
321 if(ZOverlap(primitive2) && Sgn(plane.d) != Sgn(primitive2.plane.d))
322 value = plane.d - primitive2.plane.d;
324 value = middle.z - primitive2.middle.z;
328 else if(value<-EPSILON)
334 bool ZOverlap(SortPrimitive poly2)
336 if(min.z > poly2.max.z - EPSILON || poly2.min.z > max.z - EPSILON)
342 bool XYOverlap(SortPrimitive poly2)
344 if(min.x > poly2.max.x - EPSILON || poly2.min.x > max.x - EPSILON )
346 if(min.y > poly2.max.y - EPSILON || poly2.min.y > max.y - EPSILON )
351 bool SurfaceOutside(SortPrimitive poly2)
355 PrimitiveSingle * primitive = triangle;
356 Mesh mesh = object.mesh;
357 Matrix * matrix = &object.matrix;
359 double a = poly2.plane.a, b = poly2.plane.b, c = poly2.plane.c, d = poly2.plane.d;
365 d = - (a * poly2.middle.x + b * poly2.middle.y + c * poly2.middle.z);
368 for(v = 0; v < primitive->nIndices; v++)
371 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
374 vertex.MultMatrix(local, matrix);
376 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
378 if(surface < EPSILON)
391 bool SurfaceInside(SortPrimitive poly2)
395 PrimitiveSingle * primitive = poly2.triangle;
396 Mesh mesh = poly2.object.mesh;
397 Matrix * matrix = &poly2.object.matrix;
399 double a = plane.a, b = plane.b, c = plane.c, d = plane.d;
405 d = - (a * middle.x + b * middle.y + c * middle.z);
408 for(v = 0; v < primitive->nIndices; v++)
411 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
414 vertex.MultMatrix(local, matrix);
416 surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
417 if(surface > -EPSILON)
430 bool ShouldBeSwapped(SortPrimitive poly2)
432 if (!XYOverlap(poly2)) return false;
433 if (SurfaceOutside(poly2)) return false;
434 if (SurfaceInside(poly2)) return false;
442 #define MAX_CLIP_POINTS 50
451 displaySystem.numDisplays--;
452 displaySystem.driver.DestroyDisplay(this);
454 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
459 bool Create(DisplaySystem displaySystem, void * window)
464 this.displaySystem = displaySystem;
465 this.window = window;
466 displaySystem.numDisplays++;
467 if(displaySystem.driver.CreateDisplay(this))
469 // if(!result) LogErrorCode(DisplayInitFailed, displaySystem.driver.name);
474 Surface GetSurface(int x, int y, Box clip)
476 Surface result = null;
477 Surface surface { _refCount = 1 };
480 Box box { -x, -y, -x + width - 1, -y + height - 1 };
483 surface.width = width - x;
484 surface.height = height - y;
485 surface.driver = displaySystem.driver;
486 surface.displaySystem = displaySystem;
487 surface.display = this;
489 if(displaySystem.driver.GetSurface(this, surface, x, y, box))
497 bool Resize(int width, int height)
499 return displaySystem.driver.DisplaySize(this, width, height);
502 void Position(int x, int y)
504 displaySystem.driver.DisplayPosition(this, x,y);
507 void StartUpdate(void)
509 displaySystem.driver.StartUpdate(this);
512 void Scroll(Box scroll, int x, int y, Extent dirty)
514 displaySystem.driver.Scroll(this, scroll, x, y, dirty);
517 void Update(Box updateBox)
519 displaySystem.driver.Update(this, updateBox);
524 displaySystem.driver.EndUpdate(this);
529 displaySystem.driver.NextPage(this);
532 bool Grab(Bitmap bitmap, int x, int y, int w, int h)
535 if(bitmap && w > 0 && h > 0 &&
536 displaySystem.driver.GrabScreen(this, bitmap, x, y, w, h))
543 void FontExtent(Font font, const char * text, int len, int * width, int * height)
546 FontExtent2(font, text, len, width, height, 0, null, &overHang);
547 if(width) *width += overHang;
550 void FontExtent2(Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * overHang)
552 // Fix for OnLoadGraphics time alpha blended window text extent on GDI
553 #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
554 if(this && alphaBlend && pixelFormat == pixelFormat888 &&
555 displaySystem.driver == class(GDIDisplayDriver))
557 Surface s = GetSurface(0,0,null);
561 s.TextExtent2(text, len, width, height, prevGlyph, rPrevGlyph, overHang);
567 // TODO: Should really pass display here...
568 DisplaySystem::FontExtent2(this ? displaySystem : null, font, text, len, width, height, prevGlyph, rPrevGlyph, overHang);
571 void SetPalette(ColorAlpha * palette, bool colorMatch)
573 displaySystem.driver.SetPalette(this, palette, colorMatch);
576 void RestorePalette(void)
578 displaySystem.driver.RestorePalette(this);
581 bool Lock(bool render)
586 for(c = 0; c<current; c++)
588 Logf("Locking (%d)\n", current+1);
591 // TOCHECK: Why is displaySystem null with GISDesigner?
592 result = displaySystem && displaySystem.Lock();
598 result = displaySystem.driver.Lock(this);
614 for(c = 0; c<current; c++)
616 Logf("Unlocking (%d)\n", current);
619 if(!current && displaySystem)
620 displaySystem.driver.Unlock(this);
624 displaySystem.Unlock();
627 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
628 // *** 3D GRAPHICS ***
629 void SetCamera(Surface surface, Camera camera)
633 display3D = Display3D { };
635 if(!display3D.selection)
640 if(!display3D.selection)
641 displaySystem.driver.SelectMesh(this, null);
643 display3D.material = null;
644 display3D.mesh = null;
646 if(!display3D.selection)
648 displaySystem.driver.SetCamera(this, surface, camera);
651 this.display3D.camera = camera;
656 camera.Setup(width, height, null);
658 // Always calling Update() here had broken interpolation in OrbitWithMouse!
659 if(!camera.cAngle.w && surface)
662 if(display3D.selection)
664 // Compute Picking Planes
666 Vector3D point { 0,0,0 };
668 Angle fovLeft, fovRight, fovTop, fovBottom;
671 double l = camera.origin.x - (display3D.pickX - display3D.pickWidth/2.0f);
672 double r = camera.origin.x - (display3D.pickX + display3D.pickWidth/2.0f);
673 double t = (display3D.pickY - display3D.pickHeight/2.0f) - camera.origin.y;
674 double b = (display3D.pickY + display3D.pickHeight/2.0f) - camera.origin.y;
676 fovLeft = atan(l / camera.focalX);
677 fovRight = atan(r / camera.focalX);
678 fovTop = atan(t / camera.focalY);
679 fovBottom = atan(b / camera.focalY);
682 quat.Yaw(fovLeft - Pi/2);
683 quat.ToDirection(normal);
684 display3D.viewPickingPlanes[left].FromPointNormal(normal, point);
687 quat.Yaw(fovRight + Pi/2);
688 quat.ToDirection(normal);
689 display3D.viewPickingPlanes[right].FromPointNormal(normal, point);
692 quat.Pitch(fovTop + Pi/2);
693 quat.ToDirection(normal);
694 display3D.viewPickingPlanes[top].FromPointNormal(normal, point);
697 quat.Pitch(fovBottom - Pi/2);
698 quat.ToDirection(normal);
699 display3D.viewPickingPlanes[bottom].FromPointNormal(normal, point);
702 normal.x = 0; normal.y = 0; normal.z = 1;
703 point.z = camera.zMin;
704 display3D.viewPickingPlanes[near].FromPointNormal(normal, point);
707 normal.x = 0; normal.y = 0; normal.z = -1;
708 point.z = camera.zMax;
709 display3D.viewPickingPlanes[far].FromPointNormal(normal, point);
711 for(c = 0; c<ClippingPlane::enumSize; c++)
712 display3D.worldPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], camera.inverseTranspose);
714 // Compute picking ray
717 display3D.rayView.p0 = { 0, 0, 0 };
718 p.x = display3D.pickX;
719 p.y = display3D.pickY;
721 camera.Unproject(p, display3D.rayView.delta);
723 // Convert ray to world space
724 camera.Untransform(display3D.rayView.p0, display3D.rayWorld.p0);
725 camera.Untransform(display3D.rayView.delta, p);
726 display3D.rayWorld.delta.Subtract(p, display3D.rayWorld.p0);
733 void SetLight(int id, Light light)
735 displaySystem.driver.SetLight(this, id, light);
738 void SetLights(Object object)
741 display3D._SetLights(this, object, 0);
744 // --- Transformations ---
746 void SetTransform(Matrix matrix, bool viewSpace)
748 if(display3D.selection)
752 transpose.Transpose(matrix);
756 for(c = 0; c<ClippingPlane::enumSize; c++)
757 display3D.localPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], transpose);
761 for(c = 0; c<ClippingPlane::enumSize; c++)
762 display3D.localPickingPlanes[c].MultMatrix(display3D.worldPickingPlanes[c], transpose);
766 if(display3D.intersecting)
770 p2.Add(display3D.rayView.p0, display3D.rayView.delta);
772 p2.Add(display3D.rayWorld.p0, display3D.rayWorld.delta);
774 display3D.rayLocal.p0.DivideMatrix(display3D.rayWorld.p0, matrix);
775 tp2.DivideMatrix(p2, matrix);
776 display3D.rayLocal.delta.Subtract(tp2, display3D.rayLocal.p0);
780 displaySystem.driver.SetTransform(this, matrix, viewSpace, viewSpace ? false : true);
783 void PushMatrix(void)
785 displaySystem.driver.PushMatrix(this);
790 displaySystem.driver.PopMatrix(this, true);
794 void ApplyMaterial(Material material, Mesh mesh)
796 if(material != display3D.material)
798 display3D.material = material;
799 displaySystem.driver.ApplyMaterial(this, material, mesh);
803 void DrawPrimitives(PrimitiveSingle primitive, Mesh mesh)
805 displaySystem.driver.DrawPrimitives(this, primitive, mesh);
808 void SelectMesh(Mesh mesh)
810 displaySystem.driver.SelectMesh(this, mesh);
811 display3D.mesh = mesh;
814 bool DrawMesh(Object object)
817 if(display3D.selection)
818 result = display3D.PickMesh(object, null);
821 Mesh mesh = object.mesh;
822 Material objectMaterial = object.material;
824 if(mesh.groups.first)
826 PrimitiveGroup group;
827 displaySystem.driver.SelectMesh(this, mesh);
828 display3D.mesh = mesh;
830 for(group = mesh.groups.first; group; group = group.next)
832 Material material = group.material ? group.material : objectMaterial;
833 if(!material) material = defaultMaterial;
835 if(material != display3D.material)
837 display3D.material = material;
838 displaySystem.driver.ApplyMaterial(this, material, mesh);
841 // *** Render Vertex Arrays ***
842 displaySystem.driver.DrawPrimitives(this, (PrimitiveSingle *)&group.type, mesh);
846 if(object.flags.translucent)
849 Matrix inverse, inverseTranspose;
852 if(object.flags.viewSpace)
853 matrix = object.matrix;
856 Camera camera = display3D.camera;
857 Matrix temp = object.matrix;
858 temp.m[3][0] -= camera.cPosition.x;
859 temp.m[3][1] -= camera.cPosition.y;
860 temp.m[3][2] -= camera.cPosition.z;
861 matrix.Multiply(temp, camera.viewMatrix);
864 inverse.Inverse(matrix);
865 inverseTranspose.Transpose(inverse);
867 for(c = 0; c < mesh.nPrimitives; c++)
869 PrimitiveSingle * triangle = &mesh.primitives[c];
870 SortPrimitive * sort;
871 Plane * plane = &triangle->plane;
872 if(display3D.nTriangles >= display3D.maxTriangles)
874 display3D.maxTriangles = display3D.maxTriangles ? (display3D.maxTriangles * 3 / 2) : 32768;
875 display3D.triangles = renew display3D.triangles SortPrimitive[display3D.maxTriangles];
877 sort = &display3D.triangles[display3D.nTriangles++];
878 sort->object = object;
879 sort->triangle = triangle;
880 sort->middle.MultMatrix(triangle->middle, matrix);
881 sort->middle.z *= -1;
882 // sort->plane.MultMatrix(triangle->plane, inverseTranspose);
883 sort->plane.d = plane->a * inverseTranspose.m[0][3] +
884 plane->b * inverseTranspose.m[1][3] +
885 plane->c * inverseTranspose.m[2][3] +
886 plane->d * inverseTranspose.m[3][3];
892 displaySystem.driver.SelectMesh(this, mesh);
893 display3D.mesh = mesh;
895 for(c = 0; c<mesh.nPrimitives; c++)
897 PrimitiveSingle * primitive = &mesh.primitives[c];
899 Material material = primitive->material ? primitive->material : objectMaterial;
900 if(!material) material = defaultMaterial;
902 if(material != display3D.material)
904 display3D.material = material;
905 displaySystem.driver.ApplyMaterial(this, material, mesh);
908 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
916 bool IsObjectVisible(Object object)
919 if(display3D.selection || !display3D.camera)
920 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
922 planes = object.flags.viewSpace ? display3D.camera.viewClippingPlanes : display3D.camera.worldClippingPlanes;
923 return object.InsideFrustum(planes) != outside;
926 bool DrawObject(Object object)
929 if(object && object.volume)
932 FrustumPlacement visible;
934 Camera camera = display3D.camera;
936 if(display3D.selection || !camera)
937 planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
939 planes = object.flags.viewSpace ? camera.viewClippingPlanes : camera.worldClippingPlanes;
941 visible = object.InsideFrustum(planes);
943 if(visible || display3D.pickingPlanes)
945 if(display3D.collectingHits && object.tag)
947 /*if(object.flags.root)
948 this.tags[display3D.tagIndex] = object.tag;
950 this.tags[++display3D.tagIndex] = object.tag;
952 display3D.tags[display3D.tagIndex++] = object.tag;
955 if(object.flags.mesh && object.mesh)
957 if(!display3D.selection && displaySystem.driver.PushMatrix)
958 displaySystem.driver.PushMatrix(this);
961 if(object.mesh.tangents && object.mesh.normals)
963 Mesh mesh = object.mesh;
966 int count = mesh.nVertices;
967 Vector3Df * normals = mesh.normals;
968 Vector3Df * vertices = mesh.vertices;
969 ColorRGB * lightVectors;
970 Vector3Df * tangents = mesh.tangents;
972 float * l = display3D.light0Pos;
973 Vector3Df light { l[0], l[1], l[2] };
974 Matrix o = object.matrix;
975 Matrix t, inv = camera.viewMatrix;
977 Vector3D cPos = camera.cPosition;
978 Vector3D pos = camera.position;
979 bool positional = l[3] ? true : false;
981 inv.Scale(1.0/nearPlane, -1.0/nearPlane,-1.0/nearPlane);
983 pos.MultMatrix(cPos, camera.viewMatrix);
985 ot.x = o.m[3][0] + pos.x;
986 ot.y = o.m[3][1] + pos.y;
987 ot.z = o.m[3][2] + pos.z;
996 mesh.Allocate({ lightVectors = true }, mesh.nVertices, displaySystem);
997 mesh.Lock({ lightVectors = true });
998 lightVectors = mesh.lightVectors;
999 for(i = 0; i < count; i++)
1001 Vector3Df tangent1 = tangents[i*2 + 0];
1002 Vector3Df tangent2 = tangents[i*2 + 1];
1003 Vector3Df normal = normals[i];
1004 Vector3Df tTangent1, tTangent2, tNormal;
1006 tTangent1.MultMatrix(tangent1, inv);
1007 tTangent2.MultMatrix(tangent2, inv);
1008 tNormal .MultMatrix(normal, inv);
1010 tTangent1.Normalize(tTangent1);
1011 tTangent2.Normalize(tTangent2);
1012 tNormal .Normalize(tNormal);
1017 tTangent1.x, tTangent2.x, tNormal.x, 0,
1018 tTangent1.y, tTangent2.y, tNormal.y, 0,
1019 tTangent1.z, tTangent2.z, tNormal.z, 1
1024 Vector3Df tPos = vertices[i];
1025 tPos.x += ot.x, tPos.y += ot.y, tPos.z += ot.z;
1027 // Subtract vertex from light for positional lights
1028 light.x = l[0] - tPos.x;
1029 light.y = l[1] + tPos.y;
1030 light.z = l[2] - tPos.z;
1032 n.MultMatrix(light, tbn);
1035 lightVectors[i] = { n.x / 2 + 0.5f, n.y / 2 + 0.5f, n.z / 2 + 0.5f };
1038 mesh.Unlock({ lightVectors = true });
1040 // Create normalization cube map
1045 int w = 256, h = 256, d = 256;
1046 Vector3Df min = mesh.min, max = mesh.max;
1049 (max.x - min.x) / w,
1050 (max.y - min.y) / h,
1054 for(i = 0; i < 6; i++)
1056 Bitmap face = i > 0 ? { } : mesh.normMap;
1060 face.Allocate(null, w, h, 0, pixelFormat888, false);
1061 face.driverData = mesh.normMap.driverData;
1062 p = (ColorAlpha *)face.picture;
1063 for(y = 0; y < h; y++)
1065 for(x = 0; x < w; x++, p++)
1067 Vector3Df v { min.x + x * delta.x, min.y + y * delta.y, min.z };
1069 *p = ColorAlpha { 255, {
1070 (byte)((v.x / 2.0 + 0.5) * 255),
1071 (byte)((v.y / 2.0 + 0.5) * 255),
1072 (byte)((v.z / 2.0 + 0.5) * 255) } };
1075 displaySystem.driver.MakeDDBitmap(displaySystem, face, true, (i + 1));
1078 face.driverData = 0;
1086 mesh.Free({ lightVectors = true });
1090 SetTransform(object.matrix, object.flags.viewSpace);
1091 if(display3D.selection)
1093 if(visible == intersecting || display3D.intersecting)
1095 Vector3D rayIntersect;
1096 if(display3D.PickMesh(object, rayIntersect))
1098 if(display3D.intersecting)
1100 Vector3D wresult, vresult;
1101 wresult.MultMatrix(rayIntersect, object.matrix);
1102 if(!object.flags.viewSpace)
1103 camera.TransformPoint(vresult, wresult);
1107 if(vresult.z < display3D.rayIntersect.z)
1108 display3D.rayIntersect = vresult;
1109 display3D.intersected = true;
1119 result |= DrawMesh(object);
1120 if(displaySystem.driver.PopMatrix)
1121 displaySystem.driver.PopMatrix(this, true);
1123 if(display3D.collectingHits && result /*&& object.tag*/)
1126 HitRecord hit = (HitRecord)new0 byte[sizeof(class HitRecord) + sizeof(void *) * (display3D.tagIndex/*+1*/)];
1127 display3D.hitList.Add(hit);
1128 hit.pos = display3D.hitList.count-1;
1129 hit.numTags = display3D.tagIndex /*+ 1*/;
1130 for(c = 0; c</*=*/display3D.tagIndex; c++)
1132 hit.tags[c] = display3D.tags[c];
1135 if(!object.flags.viewSpace)
1136 camera.TransformPoint(hit.center, object.wcenter);
1138 hit.center = object.wcenter;
1142 for(child = object.children.first; child; child = child.next)
1143 result |= DrawObject(child);
1145 if(display3D.collectingHits && /*!object.flags.root && */object.tag)
1146 display3D.tagIndex--;
1152 void DrawTranslucency(void)
1154 if(display3D.camera)
1156 // *** Render translucent primitives ***
1157 if(display3D.nTriangles)
1159 Matrix * matrix = null;
1164 display3D.SortTriangles();
1168 displaySystem.driver.PushMatrix(this);
1169 for(c=0; c<display3D.nTriangles; c++)
1171 SortPrimitive * sort = &display3D.triangles[c];
1172 Mesh mesh = sort->object.mesh;
1173 PrimitiveSingle * primitive = sort->triangle;
1176 if(&sort->object.matrix != matrix)
1178 matrix = &sort->object.matrix;
1180 displaySystem.driver.PopMatrix(this, false);
1181 displaySystem.driver.PushMatrix(this);
1182 SetTransform(matrix, sort->object.flags.viewSpace);
1184 if(mesh != display3D.mesh)
1186 displaySystem.driver.SelectMesh(this, mesh);
1187 display3D.mesh = mesh;
1190 material = primitive->material ? primitive->material : sort->object.material;
1191 if(!material) material = defaultMaterial;
1193 if(material != display3D.material)
1195 displaySystem.driver.ApplyMaterial(this, material, display3D.mesh);
1196 display3D.material = material;
1201 Material testMaterial { };
1204 amount = (display3D.triangles[0].middle.z - display3D.triangles[c].middle.z) /
1205 (display3D.triangles[0].middle.z - display3D.triangles[display3D.nTriangles-1].middle.z);
1207 testMaterial.flags.doubleSided = { doubleSided = true, translucent = true };
1208 testMaterial.diffuse.a = 1;
1209 testMaterial.emissive.r = testMaterial.emissive.g = testMaterial.emissive.b = amount;
1210 testMaterial.baseMap = material->baseMap;
1212 displaySystem.driver.ApplyMaterial(this, testMaterial, display3D.mesh);
1216 // *** Render primitive ***
1217 // if(sort->plane.d > 0)
1218 displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
1220 displaySystem.driver.PopMatrix(this, true);
1222 display3D.nTriangles = 0;
1229 void StartSelection(int pickX, int pickY, int pickW, int pickH)
1233 display3D = Display3D { };
1235 display3D.pickX = (float)pickX;
1236 display3D.pickY = (float)pickY;
1237 display3D.pickWidth = (float)pickW;
1238 display3D.pickHeight = (float)pickH;
1239 display3D.selection = true;
1242 void CollectHits(void)
1244 display3D.collectingHits = true;
1247 int GetHits(OldList list)
1249 display3D.collectingHits = false;
1250 display3D.hitList.Sort(HitRecord::Compare, null);
1251 list = display3D.hitList;
1252 display3D.hitList.Clear();
1256 void IntersectPolygons(void)
1258 display3D.rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1259 display3D.intersected = false;
1260 display3D.intersecting = true;
1263 bool GetIntersect(Vector3D intersect)
1265 intersect = display3D.rayIntersect;
1266 display3D.intersecting = false;
1267 return display3D.intersected;
1270 void StopSelection(void)
1272 display3D.selection = false;
1275 // --- Rendering States ---
1276 property FillModeValue fillMode { set { displaySystem.driver.SetRenderState(this, fillMode, value); } };
1277 property bool depthTest { set { displaySystem.driver.SetRenderState(this, depthTest, value); } };
1278 property bool depthWrite { set { displaySystem.driver.SetRenderState(this, depthWrite, value); } };
1279 property float fogDensity { set { displaySystem.driver.SetRenderState(this, fogDensity, RenderStateFloat { value }.ui); } };
1280 property Color fogColor { set { displaySystem.driver.SetRenderState(this, fogColor, value); } };
1281 property bool blend { set { displaySystem.driver.SetRenderState(this, blend, value); } };
1282 property Color ambient { set { displaySystem.driver.SetRenderState(this, ambient, value); } };
1283 property bool alphaWrite { set { displaySystem.driver.SetRenderState(this, alphaWrite, value); } };
1284 property bool antiAlias { set { displaySystem.driver.SetRenderState(this, antiAlias, value); } };
1285 property bool vSync { set { displaySystem.driver.SetRenderState(this, vSync, value); } };
1287 property bool pickingPlanes { set { display3D.pickingPlanes = value; } };
1289 property DisplayFlags flags { get { return displaySystem.flags; } }
1290 property PixelFormat pixelFormat { get { return /*alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat; } }
1291 property bool alphaBlend { set { alphaBlend = value; } get { return alphaBlend; } };
1292 property bool useSharedMemory { set { useSharedMemory = value; } get { return useSharedMemory; } };
1293 property void * systemWindow { get { return window; } };
1294 property DisplaySystem displaySystem { get { return displaySystem; } };
1295 #ifndef ECERE_VANILLA
1296 property GLCapabilities glCapabilities
1298 get { return ((OGLDisplay)driverData).capabilities; }
1301 glCapabilities = value;
1302 if(driverData && displaySystem.driver == class(OpenGLDisplayDriver))
1304 OGLDisplay oglDisplay = driverData;
1305 if(!oglDisplay.originalCapabilities.fixedFunction)
1306 value.shaders = true;
1307 if(!oglDisplay.originalCapabilities.shaders)
1308 value.fixedFunction = true;
1309 // Disable things that don't work with shaders
1312 value.fixedFunction = false;
1313 value.legacy = false;
1314 value.immediate = false;
1316 oglDisplay.capabilities = oglDisplay.originalCapabilities & value;
1319 OpenGLDisplayDriver::initialDisplaySetup(this, true, false);
1331 DisplaySystem displaySystem;
1337 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1338 Display3D display3D;
1341 void * windowDriverData;
1342 bool useSharedMemory;
1343 GLCapabilities glCapabilities;
1344 glCapabilities = { true, true, true, true, true, true, true, true };
1347 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
1348 private class Display3D : struct
1352 SortPrimitive * triangles;
1354 Vector3D points[MAX_CLIP_POINTS];
1355 Vector3D newPoints[MAX_CLIP_POINTS];
1356 byte goodPoints[MAX_CLIP_POINTS];
1361 Plane viewPickingPlanes[ClippingPlane], worldPickingPlanes[ClippingPlane];
1362 Plane localPickingPlanes[ClippingPlane];
1364 bool collectingHits, selection, intersecting, intersected, pickingPlanes;
1365 float pickX, pickY, pickWidth, pickHeight;
1370 Line rayView, rayWorld, rayLocal;
1371 Vector3D rayIntersect;
1379 int _SetLights(Display display, Object object, int id)
1381 if(id < NumberOfLights)
1385 if(object.flags.light && !object.light.flags.off)
1386 display.SetLight(id++, object.light);
1388 for(child = object.children.first; child; child = child.next)
1390 id = _SetLights(display, child, id);
1396 //#define TRESHOLD -1
1397 //#define TRESHOLD -0.25
1398 #define TRESHOLD -0.0025
1400 bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
1402 Plane * planes = localPickingPlanes;
1404 int nIndex = 1, nPoints = 1;
1406 bool result = false;
1407 Vector3D * points = this.points;
1408 Vector3D * newPoints = this.newPoints;
1409 byte * goodPoints = this.goodPoints;
1410 int nVertices = primitive.type.vertexRange ? primitive.nVertices : primitive.nIndices;
1413 bool i32bit = primitive.type.indices32bit;
1414 uint32 * indices32 = primitive.indices32;
1415 uint16 * indices16 = primitive.indices;
1417 switch(primitive.type.primitiveType)
1419 case triangles: nIndex = 3; nPoints = 3; break;
1420 case quads: nIndex = 4; nPoints = 4; break;
1423 nIndex = 1; nPoints = 3;
1425 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first] : mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1426 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1427 tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first+1] : mesh.vertices[(i32bit ? indices32[1] : indices16[1])];
1428 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1432 for(c = offset; c<nVertices; c += nIndex)
1434 bool outside = false;
1441 if(primitive.type.vertexRange)
1443 if(primitive.type.primitiveType == triStrip)
1445 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 1) : (c - 2)];
1446 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1447 tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 2) : (c - 1)];
1448 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1450 else if(primitive.type.primitiveType == triFan)
1452 tmp = mesh.vertices[primitive.first + 0];
1453 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1454 tmp = mesh.vertices[primitive.first + c - 1];
1455 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1457 for(i = 0; i<nIndex; i++)
1459 tmp = mesh.vertices[primitive.first + c+i];
1460 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1465 if(primitive.type.primitiveType == triStrip)
1467 i = (c & 1) ? (c - 1) : (c - 2);
1468 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1469 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1471 i = (c & 1) ? (c - 2) : (c - 1);
1472 tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
1473 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1475 else if(primitive.type.primitiveType == triFan)
1477 tmp = mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
1478 points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1479 tmp = mesh.vertices[(i32bit ? indices32[c-1] : indices16[c-1])];
1480 points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1482 for(i = 0; i<nIndex; i++)
1484 tmp = mesh.vertices[(i32bit ? indices32[c+i] : indices16[c+i])];
1485 points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
1489 for(p = 0; p < 6; p++)
1491 Plane * plane = &planes[p];
1493 int numGoodPoints = 0;
1495 memset(goodPoints, 0, n);
1496 for(i = 0; i < n; i++)
1498 double dot = plane->normal.DotProduct(points[i]);
1499 double distance = dot + plane->d;
1500 if(distance > TRESHOLD)
1511 if(numGoodPoints < n)
1522 newPoints[newN++] = points[j];
1531 for(lastGood = n-1; !goodPoints[lastGood]; lastGood--);
1533 edge.p0 = points[lastGood];
1534 edge.delta.Subtract(points[j], edge.p0);
1535 plane->IntersectLine(edge, newPoints[newN++]);
1537 for(next = j+1; next != j; next++)
1539 if(next == n) next = 0;
1540 if(goodPoints[next])
1542 int prev = next - 1;
1543 if(prev < 0) prev = n-1;
1545 edge.p0 = points[prev];
1546 edge.delta.Subtract(points[next], edge.p0);
1547 plane->IntersectLine(edge, newPoints[newN++]);
1557 // Use the new points
1558 memcpy(points, newPoints, newN * sizeof(Vector3D));
1567 // TODO: Implement intersection with TriStrip, TriFan...
1570 // Intersect primitives
1572 Vector3D intersect, diff;
1573 int i0 = c, i1 = c+1, i2 = c+2;
1575 if(primitive.type.primitiveType == triStrip)
1577 i0 = (c & 1) ? (c - 1) : (c - 2);
1578 i1 = (c & 1) ? (c - 2) : (c - 1);
1581 else if(primitive.type.primitiveType == triFan)
1588 if(primitive.type.vertexRange)
1590 mesh.vertices[primitive.first + i0],
1591 mesh.vertices[primitive.first + i1],
1592 mesh.vertices[primitive.first + i2]);
1595 mesh.vertices[(i32bit ? indices32[i0] : indices16[i0])],
1596 mesh.vertices[(i32bit ? indices32[i1] : indices16[i1])],
1597 mesh.vertices[(i32bit ? indices32[i2] : indices16[i2])]);
1599 plane.IntersectLine(rayLocal, intersect);
1600 diff.Subtract(intersect, rayLocal.p0);
1601 diff.x /= rayLocal.delta.x;
1602 diff.y /= rayLocal.delta.y;
1603 diff.z /= rayLocal.delta.z;
1604 if(diff.x < rayDiff.x || diff.y < rayDiff.y || diff.z < rayDiff.z)
1607 rayIntersect = intersect;
1614 switch(primitive.type)
1617 points[strip] = points[2];
1621 points[1] = points[2];
1628 bool PickMesh(Object object, Vector3D rayIntersect)
1630 Mesh mesh = object.mesh;
1631 bool result = false;
1632 Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1633 if(rayIntersect != null)
1634 rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1636 if(mesh.groups.first)
1638 PrimitiveGroup group;
1640 for(group = mesh.groups.first; group; group = group.next)
1642 if(PickPrimitives(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect))
1653 for(c = 0; c < mesh.nPrimitives; c++)
1655 if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
1666 void SortTriangles(void)
1669 Object object = null;
1671 for(c=0; c<nTriangles; c++)
1673 SortPrimitive * sort = &triangles[c];
1674 Mesh mesh = sort->object.mesh;
1675 PrimitiveSingle * primitive = sort->triangle;
1676 Vector3Df min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
1677 Vector3Df max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
1679 bool ix32 = primitive->type.indices32bit;
1680 if(object != sort->object)
1682 object = sort->object;
1683 if(object.flags.viewSpace)
1684 matrix = object.matrix;
1687 Camera camera = this.camera;
1688 Matrix temp = object.matrix;
1689 temp.m[3][0] -= camera.cPosition.x;
1690 temp.m[3][1] -= camera.cPosition.y;
1691 temp.m[3][2] -= camera.cPosition.z;
1692 matrix.Multiply(temp, camera.viewMatrix);
1696 for(v = 0; v<primitive->nIndices; v++)
1698 Vector3Df * local = &mesh.vertices[ix32 ? primitive->indices32[v] : primitive->indices[v]];
1701 vertex.MultMatrix(local, &matrix);
1703 if(vertex.x > max.x) max.x = vertex.x;
1704 if(vertex.y > max.y) max.y = vertex.y;
1705 if(vertex.z > max.z) max.z = vertex.z;
1706 if(vertex.x < min.x) min.x = vertex.x;
1707 if(vertex.y < min.y) min.y = vertex.y;
1708 if(vertex.z < min.z) min.z = vertex.z;
1714 sort->marked = false;
1718 Logf("========= Before Sort ==========\n");
1719 for(c=0; c<nTriangles; c++)
1721 SortPrimitive * sort = &triangles[c];
1723 Mesh mesh = sort->mesh;
1724 PrimitiveSingle * primitive = sort->triangle;
1726 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1728 for(v = 0; v<primitive->nIndices; v++)
1730 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1734 vertex.<MultMatrix(local, sort->matrix);
1736 Logf("Vertex %d:", v);
1738 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1739 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1743 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1744 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1748 // *** Sort translucent primitives ***
1749 qsort((void*) triangles, nTriangles, sizeof(SortPrimitive), SortPrimitive::Compare);
1751 Logf("\n\n========= After Sort ==========\n");
1752 for(c=0; c<nTriangles; c++)
1754 SortPrimitive * sort = &triangles[c];
1756 Mesh mesh = sort->mesh;
1757 PrimitiveSingle * primitive = sort->triangle;
1759 Logf("Triangle %d (%s):\n", c, primitive->material->name);
1761 for(v = 0; v<primitive->nIndices; v++)
1763 Vector3Df * local = &mesh.vertices[primitive->indices[v]];
1767 vertex.MultMatrix(local, sort->matrix);
1769 Logf("Vertex %d:", v);
1771 // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
1772 Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
1776 Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
1777 Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
1784 If all five tests fail for a particular Q,
1785 then P might obscure Q. Now Q must be tested.
1786 First, the algorithm checks if Q has been "marked."
1787 If Q is marked, then Q was "moved around" in the list
1788 during a previous iteration of the loop. The algorithm
1789 only allows a polygon to be moved once, to avoid the possibility
1790 of infinite loops. If Q is not marked, it is tested to see
1791 if it might obscure P. If Q cannot obscure P, then Q is possibly
1792 behind P and so it is good candidate to be drawn next.
1793 Therefore, the algorithm "abandons" the current P (that is, it
1794 stops testing Q's against the current P) and moves the current
1795 Q to the end of the list to become the next P.
1800 for(p = 0; p<nTriangles; p++)
1802 SortPrimitive * poly1 = &triangles[p];
1805 for(q = p+1; q<nTriangles; q++)
1809 SortPrimitive * poly2 = &triangles[q];
1810 if(poly1->ZOverlap(poly2) && !poly2->marked)
1812 if(poly1->ShouldBeSwapped(poly2))
1814 if(!poly2->ShouldBeSwapped(poly1))
1816 SortPrimitive temp = *poly2;
1817 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1818 triangles[0] = temp;
1819 triangles[0].marked = true;
1832 for(p = 0; p<nTriangles; p++)
1834 SortPrimitive * poly1 = &triangles[p];
1837 // for(q = p+1; q<nTriangles; q++)
1838 for(q = 0; q<nTriangles; q++)
1842 SortPrimitive * poly2 = &triangles[q];
1843 if(poly1->ZOverlap(poly2) && !poly2->marked)
1845 if(poly1->ShouldBeSwapped(poly2))
1847 if(!poly2->ShouldBeSwapped(poly1))
1849 SortPrimitive temp = *poly2;
1850 memmove(triangles+1, triangles, sizeof(SortPrimitive)*q);
1851 triangles[0] = temp;
1852 triangles[0].marked = true;
1865 for(p = nTriangles-1; p>=0; p--)
1867 SortPrimitive * poly1 = &triangles[p];
1870 for(q = nTriangles-1; q>=0; q--)
1874 SortPrimitive * poly2 = &triangles[q];
1875 if(poly1->ZOverlap(poly2) && !poly2->marked)
1877 if(poly1->ShouldBeSwapped(poly2))
1879 if(!poly2->ShouldBeSwapped(poly1))
1881 SortPrimitive temp = *poly2;
1882 memmove(triangles + q, triangles + q + 1, sizeof(SortPrimitive)*q);
1884 triangles[nTriangles-1] = temp;
1897 for(c=0; c<nTriangles; c++)
1900 SortPrimitive * poly1 = &triangles[c];
1902 // for(b=0; b<nTriangles; b++)
1903 //for(b=c+1; b<nTriangles; b++)
1905 if(b<this.nTriangles)
1907 SortPrimitive * poly2 = &this.triangles[b];
1909 if(poly1->ZOverlap(poly2) && poly1->ShouldBeSwapped(poly2))
1911 SortPrimitive temp = *poly1;
1924 bool IsDriverTextMode(const char * driverName)
1926 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1927 return driver ? driver.textMode : false;
1930 bool IsDriverPrinter(const char * driverName)
1932 subclass(DisplayDriver) driver = GetDisplayDriver(driverName);
1933 return driver ? driver.printer : false;
1936 static ColorAlpha defaultPalette[256] =
1940 0xFF000000,0xFF000080,0xFF008000,0xFF008080,0xFF800000,0xFF800080,0xFF808000,0xFFC0C0C0,
1941 0xFF808080,0xFF0000FF,0xFF00FF00,0xFF00FFFF,0xFFFF0000,0xFFFF00FF,0xFFFFFF00,0xFFFFFFFF,
1943 0xFF000000,0xFF0000AA,0xFF00AA00,0xFF00AAAA,0xFFAA0000,0xFFAA00AA,0xFFAAAA00,0xFFABABAB,
1944 0xFF555555,0xFF5555FF,0xFF55FF55,0xFF55FFFF,0xFFFF5555,0xFFFF55FF,0xFFFFFF55,0xFFFFFFFF,
1946 // 6 x 6 x 6 Color Cube
1947 0xFF000000, 0xFF000033, 0xFF000066, 0xFF000099, 0xFF0000CC, 0xFF0000FF,
1948 0xFF003300, 0xFF003333, 0xFF003366, 0xFF003399, 0xFF0033CC, 0xFF0033FF,
1949 0xFF006600, 0xFF006633, 0xFF006666, 0xFF006699, 0xFF0066CC, 0xFF0066FF,
1950 0xFF009900, 0xFF009933, 0xFF009966, 0xFF009999, 0xFF0099CC, 0xFF0099FF,
1951 0xFF00CC00, 0xFF00CC33, 0xFF00CC66, 0xFF00CC99, 0xFF00CCCC, 0xFF00CCFF,
1952 0xFF00FF00, 0xFF00FF33, 0xFF00FF66, 0xFF00FF99, 0xFF00FFCC, 0xFF00FFFF,
1954 0xFF330000, 0xFF330033, 0xFF330066, 0xFF330099, 0xFF3300CC, 0xFF3300FF,
1955 0xFF333300, 0xFF333333, 0xFF333366, 0xFF333399, 0xFF3333CC, 0xFF3333FF,
1956 0xFF336600, 0xFF336633, 0xFF336666, 0xFF336699, 0xFF3366CC, 0xFF3366FF,
1957 0xFF339900, 0xFF339933, 0xFF339966, 0xFF339999, 0xFF3399CC, 0xFF3399FF,
1958 0xFF33CC00, 0xFF33CC33, 0xFF33CC66, 0xFF33CC99, 0xFF33CCCC, 0xFF33CCFF,
1959 0xFF33FF00, 0xFF33FF33, 0xFF33FF66, 0xFF33FF99, 0xFF33FFCC, 0xFF33FFFF,
1961 0xFF660000, 0xFF660033, 0xFF660066, 0xFF660099, 0xFF6600CC, 0xFF6600FF,
1962 0xFF663300, 0xFF663333, 0xFF663366, 0xFF663399, 0xFF6633CC, 0xFF6633FF,
1963 0xFF666600, 0xFF666633, 0xFF666666, 0xFF666699, 0xFF6666CC, 0xFF6666FF,
1964 0xFF669900, 0xFF669933, 0xFF669966, 0xFF669999, 0xFF6699CC, 0xFF6699FF,
1965 0xFF66CC00, 0xFF66CC33, 0xFF66CC66, 0xFF66CC99, 0xFF66CCCC, 0xFF66CCFF,
1966 0xFF66FF00, 0xFF66FF33, 0xFF66FF66, 0xFF66FF99, 0xFF66FFCC, 0xFF66FFFF,
1968 0xFF990000, 0xFF990033, 0xFF990066, 0xFF990099, 0xFF9900CC, 0xFF9900FF,
1969 0xFF993300, 0xFF993333, 0xFF993366, 0xFF993399, 0xFF9933CC, 0xFF9933FF,
1970 0xFF996600, 0xFF996633, 0xFF996666, 0xFF996699, 0xFF9966CC, 0xFF9966FF,
1971 0xFF999900, 0xFF999933, 0xFF999966, 0xFF999999, 0xFF9999CC, 0xFF9999FF,
1972 0xFF99CC00, 0xFF99CC33, 0xFF99CC66, 0xFF99CC99, 0xFF99CCCC, 0xFF99CCFF,
1973 0xFF99FF00, 0xFF99FF33, 0xFF99FF66, 0xFF99FF99, 0xFF99FFCC, 0xFF99FFFF,
1975 0xFFCC0000, 0xFFCC0033, 0xFFCC0066, 0xFFCC0099, 0xFFCC00CC, 0xFFCC00FF,
1976 0xFFCC3300, 0xFFCC3333, 0xFFCC3366, 0xFFCC3399, 0xFFCC33CC, 0xFFCC33FF,
1977 0xFFCC6600, 0xFFCC6633, 0xFFCC6666, 0xFFCC6699, 0xFFCC66CC, 0xFFCC66FF,
1978 0xFFCC9900, 0xFFCC9933, 0xFFCC9966, 0xFFCC9999, 0xFFCC99CC, 0xFFCC99FF,
1979 0xFFCCCC00, 0xFFCCCC33, 0xFFCCCC66, 0xFFCCCC99, 0xFFCCCCCC, 0xFFCCCCFF,
1980 0xFFCCFF00, 0xFFCCFF33, 0xFFCCFF66, 0xFFCCFF99, 0xFFCCFFCC, 0xFFCCFFFF,
1982 0xFFFF0000, 0xFFFF0033, 0xFFFF0066, 0xFFFF0099, 0xFFFF00CC, 0xFFFF00FF,
1983 0xFFFF3300, 0xFFFF3333, 0xFFFF3366, 0xFFFF3399, 0xFFFF33CC, 0xFFFF33FF,
1984 0xFFFF6600, 0xFFFF6633, 0xFFFF6666, 0xFFFF6699, 0xFFFF66CC, 0xFFFF66FF,
1985 0xFFFF9900, 0xFFFF9933, 0xFFFF9966, 0xFFFF9999, 0xFFFF99CC, 0xFFFF99FF,
1986 0xFFFFCC00, 0xFFFFCC33, 0xFFFFCC66, 0xFFFFCC99, 0xFFFFCCCC, 0xFFFFCCFF,
1987 0xFFFFFF00, 0xFFFFFF33, 0xFFFFFF66, 0xFFFFFF99, 0xFFFFFFCC, 0xFFFFFFFF,
1989 // 16 Shades of gray
1990 0xFF000000,0xFF101010,0xFF202020,0xFF303030,0xFF404040,0xFF505050,0xFF606060,0xFF707070,
1991 0xFF808080,0xFF909090,0xFFA0A0A0,0xFFB0B0B0,0xFFC0C0C0,0xFFD0D0D0,0xFFE0E0E0,0xFFF0F0F0,
1994 0xFF080808,0xFF101010,0xFF585858,0xFF606060,0xFFA8A8A8,0xFFB0B0B0,0xFFF8F8F8,0xFFFFFFFF
1998 0xFF080000,0xFF100000,0xFF180000,0xFF200000,0xFF280000,0xFF300000,0xFF380000,0xFF400000,
1999 0xFF480000,0xFF500000,0xFF580000,0xFF600000,0xFF680000,0xFF700000,0xFF780000,0xFF800000,
2000 0xFF880000,0xFF900000,0xFF980000,0xFFA00000,0xFFA80000,0xFFB00000,0xFFB80000,0xFFC00000,
2001 0xFFC80000,0xFFD00000,0xFFD80000,0xFFE00000,0xFFE80000,0xFFF00000,0xFFF80000,0xFFFF0000,
2003 0xFF000800,0xFF001000,0xFF001800,0xFF002000,0xFF002800,0xFF003000,0xFF003800,0xFF004000,
2004 0xFF004800,0xFF005000,0xFF005800,0xFF006000,0xFF006800,0xFF007000,0xFF007800,0xFF008000,
2005 0xFF008800,0xFF009000,0xFF009800,0xFF00A000,0xFF00A800,0xFF00B000,0xFF00B800,0xFF00C000,
2006 0xFF00C800,0xFF00D000,0xFF00D800,0xFF00E000,0xFF00E800,0xFF00F000,0xFF00F800,0xFF00FF00,
2008 0xFF000808,0xFF001010,0xFF001818,0xFF002020,0xFF002828,0xFF003030,0xFF003838,0xFF004040,
2009 0xFF004848,0xFF005050,0xFF005858,0xFF006060,0xFF006868,0xFF007070,0xFF007878,0xFF008080,
2010 0xFF008888,0xFF009090,0xFF009898,0xFF00A0A0,0xFF00A8A8,0xFF00B0B0,0xFF00B8B8,0xFF00C0C0,
2011 0xFF00C8C8,0xFF00D0D0,0xFF00D8D8,0xFF00E0E0,0xFF00E8E8,0xFF00F0F0,0xFF00F8F8,0xFF00FFFF,
2013 0xFF000008,0xFF000010,0xFF000018,0xFF000020,0xFF000028,0xFF000030,0xFF000038,0xFF000040,
2014 0xFF000048,0xFF000050,0xFF000058,0xFF000060,0xFF000068,0xFF000070,0xFF000078,0xFF000080,
2015 0xFF000088,0xFF000090,0xFF000098,0xFF0000A0,0xFF0000A8,0xFF0000B0,0xFF0000B8,0xFF0000C0,
2016 0xFF0000C8,0xFF0000D0,0xFF0000D8,0xFF0000E0,0xFF0000E8,0xFF0000F0,0xFF0000F8,0xFF0000FF,
2018 0xFF080008,0xFF100010,0xFF180018,0xFF200020,0xFF280028,0xFF300030,0xFF380038,0xFF400040,
2019 0xFF480048,0xFF500050,0xFF580058,0xFF600060,0xFF680068,0xFF700070,0xFF780078,0xFF800080,
2020 0xFF880088,0xFF900090,0xFF980098,0xFFA000A0,0xFFA800A8,0xFFB000B0,0xFFB800B8,0xFFC000C0,
2021 0xFFC800C8,0xFFD000D0,0xFFD800D8,0xFFE000E0,0xFFE800E8,0xFFF000F0,0xFFF800F8,0xFFFF00FF,
2023 0xFF080800,0xFF101000,0xFF181800,0xFF202000,0xFF282800,0xFF303000,0xFF383800,0xFF404000,
2024 0xFF484800,0xFF505000,0xFF585800,0xFF606000,0xFF686800,0xFF707000,0xFF787800,0xFF808000,
2025 0xFF888800,0xFF909000,0xFF989800,0xFFA0A000,0xFFA8A800,0xFFB0B000,0xFFB8B800,0xFFC0C000,
2026 0xFFC8C800,0xFFD0D000,0xFFD8D800,0xFFE0E000,0xFFE8E800,0xFFF0F000,0xFFF8F800,0xFFFFFF00,
2028 0xFF080808,0xFF101010,0xFF181818,0xFF202020,0xFF282828,0xFF303030,0xFF383838,0xFF404040,
2029 0xFF484848,0xFF505050,0xFF585858,0xFF606060,0xFF686868,0xFF707070,0xFF787878,0xFF808080,
2030 0xFF888888,0xFF909090,0xFF989898,0xFFA0A0A0,0xFFA8A8A8,0xFFB0B0B0,0xFFB8B8B8,0xFFC0C0C0,
2031 0xFFC8C8C8,0xFFD0D0D0,0xFFD8D8D8,0xFFE0E0E0,0xFFE8E8E8,0xFFF0F0F0,0xFFF8F8F8,0xFFFFFFFF
2035 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
2036 static Material defaultMaterial
2039 diffuse = { 1.0f, 1.0f, 1.0f },
2040 ambient = { 1.0f, 1.0f, 1.0f },
2041 flags = { doubleSided = true, noFog = true };
2045 static byte colorDepthShifts[PixelFormat] = { 0,0,1,1,1,2,0,1,2 };
2046 static Size resolutions[Resolution] =
2049 {320,200},{320,240},{320,400},{360,480},
2050 {400,256},{400,300},{512,256},{512,384},
2051 {640,200},{640,350},{640,400},{640,480},
2052 {720,348},{800,600},{856,480},{960,720},
2053 {1024,768},{1152,864},{1280,1024},{1600,1200},
2056 static int colorDepths[PixelFormat] = {4,8,12,15,16,32,8,16,32};
2058 // --- Query utilities ---
2060 public int GetResolutionWidth(Resolution resolution)
2062 return resolutions[resolution].w;
2065 public int GetResolutionHeight(Resolution resolution)
2067 return resolutions[resolution].h;
2070 public int GetDepthBits(PixelFormat colorDepth)
2072 return colorDepths[colorDepth];
2075 public byte GetColorDepthShifts(PixelFormat format)
2077 return colorDepthShifts[format];
2080 public ColorAlpha * GetDefaultPalette()
2082 return (ColorAlpha *)defaultPalette;
2084 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
2085 public Material GetDefaultMaterial()
2087 return defaultMaterial;
2090 public int BestColorMatch(ColorAlpha * palette, int start, int end, Color rgb)
2096 int bestscore = MAXINT,score;
2097 byte r = rgb.r, g = rgb.g, b = rgb.b;
2100 for(c = start; c <= end; c++)
2103 current = palette[c];
2104 if(rgb && !c) continue;
2108 score = Abs(dr) + Abs(dg) + Abs(db);
2109 if(score <= bestscore)