From 1de4b2bdbb019be6f1b7262c3eba5568d7682edd Mon Sep 17 00:00:00 2001 From: "milo24x7@gmail.com" Date: Sun, 7 Jul 2013 21:51:48 +0000 Subject: Updated open source license declaration and fixed some formatting issues. --- Magic2/AlphaInverse.cpp | 8233 ++++++++++++++++++------------------ Magic2/AlphaPalette.cpp | 553 +-- Magic2/Command.cpp | 128 +- Magic2/Command.h | 134 +- Magic2/ContentBundle.cpp | 298 +- Magic2/ContentBundle.h | 120 +- Magic2/Editor.cpp | 848 ++-- Magic2/Editor.h | 192 +- Magic2/Grid.cpp | 716 ++-- Magic2/Grid.h | 186 +- Magic2/GridProps.cpp | 276 +- Magic2/GridProps.h | 162 +- Magic2/Locale_ss.cpp | 498 +-- Magic2/Locale_ss.h | 130 +- Magic2/M3DS.cpp | 550 +-- Magic2/M3DS.h | 680 +-- Magic2/Magic.cpp | 428 +- Magic2/Magic.h | 150 +- Magic2/MagicDoc.cpp | 1254 +++--- Magic2/MagicDoc.h | 264 +- Magic2/MagicView.cpp | 2898 ++++++------- Magic2/MagicView.h | 426 +- Magic2/MainFrm.cpp | 330 +- Magic2/MainFrm.h | 149 +- Magic2/MaterialDialog.cpp | 1410 +++--- Magic2/MaterialDialog.h | 258 +- Magic2/ModelFile3DS.cpp | 590 +-- Magic2/ModelFile3DS.h | 98 +- Magic2/ModelFileMAG.cpp | 1674 ++++---- Magic2/ModelFileMAG.h | 102 +- Magic2/ModelFileOBJ.cpp | 1604 +++---- Magic2/ModelFileOBJ.h | 98 +- Magic2/ModelView.cpp | 858 ++-- Magic2/ModelView.h | 152 +- Magic2/Primitives.cpp | 128 +- Magic2/Primitives.h | 134 +- Magic2/Selection.cpp | 406 +- Magic2/Selection.h | 172 +- Magic2/Selector.cpp | 804 ++-- Magic2/Selector.h | 176 +- Magic2/StdAfx.cpp | 16 +- Magic2/StdAfx.h | 92 +- Magic2/SurfacePropertiesDialog.cpp | 212 +- Magic2/SurfacePropertiesDialog.h | 170 +- Magic2/TexCubeDX9.cpp | 264 +- Magic2/TexCubeDX9.h | 122 +- Magic2/TextureMapDialog.cpp | 394 +- Magic2/TextureMapDialog.h | 194 +- Magic2/Thumbnail.cpp | 138 +- Magic2/Thumbnail.h | 86 +- Magic2/UVMapView.cpp | 924 ++-- Magic2/UVMapView.h | 188 +- Magic2/VideoDX9.cpp | 7258 +++++++++++++++---------------- Magic2/VideoDX9.h | 414 +- Magic2/l3ds.cpp | 3584 ++++++++-------- Magic2/l3ds.h | 912 ++-- Magic2/resource.h | 466 +- 57 files changed, 22486 insertions(+), 21215 deletions(-) (limited to 'Magic2') diff --git a/Magic2/AlphaInverse.cpp b/Magic2/AlphaInverse.cpp index 464bfda..03ea403 100644 --- a/Magic2/AlphaInverse.cpp +++ b/Magic2/AlphaInverse.cpp @@ -1,4100 +1,4133 @@ -#include "stdafx.h" - -BYTE inverse_palette[32768] = { - 0, 47, 63, 63, 62, 62, 61, 61, - 61, 60, 60, 59, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 252, 252, 252, 252, 252, 252, 252, 252, - 47, 47, 63, 63, 62, 62, 61, 61, - 61, 60, 60, 59, 59, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 55, 252, 252, 252, 252, 252, 252, 252, - 47, 46, 63, 63, 62, 62, 61, 61, - 60, 60, 60, 59, 59, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 55, - 55, 252, 252, 252, 252, 252, 252, 252, - 46, 46, 46, 62, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 4, 4, - 4, 4, 4, 4, 4, 4, 55, 55, - 55, 54, 252, 252, 252, 252, 252, 252, - 46, 46, 45, 111, 111, 79, 79, 61, - 60, 60, 59, 59, 59, 58, 58, 57, - 4, 4, 4, 4, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 79, 79, - 60, 60, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 111, 78, - 78, 78, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 110, 78, - 78, 77, 77, 77, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 111, 110, 110, 110, 110, - 78, 77, 213, 213, 213, 213, 213, 213, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 110, 110, 110, 110, 110, 110, 109, - 109, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 110, 110, 110, 110, 110, 109, 109, 109, - 109, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 212, 6, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 2, 110, 110, 110, 109, 109, 109, 109, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 212, 6, 6, 6, 6, 6, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 2, 2, 2, 109, 109, 109, 109, 108, - 213, 213, 213, 213, 213, 213, 213, 213, - 212, 6, 6, 6, 6, 6, 6, 6, - 54, 54, 54, 54, 53, 53, 53, 53, - 2, 2, 2, 2, 108, 108, 108, 108, - 213, 213, 213, 213, 213, 213, 213, 212, - 6, 6, 6, 6, 6, 6, 6, 211, - 211, 211, 70, 53, 53, 53, 53, 53, - 2, 2, 2, 2, 2, 108, 108, 108, - 213, 213, 213, 213, 213, 213, 212, 6, - 6, 6, 6, 6, 6, 6, 211, 211, - 211, 211, 211, 70, 70, 70, 53, 53, - 2, 2, 2, 2, 2, 2, 107, 107, - 107, 213, 213, 213, 213, 212, 6, 6, - 6, 6, 6, 6, 6, 211, 211, 211, - 211, 211, 211, 210, 210, 70, 70, 70, - 2, 2, 2, 2, 2, 2, 107, 107, - 107, 213, 213, 213, 212, 6, 6, 6, - 6, 6, 6, 6, 211, 211, 211, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 2, 2, 2, 2, 2, 2, 107, 107, - 106, 106, 213, 212, 6, 6, 6, 6, - 6, 6, 6, 211, 211, 211, 211, 211, - 211, 210, 210, 210, 210, 210, 210, 209, - 2, 2, 2, 2, 2, 2, 106, 106, - 106, 106, 106, 6, 6, 6, 6, 6, - 6, 6, 211, 211, 211, 211, 211, 211, - 210, 210, 210, 210, 210, 210, 209, 209, - 2, 2, 2, 2, 2, 2, 105, 105, - 105, 105, 105, 6, 6, 6, 6, 6, - 6, 211, 211, 211, 211, 211, 211, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 2, 2, 2, 2, 2, 2, 105, 105, - 105, 105, 105, 6, 6, 6, 6, 6, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 2, 2, 2, 2, 105, 105, - 104, 104, 104, 6, 6, 6, 6, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 2, 2, 2, 2, 104, 104, 104, - 104, 104, 104, 103, 6, 6, 211, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 2, 2, 2, 2, 2, 104, 104, 104, - 104, 104, 103, 103, 103, 211, 211, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 209, - 250, 250, 250, 250, 250, 104, 104, 104, - 103, 103, 103, 103, 103, 211, 211, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 209, 208, - 250, 250, 250, 250, 250, 250, 102, 102, - 103, 103, 103, 103, 103, 103, 211, 211, - 211, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 103, 103, 103, 103, 211, 211, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 250, - 102, 102, 102, 103, 103, 103, 211, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 102, 102, 102, 103, 103, 103, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 102, 102, 102, 103, 103, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 254, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 250, 102, 102, 102, 102, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 254, 254, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 250, 250, 102, 102, 102, 210, - 210, 209, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 254, 254, 254, 254, 254, - 47, 47, 63, 63, 62, 62, 61, 61, - 61, 60, 60, 59, 59, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 55, 252, 252, 252, 252, 252, 252, 252, - 47, 46, 63, 63, 62, 62, 61, 61, - 60, 60, 60, 59, 59, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 55, - 55, 252, 252, 252, 252, 252, 252, 252, - 46, 46, 46, 62, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 4, 4, - 4, 4, 4, 4, 4, 4, 55, 55, - 55, 54, 252, 252, 252, 252, 252, 252, - 46, 46, 45, 45, 62, 79, 61, 61, - 60, 60, 59, 59, 59, 58, 58, 57, - 4, 4, 4, 4, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 46, 45, 45, 45, 79, 79, 79, 79, - 60, 60, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 79, 79, 79, - 78, 60, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 79, 78, - 78, 78, 77, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 111, 111, 110, 110, 78, - 78, 77, 77, 77, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 110, 110, 110, 110, 110, - 77, 77, 77, 213, 213, 213, 213, 213, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 110, 110, 110, 110, 110, 110, 109, 109, - 109, 213, 213, 213, 213, 213, 213, 213, - 213, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 110, 110, 110, 110, 110, 109, 109, 109, - 109, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 212, 73, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 2, 110, 110, 109, 109, 109, 109, 109, - 108, 213, 213, 213, 213, 213, 213, 213, - 213, 212, 212, 212, 6, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 2, 2, 2, 109, 109, 109, 108, 108, - 108, 213, 213, 213, 213, 213, 213, 213, - 212, 212, 212, 6, 6, 6, 6, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 2, 2, 2, 2, 108, 108, 108, 108, - 108, 213, 213, 213, 213, 213, 213, 212, - 212, 212, 6, 6, 6, 6, 211, 211, - 211, 70, 70, 53, 53, 53, 53, 53, - 2, 2, 2, 2, 108, 108, 108, 107, - 107, 213, 213, 213, 213, 213, 212, 212, - 212, 6, 6, 6, 6, 211, 211, 211, - 211, 211, 70, 70, 70, 70, 53, 53, - 2, 2, 2, 2, 2, 107, 107, 107, - 107, 107, 213, 213, 213, 212, 212, 212, - 6, 6, 6, 6, 211, 211, 211, 211, - 211, 211, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 2, 107, 107, 107, - 107, 106, 213, 213, 212, 212, 212, 6, - 6, 6, 6, 211, 211, 211, 211, 211, - 211, 211, 210, 210, 210, 210, 70, 70, - 2, 2, 2, 2, 2, 107, 107, 106, - 106, 106, 106, 212, 212, 212, 6, 6, - 6, 6, 211, 211, 211, 211, 211, 211, - 211, 210, 210, 210, 210, 210, 210, 209, - 2, 2, 2, 2, 2, 2, 106, 106, - 106, 106, 106, 212, 212, 6, 6, 6, - 6, 211, 211, 211, 211, 211, 211, 211, - 210, 210, 210, 210, 210, 210, 209, 209, - 2, 2, 2, 2, 2, 105, 105, 105, - 105, 105, 105, 212, 6, 6, 6, 6, - 211, 211, 211, 211, 211, 211, 211, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 2, 2, 2, 2, 2, 105, 105, 105, - 105, 105, 105, 104, 6, 6, 6, 211, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 2, 2, 2, 105, 105, 104, - 104, 104, 104, 104, 6, 6, 211, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 2, 2, 2, 2, 104, 104, 104, - 104, 104, 104, 103, 103, 211, 211, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 2, 2, 2, 2, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 211, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 250, 250, 250, 250, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 211, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 211, 211, - 211, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 211, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 102, 103, 103, 103, 103, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 250, - 102, 102, 102, 102, 102, 103, 103, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 208, 208, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 102, 102, 102, 102, 102, 103, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 208, 208, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 102, 102, 102, 102, 102, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 208, 208, 254, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 250, 102, 102, 102, 102, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 208, 208, 208, 208, 254, 254, 254, 254, - 47, 46, 63, 63, 62, 62, 61, 61, - 60, 60, 60, 59, 59, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 55, - 55, 252, 252, 252, 252, 252, 252, 252, - 46, 46, 46, 62, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 4, 4, - 4, 4, 4, 4, 4, 4, 55, 55, - 55, 54, 252, 252, 252, 252, 252, 252, - 46, 46, 45, 45, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 58, 57, - 4, 4, 4, 4, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 46, 45, 45, 45, 45, 79, 79, 61, - 60, 60, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 45, 45, 45, 45, 79, 79, 79, 79, - 60, 60, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 111, 111, 111, 111, 111, 79, 79, 78, - 78, 78, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 78, 78, - 78, 77, 77, 77, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 111, 111, 110, 110, 78, - 78, 77, 77, 77, 76, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 111, 111, 110, 110, 110, 110, 110, 109, - 77, 77, 77, 76, 76, 213, 75, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 110, 110, 110, 110, 110, 110, 109, 109, - 109, 77, 213, 213, 213, 213, 213, 213, - 75, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 110, 110, 110, 110, 109, 109, 109, 109, - 109, 213, 213, 213, 213, 213, 213, 213, - 213, 74, 73, 73, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 110, 110, 110, 109, 109, 109, 109, 109, - 108, 213, 213, 213, 213, 213, 213, 213, - 212, 212, 212, 73, 73, 73, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 2, 2, 109, 109, 109, 108, 108, 108, - 108, 213, 213, 213, 213, 213, 213, 212, - 212, 212, 212, 212, 73, 72, 72, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 2, 2, 2, 108, 108, 108, 108, 108, - 108, 213, 213, 213, 213, 213, 212, 212, - 212, 212, 212, 212, 212, 72, 72, 71, - 70, 70, 70, 53, 53, 53, 53, 53, - 2, 2, 2, 2, 108, 108, 107, 107, - 107, 107, 213, 213, 213, 212, 212, 212, - 212, 212, 212, 212, 6, 211, 211, 211, - 70, 70, 70, 70, 70, 70, 53, 53, - 2, 2, 2, 2, 107, 107, 107, 107, - 107, 107, 213, 213, 212, 212, 212, 212, - 212, 212, 212, 6, 211, 211, 211, 211, - 211, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 107, 107, 107, 107, - 106, 106, 106, 212, 212, 212, 212, 212, - 212, 212, 6, 211, 211, 211, 211, 211, - 211, 210, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 2, 107, 106, 106, - 106, 106, 106, 212, 212, 212, 212, 212, - 212, 6, 211, 211, 211, 211, 211, 211, - 210, 210, 210, 210, 210, 210, 70, 70, - 2, 2, 2, 2, 2, 105, 106, 106, - 106, 106, 106, 106, 212, 212, 212, 212, - 6, 211, 211, 211, 211, 211, 211, 210, - 210, 210, 210, 210, 210, 210, 209, 209, - 2, 2, 2, 2, 2, 105, 105, 105, - 105, 105, 105, 105, 212, 212, 212, 6, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 2, 2, 2, 2, 105, 105, 105, 105, - 105, 105, 104, 104, 212, 212, 6, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 2, 2, 105, 105, 104, 104, - 104, 104, 104, 104, 103, 6, 211, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 2, 2, 2, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 211, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 2, 2, 2, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 211, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 250, 250, 250, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 211, 211, - 211, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 211, - 210, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 102, 102, 103, 103, 103, 103, 210, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 102, 102, 103, 103, 103, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 102, 102, 102, 103, 103, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 250, - 102, 102, 102, 102, 102, 102, 103, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 208, 208, 208, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 102, 102, 102, 102, 102, 101, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 208, 208, 208, 254, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 250, 102, 102, 102, 102, 101, 101, - 210, 209, 209, 209, 209, 209, 209, 208, - 208, 208, 208, 208, 208, 254, 254, 254, - 247, 46, 46, 62, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 4, 4, - 4, 4, 4, 4, 4, 4, 55, 55, - 55, 54, 252, 252, 252, 252, 252, 252, - 46, 46, 45, 45, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 58, 57, - 4, 4, 4, 4, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 46, 45, 45, 45, 45, 61, 61, 61, - 60, 60, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 45, 45, 45, 45, 95, 79, 79, 60, - 60, 60, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 45, 45, 45, 127, 95, 79, 79, 78, - 78, 59, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 45, 127, 127, 127, 127, 79, 78, 78, - 78, 78, 59, 59, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 111, 111, 111, 111, 111, 111, 78, 78, - 78, 77, 77, 77, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 111, 111, 111, 111, 110, 110, 78, 78, - 77, 77, 77, 77, 76, 76, 57, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 111, 110, 110, 110, 110, 110, 110, 109, - 77, 77, 77, 76, 76, 75, 75, 75, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 110, 110, 110, 110, 110, 109, 109, 109, - 109, 77, 76, 76, 76, 75, 75, 75, - 74, 74, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 110, 110, 110, 110, 109, 109, 109, 109, - 109, 76, 213, 213, 213, 213, 213, 74, - 74, 73, 73, 73, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 110, 110, 109, 109, 109, 109, 109, 108, - 108, 108, 213, 213, 213, 213, 213, 213, - 74, 73, 73, 73, 73, 73, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 2, 109, 109, 109, 109, 108, 108, 108, - 108, 108, 213, 213, 213, 213, 213, 212, - 212, 212, 73, 73, 73, 72, 72, 72, - 54, 53, 53, 53, 53, 53, 53, 53, - 2, 2, 108, 108, 108, 108, 108, 108, - 107, 107, 213, 213, 213, 213, 212, 212, - 212, 212, 212, 73, 72, 72, 72, 71, - 70, 70, 70, 53, 53, 53, 53, 53, - 2, 2, 2, 108, 108, 108, 107, 107, - 107, 107, 213, 213, 213, 212, 212, 212, - 212, 212, 212, 212, 211, 72, 71, 70, - 70, 70, 70, 70, 70, 70, 53, 53, - 2, 2, 2, 2, 107, 107, 107, 107, - 107, 106, 106, 213, 212, 212, 212, 212, - 212, 212, 212, 211, 211, 211, 211, 211, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 107, 107, 107, 106, - 106, 106, 106, 106, 212, 212, 212, 212, - 212, 212, 211, 211, 211, 211, 211, 211, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 107, 106, 106, 106, - 106, 106, 106, 106, 212, 212, 212, 212, - 212, 211, 211, 211, 211, 211, 211, 211, - 210, 210, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 2, 105, 105, 105, 105, - 105, 105, 105, 106, 212, 212, 212, 212, - 211, 211, 211, 211, 211, 211, 211, 210, - 210, 210, 210, 210, 210, 210, 209, 209, - 2, 2, 2, 2, 105, 105, 105, 105, - 105, 105, 105, 105, 212, 212, 212, 211, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 2, 2, 2, 2, 105, 105, 105, 105, - 104, 104, 104, 104, 104, 212, 211, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 2, 105, 104, 104, 104, 104, - 104, 104, 104, 103, 103, 103, 211, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 2, 2, 104, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 211, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 2, 2, 102, 102, 102, 104, 104, 104, - 103, 103, 103, 103, 103, 103, 103, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 211, - 211, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 250, 250, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 211, - 210, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 102, 102, 103, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 102, 102, 102, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 102, 102, 102, 103, 103, 103, - 210, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 102, 102, 102, 102, 101, 101, - 210, 210, 210, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 250, 250, 250, - 102, 102, 102, 102, 102, 101, 101, 101, - 210, 210, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 208, 208, 208, 208, 254, - 250, 250, 250, 250, 250, 250, 250, 250, - 250, 102, 102, 102, 102, 101, 101, 101, - 210, 209, 209, 209, 209, 209, 209, 208, - 208, 208, 208, 208, 208, 208, 254, 254, - 247, 247, 247, 247, 62, 62, 61, 61, - 60, 60, 59, 59, 59, 58, 58, 57, - 4, 4, 4, 4, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 247, 247, 247, 45, 45, 61, 61, 61, - 60, 60, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 247, 247, 45, 45, 44, 95, 61, 60, - 60, 60, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 247, 45, 45, 44, 44, 95, 79, 60, - 60, 59, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 45, 143, 143, 127, 44, 95, 79, 78, - 78, 59, 59, 59, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 159, 159, 159, 127, 127, 95, 94, 78, - 78, 77, 77, 58, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 159, 159, 159, 127, 126, 126, 94, 78, - 77, 77, 77, 77, 58, 58, 57, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 111, 111, 111, 110, 126, 126, 94, 78, - 77, 77, 77, 76, 76, 76, 75, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 110, 110, 110, 110, 110, 110, 109, 77, - 77, 77, 76, 76, 76, 75, 75, 75, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 110, 110, 110, 110, 110, 109, 109, 109, - 77, 76, 76, 76, 75, 75, 75, 75, - 74, 74, 73, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 110, 110, 110, 109, 109, 109, 109, 109, - 108, 76, 76, 76, 75, 75, 75, 74, - 74, 73, 73, 73, 73, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 110, 109, 109, 109, 109, 109, 108, 108, - 108, 108, 213, 213, 213, 75, 74, 74, - 74, 73, 73, 73, 73, 72, 72, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 2, 109, 109, 109, 108, 108, 108, 108, - 108, 108, 213, 213, 213, 213, 74, 74, - 73, 73, 73, 73, 72, 72, 72, 71, - 53, 53, 53, 53, 53, 53, 53, 53, - 2, 2, 108, 108, 108, 108, 108, 107, - 107, 107, 213, 213, 213, 213, 212, 212, - 212, 73, 73, 73, 72, 72, 72, 71, - 70, 70, 70, 53, 53, 53, 53, 53, - 2, 2, 108, 108, 108, 107, 107, 107, - 107, 107, 107, 213, 213, 212, 212, 212, - 212, 212, 212, 72, 72, 72, 71, 70, - 70, 70, 70, 70, 70, 70, 53, 53, - 2, 2, 2, 107, 107, 107, 107, 107, - 107, 106, 106, 106, 212, 212, 212, 212, - 212, 212, 212, 211, 211, 71, 71, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 107, 107, 107, 107, 106, - 106, 106, 106, 106, 212, 212, 212, 212, - 212, 212, 211, 211, 211, 211, 211, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 107, 107, 106, 106, 106, - 106, 106, 106, 106, 212, 212, 212, 212, - 212, 211, 211, 211, 211, 211, 211, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 212, 212, 212, - 211, 211, 211, 211, 211, 211, 211, 210, - 210, 210, 210, 70, 70, 70, 70, 70, - 2, 2, 2, 105, 105, 105, 105, 105, - 105, 105, 105, 104, 104, 212, 212, 211, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 210, 210, 209, 209, 209, - 2, 2, 2, 105, 105, 105, 105, 104, - 104, 104, 104, 104, 103, 103, 211, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 2, 104, 104, 104, 104, 104, - 104, 104, 104, 103, 103, 103, 211, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 2, 104, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 103, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 2, 102, 102, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 103, 211, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 250, 102, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 211, - 211, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 250, 102, 102, 102, 102, 102, - 102, 102, 102, 103, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 208, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 102, 102, 102, 102, 103, 103, 103, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 208, 208, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 102, 102, 102, 102, 101, 101, 101, - 210, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 208, 208, 207, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 102, 102, 102, 101, 101, 101, - 210, 210, 210, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 208, 208, 207, 207, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 102, 102, 101, 101, 101, 101, - 210, 210, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 208, 208, 207, 207, 207, - 250, 250, 250, 250, 250, 250, 250, 250, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 209, 209, 209, 209, 209, 209, 208, - 208, 208, 208, 208, 207, 207, 207, 207, - 247, 247, 247, 247, 247, 223, 223, 223, - 223, 223, 59, 59, 58, 58, 58, 57, - 57, 56, 56, 56, 56, 55, 55, 55, - 54, 54, 54, 252, 252, 252, 252, 252, - 247, 247, 247, 247, 44, 223, 223, 223, - 223, 223, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 247, 247, 247, 143, 143, 44, 223, 223, - 223, 59, 59, 59, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 247, 247, 143, 143, 143, 95, 95, 78, - 60, 59, 59, 59, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 143, 143, 143, 143, 143, 43, 43, 94, - 78, 77, 59, 58, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 159, 159, 159, 159, 159, 43, 94, 94, - 78, 77, 77, 77, 58, 58, 57, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 159, 159, 159, 159, 126, 126, 94, 93, - 77, 77, 77, 76, 76, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 159, 159, 159, 126, 126, 126, 94, 93, - 77, 77, 76, 76, 76, 75, 75, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 110, 110, 110, 126, 126, 125, 125, 93, - 77, 77, 76, 76, 76, 75, 75, 75, - 74, 56, 56, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 110, 110, 110, 110, 109, 109, 125, 125, - 92, 76, 76, 76, 75, 75, 75, 74, - 74, 74, 73, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 110, 110, 109, 109, 109, 109, 109, 109, - 108, 76, 76, 76, 75, 75, 75, 74, - 74, 73, 73, 73, 73, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 110, 109, 109, 109, 109, 108, 108, 108, - 108, 108, 76, 75, 75, 75, 74, 74, - 74, 73, 73, 73, 73, 72, 72, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 109, 109, 109, 108, 108, 108, 108, 108, - 108, 107, 107, 75, 75, 74, 74, 74, - 73, 73, 73, 73, 72, 72, 72, 71, - 53, 53, 53, 53, 53, 53, 53, 53, - 2, 108, 108, 108, 108, 108, 108, 107, - 107, 107, 107, 213, 213, 74, 74, 74, - 73, 73, 73, 72, 72, 72, 71, 71, - 70, 70, 70, 53, 53, 53, 53, 53, - 2, 2, 108, 108, 107, 107, 107, 107, - 107, 107, 106, 106, 213, 212, 212, 212, - 73, 73, 73, 72, 72, 72, 71, 70, - 70, 70, 70, 70, 70, 70, 52, 52, - 2, 2, 107, 107, 107, 107, 107, 107, - 106, 106, 106, 106, 106, 212, 212, 212, - 212, 212, 72, 72, 72, 71, 71, 70, - 70, 70, 70, 70, 70, 70, 70, 52, - 2, 2, 2, 107, 107, 107, 106, 106, - 106, 106, 106, 106, 106, 212, 212, 212, - 212, 212, 211, 211, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 107, 105, 105, 106, 106, - 106, 106, 106, 106, 106, 212, 212, 212, - 212, 211, 211, 211, 211, 211, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 2, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 212, 212, 212, - 211, 211, 211, 211, 211, 211, 211, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 105, 105, 105, 105, 105, 105, - 105, 105, 104, 104, 104, 103, 212, 211, - 211, 211, 211, 211, 211, 211, 210, 210, - 210, 210, 210, 70, 70, 70, 209, 209, - 2, 2, 105, 105, 105, 105, 104, 104, - 104, 104, 104, 104, 103, 103, 103, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 2, 104, 104, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 103, 211, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 2, 102, 104, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 103, 211, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 102, 102, 102, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 103, 103, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 103, - 211, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 208, - 250, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 103, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 208, 208, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 103, 103, 103, 103, - 210, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 208, 208, 207, - 250, 250, 250, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 101, 101, 101, 101, - 210, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 208, 208, 207, 207, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 210, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 208, 208, 207, 207, 207, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 102, 102, 102, 101, 101, 101, 101, - 100, 210, 210, 209, 209, 209, 209, 209, - 209, 208, 208, 208, 207, 207, 207, 207, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 210, 209, 209, 209, 209, 209, 209, - 208, 208, 208, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 250, 250, 250, 102, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 209, 209, 209, 209, 209, 209, 208, - 208, 208, 207, 207, 207, 207, 207, 207, - 246, 246, 246, 246, 223, 223, 223, 223, - 223, 223, 223, 222, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 252, 252, 252, 252, - 246, 246, 246, 246, 223, 223, 223, 223, - 223, 223, 223, 222, 58, 58, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 246, 246, 246, 143, 143, 223, 223, 223, - 223, 223, 223, 59, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 246, 246, 143, 143, 143, 143, 43, 223, - 223, 223, 59, 58, 58, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 246, 143, 143, 143, 142, 43, 43, 94, - 15, 15, 77, 58, 58, 58, 57, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 159, 159, 159, 142, 142, 43, 43, 15, - 15, 77, 77, 76, 58, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 159, 159, 158, 158, 158, 158, 42, 93, - 93, 77, 77, 76, 76, 76, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 159, 158, 158, 158, 158, 125, 125, 93, - 93, 77, 76, 76, 76, 75, 75, 75, - 56, 56, 56, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 158, 158, 158, 158, 125, 125, 125, 125, - 92, 92, 76, 76, 75, 75, 75, 75, - 74, 74, 55, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 158, 158, 158, 125, 125, 125, 125, 124, - 92, 92, 76, 76, 75, 75, 75, 74, - 74, 74, 73, 73, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 110, 110, 109, 109, 109, 125, 124, 124, - 92, 92, 76, 75, 75, 75, 74, 74, - 74, 73, 73, 73, 73, 72, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 109, 109, 109, 109, 109, 108, 108, 108, - 124, 123, 91, 75, 75, 75, 74, 74, - 74, 73, 73, 73, 72, 72, 72, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 109, 109, 108, 108, 108, 108, 108, 108, - 107, 107, 91, 75, 75, 74, 74, 74, - 73, 73, 73, 72, 72, 72, 72, 71, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 108, 108, 108, 108, 108, 107, 107, - 107, 107, 107, 75, 74, 74, 74, 73, - 73, 73, 73, 72, 72, 72, 71, 71, - 70, 70, 70, 53, 53, 52, 52, 52, - 2, 108, 108, 107, 107, 107, 107, 107, - 107, 106, 106, 106, 74, 74, 74, 73, - 73, 73, 72, 72, 72, 71, 71, 70, - 70, 70, 70, 70, 70, 52, 52, 52, - 2, 2, 107, 107, 107, 107, 107, 106, - 106, 106, 106, 106, 106, 212, 212, 73, - 73, 72, 72, 72, 71, 71, 71, 70, - 70, 70, 70, 70, 70, 70, 70, 52, - 2, 2, 107, 107, 107, 106, 106, 106, - 106, 106, 106, 106, 106, 212, 212, 212, - 212, 72, 72, 72, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 106, 106, 212, 212, 212, - 212, 211, 211, 71, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, - 2, 2, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 104, 212, 212, - 211, 211, 211, 211, 211, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 68, - 2, 2, 105, 105, 105, 105, 105, 105, - 105, 104, 104, 104, 104, 103, 103, 211, - 211, 211, 211, 211, 211, 211, 210, 70, - 70, 70, 70, 70, 70, 70, 68, 68, - 2, 105, 105, 105, 105, 104, 104, 104, - 104, 104, 104, 103, 103, 103, 103, 211, - 211, 211, 211, 211, 211, 210, 210, 210, - 210, 210, 210, 210, 209, 209, 209, 209, - 2, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 103, 103, - 211, 211, 211, 211, 210, 210, 210, 210, - 210, 210, 210, 209, 209, 209, 209, 209, - 102, 102, 102, 102, 102, 104, 104, 104, - 103, 103, 103, 103, 103, 103, 103, 103, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 209, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 103, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 209, 208, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 103, - 103, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 209, 208, 207, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 103, 103, 103, 103, 103, - 103, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 209, 208, 207, 207, - 250, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 101, 101, 101, 101, - 100, 210, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 209, 208, 207, 207, 207, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 210, 210, 210, 210, 209, 209, 209, - 209, 209, 209, 208, 207, 207, 207, 207, - 250, 250, 250, 102, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 100, 210, 210, 209, 209, 209, 209, - 209, 209, 208, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 100, - 100, 100, 210, 209, 209, 209, 209, 209, - 209, 208, 207, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 209, 209, 209, 209, 209, 209, - 208, 207, 207, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 250, 250, 102, 102, - 102, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 209, 209, 209, 209, 209, 208, - 207, 207, 207, 207, 207, 207, 207, 207, - 246, 246, 246, 246, 223, 223, 223, 223, - 223, 223, 222, 222, 222, 222, 57, 57, - 57, 56, 56, 56, 55, 55, 55, 55, - 54, 54, 54, 54, 54, 252, 252, 252, - 246, 246, 246, 246, 223, 223, 223, 223, - 223, 223, 222, 222, 222, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 246, 246, 246, 246, 143, 223, 223, 223, - 223, 223, 222, 222, 222, 58, 57, 57, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 246, 246, 246, 143, 142, 142, 223, 223, - 223, 222, 222, 222, 58, 58, 57, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 246, 143, 143, 142, 142, 142, 43, 15, - 15, 15, 222, 222, 58, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 159, 159, 142, 142, 142, 142, 15, 15, - 15, 15, 15, 76, 76, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 159, 158, 158, 158, 158, 158, 42, 15, - 15, 15, 92, 76, 76, 75, 75, 56, - 56, 56, 56, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 158, 158, 158, 158, 158, 141, 42, 42, - 41, 92, 92, 76, 76, 75, 75, 75, - 56, 56, 55, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 158, 158, 158, 158, 157, 125, 125, 41, - 92, 92, 92, 76, 75, 75, 75, 74, - 74, 74, 55, 55, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 158, 158, 158, 157, 157, 125, 124, 124, - 92, 92, 91, 91, 75, 75, 75, 74, - 74, 74, 73, 73, 55, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 157, 157, 157, 124, 124, 124, 124, - 124, 92, 91, 91, 75, 75, 74, 74, - 74, 73, 73, 73, 72, 72, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 157, 124, 124, 124, 124, 124, - 123, 123, 91, 91, 75, 74, 74, 74, - 73, 73, 73, 73, 72, 72, 72, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 108, 108, 108, 108, 108, 123, - 123, 123, 123, 90, 90, 74, 74, 74, - 73, 73, 73, 72, 72, 72, 71, 71, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 108, 108, 108, 107, 107, 107, - 107, 123, 122, 90, 90, 74, 74, 73, - 73, 73, 72, 72, 72, 71, 71, 71, - 70, 70, 70, 52, 52, 52, 52, 52, - 191, 191, 107, 107, 107, 107, 107, 107, - 106, 106, 106, 106, 90, 74, 74, 73, - 73, 73, 72, 72, 72, 71, 71, 70, - 70, 70, 70, 70, 52, 52, 52, 52, - 191, 191, 107, 107, 107, 107, 106, 106, - 106, 106, 106, 106, 106, 74, 73, 73, - 73, 72, 72, 72, 71, 71, 71, 70, - 70, 70, 70, 70, 70, 70, 52, 52, - 191, 191, 107, 107, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 73, 73, - 72, 72, 72, 71, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 51, - 2, 105, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 105, 212, 212, - 72, 72, 72, 71, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 68, - 2, 105, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 104, 104, 104, 212, 212, - 211, 211, 71, 71, 71, 70, 70, 70, - 70, 70, 70, 70, 70, 68, 68, 68, - 2, 105, 105, 105, 105, 105, 105, 104, - 104, 104, 104, 104, 103, 103, 103, 211, - 211, 211, 211, 211, 211, 70, 70, 70, - 70, 70, 70, 70, 68, 68, 68, 68, - 2, 105, 105, 104, 104, 104, 104, 104, - 104, 104, 104, 103, 103, 103, 103, 103, - 211, 211, 211, 211, 210, 210, 210, 70, - 70, 70, 69, 68, 68, 68, 68, 68, - 104, 104, 104, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 103, 103, - 211, 211, 211, 210, 210, 210, 210, 210, - 210, 210, 210, 68, 68, 209, 209, 209, - 102, 102, 102, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 103, 103, - 211, 211, 210, 210, 210, 210, 210, 210, - 210, 210, 209, 209, 209, 209, 209, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 103, - 103, 210, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 209, 209, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 103, - 100, 210, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 209, 209, 206, 206, 207, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 100, - 100, 210, 210, 210, 210, 210, 210, 209, - 209, 209, 209, 209, 206, 206, 207, 207, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 100, - 100, 100, 210, 210, 210, 210, 209, 209, - 209, 209, 209, 206, 206, 207, 207, 207, - 250, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 210, 210, 210, 209, 209, 209, - 209, 209, 206, 206, 207, 207, 207, 207, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 210, 210, 209, 209, 209, 209, - 209, 206, 206, 207, 207, 207, 207, 207, - 250, 250, 250, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 209, 209, 209, 209, 209, - 206, 206, 207, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 101, 100, 100, - 100, 100, 98, 209, 209, 209, 209, 206, - 206, 207, 207, 207, 207, 207, 207, 207, - 250, 250, 250, 250, 250, 102, 102, 102, - 102, 101, 101, 101, 101, 101, 100, 100, - 100, 98, 98, 209, 209, 209, 206, 206, - 207, 207, 207, 207, 207, 207, 207, 207, - 245, 245, 245, 245, 223, 223, 223, 223, - 223, 222, 222, 222, 222, 222, 221, 221, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 252, 252, 252, - 245, 245, 245, 245, 223, 223, 223, 223, - 223, 222, 222, 222, 222, 222, 221, 221, - 56, 56, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 245, 245, 245, 245, 223, 223, 223, 223, - 223, 222, 222, 222, 222, 221, 221, 57, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 245, 245, 245, 142, 142, 142, 223, 223, - 222, 222, 222, 222, 222, 221, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 245, 245, 142, 142, 142, 142, 15, 15, - 15, 222, 222, 222, 222, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 245, 142, 142, 142, 142, 141, 141, 15, - 15, 15, 15, 76, 76, 57, 57, 56, - 56, 56, 56, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 158, 158, 158, 158, 141, 141, 141, 15, - 15, 41, 92, 92, 76, 75, 75, 56, - 56, 56, 55, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 158, 158, 158, 158, 141, 141, 141, 41, - 41, 92, 92, 91, 91, 75, 75, 75, - 74, 56, 55, 55, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 158, 158, 157, 157, 157, 157, 157, 41, - 41, 92, 91, 91, 91, 75, 75, 74, - 74, 74, 73, 55, 55, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 158, 157, 157, 157, 157, 157, 124, 124, - 40, 40, 91, 91, 91, 75, 74, 74, - 74, 74, 73, 73, 55, 54, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 157, 157, 157, 124, 124, 124, - 123, 123, 91, 91, 90, 90, 74, 74, - 74, 73, 73, 73, 72, 72, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 191, 124, 124, 124, 124, 123, - 123, 123, 91, 90, 90, 90, 74, 74, - 73, 73, 73, 72, 72, 72, 72, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 191, 191, 124, 124, 123, 123, - 123, 123, 122, 90, 90, 90, 74, 74, - 73, 73, 73, 72, 72, 72, 71, 71, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 107, 107, 123, 123, - 122, 122, 122, 122, 90, 89, 74, 73, - 73, 73, 72, 72, 72, 71, 71, 71, - 70, 70, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 107, 107, 107, 107, - 122, 122, 122, 121, 89, 89, 89, 73, - 73, 72, 72, 72, 71, 71, 71, 70, - 70, 70, 70, 70, 52, 52, 52, 52, - 191, 191, 191, 107, 107, 107, 106, 106, - 106, 106, 121, 121, 121, 89, 89, 73, - 73, 72, 72, 72, 71, 71, 71, 70, - 70, 70, 70, 70, 70, 52, 51, 51, - 191, 191, 191, 105, 105, 105, 106, 106, - 106, 106, 106, 121, 121, 121, 88, 88, - 72, 72, 72, 71, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 70, 51, 51, - 191, 191, 105, 105, 105, 105, 105, 105, - 105, 105, 105, 105, 105, 120, 88, 88, - 72, 72, 71, 71, 71, 71, 70, 70, - 70, 70, 70, 70, 70, 68, 68, 68, - 191, 191, 105, 105, 105, 105, 105, 105, - 105, 105, 104, 104, 104, 104, 120, 87, - 72, 71, 71, 71, 71, 70, 70, 70, - 70, 70, 70, 69, 68, 68, 68, 68, - 191, 105, 105, 105, 105, 105, 104, 104, - 104, 104, 104, 104, 103, 103, 103, 103, - 211, 211, 71, 71, 70, 70, 70, 70, - 70, 69, 69, 68, 68, 68, 68, 68, - 105, 105, 104, 104, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 103, 103, - 211, 211, 211, 211, 70, 70, 70, 69, - 69, 69, 68, 68, 68, 68, 68, 68, - 102, 102, 104, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 103, 103, - 103, 211, 211, 210, 210, 210, 210, 69, - 69, 68, 68, 68, 68, 68, 68, 68, - 102, 102, 102, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 103, 103, - 103, 211, 210, 210, 210, 210, 210, 210, - 210, 68, 68, 68, 68, 68, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 100, - 100, 100, 210, 210, 210, 210, 210, 210, - 210, 209, 209, 209, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 102, 101, 101, 101, 101, 100, - 100, 100, 210, 210, 210, 210, 210, 210, - 209, 209, 209, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 100, 100, - 100, 100, 210, 210, 210, 210, 210, 209, - 209, 209, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 210, 210, 210, 209, 209, - 209, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 210, 210, 209, 209, 209, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 98, 209, 209, 209, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 250, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 98, 98, 209, 209, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 250, 250, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 101, 100, 100, 100, - 100, 98, 98, 98, 209, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 250, 250, 250, 102, 102, 102, 102, - 101, 101, 101, 101, 101, 100, 100, 100, - 98, 98, 98, 98, 206, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 245, 245, 245, 245, 245, 223, 223, 223, - 222, 222, 222, 222, 222, 221, 221, 221, - 221, 221, 56, 56, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 252, 252, - 245, 245, 245, 245, 245, 223, 223, 223, - 222, 222, 222, 222, 222, 221, 221, 221, - 221, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 245, 245, 245, 245, 245, 223, 223, 223, - 222, 222, 222, 222, 221, 221, 221, 221, - 221, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 245, 245, 245, 245, 142, 223, 223, 222, - 222, 222, 222, 222, 221, 221, 221, 221, - 56, 56, 56, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 245, 245, 245, 142, 142, 141, 141, 15, - 222, 222, 222, 222, 221, 221, 221, 56, - 56, 56, 56, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 245, 142, 142, 142, 141, 141, 141, 15, - 15, 15, 222, 222, 221, 221, 221, 56, - 56, 56, 55, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 158, 158, 158, 141, 141, 141, 141, 141, - 41, 41, 40, 91, 91, 91, 75, 75, - 56, 56, 55, 55, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 158, 158, 141, 141, 141, 141, 141, 140, - 41, 40, 40, 91, 91, 91, 75, 74, - 74, 74, 55, 55, 55, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 158, 157, 157, 157, 157, 157, 140, 140, - 40, 40, 91, 91, 91, 90, 90, 74, - 74, 74, 73, 55, 55, 54, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 157, 157, 157, 156, 156, 156, - 40, 40, 91, 91, 90, 90, 90, 74, - 74, 73, 73, 73, 72, 54, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 191, 156, 156, 156, 156, 123, - 123, 39, 39, 90, 90, 90, 90, 74, - 74, 73, 73, 72, 72, 72, 53, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 191, 191, 156, 156, 123, 123, - 123, 123, 38, 90, 90, 90, 89, 74, - 73, 73, 73, 72, 72, 72, 71, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 156, 123, 123, 123, - 123, 122, 122, 90, 90, 89, 89, 89, - 73, 73, 72, 72, 72, 71, 71, 71, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 191, 123, 123, 122, - 122, 122, 122, 122, 89, 89, 89, 88, - 73, 72, 72, 72, 72, 71, 71, 71, - 70, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 191, 122, 122, 122, - 122, 122, 121, 121, 89, 89, 89, 88, - 88, 72, 72, 72, 71, 71, 71, 70, - 70, 70, 70, 52, 52, 52, 51, 51, - 191, 191, 191, 191, 191, 106, 106, 121, - 121, 121, 121, 121, 121, 89, 88, 88, - 88, 72, 72, 71, 71, 71, 71, 70, - 70, 70, 70, 70, 51, 51, 51, 51, - 191, 191, 191, 191, 105, 105, 105, 105, - 121, 121, 121, 121, 121, 120, 88, 88, - 88, 72, 71, 71, 71, 71, 70, 70, - 70, 70, 70, 69, 69, 51, 51, 51, - 191, 191, 191, 105, 105, 105, 105, 105, - 105, 105, 121, 120, 120, 120, 88, 88, - 87, 72, 71, 71, 71, 71, 70, 70, - 70, 69, 69, 69, 68, 68, 68, 68, - 191, 190, 190, 105, 105, 105, 105, 105, - 105, 104, 104, 104, 120, 120, 120, 87, - 87, 87, 71, 71, 71, 70, 70, 69, - 69, 69, 69, 68, 68, 68, 68, 68, - 190, 190, 105, 105, 105, 104, 104, 104, - 104, 104, 104, 103, 103, 103, 103, 87, - 87, 87, 71, 71, 70, 69, 69, 69, - 69, 69, 68, 68, 68, 68, 68, 68, - 190, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 103, 103, 103, 103, 103, 103, - 87, 86, 71, 71, 69, 69, 69, 69, - 69, 68, 68, 68, 68, 68, 68, 68, - 102, 102, 102, 102, 102, 102, 104, 104, - 103, 103, 103, 103, 103, 103, 103, 103, - 100, 211, 211, 69, 69, 69, 69, 69, - 68, 68, 68, 68, 68, 68, 68, 68, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 103, 103, 103, 103, 103, 103, 100, - 100, 100, 210, 210, 210, 69, 69, 68, - 68, 68, 68, 68, 68, 68, 68, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 210, 210, 210, 210, 68, - 68, 68, 68, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 101, 101, 101, 101, 100, 100, - 100, 100, 99, 210, 210, 210, 210, 210, - 209, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 100, 99, 99, 210, 210, 210, 209, - 206, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 99, 99, 210, 210, 209, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 99, 99, 98, 209, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 250, 250, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 101, 100, 100, 100, 100, - 98, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 205, - 250, 250, 250, 102, 102, 102, 102, 101, - 101, 101, 101, 101, 100, 100, 100, 98, - 98, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 205, 205, - 244, 244, 244, 244, 244, 223, 223, 222, - 222, 222, 222, 222, 221, 221, 221, 221, - 221, 220, 220, 5, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 54, 53, 252, - 244, 244, 244, 244, 244, 223, 223, 222, - 222, 222, 222, 222, 221, 221, 221, 221, - 220, 220, 220, 220, 55, 55, 55, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 244, 244, 244, 244, 244, 223, 223, 222, - 222, 222, 222, 221, 221, 221, 221, 221, - 220, 220, 220, 55, 55, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 244, 244, 244, 244, 244, 141, 222, 222, - 222, 222, 222, 221, 221, 221, 221, 221, - 220, 220, 220, 55, 55, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 244, 244, 244, 141, 141, 141, 141, 222, - 222, 222, 222, 221, 221, 221, 221, 221, - 220, 220, 55, 55, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 244, 244, 141, 141, 141, 141, 141, 141, - 15, 222, 222, 221, 221, 221, 221, 221, - 220, 56, 55, 55, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 244, 141, 141, 141, 141, 141, 140, 140, - 140, 40, 40, 91, 91, 91, 90, 90, - 56, 56, 55, 55, 55, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 158, 141, 141, 141, 141, 140, 140, 140, - 140, 40, 40, 91, 91, 90, 90, 90, - 74, 74, 55, 55, 55, 54, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 157, 157, 140, 140, 140, 140, - 40, 40, 39, 39, 90, 90, 90, 90, - 74, 74, 73, 55, 55, 54, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 191, 156, 156, 156, 156, 156, - 139, 39, 39, 38, 90, 90, 90, 90, - 74, 73, 73, 73, 72, 53, 53, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 191, 156, 156, 156, 156, 155, - 123, 39, 38, 38, 90, 90, 90, 89, - 88, 73, 73, 72, 72, 72, 53, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 156, 156, 155, 155, - 123, 122, 38, 90, 90, 89, 89, 89, - 88, 73, 72, 72, 72, 72, 71, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 191, 155, 155, 155, - 122, 122, 122, 37, 89, 89, 89, 88, - 88, 88, 72, 72, 72, 71, 71, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 191, 155, 155, 122, - 122, 122, 122, 121, 89, 89, 89, 88, - 88, 88, 72, 72, 71, 71, 71, 71, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 191, 191, 191, 155, 122, 122, - 122, 121, 121, 121, 121, 89, 88, 88, - 88, 88, 72, 72, 71, 71, 71, 70, - 70, 70, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 122, 121, 121, - 121, 121, 121, 121, 121, 89, 88, 88, - 88, 87, 72, 71, 71, 71, 71, 70, - 70, 70, 69, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 105, 121, 121, - 121, 121, 121, 120, 120, 120, 88, 88, - 87, 87, 87, 71, 71, 71, 70, 70, - 69, 69, 69, 69, 68, 51, 51, 50, - 191, 190, 190, 190, 105, 105, 105, 105, - 121, 121, 120, 120, 120, 120, 120, 87, - 87, 87, 87, 71, 71, 70, 69, 69, - 69, 69, 69, 68, 68, 68, 68, 50, - 190, 190, 190, 190, 105, 105, 105, 105, - 104, 104, 120, 120, 120, 120, 119, 87, - 87, 87, 86, 71, 71, 69, 69, 69, - 69, 69, 68, 68, 68, 68, 68, 68, - 190, 190, 190, 105, 104, 104, 104, 104, - 104, 104, 104, 103, 120, 119, 119, 119, - 87, 86, 86, 71, 69, 69, 69, 69, - 69, 68, 68, 68, 68, 68, 68, 68, - 3, 190, 190, 104, 104, 104, 104, 104, - 104, 103, 103, 103, 103, 103, 118, 118, - 118, 86, 86, 69, 69, 69, 69, 69, - 68, 68, 68, 68, 68, 68, 68, 68, - 3, 102, 102, 102, 102, 102, 102, 102, - 103, 103, 103, 103, 103, 103, 100, 100, - 118, 86, 86, 69, 69, 69, 69, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 100, 99, 69, 69, 69, 68, 68, - 68, 68, 68, 68, 68, 68, 67, 67, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 99, 99, 69, 68, 68, 68, - 68, 68, 68, 68, 67, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 100, 100, - 100, 99, 99, 99, 210, 210, 68, 68, - 68, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 100, 99, 99, 99, 99, 210, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 99, 99, 99, 99, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 205, - 102, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 99, 99, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 205, 205, - 102, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 206, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 98, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 206, 205, 205, 205, 205, - 250, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 101, 100, 100, 100, 100, 98, - 98, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 206, 205, 205, 205, 205, 205, - 250, 250, 102, 102, 102, 102, 101, 101, - 101, 101, 101, 100, 100, 100, 98, 98, - 98, 98, 98, 98, 98, 206, 206, 206, - 206, 206, 205, 205, 205, 205, 205, 205, - 243, 243, 243, 244, 244, 244, 222, 222, - 222, 222, 222, 221, 221, 221, 221, 221, - 220, 220, 5, 5, 5, 5, 5, 54, - 54, 54, 54, 54, 54, 53, 53, 53, - 243, 243, 244, 244, 244, 223, 222, 222, - 222, 222, 222, 221, 221, 221, 221, 220, - 220, 220, 220, 5, 5, 55, 55, 54, - 54, 54, 54, 54, 53, 53, 53, 53, - 243, 244, 244, 244, 244, 223, 222, 222, - 222, 222, 221, 221, 221, 221, 221, 220, - 220, 220, 220, 220, 219, 55, 54, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 244, 244, 244, 244, 244, 141, 222, 222, - 222, 222, 221, 221, 221, 221, 221, 220, - 220, 220, 220, 220, 55, 55, 54, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 244, 244, 244, 244, 141, 141, 141, 222, - 222, 222, 221, 221, 221, 221, 221, 220, - 220, 220, 220, 55, 55, 55, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 244, 244, 244, 141, 141, 141, 140, 140, - 140, 222, 221, 221, 221, 221, 221, 220, - 220, 220, 220, 55, 55, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 244, 141, 141, 141, 140, 140, 140, 140, - 140, 40, 40, 39, 221, 221, 221, 220, - 220, 220, 55, 55, 55, 54, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 201, 201, 201, 140, 140, 140, 140, - 139, 139, 39, 39, 38, 90, 14, 14, - 14, 14, 55, 55, 55, 54, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 191, 201, 201, 140, 140, 140, 139, - 139, 139, 39, 38, 38, 90, 14, 14, - 14, 14, 73, 73, 55, 53, 53, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 191, 201, 156, 156, 139, 139, - 139, 39, 38, 38, 90, 14, 14, 14, - 14, 88, 88, 72, 72, 53, 53, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 156, 156, 155, 155, - 155, 38, 38, 38, 90, 14, 14, 14, - 88, 88, 88, 72, 72, 72, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 155, 155, 155, 155, - 155, 122, 38, 37, 37, 89, 89, 88, - 88, 88, 88, 72, 72, 71, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 191, 155, 155, 155, - 122, 122, 122, 37, 37, 89, 89, 88, - 88, 88, 88, 72, 72, 71, 71, 52, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 191, 191, 191, 155, 155, 122, - 122, 122, 121, 121, 89, 89, 88, 88, - 88, 88, 87, 72, 71, 71, 71, 71, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 155, 154, 122, - 121, 121, 121, 121, 121, 89, 88, 88, - 88, 87, 87, 71, 71, 71, 71, 70, - 70, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 191, 121, 121, - 121, 121, 121, 121, 120, 120, 88, 88, - 87, 87, 87, 87, 71, 71, 71, 69, - 69, 69, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 190, 190, 190, 121, 121, - 121, 121, 120, 120, 120, 120, 88, 87, - 87, 87, 87, 86, 71, 71, 69, 69, - 69, 69, 69, 68, 51, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 121, 121, - 121, 120, 120, 120, 120, 120, 119, 87, - 87, 87, 86, 86, 71, 69, 69, 69, - 69, 69, 68, 68, 68, 68, 50, 50, - 190, 190, 190, 190, 190, 105, 104, 120, - 120, 120, 120, 120, 120, 119, 119, 87, - 87, 86, 86, 86, 69, 69, 69, 69, - 69, 68, 68, 68, 68, 68, 68, 50, - 3, 190, 190, 190, 104, 104, 104, 104, - 104, 120, 120, 119, 119, 119, 119, 118, - 87, 86, 86, 86, 69, 69, 69, 69, - 68, 68, 68, 68, 68, 68, 68, 68, - 3, 3, 190, 190, 104, 104, 104, 104, - 104, 103, 103, 119, 119, 118, 118, 118, - 118, 86, 86, 86, 69, 69, 69, 68, - 68, 68, 68, 68, 68, 68, 68, 67, - 3, 3, 189, 102, 102, 102, 102, 102, - 102, 101, 101, 101, 101, 100, 118, 118, - 118, 117, 86, 85, 69, 69, 68, 68, - 68, 68, 68, 68, 68, 67, 67, 67, - 3, 189, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 100, 99, 99, 85, 69, 68, 68, 68, - 68, 68, 68, 67, 67, 67, 67, 67, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 99, 99, 99, 68, 68, 68, 68, - 68, 67, 67, 67, 67, 67, 67, 205, - 102, 102, 102, 102, 102, 102, 102, 102, - 101, 101, 101, 101, 100, 100, 100, 100, - 99, 99, 99, 99, 99, 68, 68, 67, - 67, 67, 67, 206, 206, 206, 205, 205, - 102, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 100, - 99, 99, 99, 99, 99, 98, 67, 67, - 206, 206, 206, 206, 206, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 99, 99, 99, 99, 98, 98, 206, 206, - 206, 206, 206, 206, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 99, 99, 98, 98, 98, 98, 206, 206, - 206, 206, 206, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 98, 98, 98, 98, 98, 98, 206, 206, - 206, 206, 205, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 98, - 98, 98, 98, 98, 98, 97, 206, 206, - 206, 205, 205, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 101, 101, 101, - 101, 101, 100, 100, 100, 100, 98, 98, - 98, 98, 98, 98, 98, 97, 206, 206, - 205, 205, 205, 205, 205, 205, 205, 205, - 250, 102, 102, 102, 102, 101, 101, 101, - 101, 101, 100, 100, 100, 98, 98, 98, - 98, 98, 98, 98, 98, 97, 206, 205, - 205, 205, 205, 205, 205, 205, 205, 205, - 243, 243, 243, 243, 243, 243, 222, 222, - 222, 222, 221, 221, 221, 221, 221, 220, - 220, 5, 5, 5, 5, 5, 5, 5, - 54, 54, 54, 54, 53, 53, 53, 53, - 243, 243, 243, 243, 243, 243, 222, 222, - 222, 222, 221, 221, 221, 221, 220, 220, - 220, 220, 5, 5, 5, 5, 219, 54, - 54, 54, 54, 53, 53, 53, 53, 53, - 243, 243, 243, 243, 243, 243, 222, 222, - 222, 221, 221, 221, 221, 221, 220, 220, - 220, 220, 220, 219, 219, 219, 219, 54, - 54, 54, 53, 53, 53, 53, 53, 53, - 243, 243, 243, 243, 175, 175, 222, 222, - 222, 221, 221, 221, 221, 221, 220, 220, - 220, 220, 220, 219, 219, 219, 54, 54, - 54, 53, 53, 53, 53, 53, 53, 53, - 243, 243, 243, 175, 175, 201, 140, 222, - 222, 221, 221, 221, 221, 221, 220, 220, - 220, 220, 220, 219, 219, 55, 54, 54, - 53, 53, 53, 53, 53, 53, 53, 53, - 243, 243, 175, 175, 201, 201, 201, 140, - 140, 221, 221, 221, 221, 221, 220, 220, - 220, 220, 220, 219, 219, 54, 54, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 175, 175, 201, 201, 201, 201, 201, 140, - 139, 139, 139, 221, 221, 221, 220, 220, - 220, 220, 219, 219, 55, 54, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 191, 201, 201, 201, 201, 201, 201, 139, - 139, 139, 139, 38, 14, 14, 14, 14, - 14, 14, 14, 55, 55, 53, 53, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 191, 191, 201, 201, 201, 201, 201, 139, - 139, 139, 38, 38, 14, 14, 14, 14, - 14, 14, 14, 88, 53, 53, 53, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 201, 201, 201, 201, 139, - 139, 139, 38, 38, 14, 14, 14, 14, - 14, 14, 88, 88, 72, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 201, 201, 155, 155, - 155, 138, 38, 37, 14, 14, 14, 14, - 14, 88, 88, 88, 72, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 191, 201, 155, 155, 155, - 138, 138, 37, 37, 37, 14, 14, 14, - 88, 88, 88, 88, 72, 71, 52, 52, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 191, 191, 191, 155, 155, 154, - 154, 154, 37, 37, 36, 36, 89, 88, - 88, 88, 87, 87, 71, 71, 52, 52, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 155, 154, 154, - 154, 154, 121, 36, 36, 36, 88, 88, - 88, 87, 87, 87, 71, 71, 71, 51, - 51, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 154, 154, 154, - 121, 121, 121, 121, 36, 35, 88, 88, - 87, 87, 87, 87, 86, 71, 71, 69, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 190, 190, 190, 154, 121, - 121, 121, 120, 120, 120, 120, 88, 87, - 87, 87, 87, 86, 86, 71, 69, 69, - 69, 69, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 121, 121, - 121, 120, 120, 120, 120, 120, 119, 87, - 87, 87, 86, 86, 86, 69, 69, 69, - 69, 69, 68, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 121, 120, - 120, 120, 120, 120, 120, 119, 119, 87, - 87, 86, 86, 86, 86, 69, 69, 69, - 69, 68, 68, 68, 68, 50, 50, 50, - 3, 190, 190, 190, 190, 190, 120, 120, - 120, 120, 120, 119, 119, 119, 119, 118, - 87, 86, 86, 86, 86, 69, 69, 69, - 68, 68, 68, 68, 68, 68, 50, 50, - 3, 3, 190, 190, 190, 190, 104, 120, - 120, 120, 119, 119, 119, 119, 118, 118, - 118, 86, 86, 86, 85, 69, 69, 68, - 68, 68, 68, 68, 68, 68, 67, 67, - 3, 3, 189, 189, 189, 102, 104, 104, - 103, 119, 119, 119, 118, 118, 118, 118, - 118, 86, 86, 85, 85, 69, 68, 68, - 68, 68, 68, 68, 67, 67, 67, 67, - 3, 189, 189, 189, 102, 102, 102, 102, - 101, 101, 101, 101, 118, 118, 118, 118, - 117, 117, 85, 85, 85, 68, 68, 68, - 68, 68, 67, 67, 67, 67, 67, 67, - 3, 189, 189, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 100, - 99, 99, 117, 85, 85, 68, 68, 68, - 67, 67, 67, 67, 67, 67, 67, 67, - 189, 189, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 99, 99, 99, 99, 84, 68, 67, 67, - 67, 67, 67, 67, 67, 67, 66, 66, - 189, 102, 102, 102, 102, 102, 102, 101, - 101, 101, 101, 100, 100, 100, 100, 99, - 99, 99, 99, 99, 99, 67, 67, 67, - 67, 67, 67, 67, 66, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 100, 99, - 99, 99, 99, 99, 98, 97, 67, 67, - 67, 67, 205, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 98, 98, 97, 97, 206, - 205, 205, 205, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 101, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 99, - 99, 98, 98, 98, 98, 97, 97, 205, - 205, 205, 205, 205, 205, 205, 205, 205, - 102, 102, 102, 102, 102, 101, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 98, - 98, 98, 98, 98, 98, 97, 97, 205, - 205, 205, 205, 205, 205, 205, 205, 204, - 102, 102, 102, 102, 102, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 98, 98, - 98, 98, 98, 98, 97, 97, 205, 205, - 205, 205, 205, 205, 205, 205, 204, 204, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 100, 100, 100, 100, 98, 98, 98, - 98, 98, 98, 98, 97, 97, 205, 205, - 205, 205, 205, 205, 205, 204, 204, 204, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 100, 100, 100, 98, 98, 98, 98, - 98, 98, 98, 98, 97, 97, 205, 205, - 205, 205, 205, 205, 204, 204, 204, 204, - 242, 242, 242, 242, 242, 242, 222, 222, - 222, 221, 221, 221, 221, 221, 220, 220, - 5, 5, 5, 5, 5, 5, 5, 218, - 218, 218, 218, 53, 53, 53, 53, 53, - 242, 242, 242, 242, 242, 175, 222, 222, - 222, 221, 221, 221, 221, 220, 220, 220, - 220, 5, 5, 5, 5, 219, 219, 218, - 218, 218, 53, 53, 53, 53, 53, 53, - 242, 242, 242, 242, 175, 175, 175, 222, - 221, 221, 221, 221, 221, 220, 220, 220, - 220, 220, 219, 219, 219, 219, 219, 218, - 218, 53, 53, 53, 53, 53, 53, 53, - 242, 242, 242, 175, 175, 175, 175, 222, - 221, 221, 221, 221, 221, 220, 220, 220, - 220, 220, 219, 219, 219, 219, 218, 218, - 53, 53, 53, 53, 53, 53, 53, 53, - 242, 175, 175, 175, 175, 175, 201, 201, - 221, 221, 221, 221, 221, 220, 220, 220, - 220, 220, 219, 219, 219, 219, 218, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 175, 175, 175, 175, 175, 201, 201, 201, - 201, 221, 221, 221, 221, 220, 220, 220, - 220, 220, 219, 219, 219, 219, 53, 53, - 53, 53, 53, 53, 53, 53, 53, 53, - 175, 175, 175, 201, 201, 201, 201, 201, - 201, 139, 139, 221, 221, 220, 220, 220, - 220, 219, 219, 219, 219, 219, 53, 53, - 53, 53, 53, 53, 53, 52, 52, 52, - 175, 201, 201, 201, 201, 201, 201, 201, - 139, 139, 139, 38, 14, 14, 14, 14, - 14, 14, 219, 219, 219, 53, 53, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 201, 201, 201, 201, 201, 201, - 139, 138, 138, 14, 14, 14, 14, 14, - 14, 14, 14, 13, 53, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 201, 201, 201, 201, 201, - 138, 138, 138, 14, 14, 14, 14, 14, - 14, 14, 88, 13, 13, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 191, 201, 201, 201, 201, 138, - 138, 138, 138, 37, 14, 14, 14, 14, - 14, 88, 88, 13, 13, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 191, 191, 201, 201, 155, 138, - 138, 138, 138, 37, 14, 14, 14, 14, - 88, 88, 13, 87, 87, 52, 52, 52, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 155, 154, 154, - 154, 154, 137, 36, 36, 36, 35, 88, - 88, 88, 87, 87, 87, 86, 52, 51, - 51, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 154, 154, 154, - 154, 154, 153, 36, 36, 35, 35, 88, - 88, 87, 87, 87, 86, 86, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 190, 190, 154, 154, 154, - 154, 153, 153, 120, 35, 35, 35, 34, - 87, 87, 87, 86, 86, 86, 69, 51, - 51, 51, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 154, 153, - 153, 120, 120, 120, 120, 35, 34, 87, - 87, 87, 86, 86, 86, 86, 69, 69, - 69, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 153, 153, - 120, 120, 120, 120, 120, 119, 34, 87, - 87, 86, 86, 86, 86, 85, 69, 69, - 69, 68, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 190, 190, 190, 120, 120, - 120, 120, 120, 119, 119, 119, 119, 87, - 87, 86, 86, 86, 85, 85, 69, 69, - 68, 68, 68, 68, 50, 50, 50, 50, - 3, 3, 190, 190, 190, 190, 120, 120, - 120, 120, 119, 119, 119, 119, 118, 118, - 86, 86, 86, 85, 85, 85, 69, 68, - 68, 68, 68, 68, 68, 67, 49, 49, - 3, 3, 189, 189, 189, 189, 120, 120, - 120, 119, 119, 119, 119, 118, 118, 118, - 118, 86, 85, 85, 85, 85, 68, 68, - 68, 68, 68, 67, 67, 67, 67, 49, - 3, 189, 189, 189, 189, 189, 102, 120, - 119, 119, 119, 119, 118, 118, 118, 118, - 117, 117, 85, 85, 85, 85, 68, 68, - 68, 67, 67, 67, 67, 67, 67, 67, - 3, 189, 189, 189, 189, 102, 102, 101, - 101, 101, 118, 118, 118, 118, 118, 118, - 117, 117, 85, 85, 85, 84, 68, 67, - 67, 67, 67, 67, 67, 67, 67, 66, - 189, 189, 189, 189, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 100, 117, - 117, 117, 116, 84, 84, 84, 67, 67, - 67, 67, 67, 67, 67, 66, 66, 66, - 189, 189, 189, 102, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 116, 84, 67, 67, 67, - 67, 67, 67, 67, 66, 66, 66, 66, - 188, 188, 102, 102, 102, 102, 101, 101, - 101, 101, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 99, 99, 67, 67, 67, - 67, 67, 66, 66, 66, 66, 66, 204, - 188, 188, 102, 102, 102, 101, 101, 101, - 101, 100, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 98, 97, 97, 67, 67, - 66, 66, 66, 204, 204, 204, 204, 204, - 188, 102, 102, 102, 102, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 99, 99, - 99, 99, 98, 98, 97, 97, 97, 66, - 204, 204, 204, 204, 204, 204, 204, 204, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 99, 99, - 98, 98, 98, 98, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 102, 102, 102, 102, 101, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 98, 98, - 98, 98, 98, 98, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 102, 102, 102, 102, 101, 101, 101, 101, - 100, 100, 100, 100, 99, 98, 98, 98, - 98, 98, 98, 97, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 100, 100, 100, 98, 98, 98, 98, - 98, 98, 98, 97, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 102, 102, 102, 101, 101, 101, 101, 101, - 100, 100, 100, 98, 98, 98, 98, 98, - 98, 98, 98, 97, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 242, 242, 241, 241, 241, 241, 175, 222, - 221, 221, 221, 221, 221, 220, 220, 5, - 5, 5, 5, 5, 5, 5, 218, 218, - 218, 218, 217, 217, 217, 53, 53, 53, - 242, 241, 241, 241, 175, 175, 175, 222, - 221, 221, 221, 221, 220, 220, 220, 220, - 5, 5, 5, 5, 219, 219, 218, 218, - 218, 218, 217, 217, 53, 53, 53, 53, - 241, 241, 241, 175, 175, 175, 175, 175, - 221, 221, 221, 221, 220, 220, 220, 220, - 220, 219, 219, 219, 219, 219, 218, 218, - 218, 218, 53, 53, 53, 53, 53, 53, - 241, 241, 175, 175, 175, 175, 175, 175, - 221, 221, 221, 221, 220, 220, 220, 220, - 220, 219, 219, 219, 219, 218, 218, 218, - 218, 53, 53, 53, 53, 53, 53, 53, - 175, 175, 175, 175, 175, 175, 175, 201, - 221, 221, 221, 221, 220, 220, 220, 220, - 220, 219, 219, 219, 219, 218, 218, 218, - 218, 53, 53, 53, 53, 53, 53, 53, - 175, 175, 175, 175, 175, 175, 201, 201, - 201, 221, 221, 221, 220, 220, 220, 220, - 220, 219, 219, 219, 219, 218, 218, 218, - 53, 53, 53, 53, 53, 52, 52, 52, - 175, 175, 175, 175, 201, 201, 201, 201, - 201, 201, 139, 221, 220, 220, 220, 220, - 219, 219, 219, 219, 219, 218, 218, 53, - 53, 52, 52, 52, 52, 52, 52, 52, - 175, 175, 201, 201, 201, 201, 201, 201, - 201, 138, 138, 14, 14, 14, 14, 14, - 14, 219, 219, 219, 219, 218, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 201, 201, 201, 201, 201, 201, - 201, 138, 138, 14, 14, 14, 14, 14, - 14, 14, 13, 13, 13, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 191, 201, 201, 201, 201, 201, 201, - 138, 138, 138, 14, 14, 14, 14, 14, - 14, 14, 13, 13, 13, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 191, 201, 201, 201, 201, 138, - 138, 138, 138, 137, 14, 14, 14, 14, - 14, 13, 13, 13, 13, 52, 52, 52, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 201, 200, 200, 138, - 138, 137, 137, 137, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 52, 51, - 51, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 191, 200, 154, 154, - 154, 137, 137, 137, 36, 35, 35, 13, - 13, 13, 13, 13, 86, 86, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 190, 190, 200, 154, 154, - 153, 153, 153, 153, 35, 35, 35, 34, - 13, 13, 13, 86, 86, 86, 51, 51, - 51, 51, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 154, 153, - 153, 153, 153, 153, 35, 35, 34, 34, - 13, 87, 86, 86, 86, 86, 85, 51, - 51, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 153, 153, - 153, 153, 153, 120, 120, 34, 34, 33, - 87, 86, 86, 86, 86, 85, 85, 69, - 51, 51, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 190, 190, 190, 153, 153, - 153, 120, 120, 119, 119, 119, 33, 33, - 33, 86, 86, 86, 85, 85, 85, 69, - 68, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 190, 190, 190, 190, 153, 153, - 120, 120, 119, 119, 119, 119, 119, 33, - 86, 86, 86, 85, 85, 85, 85, 68, - 68, 68, 68, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 189, 189, 189, 120, - 120, 119, 119, 119, 119, 118, 118, 118, - 86, 86, 85, 85, 85, 85, 85, 68, - 68, 67, 67, 67, 67, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 120, - 119, 119, 119, 119, 118, 118, 118, 118, - 117, 85, 85, 85, 85, 85, 84, 67, - 67, 67, 67, 67, 67, 67, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 119, - 119, 119, 119, 118, 118, 118, 118, 117, - 117, 117, 85, 85, 85, 84, 84, 67, - 67, 67, 67, 67, 67, 67, 66, 66, - 189, 189, 189, 189, 189, 189, 189, 101, - 101, 118, 118, 118, 118, 118, 118, 117, - 117, 117, 116, 84, 84, 84, 67, 67, - 67, 67, 67, 67, 67, 66, 66, 66, - 189, 189, 189, 189, 189, 189, 101, 101, - 101, 100, 100, 100, 100, 118, 117, 117, - 117, 116, 116, 116, 84, 84, 67, 67, - 67, 67, 67, 66, 66, 66, 66, 66, - 188, 188, 188, 188, 188, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 99, 99, - 99, 116, 116, 116, 84, 84, 67, 67, - 67, 66, 66, 66, 66, 66, 66, 66, - 188, 188, 188, 188, 102, 101, 101, 101, - 101, 100, 100, 100, 100, 99, 99, 99, - 99, 99, 99, 99, 115, 83, 67, 66, - 66, 66, 66, 66, 66, 66, 66, 66, - 188, 188, 188, 188, 101, 101, 101, 101, - 100, 100, 100, 100, 100, 99, 99, 99, - 99, 99, 98, 97, 97, 97, 66, 66, - 66, 66, 66, 66, 66, 204, 204, 204, - 188, 188, 188, 102, 101, 101, 101, 101, - 100, 100, 100, 100, 99, 99, 99, 99, - 99, 98, 98, 97, 97, 97, 97, 66, - 66, 204, 204, 204, 204, 204, 204, 204, - 188, 188, 102, 101, 101, 101, 101, 101, - 100, 100, 100, 100, 99, 99, 99, 98, - 98, 98, 98, 97, 97, 97, 97, 96, - 204, 204, 204, 204, 204, 204, 204, 204, - 187, 187, 102, 101, 101, 101, 101, 101, - 100, 100, 100, 100, 99, 98, 98, 98, - 98, 98, 98, 97, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 187, 102, 102, 101, 101, 101, 101, 100, - 100, 100, 100, 99, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 97, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 187, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 100, 98, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 96, 204, - 204, 204, 204, 204, 204, 204, 204, 204, - 187, 102, 101, 101, 101, 101, 101, 100, - 100, 100, 98, 98, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 96, 204, - 204, 204, 204, 204, 204, 204, 204, 203, - 241, 241, 241, 241, 241, 175, 175, 175, - 221, 221, 221, 221, 220, 220, 5, 5, - 5, 5, 5, 5, 5, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 241, 241, 241, 241, 175, 175, 175, 175, - 221, 221, 221, 220, 220, 220, 220, 5, - 5, 5, 5, 219, 219, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 53, 53, - 241, 241, 175, 175, 175, 175, 175, 175, - 221, 221, 221, 220, 220, 220, 220, 220, - 219, 219, 219, 219, 219, 218, 218, 218, - 218, 217, 217, 217, 217, 53, 53, 53, - 241, 175, 175, 175, 175, 175, 175, 175, - 221, 221, 221, 220, 220, 220, 220, 220, - 219, 219, 219, 219, 218, 218, 218, 218, - 218, 217, 217, 217, 53, 53, 53, 53, - 175, 175, 175, 175, 175, 175, 175, 175, - 201, 221, 221, 220, 220, 220, 220, 220, - 219, 219, 219, 219, 218, 218, 218, 218, - 218, 217, 53, 53, 53, 52, 52, 52, - 175, 175, 175, 175, 175, 175, 175, 201, - 201, 201, 221, 220, 220, 220, 220, 220, - 219, 219, 219, 219, 218, 218, 218, 218, - 218, 52, 52, 52, 52, 52, 52, 52, - 175, 175, 175, 175, 175, 201, 201, 201, - 201, 201, 138, 220, 220, 220, 220, 219, - 219, 219, 219, 219, 218, 218, 218, 218, - 52, 52, 52, 52, 52, 52, 52, 52, - 175, 175, 175, 201, 201, 201, 201, 201, - 201, 201, 138, 138, 14, 14, 14, 14, - 219, 219, 219, 219, 218, 218, 218, 52, - 52, 52, 52, 52, 52, 52, 52, 52, - 191, 201, 201, 201, 201, 201, 201, 201, - 200, 138, 138, 138, 14, 14, 14, 14, - 14, 13, 13, 13, 218, 218, 52, 52, - 52, 52, 52, 52, 52, 52, 51, 51, - 191, 191, 201, 201, 201, 201, 200, 200, - 200, 138, 137, 137, 14, 14, 14, 14, - 14, 13, 13, 13, 13, 13, 52, 52, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 191, 201, 201, 200, 200, 200, - 200, 137, 137, 137, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 52, 51, - 51, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 191, 200, 200, 200, 200, - 137, 137, 137, 137, 14, 14, 14, 13, - 13, 13, 13, 13, 13, 13, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 190, 200, 200, 200, 200, - 137, 137, 137, 137, 136, 35, 13, 13, - 13, 13, 13, 13, 13, 86, 51, 51, - 51, 51, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 190, 190, 200, 200, 153, - 153, 153, 153, 136, 136, 35, 34, 13, - 13, 13, 13, 13, 86, 86, 85, 51, - 51, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 190, 190, 153, 153, - 153, 153, 153, 136, 136, 34, 34, 13, - 13, 13, 86, 86, 86, 85, 85, 51, - 51, 51, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 190, 190, 190, 153, 153, - 153, 153, 152, 152, 152, 34, 33, 33, - 33, 86, 86, 86, 85, 85, 85, 85, - 50, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 190, 190, 190, 190, 153, 153, - 152, 152, 152, 152, 119, 119, 33, 33, - 32, 86, 86, 85, 85, 85, 85, 85, - 50, 50, 50, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 189, 189, 189, 152, - 152, 152, 119, 119, 119, 119, 118, 32, - 32, 86, 85, 85, 85, 85, 85, 84, - 67, 67, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 152, - 152, 119, 119, 119, 118, 118, 118, 118, - 32, 31, 85, 85, 85, 85, 84, 84, - 67, 67, 67, 67, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 152, - 119, 119, 119, 118, 118, 118, 118, 117, - 117, 117, 85, 85, 85, 84, 84, 67, - 67, 67, 67, 67, 67, 49, 49, 49, - 189, 189, 189, 189, 189, 189, 189, 119, - 119, 119, 118, 118, 118, 118, 117, 117, - 117, 117, 85, 84, 84, 84, 84, 67, - 67, 67, 67, 67, 66, 66, 66, 48, - 189, 189, 189, 189, 189, 189, 189, 119, - 118, 118, 118, 118, 118, 118, 117, 117, - 117, 116, 116, 84, 84, 84, 84, 67, - 67, 67, 66, 66, 66, 66, 66, 66, - 188, 188, 188, 188, 188, 188, 188, 101, - 100, 100, 100, 118, 118, 117, 117, 117, - 116, 116, 116, 116, 84, 84, 83, 67, - 66, 66, 66, 66, 66, 66, 66, 66, - 188, 188, 188, 188, 188, 188, 101, 101, - 100, 100, 100, 100, 99, 99, 99, 99, - 116, 116, 116, 116, 115, 83, 83, 66, - 66, 66, 66, 66, 66, 66, 66, 65, - 188, 188, 188, 188, 188, 101, 101, 101, - 100, 100, 100, 100, 99, 99, 99, 99, - 99, 99, 116, 115, 115, 83, 83, 66, - 66, 66, 66, 66, 66, 65, 65, 65, - 188, 188, 188, 188, 188, 101, 101, 100, - 100, 100, 100, 100, 99, 99, 99, 99, - 99, 98, 97, 97, 97, 97, 83, 66, - 66, 66, 66, 65, 65, 65, 65, 203, - 188, 188, 188, 188, 101, 101, 101, 100, - 100, 100, 100, 99, 99, 99, 99, 99, - 98, 98, 97, 97, 97, 97, 96, 66, - 65, 65, 65, 204, 204, 204, 203, 203, - 187, 187, 187, 187, 101, 101, 101, 100, - 100, 100, 100, 99, 99, 99, 98, 98, - 98, 98, 97, 97, 97, 97, 96, 96, - 204, 204, 204, 204, 204, 203, 203, 203, - 187, 187, 187, 101, 101, 101, 101, 100, - 100, 100, 100, 99, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 96, 96, - 204, 204, 204, 204, 203, 203, 203, 203, - 187, 187, 187, 101, 101, 101, 100, 100, - 100, 100, 99, 98, 98, 98, 98, 98, - 98, 97, 97, 97, 97, 97, 96, 96, - 204, 204, 204, 203, 203, 203, 203, 203, - 187, 187, 187, 101, 101, 101, 100, 100, - 100, 100, 98, 98, 98, 98, 98, 98, - 98, 97, 97, 97, 97, 96, 96, 96, - 204, 204, 203, 203, 203, 203, 203, 203, - 187, 187, 101, 101, 101, 101, 100, 100, - 100, 98, 98, 98, 98, 98, 98, 98, - 98, 97, 97, 97, 97, 96, 96, 96, - 204, 203, 203, 203, 203, 203, 203, 203, - 1, 240, 240, 240, 240, 175, 175, 175, - 221, 221, 221, 220, 220, 5, 5, 5, - 5, 5, 5, 5, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 240, 240, 240, 175, 175, 175, 175, 175, - 221, 221, 220, 220, 220, 220, 5, 5, - 5, 5, 219, 219, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 240, 240, 175, 175, 175, 175, 175, 175, - 175, 221, 220, 220, 220, 220, 220, 219, - 219, 219, 219, 219, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 240, 175, 175, 175, 175, 175, 175, 175, - 175, 221, 220, 220, 220, 220, 220, 219, - 219, 219, 219, 218, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 52, - 175, 175, 175, 175, 175, 175, 175, 175, - 175, 221, 220, 220, 220, 220, 220, 219, - 219, 219, 219, 218, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 52, 52, 52, - 175, 175, 175, 175, 175, 175, 175, 174, - 201, 201, 220, 220, 220, 220, 220, 219, - 219, 219, 219, 218, 218, 218, 218, 218, - 217, 217, 217, 52, 52, 52, 52, 52, - 175, 175, 175, 174, 174, 174, 201, 201, - 201, 200, 200, 220, 220, 220, 219, 219, - 219, 219, 219, 218, 218, 218, 218, 218, - 217, 217, 52, 52, 52, 52, 52, 52, - 174, 174, 174, 174, 174, 201, 201, 200, - 200, 200, 200, 138, 14, 14, 14, 219, - 219, 219, 219, 218, 218, 218, 218, 218, - 52, 52, 52, 52, 52, 52, 51, 51, - 174, 174, 174, 201, 201, 200, 200, 200, - 200, 200, 200, 137, 14, 14, 14, 14, - 13, 13, 13, 218, 218, 218, 218, 52, - 52, 52, 52, 51, 51, 51, 51, 51, - 191, 191, 201, 201, 200, 200, 200, 200, - 200, 200, 137, 137, 14, 14, 14, 14, - 13, 13, 13, 13, 13, 13, 52, 51, - 51, 51, 51, 51, 51, 51, 51, 51, - 191, 191, 191, 200, 200, 200, 200, 200, - 200, 200, 137, 137, 136, 14, 14, 13, - 13, 13, 13, 13, 13, 13, 51, 51, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 190, 190, 200, 200, 200, 200, 200, - 200, 137, 137, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 13, 13, 51, 51, - 51, 51, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 190, 200, 200, 200, 200, - 137, 137, 136, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 51, - 51, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 190, 200, 200, 200, - 153, 136, 136, 136, 136, 34, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 51, - 51, 51, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 190, 190, 190, 200, 153, - 153, 152, 136, 136, 136, 34, 33, 13, - 13, 13, 13, 12, 12, 12, 85, 51, - 50, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 190, 190, 190, 190, 153, 152, - 152, 152, 152, 152, 152, 33, 33, 33, - 32, 32, 32, 12, 85, 85, 85, 85, - 50, 50, 50, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 189, 189, 152, 152, - 152, 152, 152, 152, 151, 33, 33, 32, - 32, 32, 31, 85, 85, 85, 85, 84, - 50, 50, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 152, - 152, 152, 152, 151, 119, 118, 118, 32, - 32, 31, 85, 85, 85, 85, 84, 84, - 67, 49, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 152, - 152, 152, 151, 119, 118, 118, 118, 117, - 31, 31, 85, 85, 84, 84, 84, 84, - 67, 67, 67, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 189, 189, 189, 152, - 152, 151, 118, 118, 118, 118, 117, 117, - 117, 117, 85, 84, 84, 84, 84, 84, - 67, 67, 67, 66, 49, 49, 48, 48, - 189, 189, 189, 189, 189, 189, 189, 152, - 151, 118, 118, 118, 118, 118, 117, 117, - 117, 116, 116, 84, 84, 84, 84, 83, - 67, 66, 66, 66, 66, 66, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 118, 118, 118, 118, 118, 117, 117, 117, - 116, 116, 116, 84, 84, 84, 83, 83, - 66, 66, 66, 66, 66, 66, 66, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 118, 118, 118, 118, 117, 117, 117, 116, - 116, 116, 116, 115, 83, 83, 83, 83, - 66, 66, 66, 66, 66, 66, 65, 65, - 188, 188, 188, 188, 188, 188, 188, 100, - 100, 100, 100, 99, 99, 99, 117, 116, - 116, 116, 116, 115, 115, 83, 83, 66, - 66, 66, 66, 66, 65, 65, 65, 65, - 188, 188, 188, 188, 188, 188, 188, 100, - 100, 100, 100, 99, 99, 99, 99, 99, - 99, 116, 115, 115, 115, 83, 83, 66, - 66, 66, 65, 65, 65, 65, 65, 65, - 188, 188, 188, 188, 188, 188, 100, 100, - 100, 100, 100, 99, 99, 99, 99, 99, - 98, 97, 97, 97, 97, 97, 83, 66, - 65, 65, 65, 65, 65, 65, 65, 65, - 187, 187, 187, 187, 187, 187, 100, 100, - 100, 100, 99, 99, 99, 99, 99, 98, - 98, 97, 97, 97, 97, 96, 96, 96, - 65, 65, 65, 65, 65, 203, 203, 203, - 187, 187, 187, 187, 187, 101, 100, 100, - 100, 100, 99, 99, 99, 98, 98, 98, - 98, 97, 97, 97, 97, 96, 96, 96, - 65, 65, 203, 203, 203, 203, 203, 203, - 187, 187, 187, 187, 187, 101, 100, 100, - 100, 100, 99, 98, 98, 98, 98, 98, - 98, 97, 97, 97, 97, 96, 96, 96, - 96, 203, 203, 203, 203, 203, 203, 203, - 187, 187, 187, 187, 187, 100, 100, 100, - 100, 99, 98, 98, 98, 98, 98, 98, - 97, 97, 97, 97, 97, 96, 96, 96, - 203, 203, 203, 203, 203, 203, 203, 203, - 187, 187, 187, 187, 101, 100, 100, 100, - 100, 98, 98, 98, 98, 98, 98, 98, - 97, 97, 97, 97, 96, 96, 96, 96, - 203, 203, 203, 203, 203, 203, 203, 203, - 186, 186, 186, 186, 101, 100, 100, 100, - 98, 98, 98, 98, 98, 98, 98, 98, - 97, 97, 97, 97, 96, 96, 96, 96, - 203, 203, 203, 203, 203, 203, 203, 203, - 1, 240, 240, 240, 240, 175, 175, 175, - 175, 221, 220, 220, 5, 5, 5, 5, - 5, 5, 5, 218, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 240, 240, 240, 240, 175, 175, 175, 175, - 175, 220, 220, 220, 220, 5, 5, 5, - 5, 219, 219, 218, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 240, 240, 175, 175, 175, 175, 175, 175, - 175, 220, 220, 220, 220, 220, 219, 219, - 219, 219, 219, 218, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 240, 175, 175, 175, 175, 175, 175, 175, - 175, 220, 220, 220, 220, 220, 219, 219, - 219, 219, 218, 218, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 175, 175, 175, 175, 175, 174, 174, 174, - 174, 220, 220, 220, 220, 220, 219, 219, - 219, 219, 218, 218, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 175, 174, 174, 174, 174, 174, 174, 174, - 174, 200, 220, 220, 220, 220, 219, 219, - 219, 219, 218, 218, 218, 218, 218, 217, - 217, 217, 217, 216, 216, 216, 52, 52, - 174, 174, 174, 174, 174, 174, 174, 174, - 200, 200, 200, 220, 220, 219, 219, 219, - 219, 219, 218, 218, 218, 218, 218, 217, - 217, 217, 217, 216, 52, 52, 51, 51, - 174, 174, 174, 174, 174, 174, 200, 200, - 200, 200, 200, 200, 14, 219, 219, 219, - 219, 219, 218, 218, 218, 218, 218, 217, - 217, 217, 52, 51, 51, 51, 51, 51, - 174, 174, 174, 174, 174, 200, 200, 200, - 200, 200, 200, 137, 137, 14, 14, 13, - 13, 13, 218, 218, 218, 218, 218, 217, - 51, 51, 51, 51, 51, 51, 51, 51, - 173, 173, 173, 200, 200, 200, 200, 200, - 200, 200, 200, 137, 136, 14, 14, 13, - 13, 13, 13, 13, 13, 218, 217, 51, - 51, 51, 51, 51, 51, 51, 51, 50, - 191, 173, 200, 200, 200, 200, 200, 200, - 200, 200, 137, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 13, 13, 51, 51, - 51, 51, 51, 51, 51, 50, 50, 50, - 190, 190, 190, 200, 200, 200, 200, 200, - 200, 199, 136, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 51, - 51, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 190, 190, 200, 200, 200, 200, - 199, 136, 136, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 51, - 51, 51, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 190, 200, 200, 199, 199, - 199, 136, 136, 136, 136, 136, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 190, 190, 190, 199, 199, 199, - 152, 152, 152, 136, 135, 135, 33, 13, - 13, 13, 12, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 189, 189, 199, 152, - 152, 152, 152, 152, 151, 151, 33, 32, - 32, 32, 12, 12, 12, 12, 12, 84, - 50, 50, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 152, 152, - 152, 152, 152, 151, 151, 151, 32, 32, - 32, 31, 12, 12, 12, 12, 84, 84, - 49, 49, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 189, 152, - 152, 152, 151, 151, 151, 151, 32, 32, - 31, 31, 31, 12, 84, 84, 84, 84, - 84, 49, 49, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 189, 189, 189, 152, - 152, 151, 151, 151, 151, 118, 117, 117, - 31, 31, 30, 30, 84, 84, 84, 84, - 83, 49, 49, 49, 49, 49, 48, 48, - 189, 189, 189, 189, 189, 189, 189, 151, - 151, 151, 151, 151, 118, 117, 117, 117, - 117, 30, 30, 84, 84, 84, 84, 83, - 83, 66, 66, 66, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 151, 151, 118, 118, 118, 117, 117, 117, - 116, 116, 116, 84, 84, 84, 83, 83, - 83, 66, 66, 66, 66, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 151, 150, 118, 118, 117, 117, 117, 116, - 116, 116, 116, 115, 83, 83, 83, 83, - 66, 66, 66, 66, 66, 65, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 118, 118, 117, 117, 117, 117, 116, - 116, 116, 115, 115, 83, 83, 83, 83, - 66, 66, 66, 65, 65, 65, 65, 65, - 188, 188, 188, 188, 188, 188, 188, 188, - 100, 100, 99, 99, 117, 117, 116, 116, - 116, 116, 115, 115, 115, 83, 83, 82, - 66, 65, 65, 65, 65, 65, 65, 65, - 188, 188, 188, 188, 188, 188, 187, 100, - 100, 100, 99, 99, 99, 99, 99, 116, - 116, 115, 115, 115, 115, 114, 83, 82, - 65, 65, 65, 65, 65, 65, 65, 9, - 187, 187, 187, 187, 187, 187, 187, 100, - 100, 100, 99, 99, 99, 99, 99, 98, - 97, 97, 97, 97, 114, 114, 114, 82, - 65, 65, 65, 65, 65, 65, 65, 9, - 187, 187, 187, 187, 187, 187, 187, 100, - 100, 99, 99, 99, 99, 99, 98, 98, - 97, 97, 97, 97, 96, 96, 96, 96, - 65, 65, 65, 65, 65, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 100, 100, - 100, 99, 99, 99, 98, 98, 98, 98, - 97, 97, 97, 97, 96, 96, 96, 96, - 96, 65, 65, 203, 203, 203, 202, 202, - 187, 187, 187, 187, 187, 187, 100, 100, - 100, 99, 98, 98, 98, 98, 98, 98, - 97, 97, 97, 97, 96, 96, 96, 96, - 96, 203, 203, 203, 203, 202, 202, 202, - 187, 187, 187, 187, 186, 186, 100, 100, - 99, 98, 98, 98, 98, 98, 98, 97, - 97, 97, 97, 97, 96, 96, 96, 96, - 96, 203, 203, 203, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 100, 100, - 98, 98, 98, 98, 98, 98, 98, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 96, 203, 203, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 100, 98, - 98, 98, 98, 98, 98, 98, 98, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 96, 203, 202, 202, 202, 202, 202, 202, - 239, 239, 239, 239, 239, 239, 175, 175, - 175, 220, 220, 5, 5, 5, 5, 5, - 5, 5, 218, 218, 218, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 239, 239, 239, 239, 175, 175, 175, 175, - 175, 220, 220, 220, 5, 5, 5, 5, - 219, 219, 218, 218, 218, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 239, 239, 239, 175, 175, 175, 175, 174, - 174, 220, 220, 220, 220, 219, 219, 219, - 219, 219, 218, 218, 218, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 239, 239, 175, 174, 174, 174, 174, 174, - 174, 174, 220, 220, 220, 219, 219, 219, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 220, 220, 220, 219, 219, 219, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 220, 220, 220, 219, 219, 219, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 200, 200, 200, 220, 219, 219, 219, 219, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 51, - 174, 174, 174, 174, 174, 174, 174, 200, - 200, 200, 200, 200, 199, 219, 219, 219, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 216, 216, 51, 51, 51, 51, - 173, 173, 173, 173, 173, 200, 200, 200, - 200, 200, 200, 199, 136, 136, 13, 13, - 219, 218, 218, 218, 218, 218, 217, 217, - 217, 217, 51, 51, 51, 51, 51, 50, - 173, 173, 173, 173, 173, 200, 200, 200, - 200, 199, 199, 199, 136, 136, 13, 13, - 13, 13, 13, 13, 218, 217, 217, 217, - 51, 51, 51, 51, 51, 50, 50, 50, - 173, 173, 173, 173, 200, 200, 200, 200, - 199, 199, 199, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 13, 12, 12, 51, - 51, 51, 51, 50, 50, 50, 50, 50, - 190, 190, 173, 200, 200, 200, 200, 199, - 199, 199, 199, 136, 136, 136, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 51, - 51, 51, 50, 50, 50, 50, 50, 50, - 3, 190, 190, 200, 200, 199, 199, 199, - 199, 199, 136, 136, 136, 136, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 190, 190, 199, 199, 199, 199, - 199, 199, 135, 135, 135, 135, 13, 13, - 13, 13, 12, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 189, 199, 199, 199, - 199, 135, 135, 135, 135, 135, 135, 13, - 32, 12, 12, 12, 12, 12, 12, 12, - 50, 50, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 199, 199, - 152, 135, 135, 135, 135, 151, 134, 32, - 32, 12, 12, 12, 12, 12, 12, 12, - 49, 49, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 189, 199, 152, - 152, 151, 151, 151, 151, 151, 134, 32, - 31, 31, 12, 12, 12, 12, 84, 84, - 11, 49, 49, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 189, 189, 189, 152, - 151, 151, 151, 151, 151, 151, 150, 31, - 31, 31, 30, 12, 12, 84, 84, 84, - 11, 49, 49, 49, 49, 49, 48, 48, - 189, 189, 189, 189, 189, 189, 189, 151, - 151, 151, 151, 151, 150, 150, 117, 117, - 31, 30, 30, 29, 84, 84, 84, 83, - 83, 49, 49, 49, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 151, - 151, 151, 150, 150, 150, 150, 117, 117, - 116, 30, 29, 29, 84, 84, 83, 83, - 83, 66, 66, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 150, 150, 117, 117, 116, - 116, 116, 29, 29, 83, 83, 83, 83, - 82, 66, 66, 66, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 150, 117, 117, 117, 116, - 116, 116, 115, 115, 83, 83, 83, 83, - 82, 66, 65, 65, 65, 65, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 117, 117, 117, 116, 116, - 116, 116, 115, 115, 115, 83, 83, 82, - 82, 65, 65, 65, 65, 65, 65, 65, - 188, 188, 188, 188, 188, 188, 187, 187, - 150, 150, 150, 117, 117, 116, 116, 116, - 116, 115, 115, 115, 115, 83, 82, 82, - 82, 65, 65, 65, 65, 65, 65, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 100, 99, 99, 99, 99, 99, 116, 116, - 116, 115, 115, 115, 114, 114, 82, 82, - 65, 65, 65, 65, 65, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 100, 99, 99, 99, 99, 99, 98, 97, - 97, 97, 97, 114, 114, 114, 114, 81, - 65, 65, 65, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 99, 99, 99, 99, 99, 98, 98, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 65, 64, 64, 64, 64, 9, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 100, - 99, 99, 99, 98, 98, 98, 98, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 96, 64, 64, 64, 202, 202, 202, 202, - 187, 187, 187, 187, 186, 186, 186, 100, - 99, 98, 98, 98, 98, 98, 98, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 99, - 98, 98, 98, 98, 98, 98, 97, 97, - 97, 97, 97, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 98, - 98, 98, 98, 98, 98, 98, 97, 97, - 97, 97, 96, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 98, - 98, 98, 98, 98, 98, 98, 97, 97, - 97, 97, 96, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 238, 238, 238, 238, 238, 238, 238, 175, - 175, 220, 5, 5, 5, 5, 5, 5, - 5, 218, 218, 218, 218, 217, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 238, 238, 238, 238, 238, 238, 174, 174, - 174, 220, 220, 5, 5, 5, 5, 219, - 219, 218, 218, 218, 218, 217, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 238, 238, 238, 238, 174, 174, 174, 174, - 174, 174, 220, 220, 219, 219, 219, 219, - 219, 218, 218, 218, 218, 217, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 238, 238, 174, 174, 174, 174, 174, 174, - 174, 174, 220, 220, 219, 219, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 217, 216, 216, 216, 216, 215, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 220, 220, 219, 219, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 217, 216, 216, 216, 216, 215, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 200, 220, 219, 219, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 200, 200, 199, 219, 219, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 200, - 200, 200, 199, 199, 199, 219, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 200, - 199, 199, 199, 199, 199, 136, 219, 219, - 218, 218, 218, 218, 218, 217, 217, 217, - 217, 216, 216, 216, 216, 50, 50, 50, - 173, 173, 173, 173, 173, 173, 200, 199, - 199, 199, 199, 199, 199, 136, 13, 13, - 13, 13, 13, 218, 217, 217, 217, 217, - 216, 216, 51, 50, 50, 50, 50, 50, - 173, 173, 173, 173, 173, 199, 199, 199, - 199, 199, 199, 199, 136, 136, 13, 13, - 13, 13, 13, 13, 12, 12, 12, 217, - 51, 51, 50, 50, 50, 50, 50, 50, - 173, 173, 173, 173, 199, 199, 199, 199, - 199, 199, 199, 199, 135, 135, 13, 13, - 13, 13, 13, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 50, 50, - 3, 3, 173, 199, 199, 199, 199, 199, - 199, 199, 199, 135, 135, 135, 135, 13, - 13, 13, 12, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 49, 49, - 3, 3, 189, 189, 199, 199, 199, 199, - 199, 199, 135, 135, 135, 135, 135, 13, - 13, 12, 12, 12, 12, 12, 12, 12, - 50, 50, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 199, 199, 199, 199, - 199, 135, 135, 135, 135, 135, 134, 134, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 49, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 189, 199, 199, 199, - 135, 135, 135, 135, 134, 134, 134, 133, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 49, 49, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 189, 189, 199, 198, - 135, 135, 151, 151, 134, 134, 134, 133, - 31, 12, 12, 12, 12, 12, 11, 11, - 11, 49, 49, 49, 49, 49, 48, 48, - 189, 189, 189, 189, 189, 189, 189, 151, - 151, 151, 151, 150, 150, 150, 133, 133, - 31, 30, 30, 12, 12, 11, 11, 11, - 11, 49, 49, 49, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 151, - 151, 150, 150, 150, 150, 150, 133, 133, - 30, 30, 29, 29, 29, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 150, - 150, 150, 150, 150, 150, 149, 149, 149, - 116, 29, 29, 29, 28, 83, 83, 83, - 82, 82, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 150, 150, 149, 149, 116, - 116, 116, 29, 28, 28, 83, 83, 82, - 82, 82, 65, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 150, 149, 149, 116, 116, - 116, 115, 115, 115, 28, 83, 82, 82, - 82, 82, 65, 65, 65, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 187, 187, - 150, 150, 150, 149, 149, 149, 116, 116, - 116, 115, 115, 115, 114, 83, 82, 82, - 82, 65, 65, 65, 65, 65, 64, 64, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 150, 149, 149, 149, 116, 116, 116, - 115, 115, 115, 115, 114, 114, 82, 82, - 81, 65, 65, 65, 64, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 150, 149, 99, 116, 116, 116, 116, - 115, 115, 115, 114, 114, 114, 82, 81, - 81, 65, 64, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 99, 99, 99, 99, 98, 97, 97, - 97, 115, 114, 114, 114, 114, 113, 81, - 81, 64, 64, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 99, 99, 99, 99, 98, 98, 97, 97, - 97, 97, 96, 96, 96, 96, 113, 113, - 81, 64, 64, 64, 64, 9, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 99, 99, 98, 98, 98, 98, 97, 97, - 97, 97, 96, 96, 96, 96, 96, 96, - 112, 64, 64, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 98, 98, 98, 98, 98, 98, 97, 97, - 97, 97, 96, 96, 96, 96, 96, 96, - 96, 64, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 186, - 98, 98, 98, 98, 98, 97, 97, 97, - 97, 97, 96, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 186, - 98, 98, 98, 98, 98, 97, 97, 97, - 97, 96, 96, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 98, - 98, 98, 98, 98, 98, 97, 97, 97, - 97, 96, 96, 96, 96, 96, 96, 96, - 96, 202, 202, 202, 202, 202, 202, 202, - 238, 238, 238, 238, 238, 237, 237, 237, - 174, 174, 5, 5, 5, 5, 5, 5, - 218, 218, 218, 218, 217, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 238, 238, 238, 238, 237, 237, 174, 174, - 174, 174, 5, 5, 5, 5, 219, 219, - 218, 218, 218, 218, 217, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 238, 238, 238, 237, 174, 174, 174, 174, - 174, 174, 220, 219, 219, 219, 219, 219, - 218, 218, 218, 218, 217, 217, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 238, 238, 174, 174, 174, 174, 174, 174, - 174, 174, 220, 219, 219, 219, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 217, 216, 216, 216, 216, 215, 215, 215, - 238, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 219, 219, 219, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 217, 216, 216, 216, 216, 215, 215, 215, - 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 219, 219, 219, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 174, 199, 199, 199, 219, 219, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 199, 199, 199, 199, 199, 219, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 199, - 199, 199, 199, 199, 199, 199, 219, 218, - 218, 218, 218, 218, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 199, - 199, 199, 199, 199, 199, 199, 135, 13, - 13, 13, 218, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 50, 50, 50, 50, - 173, 173, 173, 173, 173, 173, 199, 199, - 199, 199, 199, 199, 199, 135, 135, 13, - 13, 13, 13, 12, 12, 12, 217, 216, - 216, 216, 50, 50, 50, 50, 50, 50, - 173, 173, 173, 173, 173, 199, 199, 199, - 199, 199, 199, 199, 135, 135, 135, 13, - 13, 13, 12, 12, 12, 12, 12, 12, - 50, 50, 50, 50, 50, 50, 49, 49, - 173, 173, 173, 173, 199, 199, 199, 199, - 199, 199, 199, 135, 135, 135, 135, 13, - 13, 12, 12, 12, 12, 12, 12, 12, - 11, 50, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 199, 199, 199, 199, 199, - 199, 198, 198, 135, 135, 135, 134, 134, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 49, 49, 49, 49, 49, 49, 49, - 3, 189, 189, 189, 199, 199, 199, 199, - 198, 198, 135, 135, 134, 134, 134, 134, - 12, 12, 12, 12, 12, 12, 11, 11, - 11, 49, 49, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 189, 199, 198, 198, - 198, 198, 135, 134, 134, 134, 134, 133, - 133, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 49, 49, 49, 49, 48, 48, - 189, 189, 189, 189, 189, 189, 198, 198, - 198, 135, 134, 134, 134, 134, 133, 133, - 133, 12, 12, 12, 12, 11, 11, 11, - 11, 11, 49, 49, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 198, 198, - 198, 150, 150, 150, 150, 133, 133, 133, - 133, 30, 29, 29, 11, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 150, - 150, 150, 150, 150, 150, 150, 133, 133, - 132, 29, 29, 29, 11, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 150, - 150, 150, 150, 150, 150, 149, 149, 149, - 132, 29, 29, 28, 28, 11, 11, 11, - 82, 82, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 188, - 150, 150, 150, 150, 149, 149, 149, 148, - 148, 115, 28, 28, 28, 27, 82, 82, - 82, 82, 82, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 187, 187, - 150, 150, 150, 149, 149, 149, 149, 148, - 148, 115, 115, 28, 27, 27, 82, 82, - 82, 82, 65, 65, 65, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 150, 150, 150, 149, 149, 149, 148, 148, - 115, 115, 115, 114, 114, 27, 82, 82, - 81, 81, 65, 64, 64, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 150, 149, 149, 149, 148, 148, 115, - 115, 115, 114, 114, 114, 114, 82, 81, - 81, 81, 64, 64, 64, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 149, 148, 116, 115, - 115, 115, 114, 114, 114, 114, 113, 81, - 81, 81, 64, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 99, 99, 98, 97, 97, 115, - 115, 114, 114, 114, 114, 113, 113, 81, - 81, 81, 64, 64, 64, 9, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 186, 99, 99, 98, 98, 97, 97, 97, - 97, 96, 96, 96, 113, 113, 113, 113, - 81, 64, 64, 64, 64, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 98, 98, 98, 98, 97, 97, 97, - 97, 96, 96, 96, 96, 96, 96, 112, - 112, 8, 64, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 98, 98, 98, 98, 97, 97, 97, - 97, 96, 96, 96, 96, 96, 96, 96, - 8, 8, 8, 202, 202, 202, 202, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 98, 98, 98, 97, 97, 97, 97, - 97, 96, 96, 96, 96, 96, 96, 96, - 8, 8, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 186, 186, 186, - 98, 98, 98, 98, 97, 97, 97, 97, - 96, 96, 96, 96, 96, 96, 96, 96, - 8, 8, 202, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 185, 185, 185, - 98, 98, 98, 98, 97, 97, 97, 97, - 96, 96, 96, 96, 96, 96, 96, 96, - 8, 8, 202, 202, 202, 202, 202, 202, - 237, 237, 237, 237, 237, 237, 237, 237, - 237, 174, 5, 5, 5, 5, 5, 218, - 218, 218, 218, 217, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 237, 237, 237, 237, 237, 237, 237, 174, - 174, 174, 5, 5, 5, 219, 219, 218, - 218, 218, 218, 217, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 237, 237, 237, 237, 237, 237, 174, 174, - 174, 174, 219, 219, 219, 219, 219, 218, - 218, 218, 218, 217, 217, 217, 217, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 237, 237, 237, 237, 174, 174, 174, 174, - 174, 174, 174, 219, 219, 219, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 217, - 216, 216, 216, 216, 215, 215, 215, 215, - 237, 237, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 219, 219, 219, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 217, - 216, 216, 216, 216, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 174, 174, 219, 219, 219, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 199, 199, 219, 219, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 199, 199, 199, 199, 219, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 199, 199, 199, 199, 199, 199, 218, 218, - 218, 218, 218, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 199, - 199, 199, 199, 199, 199, 198, 135, 13, - 13, 218, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 199, 199, - 199, 199, 199, 198, 198, 198, 135, 13, - 13, 13, 12, 12, 12, 217, 216, 216, - 216, 216, 216, 215, 50, 50, 49, 49, - 172, 172, 172, 172, 172, 199, 199, 199, - 199, 199, 198, 198, 198, 135, 135, 134, - 13, 12, 12, 12, 12, 12, 12, 12, - 11, 50, 49, 49, 49, 49, 49, 49, - 172, 172, 172, 172, 172, 199, 199, 199, - 198, 198, 198, 198, 198, 134, 134, 134, - 12, 12, 12, 12, 12, 12, 12, 11, - 11, 49, 49, 49, 49, 49, 49, 49, - 172, 172, 172, 172, 199, 199, 198, 198, - 198, 198, 198, 198, 134, 134, 134, 134, - 133, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 49, 49, 49, 49, 49, 49, - 189, 189, 189, 189, 199, 198, 198, 198, - 198, 198, 198, 198, 134, 134, 134, 133, - 133, 12, 12, 12, 12, 11, 11, 11, - 11, 11, 49, 49, 49, 49, 48, 48, - 189, 189, 189, 189, 198, 198, 198, 198, - 198, 198, 198, 134, 134, 134, 133, 133, - 133, 12, 12, 12, 12, 11, 11, 11, - 11, 11, 49, 49, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 198, 198, 198, - 198, 198, 134, 134, 134, 133, 133, 133, - 133, 132, 12, 12, 11, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 198, 198, - 198, 150, 150, 150, 150, 133, 133, 133, - 132, 132, 29, 11, 11, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 198, - 150, 150, 150, 150, 150, 133, 133, 132, - 132, 132, 29, 28, 11, 11, 11, 11, - 11, 11, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 150, - 150, 150, 150, 150, 149, 149, 149, 132, - 132, 132, 28, 28, 28, 11, 11, 11, - 11, 82, 48, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 187, 187, - 150, 150, 150, 149, 149, 149, 149, 148, - 148, 131, 131, 28, 27, 27, 27, 82, - 82, 82, 81, 48, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 150, 150, 150, 149, 149, 149, 148, 148, - 148, 147, 147, 27, 27, 27, 26, 82, - 82, 81, 81, 64, 64, 64, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 150, 149, 149, 149, 148, 148, 148, - 147, 147, 114, 114, 114, 26, 26, 81, - 81, 81, 81, 64, 64, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 149, 148, 148, 148, - 147, 114, 114, 114, 114, 113, 26, 81, - 81, 81, 81, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 148, 148, 148, 147, - 147, 114, 114, 114, 114, 113, 113, 81, - 81, 81, 64, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 186, 186, 149, 148, 148, 148, 147, 147, - 114, 114, 114, 114, 113, 113, 113, 112, - 81, 80, 64, 64, 64, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 98, 98, 97, 97, 97, 97, - 96, 96, 96, 113, 113, 113, 113, 112, - 112, 80, 64, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 98, 98, 97, 97, 97, 97, - 96, 96, 96, 96, 96, 113, 112, 112, - 8, 8, 8, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 98, 98, 97, 97, 97, 97, - 96, 96, 96, 96, 96, 96, 96, 8, - 8, 8, 8, 9, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 98, 98, 97, 97, 97, 97, 97, - 96, 96, 96, 96, 96, 96, 96, 8, - 8, 8, 8, 202, 202, 202, 202, 202, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 98, 97, 97, 97, 97, 96, - 96, 96, 96, 96, 96, 96, 96, 8, - 8, 8, 8, 202, 202, 202, 202, 202, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 98, 97, 97, 97, 97, 96, - 96, 96, 96, 96, 96, 96, 96, 8, - 8, 8, 8, 202, 202, 202, 202, 202, - 236, 236, 236, 236, 236, 236, 236, 236, - 236, 236, 5, 5, 5, 5, 218, 218, - 218, 218, 217, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 236, 236, 236, 236, 236, 236, 236, 236, - 236, 174, 5, 5, 219, 219, 218, 218, - 218, 218, 217, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 236, 236, 236, 236, 236, 236, 236, 174, - 174, 174, 174, 219, 219, 219, 218, 218, - 218, 218, 217, 217, 217, 217, 217, 216, - 216, 216, 216, 216, 215, 215, 215, 215, - 236, 236, 236, 236, 236, 174, 174, 174, - 174, 174, 174, 219, 219, 218, 218, 218, - 218, 218, 217, 217, 217, 217, 217, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 236, 236, 236, 173, 173, 173, 173, 173, - 173, 173, 174, 219, 219, 218, 218, 218, - 218, 218, 217, 217, 217, 217, 217, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 219, 219, 218, 218, 218, - 218, 218, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 199, 199, 199, 218, 218, 218, - 218, 218, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 199, 199, 199, 199, 198, 218, 218, - 218, 218, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 215, - 173, 173, 173, 173, 173, 173, 173, 173, - 199, 199, 199, 199, 198, 198, 198, 218, - 218, 218, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 214, - 172, 172, 172, 172, 173, 173, 173, 199, - 199, 199, 198, 198, 198, 198, 198, 197, - 218, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 172, 172, 172, 172, 172, 172, 172, 199, - 198, 198, 198, 198, 198, 198, 197, 197, - 197, 12, 12, 12, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 49, - 172, 172, 172, 172, 172, 172, 199, 198, - 198, 198, 198, 198, 198, 197, 197, 197, - 197, 12, 12, 12, 12, 12, 12, 11, - 216, 216, 215, 49, 49, 49, 49, 49, - 172, 172, 172, 172, 172, 198, 198, 198, - 198, 198, 198, 198, 198, 197, 197, 197, - 133, 12, 12, 12, 12, 12, 11, 11, - 11, 11, 49, 49, 49, 49, 49, 49, - 172, 172, 172, 172, 172, 198, 198, 198, - 198, 198, 198, 198, 197, 197, 197, 133, - 133, 12, 12, 12, 12, 11, 11, 11, - 11, 11, 49, 49, 49, 49, 48, 48, - 172, 172, 172, 172, 198, 198, 198, 198, - 198, 198, 198, 197, 197, 197, 133, 133, - 133, 133, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 49, 48, 48, 48, 48, - 188, 188, 188, 188, 198, 198, 198, 198, - 198, 198, 197, 197, 197, 197, 133, 133, - 133, 132, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 198, 198, 198, - 198, 198, 197, 197, 197, 133, 133, 133, - 132, 132, 132, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 198, 198, - 198, 197, 197, 197, 133, 133, 133, 132, - 132, 132, 131, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 188, 198, - 197, 197, 150, 150, 133, 133, 132, 132, - 132, 132, 131, 11, 11, 11, 11, 11, - 11, 11, 10, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 187, 150, - 150, 150, 150, 150, 149, 149, 149, 132, - 132, 131, 131, 131, 11, 11, 11, 11, - 11, 10, 10, 48, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 150, 150, 150, 149, 149, 149, 148, 148, - 148, 131, 131, 131, 27, 27, 26, 10, - 10, 10, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 150, 150, 149, 149, 149, 148, 148, 148, - 147, 147, 147, 130, 27, 26, 26, 10, - 10, 10, 10, 80, 64, 64, 64, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 149, 148, 148, 148, - 147, 147, 147, 114, 26, 26, 26, 25, - 81, 81, 80, 80, 64, 64, 9, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 148, 148, 148, 147, - 147, 147, 114, 114, 113, 113, 25, 25, - 81, 80, 80, 64, 64, 64, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 186, 149, 149, 148, 148, 148, 147, 147, - 147, 147, 114, 114, 113, 113, 113, 81, - 80, 80, 80, 64, 64, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 149, 148, 148, 148, 147, 147, - 147, 114, 114, 113, 113, 113, 113, 112, - 80, 80, 80, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 148, 148, 148, 147, 147, 147, - 114, 114, 113, 113, 113, 113, 112, 112, - 112, 80, 80, 64, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 181, 97, 97, 97, 97, 96, - 96, 96, 96, 96, 113, 112, 112, 112, - 8, 8, 8, 8, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 182, 181, 97, 97, 97, 97, 96, - 96, 96, 96, 96, 96, 112, 112, 8, - 8, 8, 8, 8, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 181, 97, 97, 97, 97, 96, - 96, 96, 96, 96, 96, 96, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 97, 97, 96, 96, - 96, 96, 96, 96, 96, 96, 8, 8, - 8, 8, 8, 8, 202, 202, 202, 202, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 97, 97, 96, 96, - 96, 96, 96, 96, 96, 96, 8, 8, - 8, 8, 8, 8, 202, 202, 202, 202, - 236, 236, 236, 236, 236, 236, 236, 236, - 236, 236, 236, 5, 5, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 214, - 236, 236, 236, 236, 236, 236, 236, 236, - 236, 236, 236, 219, 219, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 214, - 236, 236, 236, 236, 236, 236, 236, 236, - 236, 174, 174, 219, 219, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 216, 216, 216, 215, 215, 215, 215, 214, - 236, 236, 236, 236, 236, 236, 236, 173, - 173, 173, 173, 219, 218, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 236, 236, 236, 236, 173, 173, 173, 173, - 173, 173, 173, 219, 218, 218, 218, 218, - 218, 217, 217, 217, 217, 217, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 236, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 173, 218, 218, 218, 218, - 218, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 173, 173, 173, 173, 173, 173, 173, 173, - 173, 173, 173, 199, 198, 218, 218, 218, - 218, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 172, 172, 173, 173, 173, 173, 173, 173, - 173, 173, 198, 198, 198, 198, 218, 218, - 218, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 215, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 198, 198, 198, 198, 198, 198, 218, - 218, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 198, 198, 198, 198, 198, 198, 197, 197, - 197, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 198, - 198, 198, 198, 198, 198, 197, 197, 197, - 197, 197, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 198, - 198, 198, 198, 198, 198, 197, 197, 197, - 197, 196, 12, 12, 12, 12, 11, 216, - 216, 215, 215, 215, 215, 215, 49, 49, - 172, 172, 172, 172, 172, 172, 198, 198, - 198, 198, 198, 198, 197, 197, 197, 197, - 196, 196, 12, 12, 12, 11, 11, 11, - 11, 11, 11, 49, 49, 49, 48, 48, - 171, 171, 172, 172, 172, 198, 198, 198, - 198, 198, 198, 197, 197, 197, 197, 196, - 196, 196, 12, 12, 11, 11, 11, 11, - 11, 11, 11, 49, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 198, 198, 198, - 198, 198, 198, 197, 197, 197, 197, 196, - 196, 196, 132, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 171, 171, 171, 171, 198, 198, 198, 198, - 198, 198, 197, 197, 197, 197, 196, 196, - 196, 132, 132, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 198, 198, 198, - 198, 197, 197, 197, 197, 196, 196, 196, - 132, 132, 132, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 198, 198, 198, - 197, 197, 197, 197, 196, 196, 196, 132, - 132, 132, 131, 131, 11, 11, 11, 11, - 11, 11, 10, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 188, 198, 198, - 197, 197, 197, 196, 196, 196, 132, 132, - 132, 131, 131, 131, 11, 11, 11, 11, - 11, 10, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 197, - 197, 197, 197, 196, 196, 149, 132, 132, - 131, 131, 131, 131, 11, 11, 11, 10, - 10, 10, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 197, 150, 149, 149, 149, 148, 148, 148, - 131, 131, 131, 130, 130, 26, 26, 10, - 10, 10, 10, 10, 10, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 150, 149, 149, 149, 149, 148, 148, 148, - 147, 147, 147, 130, 130, 26, 26, 10, - 10, 10, 10, 10, 80, 64, 64, 9, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 149, 149, 149, 148, 148, 148, 147, - 147, 147, 146, 146, 146, 26, 25, 10, - 10, 10, 80, 80, 80, 64, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 186, 149, 149, 148, 148, 148, 147, 147, - 147, 147, 146, 146, 113, 25, 25, 24, - 24, 80, 80, 80, 80, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 149, 148, 148, 148, 147, 147, - 147, 146, 146, 113, 113, 113, 112, 24, - 24, 80, 80, 80, 64, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 148, 148, 148, 147, 147, 147, - 147, 146, 113, 113, 113, 113, 112, 112, - 7, 80, 80, 80, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 181, 148, 147, 147, 147, 147, - 146, 113, 113, 113, 113, 112, 112, 112, - 112, 8, 22, 22, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 182, 181, 181, 179, 147, 147, 96, - 96, 96, 113, 113, 112, 112, 112, 8, - 8, 8, 8, 8, 9, 9, 9, 9, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 181, 181, 179, 97, 96, 96, - 96, 96, 96, 96, 112, 112, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 96, 96, - 96, 96, 96, 96, 96, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 96, 96, - 96, 96, 96, 96, 96, 8, 8, 8, - 8, 8, 8, 8, 8, 202, 202, 202, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 96, 96, - 96, 96, 96, 96, 96, 8, 8, 8, - 8, 8, 8, 8, 8, 202, 202, 202, - 235, 235, 235, 235, 235, 235, 235, 234, - 234, 234, 234, 5, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 214, 214, - 235, 235, 235, 235, 235, 235, 234, 234, - 234, 234, 234, 219, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 214, 214, - 235, 235, 235, 235, 235, 234, 234, 234, - 234, 234, 228, 219, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 216, 216, 215, 215, 215, 215, 214, 214, - 235, 235, 235, 235, 234, 234, 234, 234, - 234, 228, 227, 227, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 235, 235, 235, 234, 234, 234, 173, 173, - 173, 173, 227, 227, 218, 218, 218, 218, - 217, 217, 217, 217, 217, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 235, 235, 173, 173, 173, 173, 173, 173, - 173, 173, 227, 226, 226, 218, 218, 218, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 226, 226, 226, 218, 218, 218, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 172, 198, 198, 198, 225, 218, 218, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 215, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 198, 198, 198, 198, 198, 197, 197, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 198, 198, 198, 198, 198, 198, 197, 197, - 197, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 198, 198, 198, 198, 198, 197, 197, 197, - 197, 196, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 198, - 198, 198, 198, 198, 197, 197, 197, 197, - 197, 196, 196, 12, 12, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 171, 171, 171, 171, 172, 172, 198, 198, - 198, 198, 198, 197, 197, 197, 197, 197, - 196, 196, 196, 12, 11, 11, 11, 11, - 11, 11, 215, 215, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 171, 198, 198, - 198, 198, 198, 197, 197, 197, 197, 196, - 196, 196, 195, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 198, 198, 198, - 198, 198, 197, 197, 197, 197, 196, 196, - 196, 196, 195, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 198, 198, 198, - 198, 197, 197, 197, 197, 196, 196, 196, - 196, 195, 195, 11, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 198, 198, 198, - 197, 197, 197, 197, 197, 196, 196, 196, - 195, 195, 195, 131, 11, 11, 11, 11, - 11, 11, 11, 48, 48, 48, 48, 48, - 188, 188, 188, 188, 188, 198, 198, 198, - 197, 197, 197, 197, 196, 196, 196, 195, - 195, 195, 131, 131, 11, 11, 11, 11, - 11, 10, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 198, 197, - 197, 197, 197, 196, 196, 196, 195, 195, - 195, 131, 131, 131, 11, 11, 11, 11, - 10, 10, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 197, - 197, 197, 196, 196, 196, 196, 195, 195, - 195, 131, 131, 130, 130, 11, 10, 10, - 10, 10, 10, 10, 10, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 197, 196, 196, 196, 196, 195, 195, 195, - 131, 131, 130, 130, 130, 130, 10, 10, - 10, 10, 10, 10, 10, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 187, 196, 196, 196, 195, 148, 148, 147, - 147, 147, 130, 130, 130, 129, 10, 10, - 10, 10, 10, 10, 80, 80, 9, 9, - 187, 187, 187, 187, 186, 186, 186, 186, - 186, 149, 149, 148, 148, 148, 148, 147, - 147, 147, 146, 146, 146, 129, 25, 10, - 10, 10, 80, 80, 80, 80, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 149, 148, 148, 148, 147, 147, - 147, 146, 146, 146, 145, 145, 24, 24, - 24, 80, 80, 80, 80, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 148, 148, 148, 147, 147, 147, - 147, 146, 146, 145, 145, 145, 24, 24, - 7, 23, 80, 80, 22, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 181, 148, 147, 147, 147, 147, - 146, 146, 145, 145, 145, 112, 112, 112, - 23, 23, 22, 22, 22, 9, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 182, 181, 181, 147, 147, 147, 147, - 146, 145, 145, 145, 112, 112, 112, 112, - 8, 22, 22, 22, 21, 9, 9, 9, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 147, 145, - 145, 145, 145, 112, 112, 112, 112, 8, - 8, 8, 8, 21, 21, 21, 9, 9, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 179, 96, - 96, 96, 96, 112, 112, 112, 8, 8, - 8, 8, 8, 21, 21, 20, 9, 9, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 96, 96, 96, 96, 8, 8, 8, 8, - 8, 8, 8, 8, 20, 20, 19, 9, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 96, 96, 96, 96, 8, 8, 8, 8, - 8, 8, 8, 8, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 185, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 96, 96, 96, 96, 8, 8, 8, 8, - 8, 8, 8, 8, 19, 19, 19, 18, - 235, 234, 234, 234, 234, 234, 234, 234, - 234, 234, 234, 228, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 234, - 234, 234, 228, 228, 218, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 234, - 234, 228, 228, 227, 227, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 216, 215, 215, 215, 215, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 234, - 228, 228, 227, 227, 227, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 228, - 228, 227, 227, 227, 226, 218, 218, 217, - 217, 217, 217, 217, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 234, 234, 234, 172, 172, 172, 172, 172, - 227, 227, 227, 226, 226, 226, 218, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 227, 227, 226, 226, 226, 225, 225, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 226, 226, 226, 225, 225, 225, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 215, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 226, 226, 225, 225, 225, 224, 224, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 172, 198, 198, 198, 225, 224, 224, 224, - 224, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 198, 198, 198, 198, 197, 197, 197, 197, - 197, 196, 196, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 172, 172, 198, - 198, 198, 198, 197, 197, 197, 197, 197, - 196, 196, 196, 196, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 198, - 198, 198, 198, 197, 197, 197, 197, 196, - 196, 196, 196, 195, 11, 11, 11, 11, - 11, 215, 215, 215, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 198, 198, - 198, 198, 197, 197, 197, 197, 197, 196, - 196, 196, 195, 195, 11, 11, 11, 11, - 11, 11, 11, 11, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 171, 198, 198, - 198, 197, 197, 197, 197, 197, 196, 196, - 196, 195, 195, 195, 11, 11, 11, 11, - 11, 11, 11, 11, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 171, 198, 198, - 197, 197, 197, 197, 197, 196, 196, 196, - 195, 195, 195, 194, 11, 11, 11, 11, - 11, 11, 11, 10, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 198, 198, 198, - 197, 197, 197, 197, 196, 196, 196, 196, - 195, 195, 194, 194, 194, 11, 11, 11, - 11, 11, 10, 10, 48, 48, 48, 48, - 187, 187, 187, 171, 171, 198, 198, 197, - 197, 197, 197, 196, 196, 196, 196, 195, - 195, 195, 194, 194, 194, 11, 11, 11, - 10, 10, 10, 10, 10, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 197, 197, - 197, 197, 197, 196, 196, 196, 195, 195, - 195, 194, 194, 194, 194, 11, 11, 10, - 10, 10, 10, 10, 10, 48, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 197, - 197, 197, 196, 196, 196, 195, 195, 195, - 195, 194, 194, 194, 130, 130, 10, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 187, 187, 187, 187, 187, 187, 187, 187, - 197, 196, 196, 196, 195, 195, 195, 195, - 194, 194, 194, 130, 130, 129, 10, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 187, 187, 187, 187, 186, 186, 186, 186, - 196, 196, 196, 196, 195, 195, 195, 194, - 194, 194, 130, 130, 129, 129, 10, 10, - 10, 10, 10, 10, 80, 80, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 196, 196, 195, 195, 195, 195, 147, - 147, 146, 146, 129, 129, 129, 128, 10, - 10, 10, 80, 80, 80, 80, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 195, 195, 195, 147, 147, 147, - 147, 146, 146, 145, 145, 145, 128, 24, - 7, 23, 23, 22, 22, 22, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 148, 148, 148, 147, 147, 147, - 146, 146, 145, 145, 145, 128, 128, 7, - 23, 23, 22, 22, 22, 21, 9, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 182, 181, 181, 147, 147, 147, 147, - 146, 145, 145, 145, 145, 144, 144, 23, - 23, 22, 22, 22, 21, 21, 21, 9, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 147, 145, - 145, 145, 145, 145, 144, 144, 112, 112, - 22, 22, 22, 21, 21, 21, 20, 9, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 179, 145, - 145, 145, 145, 144, 144, 112, 8, 8, - 8, 8, 21, 21, 21, 20, 20, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 145, 145, 144, 112, 8, 8, 8, - 8, 8, 21, 21, 20, 20, 19, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 112, 8, 8, 8, 8, - 8, 8, 8, 20, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 185, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 8, 8, 8, 8, 8, - 8, 8, 8, 20, 19, 19, 19, 18, - 185, 185, 185, 185, 185, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 8, 8, 8, 8, - 8, 8, 8, 19, 19, 19, 18, 18, - 234, 234, 234, 234, 234, 234, 234, 234, - 234, 229, 229, 228, 228, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 214, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 234, - 229, 229, 228, 228, 227, 218, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 214, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 234, 229, - 229, 228, 228, 227, 227, 227, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 216, - 215, 215, 215, 215, 214, 214, 214, 214, - 234, 234, 234, 234, 234, 234, 229, 229, - 228, 228, 227, 227, 227, 226, 217, 217, - 217, 217, 217, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 234, 234, 234, 234, 234, 229, 229, 228, - 228, 227, 227, 227, 226, 226, 226, 217, - 217, 217, 217, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 234, 234, 234, 234, 172, 229, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 217, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 215, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 172, 172, 172, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 172, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 198, 198, 225, 197, 197, 224, 224, 224, - 196, 196, 196, 195, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 198, 198, 197, 197, 197, 197, 197, 196, - 196, 196, 196, 195, 194, 11, 11, 11, - 215, 215, 215, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 198, - 198, 197, 197, 197, 197, 197, 196, 196, - 196, 196, 195, 195, 194, 11, 11, 11, - 11, 11, 11, 214, 214, 214, 48, 48, - 171, 171, 171, 171, 171, 171, 171, 198, - 197, 197, 197, 197, 197, 196, 196, 196, - 196, 195, 195, 194, 194, 11, 11, 11, - 11, 11, 11, 10, 48, 48, 48, 48, - 171, 171, 171, 171, 171, 171, 171, 198, - 197, 197, 197, 197, 197, 196, 196, 196, - 195, 195, 195, 194, 194, 11, 11, 11, - 11, 11, 10, 10, 10, 48, 48, 48, - 170, 171, 171, 171, 171, 171, 198, 197, - 197, 197, 197, 197, 196, 196, 196, 195, - 195, 195, 194, 194, 194, 194, 11, 11, - 10, 10, 10, 10, 10, 48, 48, 48, - 170, 170, 170, 171, 171, 169, 197, 197, - 197, 197, 197, 196, 196, 196, 195, 195, - 195, 194, 194, 194, 194, 193, 11, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 187, 187, 187, 187, 169, 169, 169, 197, - 197, 197, 196, 196, 196, 196, 195, 195, - 195, 194, 194, 194, 193, 193, 193, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 187, 187, 187, 187, 187, 187, 169, 197, - 197, 196, 196, 196, 196, 195, 195, 195, - 194, 194, 194, 194, 193, 193, 193, 10, - 10, 10, 10, 10, 10, 10, 10, 48, - 187, 187, 187, 187, 186, 186, 186, 167, - 197, 196, 196, 196, 195, 195, 195, 195, - 194, 194, 194, 193, 193, 193, 192, 10, - 10, 10, 10, 10, 10, 10, 80, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 167, 196, 196, 195, 195, 195, 195, 194, - 194, 194, 193, 193, 193, 192, 192, 10, - 10, 10, 10, 10, 22, 22, 22, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 196, 195, 195, 195, 195, 194, 194, - 194, 193, 193, 193, 129, 192, 192, 128, - 10, 23, 23, 22, 22, 22, 21, 9, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 166, 195, 195, 195, 195, 194, 194, - 193, 193, 193, 145, 145, 192, 128, 128, - 23, 23, 22, 22, 22, 21, 21, 21, - 186, 186, 186, 186, 186, 186, 186, 186, - 186, 182, 181, 195, 195, 147, 147, 193, - 193, 145, 145, 145, 145, 128, 128, 128, - 23, 22, 22, 22, 21, 21, 21, 20, - 186, 186, 186, 186, 186, 185, 185, 185, - 182, 182, 181, 181, 179, 147, 147, 145, - 145, 145, 145, 145, 144, 144, 144, 144, - 22, 22, 22, 21, 21, 21, 20, 20, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 179, 145, - 145, 145, 145, 145, 144, 144, 144, 144, - 22, 22, 21, 21, 21, 20, 20, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 145, 145, 145, 144, 144, 144, 144, 8, - 8, 21, 21, 21, 20, 20, 19, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 144, 144, 144, 144, 8, 8, - 8, 21, 21, 20, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 185, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 8, 8, 8, 8, - 8, 8, 20, 20, 19, 19, 19, 18, - 185, 185, 185, 185, 185, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 8, 8, 8, 8, - 8, 8, 20, 19, 19, 19, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 176, 8, 8, 8, - 8, 8, 19, 19, 19, 18, 18, 18, - 233, 233, 233, 233, 233, 233, 233, 233, - 229, 229, 228, 228, 228, 227, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 214, 214, 214, 214, 253, - 233, 233, 233, 233, 233, 233, 233, 229, - 229, 228, 228, 228, 227, 227, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 233, 233, 233, 233, 233, 233, 229, 229, - 228, 228, 228, 227, 227, 227, 217, 217, - 217, 217, 216, 216, 216, 216, 216, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 233, 233, 233, 233, 233, 229, 229, 228, - 228, 228, 227, 227, 227, 226, 226, 217, - 217, 217, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 233, 233, 233, 233, 229, 229, 228, 228, - 228, 227, 227, 227, 226, 226, 226, 217, - 217, 217, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 233, 233, 233, 229, 229, 228, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 225, - 217, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 233, 172, 172, 229, 228, 228, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 224, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 172, 172, 172, 172, 172, 228, 227, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 215, 214, 214, 214, 214, 214, - 171, 171, 172, 172, 172, 172, 227, 227, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 224, 216, 216, 216, 216, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 226, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 224, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 226, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 225, 225, 225, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 225, 225, 224, 224, 224, 224, 224, 224, - 224, 196, 195, 195, 194, 194, 11, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 198, 197, 197, 197, 197, 197, 196, 196, - 196, 195, 195, 194, 194, 194, 11, 11, - 11, 11, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 171, - 197, 197, 197, 197, 197, 196, 196, 196, - 196, 195, 195, 194, 194, 194, 11, 11, - 11, 11, 10, 10, 10, 48, 48, 48, - 170, 170, 171, 171, 171, 171, 171, 197, - 197, 197, 197, 197, 196, 196, 196, 196, - 195, 195, 194, 194, 194, 194, 11, 11, - 11, 10, 10, 10, 10, 48, 48, 48, - 170, 170, 170, 170, 171, 171, 169, 197, - 197, 197, 197, 196, 196, 196, 196, 195, - 195, 195, 194, 194, 194, 194, 193, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 170, 170, 170, 170, 169, 169, 169, 197, - 197, 197, 197, 196, 196, 196, 195, 195, - 195, 194, 194, 194, 194, 193, 193, 10, - 10, 10, 10, 10, 10, 10, 48, 48, - 170, 168, 168, 168, 169, 169, 169, 169, - 197, 197, 196, 196, 196, 195, 195, 195, - 194, 194, 194, 194, 193, 193, 193, 10, - 10, 10, 10, 10, 10, 10, 10, 48, - 168, 168, 168, 168, 169, 169, 169, 169, - 197, 196, 196, 196, 195, 195, 195, 195, - 194, 194, 194, 193, 193, 193, 193, 192, - 10, 10, 10, 10, 10, 10, 10, 48, - 186, 186, 186, 168, 168, 167, 167, 167, - 167, 196, 196, 196, 195, 195, 195, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 10, 10, 10, 10, 10, 22, 22, 21, - 186, 186, 186, 186, 186, 167, 167, 167, - 167, 167, 196, 195, 195, 195, 195, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 10, 10, 22, 22, 22, 21, 21, - 186, 186, 186, 186, 186, 186, 167, 167, - 167, 167, 195, 195, 195, 195, 194, 194, - 194, 193, 193, 193, 192, 192, 192, 192, - 192, 23, 22, 22, 22, 21, 21, 21, - 186, 186, 186, 186, 186, 186, 186, 166, - 166, 166, 166, 195, 195, 194, 194, 194, - 193, 193, 193, 193, 192, 192, 192, 128, - 128, 22, 22, 22, 21, 21, 21, 20, - 186, 186, 186, 186, 186, 185, 185, 166, - 166, 166, 181, 181, 195, 194, 194, 193, - 193, 193, 145, 145, 192, 128, 128, 128, - 22, 22, 22, 21, 21, 21, 20, 20, - 185, 185, 185, 185, 185, 185, 185, 185, - 182, 182, 181, 181, 179, 179, 163, 193, - 145, 145, 145, 145, 144, 144, 144, 144, - 22, 22, 21, 21, 21, 20, 20, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 163, 163, - 145, 145, 145, 144, 144, 144, 144, 144, - 22, 21, 21, 21, 20, 20, 19, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 144, 144, 144, 144, 144, 144, - 21, 21, 21, 20, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 185, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 144, 144, 144, 144, 8, - 21, 21, 20, 20, 19, 19, 19, 18, - 185, 185, 185, 185, 185, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 176, 8, 8, 8, - 8, 20, 20, 19, 19, 19, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 176, 8, 8, 8, - 8, 20, 19, 19, 19, 18, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 8, - 8, 19, 19, 19, 18, 18, 18, 17, - 233, 232, 232, 232, 232, 232, 232, 229, - 229, 229, 228, 228, 228, 227, 217, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 214, 214, 214, 214, 253, 253, - 232, 232, 232, 232, 232, 232, 229, 229, - 229, 228, 228, 228, 227, 227, 227, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 253, - 232, 232, 232, 232, 232, 229, 229, 229, - 228, 228, 228, 227, 227, 227, 226, 217, - 217, 216, 216, 216, 216, 216, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 232, 232, 232, 232, 229, 229, 229, 228, - 228, 228, 227, 227, 227, 226, 226, 226, - 217, 216, 216, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 232, 232, 232, 229, 229, 229, 228, 228, - 228, 227, 227, 227, 226, 226, 226, 225, - 217, 216, 216, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 232, 232, 229, 229, 229, 228, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 225, - 225, 216, 216, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 232, 229, 229, 229, 228, 228, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 224, 216, 216, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 229, 228, 228, 228, 227, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 224, 216, 216, 216, 215, 215, 215, - 215, 215, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 227, 227, 227, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 224, 224, 216, 216, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 227, 226, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 224, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 226, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 224, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 226, - 225, 225, 225, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 171, 225, - 225, 225, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 195, 194, 194, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 170, 171, 171, 171, 171, 171, 171, 171, - 225, 224, 224, 224, 224, 224, 224, 224, - 224, 195, 195, 194, 194, 194, 194, 11, - 11, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 171, 171, 171, 171, 171, - 224, 224, 224, 224, 224, 224, 224, 196, - 195, 195, 194, 194, 194, 194, 194, 11, - 11, 10, 10, 10, 10, 214, 214, 214, - 170, 170, 170, 170, 170, 171, 171, 169, - 197, 197, 197, 197, 196, 196, 196, 195, - 195, 195, 194, 194, 194, 194, 193, 193, - 10, 10, 10, 10, 10, 10, 48, 48, - 170, 170, 170, 170, 170, 169, 169, 169, - 197, 197, 197, 196, 196, 196, 196, 195, - 195, 194, 194, 194, 194, 193, 193, 193, - 10, 10, 10, 10, 10, 10, 10, 48, - 170, 170, 170, 169, 169, 169, 169, 169, - 169, 197, 196, 196, 196, 196, 195, 195, - 195, 194, 194, 194, 193, 193, 193, 193, - 10, 10, 10, 10, 10, 10, 10, 48, - 168, 168, 168, 168, 169, 169, 169, 169, - 169, 196, 196, 196, 196, 195, 195, 195, - 194, 194, 194, 194, 193, 193, 193, 192, - 192, 10, 10, 10, 10, 10, 10, 10, - 168, 168, 168, 168, 169, 169, 169, 169, - 167, 196, 196, 196, 195, 195, 195, 194, - 194, 194, 194, 193, 193, 193, 192, 192, - 192, 10, 10, 10, 10, 10, 22, 21, - 168, 168, 168, 168, 168, 167, 167, 167, - 167, 167, 196, 195, 195, 195, 195, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 192, 192, 10, 10, 22, 22, 21, 21, - 168, 168, 168, 168, 167, 167, 167, 167, - 167, 167, 167, 195, 195, 195, 194, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 192, 22, 22, 22, 21, 21, 21, - 186, 186, 186, 186, 167, 167, 167, 167, - 167, 167, 167, 195, 195, 195, 194, 194, - 193, 193, 193, 193, 192, 192, 192, 192, - 192, 192, 22, 22, 21, 21, 21, 20, - 186, 186, 186, 186, 166, 166, 166, 166, - 166, 166, 166, 195, 195, 194, 194, 193, - 193, 193, 193, 192, 192, 192, 192, 192, - 128, 22, 22, 21, 21, 21, 20, 20, - 185, 185, 185, 185, 185, 166, 166, 166, - 166, 166, 166, 181, 163, 163, 193, 193, - 193, 193, 193, 192, 192, 192, 192, 128, - 128, 22, 21, 21, 21, 20, 20, 19, - 185, 185, 185, 185, 185, 185, 185, 164, - 182, 182, 181, 181, 179, 163, 163, 163, - 193, 145, 145, 192, 144, 144, 144, 144, - 22, 21, 21, 21, 20, 20, 19, 19, - 185, 185, 185, 185, 185, 185, 185, 182, - 182, 182, 181, 181, 179, 163, 163, 163, - 163, 145, 145, 144, 144, 144, 144, 144, - 21, 21, 21, 20, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 185, 183, 182, - 182, 182, 181, 181, 179, 179, 163, 163, - 177, 176, 176, 144, 144, 144, 144, 144, - 21, 21, 20, 20, 19, 19, 19, 18, - 185, 185, 185, 185, 185, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 144, 144, 144, 21, - 21, 20, 20, 19, 19, 19, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 179, 177, - 177, 176, 176, 176, 176, 176, 8, 8, - 20, 20, 19, 19, 19, 18, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 20, 19, 19, 19, 18, 18, 18, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 19, 18, 18, 18, 17, 17, - 232, 232, 232, 232, 232, 230, 230, 229, - 229, 229, 228, 228, 228, 227, 227, 217, - 216, 216, 216, 216, 216, 215, 215, 215, - 215, 214, 214, 214, 214, 253, 253, 253, - 232, 232, 232, 232, 230, 230, 229, 229, - 229, 228, 228, 228, 227, 227, 227, 226, - 216, 216, 216, 216, 216, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 253, 253, - 232, 232, 232, 230, 230, 229, 229, 229, - 228, 228, 228, 227, 227, 227, 226, 226, - 216, 216, 216, 216, 216, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 253, - 232, 232, 230, 230, 229, 229, 229, 228, - 228, 228, 227, 227, 227, 226, 226, 226, - 216, 216, 216, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 232, 230, 230, 229, 229, 229, 228, 228, - 228, 227, 227, 227, 226, 226, 226, 225, - 225, 216, 216, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 230, 230, 229, 229, 229, 228, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 225, - 225, 216, 216, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 230, 229, 229, 229, 228, 228, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 224, 224, 216, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 229, 229, 229, 228, 228, 228, 227, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 224, 224, 216, 215, 215, 215, 215, - 215, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 228, 228, 227, 227, 227, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 224, 224, 216, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 227, 227, 226, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 224, 224, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 226, 226, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 171, 171, 226, 226, - 225, 225, 225, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 171, 171, 171, 171, 171, 225, - 225, 225, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 194, 194, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 171, 171, 171, 225, - 225, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 194, 194, 194, 194, 194, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 170, 225, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 195, 194, 194, 194, 194, 194, 193, - 193, 10, 10, 10, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 169, 169, - 224, 224, 224, 224, 224, 224, 224, 195, - 195, 194, 194, 194, 194, 194, 193, 193, - 193, 10, 10, 10, 10, 10, 10, 48, - 170, 170, 170, 170, 169, 169, 169, 169, - 169, 224, 224, 224, 196, 196, 195, 195, - 195, 194, 194, 194, 194, 193, 193, 193, - 192, 10, 10, 10, 10, 10, 10, 48, - 170, 170, 168, 169, 169, 169, 169, 169, - 169, 169, 196, 196, 196, 195, 195, 195, - 194, 194, 194, 194, 193, 193, 193, 193, - 192, 192, 10, 10, 10, 10, 10, 10, - 168, 168, 168, 168, 169, 169, 169, 169, - 169, 169, 196, 196, 196, 195, 195, 195, - 194, 194, 194, 193, 193, 193, 193, 192, - 192, 192, 10, 10, 10, 10, 10, 21, - 168, 168, 168, 168, 169, 169, 169, 169, - 167, 167, 196, 196, 195, 195, 195, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 192, 192, 192, 10, 10, 22, 21, 21, - 168, 168, 168, 168, 168, 167, 167, 167, - 167, 167, 167, 195, 195, 195, 194, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 192, 192, 22, 22, 21, 21, 21, - 168, 168, 168, 168, 167, 167, 167, 167, - 167, 167, 167, 195, 195, 195, 194, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 192, 22, 22, 21, 21, 21, 20, - 165, 165, 165, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 195, 194, 194, 194, - 193, 193, 193, 193, 192, 192, 192, 192, - 192, 192, 22, 21, 21, 21, 20, 20, - 165, 165, 165, 165, 166, 166, 166, 166, - 166, 166, 166, 166, 163, 194, 194, 193, - 193, 193, 193, 192, 192, 192, 192, 192, - 192, 22, 21, 21, 21, 20, 20, 19, - 165, 165, 165, 165, 165, 166, 166, 166, - 166, 166, 166, 181, 163, 163, 163, 193, - 193, 193, 192, 192, 192, 192, 192, 192, - 128, 21, 21, 21, 20, 20, 19, 19, - 185, 185, 185, 185, 165, 164, 164, 164, - 164, 182, 181, 181, 163, 163, 163, 163, - 163, 193, 192, 192, 192, 144, 144, 144, - 144, 21, 21, 20, 20, 19, 19, 19, - 185, 185, 185, 185, 185, 164, 164, 164, - 182, 182, 181, 181, 179, 163, 163, 163, - 163, 163, 176, 144, 144, 144, 144, 144, - 21, 21, 20, 20, 19, 19, 19, 18, - 185, 185, 185, 185, 185, 183, 183, 182, - 182, 182, 181, 181, 179, 163, 163, 163, - 163, 176, 176, 176, 144, 144, 144, 144, - 21, 20, 20, 19, 19, 19, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 182, 181, 181, 179, 179, 163, 163, - 177, 176, 176, 176, 176, 144, 144, 21, - 20, 20, 19, 19, 19, 18, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 20, 19, 19, 19, 18, 18, 18, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 19, 18, 18, 18, 17, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 18, 18, 18, 17, 17, 17, - 249, 231, 231, 231, 230, 230, 230, 229, - 229, 229, 228, 228, 228, 227, 227, 227, - 216, 216, 216, 216, 215, 215, 215, 215, - 214, 214, 214, 214, 253, 253, 253, 253, - 231, 231, 231, 230, 230, 230, 229, 229, - 229, 228, 228, 228, 227, 227, 227, 226, - 216, 216, 216, 216, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 253, 253, 253, - 231, 231, 230, 230, 230, 229, 229, 229, - 228, 228, 228, 227, 227, 227, 226, 226, - 226, 216, 216, 216, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 253, 253, - 231, 230, 230, 230, 229, 229, 229, 228, - 228, 228, 227, 227, 227, 226, 226, 226, - 225, 216, 216, 215, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 253, - 230, 230, 230, 229, 229, 229, 228, 228, - 228, 227, 227, 227, 226, 226, 226, 225, - 225, 216, 216, 215, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 230, 230, 229, 229, 229, 228, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 225, - 225, 224, 216, 215, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 230, 229, 229, 229, 228, 228, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 224, 224, 224, 215, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 229, 229, 229, 228, 228, 228, 227, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 224, 224, 215, 215, 215, 215, 215, - 214, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 228, 228, 228, 227, 227, 227, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 224, 224, 224, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 171, 171, 171, 171, 227, 227, 227, 226, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 224, 224, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 171, 171, 171, 171, 227, 226, 226, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 171, 171, 171, 226, 226, - 225, 225, 225, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 226, 225, - 225, 225, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 194, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 170, 225, - 225, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 194, 194, 194, 193, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 170, 225, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 194, 194, 194, 194, 193, 193, - 193, 10, 10, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 169, 169, 169, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 194, 194, 194, 194, 193, 193, 193, - 193, 192, 10, 10, 10, 10, 10, 214, - 170, 170, 170, 170, 169, 169, 169, 169, - 169, 224, 224, 224, 224, 224, 224, 195, - 194, 194, 194, 194, 194, 193, 193, 193, - 192, 192, 10, 10, 10, 10, 10, 10, - 170, 168, 168, 169, 169, 169, 169, 169, - 169, 169, 224, 224, 224, 195, 195, 195, - 194, 194, 194, 194, 193, 193, 193, 192, - 192, 192, 192, 10, 10, 10, 10, 10, - 168, 168, 168, 168, 169, 169, 169, 169, - 169, 169, 169, 196, 195, 195, 195, 194, - 194, 194, 194, 193, 193, 193, 193, 192, - 192, 192, 192, 10, 10, 10, 21, 21, - 168, 168, 168, 168, 169, 169, 169, 169, - 167, 167, 167, 195, 195, 195, 195, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 192, 192, 192, 192, 22, 21, 21, 21, - 168, 168, 168, 168, 168, 167, 167, 167, - 167, 167, 167, 167, 195, 195, 194, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 192, 192, 22, 21, 21, 21, 20, - 168, 168, 168, 168, 167, 167, 167, 167, - 167, 167, 167, 167, 195, 194, 194, 194, - 193, 193, 193, 193, 192, 192, 192, 192, - 192, 192, 192, 21, 21, 21, 20, 20, - 165, 165, 165, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 194, 194, 193, - 193, 193, 193, 193, 192, 192, 192, 192, - 192, 192, 21, 21, 21, 20, 20, 19, - 165, 165, 165, 165, 166, 166, 166, 166, - 166, 166, 166, 166, 163, 163, 163, 193, - 193, 193, 193, 192, 192, 192, 192, 192, - 192, 192, 21, 21, 20, 20, 19, 19, - 165, 165, 165, 165, 165, 166, 166, 166, - 166, 166, 166, 181, 163, 163, 163, 163, - 193, 193, 192, 192, 192, 192, 192, 192, - 192, 21, 21, 20, 20, 19, 19, 19, - 165, 165, 165, 165, 165, 164, 164, 164, - 164, 164, 181, 181, 163, 163, 163, 163, - 163, 163, 192, 192, 192, 192, 192, 144, - 21, 21, 20, 20, 19, 19, 19, 18, - 165, 165, 165, 165, 164, 164, 164, 164, - 164, 182, 181, 181, 163, 163, 163, 163, - 163, 163, 176, 192, 144, 144, 144, 144, - 21, 20, 20, 19, 19, 19, 18, 18, - 184, 184, 184, 184, 164, 164, 164, 164, - 182, 182, 181, 181, 179, 163, 163, 163, - 163, 176, 176, 176, 176, 144, 144, 144, - 20, 20, 19, 19, 19, 18, 18, 18, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 163, 163, 163, - 163, 176, 176, 176, 176, 160, 160, 160, - 20, 19, 19, 19, 18, 18, 18, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 163, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 19, 18, 18, 18, 17, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 179, 177, 177, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 18, 18, 18, 17, 17, 17, - 251, 184, 184, 184, 183, 183, 183, 182, - 180, 180, 181, 178, 178, 179, 177, 177, - 177, 176, 176, 176, 160, 160, 160, 160, - 160, 160, 18, 18, 17, 17, 17, 16, - 249, 249, 231, 231, 230, 230, 230, 229, - 229, 229, 228, 228, 228, 227, 227, 227, - 216, 216, 216, 215, 215, 215, 215, 214, - 214, 214, 214, 253, 253, 253, 253, 253, - 249, 231, 231, 230, 230, 230, 229, 229, - 229, 228, 228, 228, 227, 227, 227, 226, - 226, 216, 216, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 253, 253, 253, 253, - 231, 231, 230, 230, 230, 229, 229, 229, - 228, 228, 228, 227, 227, 227, 226, 226, - 226, 216, 216, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 253, 253, 253, - 231, 230, 230, 230, 229, 229, 229, 228, - 228, 228, 227, 227, 227, 226, 226, 226, - 225, 225, 215, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 253, 253, - 230, 230, 230, 229, 229, 229, 228, 228, - 228, 227, 227, 227, 226, 226, 226, 225, - 225, 225, 215, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 253, - 230, 230, 229, 229, 229, 228, 228, 228, - 227, 227, 227, 226, 226, 226, 225, 225, - 225, 224, 224, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 230, 229, 229, 229, 228, 228, 228, 227, - 227, 227, 226, 226, 226, 225, 225, 225, - 224, 224, 224, 215, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 229, 229, 229, 228, 228, 228, 227, 227, - 227, 226, 226, 226, 225, 225, 225, 224, - 224, 224, 224, 224, 215, 215, 215, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 229, 229, 228, 228, 228, 227, 227, 227, - 226, 226, 226, 225, 225, 225, 224, 224, - 224, 224, 224, 224, 215, 215, 214, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 171, 228, 227, 227, 227, 226, - 226, 226, 225, 225, 225, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 214, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 227, 227, 226, 226, - 226, 225, 225, 225, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 215, 214, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 226, 226, 226, - 225, 225, 225, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 214, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 226, 225, - 225, 225, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 224, 214, 214, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 170, 225, - 225, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 224, 224, 194, 194, 193, - 214, 214, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 170, 169, 169, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 224, 194, 194, 194, 193, 193, - 193, 192, 214, 214, 214, 214, 214, 214, - 170, 170, 170, 170, 170, 169, 169, 169, - 224, 224, 224, 224, 224, 224, 224, 224, - 224, 224, 194, 194, 194, 193, 193, 193, - 193, 192, 192, 10, 10, 10, 214, 214, - 170, 170, 170, 169, 169, 169, 169, 169, - 169, 224, 224, 224, 224, 224, 224, 224, - 194, 194, 194, 194, 193, 193, 193, 193, - 192, 192, 192, 192, 10, 10, 10, 10, - 168, 168, 168, 169, 169, 169, 169, 169, - 169, 169, 224, 224, 224, 224, 224, 194, - 194, 194, 194, 193, 193, 193, 193, 192, - 192, 192, 192, 192, 10, 10, 10, 21, - 168, 168, 168, 168, 169, 169, 169, 169, - 169, 169, 169, 224, 224, 195, 195, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 192, 192, 192, 192, 192, 21, 21, 21, - 168, 168, 168, 168, 169, 169, 169, 169, - 167, 167, 167, 167, 195, 195, 194, 194, - 194, 194, 193, 193, 193, 193, 192, 192, - 192, 192, 192, 192, 21, 21, 21, 20, - 168, 168, 168, 168, 168, 167, 167, 167, - 167, 167, 167, 167, 167, 195, 194, 194, - 194, 193, 193, 193, 193, 192, 192, 192, - 192, 192, 192, 192, 21, 21, 20, 20, - 168, 168, 168, 168, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 194, 194, 194, - 193, 193, 193, 193, 192, 192, 192, 192, - 192, 192, 192, 21, 21, 20, 20, 19, - 165, 165, 165, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 194, 194, 193, - 193, 193, 193, 192, 192, 192, 192, 192, - 192, 192, 21, 21, 20, 20, 19, 19, - 165, 165, 165, 165, 166, 166, 166, 166, - 166, 166, 166, 166, 163, 163, 163, 163, - 193, 193, 193, 192, 192, 192, 192, 192, - 192, 192, 21, 20, 20, 19, 19, 19, - 165, 165, 165, 165, 165, 166, 166, 166, - 166, 166, 166, 166, 163, 163, 163, 163, - 163, 193, 192, 192, 192, 192, 192, 192, - 192, 21, 20, 20, 19, 19, 19, 18, - 165, 165, 165, 165, 165, 164, 164, 164, - 164, 164, 164, 163, 163, 163, 163, 163, - 163, 163, 192, 192, 192, 192, 192, 192, - 21, 20, 20, 19, 19, 19, 18, 18, - 165, 165, 165, 165, 164, 164, 164, 164, - 164, 164, 181, 181, 163, 163, 163, 163, - 163, 163, 176, 176, 192, 144, 144, 144, - 20, 20, 19, 19, 19, 18, 18, 18, - 165, 165, 165, 164, 164, 164, 164, 164, - 164, 181, 181, 181, 163, 163, 163, 163, - 163, 163, 176, 176, 176, 160, 160, 160, - 20, 19, 19, 19, 18, 18, 18, 17, - 184, 184, 184, 184, 164, 164, 164, 182, - 182, 181, 181, 181, 179, 163, 163, 163, - 163, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 19, 18, 18, 18, 17, 17, - 184, 184, 184, 184, 183, 183, 183, 182, - 182, 181, 181, 181, 179, 163, 163, 163, - 177, 176, 176, 176, 176, 160, 160, 160, - 160, 19, 18, 18, 18, 17, 17, 17, - 251, 184, 184, 184, 183, 183, 183, 182, - 180, 180, 181, 178, 178, 162, 163, 177, - 177, 176, 176, 176, 160, 160, 160, 160, - 160, 160, 18, 18, 17, 17, 17, 16, - 251, 251, 184, 184, 183, 183, 183, 180, - 180, 180, 180, 178, 178, 162, 162, 177, - 161, 176, 176, 176, 160, 160, 160, 160, - 160, 160, 18, 17, 17, 17, 16, 16, -}; +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: AlphaInverse.cpp + AUTHOR: John DiCamillo +*/ + +#include "stdafx.h" + +BYTE inverse_palette[32768] = { + 0, 47, 63, 63, 62, 62, 61, 61, + 61, 60, 60, 59, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 252, 252, 252, 252, 252, 252, 252, 252, + 47, 47, 63, 63, 62, 62, 61, 61, + 61, 60, 60, 59, 59, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 55, 252, 252, 252, 252, 252, 252, 252, + 47, 46, 63, 63, 62, 62, 61, 61, + 60, 60, 60, 59, 59, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 55, + 55, 252, 252, 252, 252, 252, 252, 252, + 46, 46, 46, 62, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 4, 4, + 4, 4, 4, 4, 4, 4, 55, 55, + 55, 54, 252, 252, 252, 252, 252, 252, + 46, 46, 45, 111, 111, 79, 79, 61, + 60, 60, 59, 59, 59, 58, 58, 57, + 4, 4, 4, 4, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 79, 79, + 60, 60, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 111, 78, + 78, 78, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 110, 78, + 78, 77, 77, 77, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 111, 110, 110, 110, 110, + 78, 77, 213, 213, 213, 213, 213, 213, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 110, 110, 110, 110, 110, 110, 109, + 109, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 110, 110, 110, 110, 110, 109, 109, 109, + 109, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 212, 6, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 2, 110, 110, 110, 109, 109, 109, 109, + 213, 213, 213, 213, 213, 213, 213, 213, + 213, 212, 6, 6, 6, 6, 6, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 2, 2, 2, 109, 109, 109, 109, 108, + 213, 213, 213, 213, 213, 213, 213, 213, + 212, 6, 6, 6, 6, 6, 6, 6, + 54, 54, 54, 54, 53, 53, 53, 53, + 2, 2, 2, 2, 108, 108, 108, 108, + 213, 213, 213, 213, 213, 213, 213, 212, + 6, 6, 6, 6, 6, 6, 6, 211, + 211, 211, 70, 53, 53, 53, 53, 53, + 2, 2, 2, 2, 2, 108, 108, 108, + 213, 213, 213, 213, 213, 213, 212, 6, + 6, 6, 6, 6, 6, 6, 211, 211, + 211, 211, 211, 70, 70, 70, 53, 53, + 2, 2, 2, 2, 2, 2, 107, 107, + 107, 213, 213, 213, 213, 212, 6, 6, + 6, 6, 6, 6, 6, 211, 211, 211, + 211, 211, 211, 210, 210, 70, 70, 70, + 2, 2, 2, 2, 2, 2, 107, 107, + 107, 213, 213, 213, 212, 6, 6, 6, + 6, 6, 6, 6, 211, 211, 211, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 2, 2, 2, 2, 2, 2, 107, 107, + 106, 106, 213, 212, 6, 6, 6, 6, + 6, 6, 6, 211, 211, 211, 211, 211, + 211, 210, 210, 210, 210, 210, 210, 209, + 2, 2, 2, 2, 2, 2, 106, 106, + 106, 106, 106, 6, 6, 6, 6, 6, + 6, 6, 211, 211, 211, 211, 211, 211, + 210, 210, 210, 210, 210, 210, 209, 209, + 2, 2, 2, 2, 2, 2, 105, 105, + 105, 105, 105, 6, 6, 6, 6, 6, + 6, 211, 211, 211, 211, 211, 211, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 2, 2, 2, 2, 2, 2, 105, 105, + 105, 105, 105, 6, 6, 6, 6, 6, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 2, 2, 2, 2, 105, 105, + 104, 104, 104, 6, 6, 6, 6, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 2, 2, 2, 2, 104, 104, 104, + 104, 104, 104, 103, 6, 6, 211, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 2, 2, 2, 2, 2, 104, 104, 104, + 104, 104, 103, 103, 103, 211, 211, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 209, + 250, 250, 250, 250, 250, 104, 104, 104, + 103, 103, 103, 103, 103, 211, 211, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 209, 208, + 250, 250, 250, 250, 250, 250, 102, 102, + 103, 103, 103, 103, 103, 103, 211, 211, + 211, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 103, 103, 103, 103, 211, 211, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 250, + 102, 102, 102, 103, 103, 103, 211, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 102, 102, 102, 103, 103, 103, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 102, 102, 102, 103, 103, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 254, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 102, 102, 102, 102, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 254, 254, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 102, 102, 102, 210, + 210, 209, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 254, 254, 254, 254, 254, + 47, 47, 63, 63, 62, 62, 61, 61, + 61, 60, 60, 59, 59, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 55, 252, 252, 252, 252, 252, 252, 252, + 47, 46, 63, 63, 62, 62, 61, 61, + 60, 60, 60, 59, 59, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 55, + 55, 252, 252, 252, 252, 252, 252, 252, + 46, 46, 46, 62, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 4, 4, + 4, 4, 4, 4, 4, 4, 55, 55, + 55, 54, 252, 252, 252, 252, 252, 252, + 46, 46, 45, 45, 62, 79, 61, 61, + 60, 60, 59, 59, 59, 58, 58, 57, + 4, 4, 4, 4, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 46, 45, 45, 45, 79, 79, 79, 79, + 60, 60, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 79, 79, 79, + 78, 60, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 79, 78, + 78, 78, 77, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 111, 111, 110, 110, 78, + 78, 77, 77, 77, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 110, 110, 110, 110, 110, + 77, 77, 77, 213, 213, 213, 213, 213, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 110, 110, 110, 110, 110, 110, 109, 109, + 109, 213, 213, 213, 213, 213, 213, 213, + 213, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 110, 110, 110, 110, 110, 109, 109, 109, + 109, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 212, 73, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 2, 110, 110, 109, 109, 109, 109, 109, + 108, 213, 213, 213, 213, 213, 213, 213, + 213, 212, 212, 212, 6, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 2, 2, 2, 109, 109, 109, 108, 108, + 108, 213, 213, 213, 213, 213, 213, 213, + 212, 212, 212, 6, 6, 6, 6, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 2, 2, 2, 2, 108, 108, 108, 108, + 108, 213, 213, 213, 213, 213, 213, 212, + 212, 212, 6, 6, 6, 6, 211, 211, + 211, 70, 70, 53, 53, 53, 53, 53, + 2, 2, 2, 2, 108, 108, 108, 107, + 107, 213, 213, 213, 213, 213, 212, 212, + 212, 6, 6, 6, 6, 211, 211, 211, + 211, 211, 70, 70, 70, 70, 53, 53, + 2, 2, 2, 2, 2, 107, 107, 107, + 107, 107, 213, 213, 213, 212, 212, 212, + 6, 6, 6, 6, 211, 211, 211, 211, + 211, 211, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 2, 107, 107, 107, + 107, 106, 213, 213, 212, 212, 212, 6, + 6, 6, 6, 211, 211, 211, 211, 211, + 211, 211, 210, 210, 210, 210, 70, 70, + 2, 2, 2, 2, 2, 107, 107, 106, + 106, 106, 106, 212, 212, 212, 6, 6, + 6, 6, 211, 211, 211, 211, 211, 211, + 211, 210, 210, 210, 210, 210, 210, 209, + 2, 2, 2, 2, 2, 2, 106, 106, + 106, 106, 106, 212, 212, 6, 6, 6, + 6, 211, 211, 211, 211, 211, 211, 211, + 210, 210, 210, 210, 210, 210, 209, 209, + 2, 2, 2, 2, 2, 105, 105, 105, + 105, 105, 105, 212, 6, 6, 6, 6, + 211, 211, 211, 211, 211, 211, 211, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 2, 2, 2, 2, 2, 105, 105, 105, + 105, 105, 105, 104, 6, 6, 6, 211, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 2, 2, 2, 105, 105, 104, + 104, 104, 104, 104, 6, 6, 211, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 2, 2, 2, 2, 104, 104, 104, + 104, 104, 104, 103, 103, 211, 211, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 2, 2, 2, 2, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 211, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 250, 250, 250, 250, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 211, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 211, 211, + 211, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 211, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 102, 103, 103, 103, 103, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 250, + 102, 102, 102, 102, 102, 103, 103, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 208, 208, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 102, 102, 102, 102, 102, 103, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 208, 208, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 102, 102, 102, 102, 102, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 208, 208, 254, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 102, 102, 102, 102, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 208, 208, 208, 208, 254, 254, 254, 254, + 47, 46, 63, 63, 62, 62, 61, 61, + 60, 60, 60, 59, 59, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 55, + 55, 252, 252, 252, 252, 252, 252, 252, + 46, 46, 46, 62, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 4, 4, + 4, 4, 4, 4, 4, 4, 55, 55, + 55, 54, 252, 252, 252, 252, 252, 252, + 46, 46, 45, 45, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 58, 57, + 4, 4, 4, 4, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 46, 45, 45, 45, 45, 79, 79, 61, + 60, 60, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 45, 45, 45, 45, 79, 79, 79, 79, + 60, 60, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 111, 111, 111, 111, 111, 79, 79, 78, + 78, 78, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 78, 78, + 78, 77, 77, 77, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 111, 111, 110, 110, 78, + 78, 77, 77, 77, 76, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 111, 111, 110, 110, 110, 110, 110, 109, + 77, 77, 77, 76, 76, 213, 75, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 110, 110, 110, 110, 110, 110, 109, 109, + 109, 77, 213, 213, 213, 213, 213, 213, + 75, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 110, 110, 110, 110, 109, 109, 109, 109, + 109, 213, 213, 213, 213, 213, 213, 213, + 213, 74, 73, 73, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 110, 110, 110, 109, 109, 109, 109, 109, + 108, 213, 213, 213, 213, 213, 213, 213, + 212, 212, 212, 73, 73, 73, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 2, 2, 109, 109, 109, 108, 108, 108, + 108, 213, 213, 213, 213, 213, 213, 212, + 212, 212, 212, 212, 73, 72, 72, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 2, 2, 2, 108, 108, 108, 108, 108, + 108, 213, 213, 213, 213, 213, 212, 212, + 212, 212, 212, 212, 212, 72, 72, 71, + 70, 70, 70, 53, 53, 53, 53, 53, + 2, 2, 2, 2, 108, 108, 107, 107, + 107, 107, 213, 213, 213, 212, 212, 212, + 212, 212, 212, 212, 6, 211, 211, 211, + 70, 70, 70, 70, 70, 70, 53, 53, + 2, 2, 2, 2, 107, 107, 107, 107, + 107, 107, 213, 213, 212, 212, 212, 212, + 212, 212, 212, 6, 211, 211, 211, 211, + 211, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 107, 107, 107, 107, + 106, 106, 106, 212, 212, 212, 212, 212, + 212, 212, 6, 211, 211, 211, 211, 211, + 211, 210, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 2, 107, 106, 106, + 106, 106, 106, 212, 212, 212, 212, 212, + 212, 6, 211, 211, 211, 211, 211, 211, + 210, 210, 210, 210, 210, 210, 70, 70, + 2, 2, 2, 2, 2, 105, 106, 106, + 106, 106, 106, 106, 212, 212, 212, 212, + 6, 211, 211, 211, 211, 211, 211, 210, + 210, 210, 210, 210, 210, 210, 209, 209, + 2, 2, 2, 2, 2, 105, 105, 105, + 105, 105, 105, 105, 212, 212, 212, 6, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 2, 2, 2, 2, 105, 105, 105, 105, + 105, 105, 104, 104, 212, 212, 6, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 2, 2, 105, 105, 104, 104, + 104, 104, 104, 104, 103, 6, 211, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 2, 2, 2, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 211, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 2, 2, 2, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 211, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 250, 250, 250, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 211, 211, + 211, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 211, + 210, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 210, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 102, 102, 103, 103, 103, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 102, 102, 102, 103, 103, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 250, + 102, 102, 102, 102, 102, 102, 103, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 208, 208, 208, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 102, 102, 102, 102, 102, 101, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 208, 208, 208, 254, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 102, 102, 102, 102, 101, 101, + 210, 209, 209, 209, 209, 209, 209, 208, + 208, 208, 208, 208, 208, 254, 254, 254, + 247, 46, 46, 62, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 4, 4, + 4, 4, 4, 4, 4, 4, 55, 55, + 55, 54, 252, 252, 252, 252, 252, 252, + 46, 46, 45, 45, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 58, 57, + 4, 4, 4, 4, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 46, 45, 45, 45, 45, 61, 61, 61, + 60, 60, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 45, 45, 45, 45, 95, 79, 79, 60, + 60, 60, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 45, 45, 45, 127, 95, 79, 79, 78, + 78, 59, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 45, 127, 127, 127, 127, 79, 78, 78, + 78, 78, 59, 59, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 111, 111, 111, 111, 111, 111, 78, 78, + 78, 77, 77, 77, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 111, 111, 111, 111, 110, 110, 78, 78, + 77, 77, 77, 77, 76, 76, 57, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 111, 110, 110, 110, 110, 110, 110, 109, + 77, 77, 77, 76, 76, 75, 75, 75, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 110, 110, 110, 110, 110, 109, 109, 109, + 109, 77, 76, 76, 76, 75, 75, 75, + 74, 74, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 110, 110, 110, 110, 109, 109, 109, 109, + 109, 76, 213, 213, 213, 213, 213, 74, + 74, 73, 73, 73, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 110, 110, 109, 109, 109, 109, 109, 108, + 108, 108, 213, 213, 213, 213, 213, 213, + 74, 73, 73, 73, 73, 73, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 2, 109, 109, 109, 109, 108, 108, 108, + 108, 108, 213, 213, 213, 213, 213, 212, + 212, 212, 73, 73, 73, 72, 72, 72, + 54, 53, 53, 53, 53, 53, 53, 53, + 2, 2, 108, 108, 108, 108, 108, 108, + 107, 107, 213, 213, 213, 213, 212, 212, + 212, 212, 212, 73, 72, 72, 72, 71, + 70, 70, 70, 53, 53, 53, 53, 53, + 2, 2, 2, 108, 108, 108, 107, 107, + 107, 107, 213, 213, 213, 212, 212, 212, + 212, 212, 212, 212, 211, 72, 71, 70, + 70, 70, 70, 70, 70, 70, 53, 53, + 2, 2, 2, 2, 107, 107, 107, 107, + 107, 106, 106, 213, 212, 212, 212, 212, + 212, 212, 212, 211, 211, 211, 211, 211, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 107, 107, 107, 106, + 106, 106, 106, 106, 212, 212, 212, 212, + 212, 212, 211, 211, 211, 211, 211, 211, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 107, 106, 106, 106, + 106, 106, 106, 106, 212, 212, 212, 212, + 212, 211, 211, 211, 211, 211, 211, 211, + 210, 210, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 2, 105, 105, 105, 105, + 105, 105, 105, 106, 212, 212, 212, 212, + 211, 211, 211, 211, 211, 211, 211, 210, + 210, 210, 210, 210, 210, 210, 209, 209, + 2, 2, 2, 2, 105, 105, 105, 105, + 105, 105, 105, 105, 212, 212, 212, 211, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 2, 2, 2, 2, 105, 105, 105, 105, + 104, 104, 104, 104, 104, 212, 211, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 2, 105, 104, 104, 104, 104, + 104, 104, 104, 103, 103, 103, 211, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 2, 2, 104, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 211, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 2, 2, 102, 102, 102, 104, 104, 104, + 103, 103, 103, 103, 103, 103, 103, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 211, + 211, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 250, 250, 102, 102, 102, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 211, + 210, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 102, 102, 102, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 102, 102, 102, 103, 103, 103, + 210, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 102, 102, 102, 102, 101, 101, + 210, 210, 210, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 250, 250, 250, + 102, 102, 102, 102, 102, 101, 101, 101, + 210, 210, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 208, 208, 208, 208, 254, + 250, 250, 250, 250, 250, 250, 250, 250, + 250, 102, 102, 102, 102, 101, 101, 101, + 210, 209, 209, 209, 209, 209, 209, 208, + 208, 208, 208, 208, 208, 208, 254, 254, + 247, 247, 247, 247, 62, 62, 61, 61, + 60, 60, 59, 59, 59, 58, 58, 57, + 4, 4, 4, 4, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 247, 247, 247, 45, 45, 61, 61, 61, + 60, 60, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 247, 247, 45, 45, 44, 95, 61, 60, + 60, 60, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 247, 45, 45, 44, 44, 95, 79, 60, + 60, 59, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 45, 143, 143, 127, 44, 95, 79, 78, + 78, 59, 59, 59, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 159, 159, 159, 127, 127, 95, 94, 78, + 78, 77, 77, 58, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 159, 159, 159, 127, 126, 126, 94, 78, + 77, 77, 77, 77, 58, 58, 57, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 111, 111, 111, 110, 126, 126, 94, 78, + 77, 77, 77, 76, 76, 76, 75, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 110, 110, 110, 110, 110, 110, 109, 77, + 77, 77, 76, 76, 76, 75, 75, 75, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 110, 110, 110, 110, 110, 109, 109, 109, + 77, 76, 76, 76, 75, 75, 75, 75, + 74, 74, 73, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 110, 110, 110, 109, 109, 109, 109, 109, + 108, 76, 76, 76, 75, 75, 75, 74, + 74, 73, 73, 73, 73, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 110, 109, 109, 109, 109, 109, 108, 108, + 108, 108, 213, 213, 213, 75, 74, 74, + 74, 73, 73, 73, 73, 72, 72, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 2, 109, 109, 109, 108, 108, 108, 108, + 108, 108, 213, 213, 213, 213, 74, 74, + 73, 73, 73, 73, 72, 72, 72, 71, + 53, 53, 53, 53, 53, 53, 53, 53, + 2, 2, 108, 108, 108, 108, 108, 107, + 107, 107, 213, 213, 213, 213, 212, 212, + 212, 73, 73, 73, 72, 72, 72, 71, + 70, 70, 70, 53, 53, 53, 53, 53, + 2, 2, 108, 108, 108, 107, 107, 107, + 107, 107, 107, 213, 213, 212, 212, 212, + 212, 212, 212, 72, 72, 72, 71, 70, + 70, 70, 70, 70, 70, 70, 53, 53, + 2, 2, 2, 107, 107, 107, 107, 107, + 107, 106, 106, 106, 212, 212, 212, 212, + 212, 212, 212, 211, 211, 71, 71, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 107, 107, 107, 107, 106, + 106, 106, 106, 106, 212, 212, 212, 212, + 212, 212, 211, 211, 211, 211, 211, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 107, 107, 106, 106, 106, + 106, 106, 106, 106, 212, 212, 212, 212, + 212, 211, 211, 211, 211, 211, 211, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 212, 212, 212, + 211, 211, 211, 211, 211, 211, 211, 210, + 210, 210, 210, 70, 70, 70, 70, 70, + 2, 2, 2, 105, 105, 105, 105, 105, + 105, 105, 105, 104, 104, 212, 212, 211, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 210, 210, 209, 209, 209, + 2, 2, 2, 105, 105, 105, 105, 104, + 104, 104, 104, 104, 103, 103, 211, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 2, 104, 104, 104, 104, 104, + 104, 104, 104, 103, 103, 103, 211, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 2, 104, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 103, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 2, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 211, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 250, 102, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 211, + 211, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 250, 102, 102, 102, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 208, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 103, 103, 103, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 208, 208, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 102, 102, 102, 102, 101, 101, 101, + 210, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 208, 208, 207, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 102, 102, 102, 101, 101, 101, + 210, 210, 210, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 208, 208, 207, 207, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 102, 102, 101, 101, 101, 101, + 210, 210, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 208, 208, 207, 207, 207, + 250, 250, 250, 250, 250, 250, 250, 250, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 209, 209, 209, 209, 209, 209, 208, + 208, 208, 208, 208, 207, 207, 207, 207, + 247, 247, 247, 247, 247, 223, 223, 223, + 223, 223, 59, 59, 58, 58, 58, 57, + 57, 56, 56, 56, 56, 55, 55, 55, + 54, 54, 54, 252, 252, 252, 252, 252, + 247, 247, 247, 247, 44, 223, 223, 223, + 223, 223, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 247, 247, 247, 143, 143, 44, 223, 223, + 223, 59, 59, 59, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 247, 247, 143, 143, 143, 95, 95, 78, + 60, 59, 59, 59, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 143, 143, 143, 143, 143, 43, 43, 94, + 78, 77, 59, 58, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 159, 159, 159, 159, 159, 43, 94, 94, + 78, 77, 77, 77, 58, 58, 57, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 159, 159, 159, 159, 126, 126, 94, 93, + 77, 77, 77, 76, 76, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 159, 159, 159, 126, 126, 126, 94, 93, + 77, 77, 76, 76, 76, 75, 75, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 110, 110, 110, 126, 126, 125, 125, 93, + 77, 77, 76, 76, 76, 75, 75, 75, + 74, 56, 56, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 110, 110, 110, 110, 109, 109, 125, 125, + 92, 76, 76, 76, 75, 75, 75, 74, + 74, 74, 73, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 110, 110, 109, 109, 109, 109, 109, 109, + 108, 76, 76, 76, 75, 75, 75, 74, + 74, 73, 73, 73, 73, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 110, 109, 109, 109, 109, 108, 108, 108, + 108, 108, 76, 75, 75, 75, 74, 74, + 74, 73, 73, 73, 73, 72, 72, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 109, 109, 109, 108, 108, 108, 108, 108, + 108, 107, 107, 75, 75, 74, 74, 74, + 73, 73, 73, 73, 72, 72, 72, 71, + 53, 53, 53, 53, 53, 53, 53, 53, + 2, 108, 108, 108, 108, 108, 108, 107, + 107, 107, 107, 213, 213, 74, 74, 74, + 73, 73, 73, 72, 72, 72, 71, 71, + 70, 70, 70, 53, 53, 53, 53, 53, + 2, 2, 108, 108, 107, 107, 107, 107, + 107, 107, 106, 106, 213, 212, 212, 212, + 73, 73, 73, 72, 72, 72, 71, 70, + 70, 70, 70, 70, 70, 70, 52, 52, + 2, 2, 107, 107, 107, 107, 107, 107, + 106, 106, 106, 106, 106, 212, 212, 212, + 212, 212, 72, 72, 72, 71, 71, 70, + 70, 70, 70, 70, 70, 70, 70, 52, + 2, 2, 2, 107, 107, 107, 106, 106, + 106, 106, 106, 106, 106, 212, 212, 212, + 212, 212, 211, 211, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 107, 105, 105, 106, 106, + 106, 106, 106, 106, 106, 212, 212, 212, + 212, 211, 211, 211, 211, 211, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 2, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 212, 212, 212, + 211, 211, 211, 211, 211, 211, 211, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 105, 105, 105, 105, 105, 105, + 105, 105, 104, 104, 104, 103, 212, 211, + 211, 211, 211, 211, 211, 211, 210, 210, + 210, 210, 210, 70, 70, 70, 209, 209, + 2, 2, 105, 105, 105, 105, 104, 104, + 104, 104, 104, 104, 103, 103, 103, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 2, 104, 104, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 103, 211, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 2, 102, 104, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 103, 211, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 103, + 211, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 208, + 250, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 208, 208, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 103, 103, 103, 103, + 210, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 208, 208, 207, + 250, 250, 250, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 101, 101, 101, 101, + 210, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 208, 208, 207, 207, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 210, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 208, 208, 207, 207, 207, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 102, 102, 102, 101, 101, 101, 101, + 100, 210, 210, 209, 209, 209, 209, 209, + 209, 208, 208, 208, 207, 207, 207, 207, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 210, 209, 209, 209, 209, 209, 209, + 208, 208, 208, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 250, 250, 250, 102, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 209, 209, 209, 209, 209, 209, 208, + 208, 208, 207, 207, 207, 207, 207, 207, + 246, 246, 246, 246, 223, 223, 223, 223, + 223, 223, 223, 222, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 252, 252, 252, 252, + 246, 246, 246, 246, 223, 223, 223, 223, + 223, 223, 223, 222, 58, 58, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 246, 246, 246, 143, 143, 223, 223, 223, + 223, 223, 223, 59, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 246, 246, 143, 143, 143, 143, 43, 223, + 223, 223, 59, 58, 58, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 246, 143, 143, 143, 142, 43, 43, 94, + 15, 15, 77, 58, 58, 58, 57, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 159, 159, 159, 142, 142, 43, 43, 15, + 15, 77, 77, 76, 58, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 159, 159, 158, 158, 158, 158, 42, 93, + 93, 77, 77, 76, 76, 76, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 159, 158, 158, 158, 158, 125, 125, 93, + 93, 77, 76, 76, 76, 75, 75, 75, + 56, 56, 56, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 158, 158, 158, 158, 125, 125, 125, 125, + 92, 92, 76, 76, 75, 75, 75, 75, + 74, 74, 55, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 158, 158, 158, 125, 125, 125, 125, 124, + 92, 92, 76, 76, 75, 75, 75, 74, + 74, 74, 73, 73, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 110, 110, 109, 109, 109, 125, 124, 124, + 92, 92, 76, 75, 75, 75, 74, 74, + 74, 73, 73, 73, 73, 72, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 109, 109, 109, 109, 109, 108, 108, 108, + 124, 123, 91, 75, 75, 75, 74, 74, + 74, 73, 73, 73, 72, 72, 72, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 109, 109, 108, 108, 108, 108, 108, 108, + 107, 107, 91, 75, 75, 74, 74, 74, + 73, 73, 73, 72, 72, 72, 72, 71, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 108, 108, 108, 108, 108, 107, 107, + 107, 107, 107, 75, 74, 74, 74, 73, + 73, 73, 73, 72, 72, 72, 71, 71, + 70, 70, 70, 53, 53, 52, 52, 52, + 2, 108, 108, 107, 107, 107, 107, 107, + 107, 106, 106, 106, 74, 74, 74, 73, + 73, 73, 72, 72, 72, 71, 71, 70, + 70, 70, 70, 70, 70, 52, 52, 52, + 2, 2, 107, 107, 107, 107, 107, 106, + 106, 106, 106, 106, 106, 212, 212, 73, + 73, 72, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 70, 70, 70, 70, 52, + 2, 2, 107, 107, 107, 106, 106, 106, + 106, 106, 106, 106, 106, 212, 212, 212, + 212, 72, 72, 72, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 106, 106, 212, 212, 212, + 212, 211, 211, 71, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 2, 2, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 104, 212, 212, + 211, 211, 211, 211, 211, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 68, + 2, 2, 105, 105, 105, 105, 105, 105, + 105, 104, 104, 104, 104, 103, 103, 211, + 211, 211, 211, 211, 211, 211, 210, 70, + 70, 70, 70, 70, 70, 70, 68, 68, + 2, 105, 105, 105, 105, 104, 104, 104, + 104, 104, 104, 103, 103, 103, 103, 211, + 211, 211, 211, 211, 211, 210, 210, 210, + 210, 210, 210, 210, 209, 209, 209, 209, + 2, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 103, 103, + 211, 211, 211, 211, 210, 210, 210, 210, + 210, 210, 210, 209, 209, 209, 209, 209, + 102, 102, 102, 102, 102, 104, 104, 104, + 103, 103, 103, 103, 103, 103, 103, 103, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 209, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 103, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 209, 208, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 103, + 103, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 209, 208, 207, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 103, + 103, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 209, 208, 207, 207, + 250, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 101, 101, 101, 101, + 100, 210, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 209, 208, 207, 207, 207, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 210, 210, 210, 210, 209, 209, 209, + 209, 209, 209, 208, 207, 207, 207, 207, + 250, 250, 250, 102, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 100, 210, 210, 209, 209, 209, 209, + 209, 209, 208, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 100, + 100, 100, 210, 209, 209, 209, 209, 209, + 209, 208, 207, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 209, 209, 209, 209, 209, 209, + 208, 207, 207, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 250, 250, 102, 102, + 102, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 209, 209, 209, 209, 209, 208, + 207, 207, 207, 207, 207, 207, 207, 207, + 246, 246, 246, 246, 223, 223, 223, 223, + 223, 223, 222, 222, 222, 222, 57, 57, + 57, 56, 56, 56, 55, 55, 55, 55, + 54, 54, 54, 54, 54, 252, 252, 252, + 246, 246, 246, 246, 223, 223, 223, 223, + 223, 223, 222, 222, 222, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 246, 246, 246, 246, 143, 223, 223, 223, + 223, 223, 222, 222, 222, 58, 57, 57, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 246, 246, 246, 143, 142, 142, 223, 223, + 223, 222, 222, 222, 58, 58, 57, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 246, 143, 143, 142, 142, 142, 43, 15, + 15, 15, 222, 222, 58, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 159, 159, 142, 142, 142, 142, 15, 15, + 15, 15, 15, 76, 76, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 159, 158, 158, 158, 158, 158, 42, 15, + 15, 15, 92, 76, 76, 75, 75, 56, + 56, 56, 56, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 158, 158, 158, 158, 158, 141, 42, 42, + 41, 92, 92, 76, 76, 75, 75, 75, + 56, 56, 55, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 158, 158, 158, 158, 157, 125, 125, 41, + 92, 92, 92, 76, 75, 75, 75, 74, + 74, 74, 55, 55, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 158, 158, 158, 157, 157, 125, 124, 124, + 92, 92, 91, 91, 75, 75, 75, 74, + 74, 74, 73, 73, 55, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 157, 157, 157, 124, 124, 124, 124, + 124, 92, 91, 91, 75, 75, 74, 74, + 74, 73, 73, 73, 72, 72, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 157, 124, 124, 124, 124, 124, + 123, 123, 91, 91, 75, 74, 74, 74, + 73, 73, 73, 73, 72, 72, 72, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 108, 108, 108, 108, 108, 123, + 123, 123, 123, 90, 90, 74, 74, 74, + 73, 73, 73, 72, 72, 72, 71, 71, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 108, 108, 108, 107, 107, 107, + 107, 123, 122, 90, 90, 74, 74, 73, + 73, 73, 72, 72, 72, 71, 71, 71, + 70, 70, 70, 52, 52, 52, 52, 52, + 191, 191, 107, 107, 107, 107, 107, 107, + 106, 106, 106, 106, 90, 74, 74, 73, + 73, 73, 72, 72, 72, 71, 71, 70, + 70, 70, 70, 70, 52, 52, 52, 52, + 191, 191, 107, 107, 107, 107, 106, 106, + 106, 106, 106, 106, 106, 74, 73, 73, + 73, 72, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 70, 70, 70, 52, 52, + 191, 191, 107, 107, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 73, 73, + 72, 72, 72, 71, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 51, + 2, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 212, 212, + 72, 72, 72, 71, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 68, + 2, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 104, 104, 104, 212, 212, + 211, 211, 71, 71, 71, 70, 70, 70, + 70, 70, 70, 70, 70, 68, 68, 68, + 2, 105, 105, 105, 105, 105, 105, 104, + 104, 104, 104, 104, 103, 103, 103, 211, + 211, 211, 211, 211, 211, 70, 70, 70, + 70, 70, 70, 70, 68, 68, 68, 68, + 2, 105, 105, 104, 104, 104, 104, 104, + 104, 104, 104, 103, 103, 103, 103, 103, + 211, 211, 211, 211, 210, 210, 210, 70, + 70, 70, 69, 68, 68, 68, 68, 68, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 103, 103, + 211, 211, 211, 210, 210, 210, 210, 210, + 210, 210, 210, 68, 68, 209, 209, 209, + 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, + 211, 211, 210, 210, 210, 210, 210, 210, + 210, 210, 209, 209, 209, 209, 209, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 103, + 103, 210, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 209, 209, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 103, + 100, 210, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 209, 209, 206, 206, 207, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 100, + 100, 210, 210, 210, 210, 210, 210, 209, + 209, 209, 209, 209, 206, 206, 207, 207, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 100, + 100, 100, 210, 210, 210, 210, 209, 209, + 209, 209, 209, 206, 206, 207, 207, 207, + 250, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 210, 210, 210, 209, 209, 209, + 209, 209, 206, 206, 207, 207, 207, 207, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 210, 210, 209, 209, 209, 209, + 209, 206, 206, 207, 207, 207, 207, 207, + 250, 250, 250, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 209, 209, 209, 209, 209, + 206, 206, 207, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 101, 100, 100, + 100, 100, 98, 209, 209, 209, 209, 206, + 206, 207, 207, 207, 207, 207, 207, 207, + 250, 250, 250, 250, 250, 102, 102, 102, + 102, 101, 101, 101, 101, 101, 100, 100, + 100, 98, 98, 209, 209, 209, 206, 206, + 207, 207, 207, 207, 207, 207, 207, 207, + 245, 245, 245, 245, 223, 223, 223, 223, + 223, 222, 222, 222, 222, 222, 221, 221, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 252, 252, 252, + 245, 245, 245, 245, 223, 223, 223, 223, + 223, 222, 222, 222, 222, 222, 221, 221, + 56, 56, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 245, 245, 245, 245, 223, 223, 223, 223, + 223, 222, 222, 222, 222, 221, 221, 57, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 245, 245, 245, 142, 142, 142, 223, 223, + 222, 222, 222, 222, 222, 221, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 245, 245, 142, 142, 142, 142, 15, 15, + 15, 222, 222, 222, 222, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 245, 142, 142, 142, 142, 141, 141, 15, + 15, 15, 15, 76, 76, 57, 57, 56, + 56, 56, 56, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 158, 158, 158, 158, 141, 141, 141, 15, + 15, 41, 92, 92, 76, 75, 75, 56, + 56, 56, 55, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 158, 158, 158, 158, 141, 141, 141, 41, + 41, 92, 92, 91, 91, 75, 75, 75, + 74, 56, 55, 55, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 158, 158, 157, 157, 157, 157, 157, 41, + 41, 92, 91, 91, 91, 75, 75, 74, + 74, 74, 73, 55, 55, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 158, 157, 157, 157, 157, 157, 124, 124, + 40, 40, 91, 91, 91, 75, 74, 74, + 74, 74, 73, 73, 55, 54, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 157, 157, 157, 124, 124, 124, + 123, 123, 91, 91, 90, 90, 74, 74, + 74, 73, 73, 73, 72, 72, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 191, 124, 124, 124, 124, 123, + 123, 123, 91, 90, 90, 90, 74, 74, + 73, 73, 73, 72, 72, 72, 72, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 191, 191, 124, 124, 123, 123, + 123, 123, 122, 90, 90, 90, 74, 74, + 73, 73, 73, 72, 72, 72, 71, 71, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 107, 107, 123, 123, + 122, 122, 122, 122, 90, 89, 74, 73, + 73, 73, 72, 72, 72, 71, 71, 71, + 70, 70, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 107, 107, 107, 107, + 122, 122, 122, 121, 89, 89, 89, 73, + 73, 72, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 70, 52, 52, 52, 52, + 191, 191, 191, 107, 107, 107, 106, 106, + 106, 106, 121, 121, 121, 89, 89, 73, + 73, 72, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 70, 70, 52, 51, 51, + 191, 191, 191, 105, 105, 105, 106, 106, + 106, 106, 106, 121, 121, 121, 88, 88, + 72, 72, 72, 71, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 70, 51, 51, + 191, 191, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 120, 88, 88, + 72, 72, 71, 71, 71, 71, 70, 70, + 70, 70, 70, 70, 70, 68, 68, 68, + 191, 191, 105, 105, 105, 105, 105, 105, + 105, 105, 104, 104, 104, 104, 120, 87, + 72, 71, 71, 71, 71, 70, 70, 70, + 70, 70, 70, 69, 68, 68, 68, 68, + 191, 105, 105, 105, 105, 105, 104, 104, + 104, 104, 104, 104, 103, 103, 103, 103, + 211, 211, 71, 71, 70, 70, 70, 70, + 70, 69, 69, 68, 68, 68, 68, 68, + 105, 105, 104, 104, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 103, 103, + 211, 211, 211, 211, 70, 70, 70, 69, + 69, 69, 68, 68, 68, 68, 68, 68, + 102, 102, 104, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 103, 103, + 103, 211, 211, 210, 210, 210, 210, 69, + 69, 68, 68, 68, 68, 68, 68, 68, + 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, + 103, 211, 210, 210, 210, 210, 210, 210, + 210, 68, 68, 68, 68, 68, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 103, 103, 103, 103, 103, 100, + 100, 100, 210, 210, 210, 210, 210, 210, + 210, 209, 209, 209, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 101, 101, 101, 101, 100, + 100, 100, 210, 210, 210, 210, 210, 210, + 209, 209, 209, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 100, 100, + 100, 100, 210, 210, 210, 210, 210, 209, + 209, 209, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 210, 210, 210, 209, 209, + 209, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 210, 210, 209, 209, 209, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 98, 209, 209, 209, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 250, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 98, 98, 209, 209, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 250, 250, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 101, 100, 100, 100, + 100, 98, 98, 98, 209, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 250, 250, 250, 102, 102, 102, 102, + 101, 101, 101, 101, 101, 100, 100, 100, + 98, 98, 98, 98, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 245, 245, 245, 245, 245, 223, 223, 223, + 222, 222, 222, 222, 222, 221, 221, 221, + 221, 221, 56, 56, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 252, 252, + 245, 245, 245, 245, 245, 223, 223, 223, + 222, 222, 222, 222, 222, 221, 221, 221, + 221, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 245, 245, 245, 245, 245, 223, 223, 223, + 222, 222, 222, 222, 221, 221, 221, 221, + 221, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 245, 245, 245, 245, 142, 223, 223, 222, + 222, 222, 222, 222, 221, 221, 221, 221, + 56, 56, 56, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 245, 245, 245, 142, 142, 141, 141, 15, + 222, 222, 222, 222, 221, 221, 221, 56, + 56, 56, 56, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 245, 142, 142, 142, 141, 141, 141, 15, + 15, 15, 222, 222, 221, 221, 221, 56, + 56, 56, 55, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 158, 158, 158, 141, 141, 141, 141, 141, + 41, 41, 40, 91, 91, 91, 75, 75, + 56, 56, 55, 55, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 158, 158, 141, 141, 141, 141, 141, 140, + 41, 40, 40, 91, 91, 91, 75, 74, + 74, 74, 55, 55, 55, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 158, 157, 157, 157, 157, 157, 140, 140, + 40, 40, 91, 91, 91, 90, 90, 74, + 74, 74, 73, 55, 55, 54, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 157, 157, 157, 156, 156, 156, + 40, 40, 91, 91, 90, 90, 90, 74, + 74, 73, 73, 73, 72, 54, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 191, 156, 156, 156, 156, 123, + 123, 39, 39, 90, 90, 90, 90, 74, + 74, 73, 73, 72, 72, 72, 53, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 191, 191, 156, 156, 123, 123, + 123, 123, 38, 90, 90, 90, 89, 74, + 73, 73, 73, 72, 72, 72, 71, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 156, 123, 123, 123, + 123, 122, 122, 90, 90, 89, 89, 89, + 73, 73, 72, 72, 72, 71, 71, 71, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 191, 123, 123, 122, + 122, 122, 122, 122, 89, 89, 89, 88, + 73, 72, 72, 72, 72, 71, 71, 71, + 70, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 191, 122, 122, 122, + 122, 122, 121, 121, 89, 89, 89, 88, + 88, 72, 72, 72, 71, 71, 71, 70, + 70, 70, 70, 52, 52, 52, 51, 51, + 191, 191, 191, 191, 191, 106, 106, 121, + 121, 121, 121, 121, 121, 89, 88, 88, + 88, 72, 72, 71, 71, 71, 71, 70, + 70, 70, 70, 70, 51, 51, 51, 51, + 191, 191, 191, 191, 105, 105, 105, 105, + 121, 121, 121, 121, 121, 120, 88, 88, + 88, 72, 71, 71, 71, 71, 70, 70, + 70, 70, 70, 69, 69, 51, 51, 51, + 191, 191, 191, 105, 105, 105, 105, 105, + 105, 105, 121, 120, 120, 120, 88, 88, + 87, 72, 71, 71, 71, 71, 70, 70, + 70, 69, 69, 69, 68, 68, 68, 68, + 191, 190, 190, 105, 105, 105, 105, 105, + 105, 104, 104, 104, 120, 120, 120, 87, + 87, 87, 71, 71, 71, 70, 70, 69, + 69, 69, 69, 68, 68, 68, 68, 68, + 190, 190, 105, 105, 105, 104, 104, 104, + 104, 104, 104, 103, 103, 103, 103, 87, + 87, 87, 71, 71, 70, 69, 69, 69, + 69, 69, 68, 68, 68, 68, 68, 68, + 190, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 103, 103, 103, 103, 103, 103, + 87, 86, 71, 71, 69, 69, 69, 69, + 69, 68, 68, 68, 68, 68, 68, 68, + 102, 102, 102, 102, 102, 102, 104, 104, + 103, 103, 103, 103, 103, 103, 103, 103, + 100, 211, 211, 69, 69, 69, 69, 69, + 68, 68, 68, 68, 68, 68, 68, 68, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 100, + 100, 100, 210, 210, 210, 69, 69, 68, + 68, 68, 68, 68, 68, 68, 68, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 210, 210, 210, 210, 68, + 68, 68, 68, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 101, 101, 101, 101, 100, 100, + 100, 100, 99, 210, 210, 210, 210, 210, + 209, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 100, 99, 99, 210, 210, 210, 209, + 206, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 99, 99, 210, 210, 209, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 99, 99, 98, 209, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 250, 250, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 101, 100, 100, 100, 100, + 98, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 205, + 250, 250, 250, 102, 102, 102, 102, 101, + 101, 101, 101, 101, 100, 100, 100, 98, + 98, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 205, 205, + 244, 244, 244, 244, 244, 223, 223, 222, + 222, 222, 222, 222, 221, 221, 221, 221, + 221, 220, 220, 5, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 54, 53, 252, + 244, 244, 244, 244, 244, 223, 223, 222, + 222, 222, 222, 222, 221, 221, 221, 221, + 220, 220, 220, 220, 55, 55, 55, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 244, 244, 244, 244, 244, 223, 223, 222, + 222, 222, 222, 221, 221, 221, 221, 221, + 220, 220, 220, 55, 55, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 244, 244, 244, 244, 244, 141, 222, 222, + 222, 222, 222, 221, 221, 221, 221, 221, + 220, 220, 220, 55, 55, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 244, 244, 244, 141, 141, 141, 141, 222, + 222, 222, 222, 221, 221, 221, 221, 221, + 220, 220, 55, 55, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 244, 244, 141, 141, 141, 141, 141, 141, + 15, 222, 222, 221, 221, 221, 221, 221, + 220, 56, 55, 55, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 244, 141, 141, 141, 141, 141, 140, 140, + 140, 40, 40, 91, 91, 91, 90, 90, + 56, 56, 55, 55, 55, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 158, 141, 141, 141, 141, 140, 140, 140, + 140, 40, 40, 91, 91, 90, 90, 90, + 74, 74, 55, 55, 55, 54, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 157, 157, 140, 140, 140, 140, + 40, 40, 39, 39, 90, 90, 90, 90, + 74, 74, 73, 55, 55, 54, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 191, 156, 156, 156, 156, 156, + 139, 39, 39, 38, 90, 90, 90, 90, + 74, 73, 73, 73, 72, 53, 53, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 191, 156, 156, 156, 156, 155, + 123, 39, 38, 38, 90, 90, 90, 89, + 88, 73, 73, 72, 72, 72, 53, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 156, 156, 155, 155, + 123, 122, 38, 90, 90, 89, 89, 89, + 88, 73, 72, 72, 72, 72, 71, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 191, 155, 155, 155, + 122, 122, 122, 37, 89, 89, 89, 88, + 88, 88, 72, 72, 72, 71, 71, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 191, 155, 155, 122, + 122, 122, 122, 121, 89, 89, 89, 88, + 88, 88, 72, 72, 71, 71, 71, 71, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 191, 191, 191, 155, 122, 122, + 122, 121, 121, 121, 121, 89, 88, 88, + 88, 88, 72, 72, 71, 71, 71, 70, + 70, 70, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 122, 121, 121, + 121, 121, 121, 121, 121, 89, 88, 88, + 88, 87, 72, 71, 71, 71, 71, 70, + 70, 70, 69, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 105, 121, 121, + 121, 121, 121, 120, 120, 120, 88, 88, + 87, 87, 87, 71, 71, 71, 70, 70, + 69, 69, 69, 69, 68, 51, 51, 50, + 191, 190, 190, 190, 105, 105, 105, 105, + 121, 121, 120, 120, 120, 120, 120, 87, + 87, 87, 87, 71, 71, 70, 69, 69, + 69, 69, 69, 68, 68, 68, 68, 50, + 190, 190, 190, 190, 105, 105, 105, 105, + 104, 104, 120, 120, 120, 120, 119, 87, + 87, 87, 86, 71, 71, 69, 69, 69, + 69, 69, 68, 68, 68, 68, 68, 68, + 190, 190, 190, 105, 104, 104, 104, 104, + 104, 104, 104, 103, 120, 119, 119, 119, + 87, 86, 86, 71, 69, 69, 69, 69, + 69, 68, 68, 68, 68, 68, 68, 68, + 3, 190, 190, 104, 104, 104, 104, 104, + 104, 103, 103, 103, 103, 103, 118, 118, + 118, 86, 86, 69, 69, 69, 69, 69, + 68, 68, 68, 68, 68, 68, 68, 68, + 3, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 100, 100, + 118, 86, 86, 69, 69, 69, 69, 68, + 68, 68, 68, 68, 68, 68, 68, 68, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 100, 99, 69, 69, 69, 68, 68, + 68, 68, 68, 68, 68, 68, 67, 67, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 99, 99, 69, 68, 68, 68, + 68, 68, 68, 68, 67, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 100, 100, + 100, 99, 99, 99, 210, 210, 68, 68, + 68, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 100, 99, 99, 99, 99, 210, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 99, 99, 99, 99, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 205, + 102, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 99, 99, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 205, 205, + 102, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 206, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 98, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 206, 205, 205, 205, 205, + 250, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 101, 100, 100, 100, 100, 98, + 98, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 206, 205, 205, 205, 205, 205, + 250, 250, 102, 102, 102, 102, 101, 101, + 101, 101, 101, 100, 100, 100, 98, 98, + 98, 98, 98, 98, 98, 206, 206, 206, + 206, 206, 205, 205, 205, 205, 205, 205, + 243, 243, 243, 244, 244, 244, 222, 222, + 222, 222, 222, 221, 221, 221, 221, 221, + 220, 220, 5, 5, 5, 5, 5, 54, + 54, 54, 54, 54, 54, 53, 53, 53, + 243, 243, 244, 244, 244, 223, 222, 222, + 222, 222, 222, 221, 221, 221, 221, 220, + 220, 220, 220, 5, 5, 55, 55, 54, + 54, 54, 54, 54, 53, 53, 53, 53, + 243, 244, 244, 244, 244, 223, 222, 222, + 222, 222, 221, 221, 221, 221, 221, 220, + 220, 220, 220, 220, 219, 55, 54, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 244, 244, 244, 244, 244, 141, 222, 222, + 222, 222, 221, 221, 221, 221, 221, 220, + 220, 220, 220, 220, 55, 55, 54, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 244, 244, 244, 244, 141, 141, 141, 222, + 222, 222, 221, 221, 221, 221, 221, 220, + 220, 220, 220, 55, 55, 55, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 244, 244, 244, 141, 141, 141, 140, 140, + 140, 222, 221, 221, 221, 221, 221, 220, + 220, 220, 220, 55, 55, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 244, 141, 141, 141, 140, 140, 140, 140, + 140, 40, 40, 39, 221, 221, 221, 220, + 220, 220, 55, 55, 55, 54, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 201, 201, 201, 140, 140, 140, 140, + 139, 139, 39, 39, 38, 90, 14, 14, + 14, 14, 55, 55, 55, 54, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 191, 201, 201, 140, 140, 140, 139, + 139, 139, 39, 38, 38, 90, 14, 14, + 14, 14, 73, 73, 55, 53, 53, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 191, 201, 156, 156, 139, 139, + 139, 39, 38, 38, 90, 14, 14, 14, + 14, 88, 88, 72, 72, 53, 53, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 156, 156, 155, 155, + 155, 38, 38, 38, 90, 14, 14, 14, + 88, 88, 88, 72, 72, 72, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 155, 155, 155, 155, + 155, 122, 38, 37, 37, 89, 89, 88, + 88, 88, 88, 72, 72, 71, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 191, 155, 155, 155, + 122, 122, 122, 37, 37, 89, 89, 88, + 88, 88, 88, 72, 72, 71, 71, 52, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 191, 191, 191, 155, 155, 122, + 122, 122, 121, 121, 89, 89, 88, 88, + 88, 88, 87, 72, 71, 71, 71, 71, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 155, 154, 122, + 121, 121, 121, 121, 121, 89, 88, 88, + 88, 87, 87, 71, 71, 71, 71, 70, + 70, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 191, 121, 121, + 121, 121, 121, 121, 120, 120, 88, 88, + 87, 87, 87, 87, 71, 71, 71, 69, + 69, 69, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 190, 190, 190, 121, 121, + 121, 121, 120, 120, 120, 120, 88, 87, + 87, 87, 87, 86, 71, 71, 69, 69, + 69, 69, 69, 68, 51, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 121, 121, + 121, 120, 120, 120, 120, 120, 119, 87, + 87, 87, 86, 86, 71, 69, 69, 69, + 69, 69, 68, 68, 68, 68, 50, 50, + 190, 190, 190, 190, 190, 105, 104, 120, + 120, 120, 120, 120, 120, 119, 119, 87, + 87, 86, 86, 86, 69, 69, 69, 69, + 69, 68, 68, 68, 68, 68, 68, 50, + 3, 190, 190, 190, 104, 104, 104, 104, + 104, 120, 120, 119, 119, 119, 119, 118, + 87, 86, 86, 86, 69, 69, 69, 69, + 68, 68, 68, 68, 68, 68, 68, 68, + 3, 3, 190, 190, 104, 104, 104, 104, + 104, 103, 103, 119, 119, 118, 118, 118, + 118, 86, 86, 86, 69, 69, 69, 68, + 68, 68, 68, 68, 68, 68, 68, 67, + 3, 3, 189, 102, 102, 102, 102, 102, + 102, 101, 101, 101, 101, 100, 118, 118, + 118, 117, 86, 85, 69, 69, 68, 68, + 68, 68, 68, 68, 68, 67, 67, 67, + 3, 189, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 100, 99, 99, 85, 69, 68, 68, 68, + 68, 68, 68, 67, 67, 67, 67, 67, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 99, 99, 99, 68, 68, 68, 68, + 68, 67, 67, 67, 67, 67, 67, 205, + 102, 102, 102, 102, 102, 102, 102, 102, + 101, 101, 101, 101, 100, 100, 100, 100, + 99, 99, 99, 99, 99, 68, 68, 67, + 67, 67, 67, 206, 206, 206, 205, 205, + 102, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 100, + 99, 99, 99, 99, 99, 98, 67, 67, + 206, 206, 206, 206, 206, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 99, 99, 99, 99, 98, 98, 206, 206, + 206, 206, 206, 206, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 99, 99, 98, 98, 98, 98, 206, 206, + 206, 206, 206, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 98, 98, 98, 98, 98, 98, 206, 206, + 206, 206, 205, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 98, + 98, 98, 98, 98, 98, 97, 206, 206, + 206, 205, 205, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 101, 101, 101, + 101, 101, 100, 100, 100, 100, 98, 98, + 98, 98, 98, 98, 98, 97, 206, 206, + 205, 205, 205, 205, 205, 205, 205, 205, + 250, 102, 102, 102, 102, 101, 101, 101, + 101, 101, 100, 100, 100, 98, 98, 98, + 98, 98, 98, 98, 98, 97, 206, 205, + 205, 205, 205, 205, 205, 205, 205, 205, + 243, 243, 243, 243, 243, 243, 222, 222, + 222, 222, 221, 221, 221, 221, 221, 220, + 220, 5, 5, 5, 5, 5, 5, 5, + 54, 54, 54, 54, 53, 53, 53, 53, + 243, 243, 243, 243, 243, 243, 222, 222, + 222, 222, 221, 221, 221, 221, 220, 220, + 220, 220, 5, 5, 5, 5, 219, 54, + 54, 54, 54, 53, 53, 53, 53, 53, + 243, 243, 243, 243, 243, 243, 222, 222, + 222, 221, 221, 221, 221, 221, 220, 220, + 220, 220, 220, 219, 219, 219, 219, 54, + 54, 54, 53, 53, 53, 53, 53, 53, + 243, 243, 243, 243, 175, 175, 222, 222, + 222, 221, 221, 221, 221, 221, 220, 220, + 220, 220, 220, 219, 219, 219, 54, 54, + 54, 53, 53, 53, 53, 53, 53, 53, + 243, 243, 243, 175, 175, 201, 140, 222, + 222, 221, 221, 221, 221, 221, 220, 220, + 220, 220, 220, 219, 219, 55, 54, 54, + 53, 53, 53, 53, 53, 53, 53, 53, + 243, 243, 175, 175, 201, 201, 201, 140, + 140, 221, 221, 221, 221, 221, 220, 220, + 220, 220, 220, 219, 219, 54, 54, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 175, 175, 201, 201, 201, 201, 201, 140, + 139, 139, 139, 221, 221, 221, 220, 220, + 220, 220, 219, 219, 55, 54, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 191, 201, 201, 201, 201, 201, 201, 139, + 139, 139, 139, 38, 14, 14, 14, 14, + 14, 14, 14, 55, 55, 53, 53, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 191, 191, 201, 201, 201, 201, 201, 139, + 139, 139, 38, 38, 14, 14, 14, 14, + 14, 14, 14, 88, 53, 53, 53, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 201, 201, 201, 201, 139, + 139, 139, 38, 38, 14, 14, 14, 14, + 14, 14, 88, 88, 72, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 201, 201, 155, 155, + 155, 138, 38, 37, 14, 14, 14, 14, + 14, 88, 88, 88, 72, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 191, 201, 155, 155, 155, + 138, 138, 37, 37, 37, 14, 14, 14, + 88, 88, 88, 88, 72, 71, 52, 52, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 191, 191, 191, 155, 155, 154, + 154, 154, 37, 37, 36, 36, 89, 88, + 88, 88, 87, 87, 71, 71, 52, 52, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 155, 154, 154, + 154, 154, 121, 36, 36, 36, 88, 88, + 88, 87, 87, 87, 71, 71, 71, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 154, 154, 154, + 121, 121, 121, 121, 36, 35, 88, 88, + 87, 87, 87, 87, 86, 71, 71, 69, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 190, 190, 190, 154, 121, + 121, 121, 120, 120, 120, 120, 88, 87, + 87, 87, 87, 86, 86, 71, 69, 69, + 69, 69, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 121, 121, + 121, 120, 120, 120, 120, 120, 119, 87, + 87, 87, 86, 86, 86, 69, 69, 69, + 69, 69, 68, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 121, 120, + 120, 120, 120, 120, 120, 119, 119, 87, + 87, 86, 86, 86, 86, 69, 69, 69, + 69, 68, 68, 68, 68, 50, 50, 50, + 3, 190, 190, 190, 190, 190, 120, 120, + 120, 120, 120, 119, 119, 119, 119, 118, + 87, 86, 86, 86, 86, 69, 69, 69, + 68, 68, 68, 68, 68, 68, 50, 50, + 3, 3, 190, 190, 190, 190, 104, 120, + 120, 120, 119, 119, 119, 119, 118, 118, + 118, 86, 86, 86, 85, 69, 69, 68, + 68, 68, 68, 68, 68, 68, 67, 67, + 3, 3, 189, 189, 189, 102, 104, 104, + 103, 119, 119, 119, 118, 118, 118, 118, + 118, 86, 86, 85, 85, 69, 68, 68, + 68, 68, 68, 68, 67, 67, 67, 67, + 3, 189, 189, 189, 102, 102, 102, 102, + 101, 101, 101, 101, 118, 118, 118, 118, + 117, 117, 85, 85, 85, 68, 68, 68, + 68, 68, 67, 67, 67, 67, 67, 67, + 3, 189, 189, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 100, + 99, 99, 117, 85, 85, 68, 68, 68, + 67, 67, 67, 67, 67, 67, 67, 67, + 189, 189, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 99, 99, 99, 99, 84, 68, 67, 67, + 67, 67, 67, 67, 67, 67, 66, 66, + 189, 102, 102, 102, 102, 102, 102, 101, + 101, 101, 101, 100, 100, 100, 100, 99, + 99, 99, 99, 99, 99, 67, 67, 67, + 67, 67, 67, 67, 66, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 100, 99, + 99, 99, 99, 99, 98, 97, 67, 67, + 67, 67, 205, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 99, + 99, 99, 99, 98, 98, 97, 97, 206, + 205, 205, 205, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 101, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 99, + 99, 98, 98, 98, 98, 97, 97, 205, + 205, 205, 205, 205, 205, 205, 205, 205, + 102, 102, 102, 102, 102, 101, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 98, + 98, 98, 98, 98, 98, 97, 97, 205, + 205, 205, 205, 205, 205, 205, 205, 204, + 102, 102, 102, 102, 102, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 98, 98, + 98, 98, 98, 98, 97, 97, 205, 205, + 205, 205, 205, 205, 205, 205, 204, 204, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 100, 100, 100, 100, 98, 98, 98, + 98, 98, 98, 98, 97, 97, 205, 205, + 205, 205, 205, 205, 205, 204, 204, 204, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 100, 100, 100, 98, 98, 98, 98, + 98, 98, 98, 98, 97, 97, 205, 205, + 205, 205, 205, 205, 204, 204, 204, 204, + 242, 242, 242, 242, 242, 242, 222, 222, + 222, 221, 221, 221, 221, 221, 220, 220, + 5, 5, 5, 5, 5, 5, 5, 218, + 218, 218, 218, 53, 53, 53, 53, 53, + 242, 242, 242, 242, 242, 175, 222, 222, + 222, 221, 221, 221, 221, 220, 220, 220, + 220, 5, 5, 5, 5, 219, 219, 218, + 218, 218, 53, 53, 53, 53, 53, 53, + 242, 242, 242, 242, 175, 175, 175, 222, + 221, 221, 221, 221, 221, 220, 220, 220, + 220, 220, 219, 219, 219, 219, 219, 218, + 218, 53, 53, 53, 53, 53, 53, 53, + 242, 242, 242, 175, 175, 175, 175, 222, + 221, 221, 221, 221, 221, 220, 220, 220, + 220, 220, 219, 219, 219, 219, 218, 218, + 53, 53, 53, 53, 53, 53, 53, 53, + 242, 175, 175, 175, 175, 175, 201, 201, + 221, 221, 221, 221, 221, 220, 220, 220, + 220, 220, 219, 219, 219, 219, 218, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 175, 175, 175, 175, 175, 201, 201, 201, + 201, 221, 221, 221, 221, 220, 220, 220, + 220, 220, 219, 219, 219, 219, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, + 175, 175, 175, 201, 201, 201, 201, 201, + 201, 139, 139, 221, 221, 220, 220, 220, + 220, 219, 219, 219, 219, 219, 53, 53, + 53, 53, 53, 53, 53, 52, 52, 52, + 175, 201, 201, 201, 201, 201, 201, 201, + 139, 139, 139, 38, 14, 14, 14, 14, + 14, 14, 219, 219, 219, 53, 53, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 201, 201, 201, 201, 201, 201, + 139, 138, 138, 14, 14, 14, 14, 14, + 14, 14, 14, 13, 53, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 201, 201, 201, 201, 201, + 138, 138, 138, 14, 14, 14, 14, 14, + 14, 14, 88, 13, 13, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 191, 201, 201, 201, 201, 138, + 138, 138, 138, 37, 14, 14, 14, 14, + 14, 88, 88, 13, 13, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 191, 191, 201, 201, 155, 138, + 138, 138, 138, 37, 14, 14, 14, 14, + 88, 88, 13, 87, 87, 52, 52, 52, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 155, 154, 154, + 154, 154, 137, 36, 36, 36, 35, 88, + 88, 88, 87, 87, 87, 86, 52, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 154, 154, 154, + 154, 154, 153, 36, 36, 35, 35, 88, + 88, 87, 87, 87, 86, 86, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 190, 190, 154, 154, 154, + 154, 153, 153, 120, 35, 35, 35, 34, + 87, 87, 87, 86, 86, 86, 69, 51, + 51, 51, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 154, 153, + 153, 120, 120, 120, 120, 35, 34, 87, + 87, 87, 86, 86, 86, 86, 69, 69, + 69, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 153, 153, + 120, 120, 120, 120, 120, 119, 34, 87, + 87, 86, 86, 86, 86, 85, 69, 69, + 69, 68, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 190, 190, 190, 120, 120, + 120, 120, 120, 119, 119, 119, 119, 87, + 87, 86, 86, 86, 85, 85, 69, 69, + 68, 68, 68, 68, 50, 50, 50, 50, + 3, 3, 190, 190, 190, 190, 120, 120, + 120, 120, 119, 119, 119, 119, 118, 118, + 86, 86, 86, 85, 85, 85, 69, 68, + 68, 68, 68, 68, 68, 67, 49, 49, + 3, 3, 189, 189, 189, 189, 120, 120, + 120, 119, 119, 119, 119, 118, 118, 118, + 118, 86, 85, 85, 85, 85, 68, 68, + 68, 68, 68, 67, 67, 67, 67, 49, + 3, 189, 189, 189, 189, 189, 102, 120, + 119, 119, 119, 119, 118, 118, 118, 118, + 117, 117, 85, 85, 85, 85, 68, 68, + 68, 67, 67, 67, 67, 67, 67, 67, + 3, 189, 189, 189, 189, 102, 102, 101, + 101, 101, 118, 118, 118, 118, 118, 118, + 117, 117, 85, 85, 85, 84, 68, 67, + 67, 67, 67, 67, 67, 67, 67, 66, + 189, 189, 189, 189, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 100, 117, + 117, 117, 116, 84, 84, 84, 67, 67, + 67, 67, 67, 67, 67, 66, 66, 66, + 189, 189, 189, 102, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 99, + 99, 99, 99, 116, 84, 67, 67, 67, + 67, 67, 67, 67, 66, 66, 66, 66, + 188, 188, 102, 102, 102, 102, 101, 101, + 101, 101, 100, 100, 100, 100, 99, 99, + 99, 99, 99, 99, 99, 67, 67, 67, + 67, 67, 66, 66, 66, 66, 66, 204, + 188, 188, 102, 102, 102, 101, 101, 101, + 101, 100, 100, 100, 100, 100, 99, 99, + 99, 99, 99, 98, 97, 97, 67, 67, + 66, 66, 66, 204, 204, 204, 204, 204, + 188, 102, 102, 102, 102, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 99, 99, + 99, 99, 98, 98, 97, 97, 97, 66, + 204, 204, 204, 204, 204, 204, 204, 204, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 99, 99, + 98, 98, 98, 98, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 102, 102, 102, 102, 101, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 98, 98, + 98, 98, 98, 98, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 102, 102, 102, 102, 101, 101, 101, 101, + 100, 100, 100, 100, 99, 98, 98, 98, + 98, 98, 98, 97, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 100, 100, 100, 98, 98, 98, 98, + 98, 98, 98, 97, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 102, 102, 102, 101, 101, 101, 101, 101, + 100, 100, 100, 98, 98, 98, 98, 98, + 98, 98, 98, 97, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 242, 242, 241, 241, 241, 241, 175, 222, + 221, 221, 221, 221, 221, 220, 220, 5, + 5, 5, 5, 5, 5, 5, 218, 218, + 218, 218, 217, 217, 217, 53, 53, 53, + 242, 241, 241, 241, 175, 175, 175, 222, + 221, 221, 221, 221, 220, 220, 220, 220, + 5, 5, 5, 5, 219, 219, 218, 218, + 218, 218, 217, 217, 53, 53, 53, 53, + 241, 241, 241, 175, 175, 175, 175, 175, + 221, 221, 221, 221, 220, 220, 220, 220, + 220, 219, 219, 219, 219, 219, 218, 218, + 218, 218, 53, 53, 53, 53, 53, 53, + 241, 241, 175, 175, 175, 175, 175, 175, + 221, 221, 221, 221, 220, 220, 220, 220, + 220, 219, 219, 219, 219, 218, 218, 218, + 218, 53, 53, 53, 53, 53, 53, 53, + 175, 175, 175, 175, 175, 175, 175, 201, + 221, 221, 221, 221, 220, 220, 220, 220, + 220, 219, 219, 219, 219, 218, 218, 218, + 218, 53, 53, 53, 53, 53, 53, 53, + 175, 175, 175, 175, 175, 175, 201, 201, + 201, 221, 221, 221, 220, 220, 220, 220, + 220, 219, 219, 219, 219, 218, 218, 218, + 53, 53, 53, 53, 53, 52, 52, 52, + 175, 175, 175, 175, 201, 201, 201, 201, + 201, 201, 139, 221, 220, 220, 220, 220, + 219, 219, 219, 219, 219, 218, 218, 53, + 53, 52, 52, 52, 52, 52, 52, 52, + 175, 175, 201, 201, 201, 201, 201, 201, + 201, 138, 138, 14, 14, 14, 14, 14, + 14, 219, 219, 219, 219, 218, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 201, 201, 201, 201, 201, 201, + 201, 138, 138, 14, 14, 14, 14, 14, + 14, 14, 13, 13, 13, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 191, 201, 201, 201, 201, 201, 201, + 138, 138, 138, 14, 14, 14, 14, 14, + 14, 14, 13, 13, 13, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 191, 201, 201, 201, 201, 138, + 138, 138, 138, 137, 14, 14, 14, 14, + 14, 13, 13, 13, 13, 52, 52, 52, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 201, 200, 200, 138, + 138, 137, 137, 137, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 52, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 191, 200, 154, 154, + 154, 137, 137, 137, 36, 35, 35, 13, + 13, 13, 13, 13, 86, 86, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 190, 190, 200, 154, 154, + 153, 153, 153, 153, 35, 35, 35, 34, + 13, 13, 13, 86, 86, 86, 51, 51, + 51, 51, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 154, 153, + 153, 153, 153, 153, 35, 35, 34, 34, + 13, 87, 86, 86, 86, 86, 85, 51, + 51, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 153, 153, + 153, 153, 153, 120, 120, 34, 34, 33, + 87, 86, 86, 86, 86, 85, 85, 69, + 51, 51, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 190, 190, 190, 153, 153, + 153, 120, 120, 119, 119, 119, 33, 33, + 33, 86, 86, 86, 85, 85, 85, 69, + 68, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 190, 190, 190, 190, 153, 153, + 120, 120, 119, 119, 119, 119, 119, 33, + 86, 86, 86, 85, 85, 85, 85, 68, + 68, 68, 68, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 189, 189, 189, 120, + 120, 119, 119, 119, 119, 118, 118, 118, + 86, 86, 85, 85, 85, 85, 85, 68, + 68, 67, 67, 67, 67, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 120, + 119, 119, 119, 119, 118, 118, 118, 118, + 117, 85, 85, 85, 85, 85, 84, 67, + 67, 67, 67, 67, 67, 67, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 119, + 119, 119, 119, 118, 118, 118, 118, 117, + 117, 117, 85, 85, 85, 84, 84, 67, + 67, 67, 67, 67, 67, 67, 66, 66, + 189, 189, 189, 189, 189, 189, 189, 101, + 101, 118, 118, 118, 118, 118, 118, 117, + 117, 117, 116, 84, 84, 84, 67, 67, + 67, 67, 67, 67, 67, 66, 66, 66, + 189, 189, 189, 189, 189, 189, 101, 101, + 101, 100, 100, 100, 100, 118, 117, 117, + 117, 116, 116, 116, 84, 84, 67, 67, + 67, 67, 67, 66, 66, 66, 66, 66, + 188, 188, 188, 188, 188, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 99, 99, + 99, 116, 116, 116, 84, 84, 67, 67, + 67, 66, 66, 66, 66, 66, 66, 66, + 188, 188, 188, 188, 102, 101, 101, 101, + 101, 100, 100, 100, 100, 99, 99, 99, + 99, 99, 99, 99, 115, 83, 67, 66, + 66, 66, 66, 66, 66, 66, 66, 66, + 188, 188, 188, 188, 101, 101, 101, 101, + 100, 100, 100, 100, 100, 99, 99, 99, + 99, 99, 98, 97, 97, 97, 66, 66, + 66, 66, 66, 66, 66, 204, 204, 204, + 188, 188, 188, 102, 101, 101, 101, 101, + 100, 100, 100, 100, 99, 99, 99, 99, + 99, 98, 98, 97, 97, 97, 97, 66, + 66, 204, 204, 204, 204, 204, 204, 204, + 188, 188, 102, 101, 101, 101, 101, 101, + 100, 100, 100, 100, 99, 99, 99, 98, + 98, 98, 98, 97, 97, 97, 97, 96, + 204, 204, 204, 204, 204, 204, 204, 204, + 187, 187, 102, 101, 101, 101, 101, 101, + 100, 100, 100, 100, 99, 98, 98, 98, + 98, 98, 98, 97, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 187, 102, 102, 101, 101, 101, 101, 100, + 100, 100, 100, 99, 98, 98, 98, 98, + 98, 98, 97, 97, 97, 97, 97, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 187, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 100, 98, 98, 98, 98, 98, + 98, 98, 97, 97, 97, 97, 96, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 187, 102, 101, 101, 101, 101, 101, 100, + 100, 100, 98, 98, 98, 98, 98, 98, + 98, 98, 97, 97, 97, 97, 96, 204, + 204, 204, 204, 204, 204, 204, 204, 203, + 241, 241, 241, 241, 241, 175, 175, 175, + 221, 221, 221, 221, 220, 220, 5, 5, + 5, 5, 5, 5, 5, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 241, 241, 241, 241, 175, 175, 175, 175, + 221, 221, 221, 220, 220, 220, 220, 5, + 5, 5, 5, 219, 219, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 53, 53, + 241, 241, 175, 175, 175, 175, 175, 175, + 221, 221, 221, 220, 220, 220, 220, 220, + 219, 219, 219, 219, 219, 218, 218, 218, + 218, 217, 217, 217, 217, 53, 53, 53, + 241, 175, 175, 175, 175, 175, 175, 175, + 221, 221, 221, 220, 220, 220, 220, 220, + 219, 219, 219, 219, 218, 218, 218, 218, + 218, 217, 217, 217, 53, 53, 53, 53, + 175, 175, 175, 175, 175, 175, 175, 175, + 201, 221, 221, 220, 220, 220, 220, 220, + 219, 219, 219, 219, 218, 218, 218, 218, + 218, 217, 53, 53, 53, 52, 52, 52, + 175, 175, 175, 175, 175, 175, 175, 201, + 201, 201, 221, 220, 220, 220, 220, 220, + 219, 219, 219, 219, 218, 218, 218, 218, + 218, 52, 52, 52, 52, 52, 52, 52, + 175, 175, 175, 175, 175, 201, 201, 201, + 201, 201, 138, 220, 220, 220, 220, 219, + 219, 219, 219, 219, 218, 218, 218, 218, + 52, 52, 52, 52, 52, 52, 52, 52, + 175, 175, 175, 201, 201, 201, 201, 201, + 201, 201, 138, 138, 14, 14, 14, 14, + 219, 219, 219, 219, 218, 218, 218, 52, + 52, 52, 52, 52, 52, 52, 52, 52, + 191, 201, 201, 201, 201, 201, 201, 201, + 200, 138, 138, 138, 14, 14, 14, 14, + 14, 13, 13, 13, 218, 218, 52, 52, + 52, 52, 52, 52, 52, 52, 51, 51, + 191, 191, 201, 201, 201, 201, 200, 200, + 200, 138, 137, 137, 14, 14, 14, 14, + 14, 13, 13, 13, 13, 13, 52, 52, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 191, 201, 201, 200, 200, 200, + 200, 137, 137, 137, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 52, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 191, 200, 200, 200, 200, + 137, 137, 137, 137, 14, 14, 14, 13, + 13, 13, 13, 13, 13, 13, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 190, 200, 200, 200, 200, + 137, 137, 137, 137, 136, 35, 13, 13, + 13, 13, 13, 13, 13, 86, 51, 51, + 51, 51, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 190, 190, 200, 200, 153, + 153, 153, 153, 136, 136, 35, 34, 13, + 13, 13, 13, 13, 86, 86, 85, 51, + 51, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 190, 190, 153, 153, + 153, 153, 153, 136, 136, 34, 34, 13, + 13, 13, 86, 86, 86, 85, 85, 51, + 51, 51, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 190, 190, 190, 153, 153, + 153, 153, 152, 152, 152, 34, 33, 33, + 33, 86, 86, 86, 85, 85, 85, 85, + 50, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 190, 190, 190, 190, 153, 153, + 152, 152, 152, 152, 119, 119, 33, 33, + 32, 86, 86, 85, 85, 85, 85, 85, + 50, 50, 50, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 189, 189, 189, 152, + 152, 152, 119, 119, 119, 119, 118, 32, + 32, 86, 85, 85, 85, 85, 85, 84, + 67, 67, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 152, + 152, 119, 119, 119, 118, 118, 118, 118, + 32, 31, 85, 85, 85, 85, 84, 84, + 67, 67, 67, 67, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 152, + 119, 119, 119, 118, 118, 118, 118, 117, + 117, 117, 85, 85, 85, 84, 84, 67, + 67, 67, 67, 67, 67, 49, 49, 49, + 189, 189, 189, 189, 189, 189, 189, 119, + 119, 119, 118, 118, 118, 118, 117, 117, + 117, 117, 85, 84, 84, 84, 84, 67, + 67, 67, 67, 67, 66, 66, 66, 48, + 189, 189, 189, 189, 189, 189, 189, 119, + 118, 118, 118, 118, 118, 118, 117, 117, + 117, 116, 116, 84, 84, 84, 84, 67, + 67, 67, 66, 66, 66, 66, 66, 66, + 188, 188, 188, 188, 188, 188, 188, 101, + 100, 100, 100, 118, 118, 117, 117, 117, + 116, 116, 116, 116, 84, 84, 83, 67, + 66, 66, 66, 66, 66, 66, 66, 66, + 188, 188, 188, 188, 188, 188, 101, 101, + 100, 100, 100, 100, 99, 99, 99, 99, + 116, 116, 116, 116, 115, 83, 83, 66, + 66, 66, 66, 66, 66, 66, 66, 65, + 188, 188, 188, 188, 188, 101, 101, 101, + 100, 100, 100, 100, 99, 99, 99, 99, + 99, 99, 116, 115, 115, 83, 83, 66, + 66, 66, 66, 66, 66, 65, 65, 65, + 188, 188, 188, 188, 188, 101, 101, 100, + 100, 100, 100, 100, 99, 99, 99, 99, + 99, 98, 97, 97, 97, 97, 83, 66, + 66, 66, 66, 65, 65, 65, 65, 203, + 188, 188, 188, 188, 101, 101, 101, 100, + 100, 100, 100, 99, 99, 99, 99, 99, + 98, 98, 97, 97, 97, 97, 96, 66, + 65, 65, 65, 204, 204, 204, 203, 203, + 187, 187, 187, 187, 101, 101, 101, 100, + 100, 100, 100, 99, 99, 99, 98, 98, + 98, 98, 97, 97, 97, 97, 96, 96, + 204, 204, 204, 204, 204, 203, 203, 203, + 187, 187, 187, 101, 101, 101, 101, 100, + 100, 100, 100, 99, 98, 98, 98, 98, + 98, 98, 97, 97, 97, 97, 96, 96, + 204, 204, 204, 204, 203, 203, 203, 203, + 187, 187, 187, 101, 101, 101, 100, 100, + 100, 100, 99, 98, 98, 98, 98, 98, + 98, 97, 97, 97, 97, 97, 96, 96, + 204, 204, 204, 203, 203, 203, 203, 203, + 187, 187, 187, 101, 101, 101, 100, 100, + 100, 100, 98, 98, 98, 98, 98, 98, + 98, 97, 97, 97, 97, 96, 96, 96, + 204, 204, 203, 203, 203, 203, 203, 203, + 187, 187, 101, 101, 101, 101, 100, 100, + 100, 98, 98, 98, 98, 98, 98, 98, + 98, 97, 97, 97, 97, 96, 96, 96, + 204, 203, 203, 203, 203, 203, 203, 203, + 1, 240, 240, 240, 240, 175, 175, 175, + 221, 221, 221, 220, 220, 5, 5, 5, + 5, 5, 5, 5, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 240, 240, 240, 175, 175, 175, 175, 175, + 221, 221, 220, 220, 220, 220, 5, 5, + 5, 5, 219, 219, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 240, 240, 175, 175, 175, 175, 175, 175, + 175, 221, 220, 220, 220, 220, 220, 219, + 219, 219, 219, 219, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 240, 175, 175, 175, 175, 175, 175, 175, + 175, 221, 220, 220, 220, 220, 220, 219, + 219, 219, 219, 218, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 52, + 175, 175, 175, 175, 175, 175, 175, 175, + 175, 221, 220, 220, 220, 220, 220, 219, + 219, 219, 219, 218, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 52, 52, 52, + 175, 175, 175, 175, 175, 175, 175, 174, + 201, 201, 220, 220, 220, 220, 220, 219, + 219, 219, 219, 218, 218, 218, 218, 218, + 217, 217, 217, 52, 52, 52, 52, 52, + 175, 175, 175, 174, 174, 174, 201, 201, + 201, 200, 200, 220, 220, 220, 219, 219, + 219, 219, 219, 218, 218, 218, 218, 218, + 217, 217, 52, 52, 52, 52, 52, 52, + 174, 174, 174, 174, 174, 201, 201, 200, + 200, 200, 200, 138, 14, 14, 14, 219, + 219, 219, 219, 218, 218, 218, 218, 218, + 52, 52, 52, 52, 52, 52, 51, 51, + 174, 174, 174, 201, 201, 200, 200, 200, + 200, 200, 200, 137, 14, 14, 14, 14, + 13, 13, 13, 218, 218, 218, 218, 52, + 52, 52, 52, 51, 51, 51, 51, 51, + 191, 191, 201, 201, 200, 200, 200, 200, + 200, 200, 137, 137, 14, 14, 14, 14, + 13, 13, 13, 13, 13, 13, 52, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 191, 191, 191, 200, 200, 200, 200, 200, + 200, 200, 137, 137, 136, 14, 14, 13, + 13, 13, 13, 13, 13, 13, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 190, 190, 200, 200, 200, 200, 200, + 200, 137, 137, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 13, 13, 51, 51, + 51, 51, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 190, 200, 200, 200, 200, + 137, 137, 136, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 51, + 51, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 190, 200, 200, 200, + 153, 136, 136, 136, 136, 34, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 51, + 51, 51, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 190, 190, 190, 200, 153, + 153, 152, 136, 136, 136, 34, 33, 13, + 13, 13, 13, 12, 12, 12, 85, 51, + 50, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 190, 190, 190, 190, 153, 152, + 152, 152, 152, 152, 152, 33, 33, 33, + 32, 32, 32, 12, 85, 85, 85, 85, + 50, 50, 50, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 189, 189, 152, 152, + 152, 152, 152, 152, 151, 33, 33, 32, + 32, 32, 31, 85, 85, 85, 85, 84, + 50, 50, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 152, + 152, 152, 152, 151, 119, 118, 118, 32, + 32, 31, 85, 85, 85, 85, 84, 84, + 67, 49, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 152, + 152, 152, 151, 119, 118, 118, 118, 117, + 31, 31, 85, 85, 84, 84, 84, 84, + 67, 67, 67, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 189, 189, 189, 152, + 152, 151, 118, 118, 118, 118, 117, 117, + 117, 117, 85, 84, 84, 84, 84, 84, + 67, 67, 67, 66, 49, 49, 48, 48, + 189, 189, 189, 189, 189, 189, 189, 152, + 151, 118, 118, 118, 118, 118, 117, 117, + 117, 116, 116, 84, 84, 84, 84, 83, + 67, 66, 66, 66, 66, 66, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 118, 118, 118, 118, 118, 117, 117, 117, + 116, 116, 116, 84, 84, 84, 83, 83, + 66, 66, 66, 66, 66, 66, 66, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 118, 118, 118, 118, 117, 117, 117, 116, + 116, 116, 116, 115, 83, 83, 83, 83, + 66, 66, 66, 66, 66, 66, 65, 65, + 188, 188, 188, 188, 188, 188, 188, 100, + 100, 100, 100, 99, 99, 99, 117, 116, + 116, 116, 116, 115, 115, 83, 83, 66, + 66, 66, 66, 66, 65, 65, 65, 65, + 188, 188, 188, 188, 188, 188, 188, 100, + 100, 100, 100, 99, 99, 99, 99, 99, + 99, 116, 115, 115, 115, 83, 83, 66, + 66, 66, 65, 65, 65, 65, 65, 65, + 188, 188, 188, 188, 188, 188, 100, 100, + 100, 100, 100, 99, 99, 99, 99, 99, + 98, 97, 97, 97, 97, 97, 83, 66, + 65, 65, 65, 65, 65, 65, 65, 65, + 187, 187, 187, 187, 187, 187, 100, 100, + 100, 100, 99, 99, 99, 99, 99, 98, + 98, 97, 97, 97, 97, 96, 96, 96, + 65, 65, 65, 65, 65, 203, 203, 203, + 187, 187, 187, 187, 187, 101, 100, 100, + 100, 100, 99, 99, 99, 98, 98, 98, + 98, 97, 97, 97, 97, 96, 96, 96, + 65, 65, 203, 203, 203, 203, 203, 203, + 187, 187, 187, 187, 187, 101, 100, 100, + 100, 100, 99, 98, 98, 98, 98, 98, + 98, 97, 97, 97, 97, 96, 96, 96, + 96, 203, 203, 203, 203, 203, 203, 203, + 187, 187, 187, 187, 187, 100, 100, 100, + 100, 99, 98, 98, 98, 98, 98, 98, + 97, 97, 97, 97, 97, 96, 96, 96, + 203, 203, 203, 203, 203, 203, 203, 203, + 187, 187, 187, 187, 101, 100, 100, 100, + 100, 98, 98, 98, 98, 98, 98, 98, + 97, 97, 97, 97, 96, 96, 96, 96, + 203, 203, 203, 203, 203, 203, 203, 203, + 186, 186, 186, 186, 101, 100, 100, 100, + 98, 98, 98, 98, 98, 98, 98, 98, + 97, 97, 97, 97, 96, 96, 96, 96, + 203, 203, 203, 203, 203, 203, 203, 203, + 1, 240, 240, 240, 240, 175, 175, 175, + 175, 221, 220, 220, 5, 5, 5, 5, + 5, 5, 5, 218, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 240, 240, 240, 240, 175, 175, 175, 175, + 175, 220, 220, 220, 220, 5, 5, 5, + 5, 219, 219, 218, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 240, 240, 175, 175, 175, 175, 175, 175, + 175, 220, 220, 220, 220, 220, 219, 219, + 219, 219, 219, 218, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 240, 175, 175, 175, 175, 175, 175, 175, + 175, 220, 220, 220, 220, 220, 219, 219, + 219, 219, 218, 218, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 175, 175, 175, 175, 175, 174, 174, 174, + 174, 220, 220, 220, 220, 220, 219, 219, + 219, 219, 218, 218, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 175, 174, 174, 174, 174, 174, 174, 174, + 174, 200, 220, 220, 220, 220, 219, 219, + 219, 219, 218, 218, 218, 218, 218, 217, + 217, 217, 217, 216, 216, 216, 52, 52, + 174, 174, 174, 174, 174, 174, 174, 174, + 200, 200, 200, 220, 220, 219, 219, 219, + 219, 219, 218, 218, 218, 218, 218, 217, + 217, 217, 217, 216, 52, 52, 51, 51, + 174, 174, 174, 174, 174, 174, 200, 200, + 200, 200, 200, 200, 14, 219, 219, 219, + 219, 219, 218, 218, 218, 218, 218, 217, + 217, 217, 52, 51, 51, 51, 51, 51, + 174, 174, 174, 174, 174, 200, 200, 200, + 200, 200, 200, 137, 137, 14, 14, 13, + 13, 13, 218, 218, 218, 218, 218, 217, + 51, 51, 51, 51, 51, 51, 51, 51, + 173, 173, 173, 200, 200, 200, 200, 200, + 200, 200, 200, 137, 136, 14, 14, 13, + 13, 13, 13, 13, 13, 218, 217, 51, + 51, 51, 51, 51, 51, 51, 51, 50, + 191, 173, 200, 200, 200, 200, 200, 200, + 200, 200, 137, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 13, 13, 51, 51, + 51, 51, 51, 51, 51, 50, 50, 50, + 190, 190, 190, 200, 200, 200, 200, 200, + 200, 199, 136, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 51, + 51, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 190, 190, 200, 200, 200, 200, + 199, 136, 136, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 51, + 51, 51, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 190, 200, 200, 199, 199, + 199, 136, 136, 136, 136, 136, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 190, 190, 190, 199, 199, 199, + 152, 152, 152, 136, 135, 135, 33, 13, + 13, 13, 12, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 189, 189, 199, 152, + 152, 152, 152, 152, 151, 151, 33, 32, + 32, 32, 12, 12, 12, 12, 12, 84, + 50, 50, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 152, 152, + 152, 152, 152, 151, 151, 151, 32, 32, + 32, 31, 12, 12, 12, 12, 84, 84, + 49, 49, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 189, 152, + 152, 152, 151, 151, 151, 151, 32, 32, + 31, 31, 31, 12, 84, 84, 84, 84, + 84, 49, 49, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 189, 189, 189, 152, + 152, 151, 151, 151, 151, 118, 117, 117, + 31, 31, 30, 30, 84, 84, 84, 84, + 83, 49, 49, 49, 49, 49, 48, 48, + 189, 189, 189, 189, 189, 189, 189, 151, + 151, 151, 151, 151, 118, 117, 117, 117, + 117, 30, 30, 84, 84, 84, 84, 83, + 83, 66, 66, 66, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 151, 151, 118, 118, 118, 117, 117, 117, + 116, 116, 116, 84, 84, 84, 83, 83, + 83, 66, 66, 66, 66, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 151, 150, 118, 118, 117, 117, 117, 116, + 116, 116, 116, 115, 83, 83, 83, 83, + 66, 66, 66, 66, 66, 65, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 118, 118, 117, 117, 117, 117, 116, + 116, 116, 115, 115, 83, 83, 83, 83, + 66, 66, 66, 65, 65, 65, 65, 65, + 188, 188, 188, 188, 188, 188, 188, 188, + 100, 100, 99, 99, 117, 117, 116, 116, + 116, 116, 115, 115, 115, 83, 83, 82, + 66, 65, 65, 65, 65, 65, 65, 65, + 188, 188, 188, 188, 188, 188, 187, 100, + 100, 100, 99, 99, 99, 99, 99, 116, + 116, 115, 115, 115, 115, 114, 83, 82, + 65, 65, 65, 65, 65, 65, 65, 9, + 187, 187, 187, 187, 187, 187, 187, 100, + 100, 100, 99, 99, 99, 99, 99, 98, + 97, 97, 97, 97, 114, 114, 114, 82, + 65, 65, 65, 65, 65, 65, 65, 9, + 187, 187, 187, 187, 187, 187, 187, 100, + 100, 99, 99, 99, 99, 99, 98, 98, + 97, 97, 97, 97, 96, 96, 96, 96, + 65, 65, 65, 65, 65, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 100, 100, + 100, 99, 99, 99, 98, 98, 98, 98, + 97, 97, 97, 97, 96, 96, 96, 96, + 96, 65, 65, 203, 203, 203, 202, 202, + 187, 187, 187, 187, 187, 187, 100, 100, + 100, 99, 98, 98, 98, 98, 98, 98, + 97, 97, 97, 97, 96, 96, 96, 96, + 96, 203, 203, 203, 203, 202, 202, 202, + 187, 187, 187, 187, 186, 186, 100, 100, + 99, 98, 98, 98, 98, 98, 98, 97, + 97, 97, 97, 97, 96, 96, 96, 96, + 96, 203, 203, 203, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 100, 100, + 98, 98, 98, 98, 98, 98, 98, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 96, 203, 203, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 100, 98, + 98, 98, 98, 98, 98, 98, 98, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 96, 203, 202, 202, 202, 202, 202, 202, + 239, 239, 239, 239, 239, 239, 175, 175, + 175, 220, 220, 5, 5, 5, 5, 5, + 5, 5, 218, 218, 218, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 239, 239, 239, 239, 175, 175, 175, 175, + 175, 220, 220, 220, 5, 5, 5, 5, + 219, 219, 218, 218, 218, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 239, 239, 239, 175, 175, 175, 175, 174, + 174, 220, 220, 220, 220, 219, 219, 219, + 219, 219, 218, 218, 218, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 239, 239, 175, 174, 174, 174, 174, 174, + 174, 174, 220, 220, 220, 219, 219, 219, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 220, 220, 220, 219, 219, 219, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 220, 220, 220, 219, 219, 219, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 200, 200, 200, 220, 219, 219, 219, 219, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 51, + 174, 174, 174, 174, 174, 174, 174, 200, + 200, 200, 200, 200, 199, 219, 219, 219, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 216, 216, 51, 51, 51, 51, + 173, 173, 173, 173, 173, 200, 200, 200, + 200, 200, 200, 199, 136, 136, 13, 13, + 219, 218, 218, 218, 218, 218, 217, 217, + 217, 217, 51, 51, 51, 51, 51, 50, + 173, 173, 173, 173, 173, 200, 200, 200, + 200, 199, 199, 199, 136, 136, 13, 13, + 13, 13, 13, 13, 218, 217, 217, 217, + 51, 51, 51, 51, 51, 50, 50, 50, + 173, 173, 173, 173, 200, 200, 200, 200, + 199, 199, 199, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 13, 12, 12, 51, + 51, 51, 51, 50, 50, 50, 50, 50, + 190, 190, 173, 200, 200, 200, 200, 199, + 199, 199, 199, 136, 136, 136, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 51, + 51, 51, 50, 50, 50, 50, 50, 50, + 3, 190, 190, 200, 200, 199, 199, 199, + 199, 199, 136, 136, 136, 136, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 190, 190, 199, 199, 199, 199, + 199, 199, 135, 135, 135, 135, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 189, 199, 199, 199, + 199, 135, 135, 135, 135, 135, 135, 13, + 32, 12, 12, 12, 12, 12, 12, 12, + 50, 50, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 199, 199, + 152, 135, 135, 135, 135, 151, 134, 32, + 32, 12, 12, 12, 12, 12, 12, 12, + 49, 49, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 189, 199, 152, + 152, 151, 151, 151, 151, 151, 134, 32, + 31, 31, 12, 12, 12, 12, 84, 84, + 11, 49, 49, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 189, 189, 189, 152, + 151, 151, 151, 151, 151, 151, 150, 31, + 31, 31, 30, 12, 12, 84, 84, 84, + 11, 49, 49, 49, 49, 49, 48, 48, + 189, 189, 189, 189, 189, 189, 189, 151, + 151, 151, 151, 151, 150, 150, 117, 117, + 31, 30, 30, 29, 84, 84, 84, 83, + 83, 49, 49, 49, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 151, + 151, 151, 150, 150, 150, 150, 117, 117, + 116, 30, 29, 29, 84, 84, 83, 83, + 83, 66, 66, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 150, 150, 117, 117, 116, + 116, 116, 29, 29, 83, 83, 83, 83, + 82, 66, 66, 66, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 150, 117, 117, 117, 116, + 116, 116, 115, 115, 83, 83, 83, 83, + 82, 66, 65, 65, 65, 65, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 117, 117, 117, 116, 116, + 116, 116, 115, 115, 115, 83, 83, 82, + 82, 65, 65, 65, 65, 65, 65, 65, + 188, 188, 188, 188, 188, 188, 187, 187, + 150, 150, 150, 117, 117, 116, 116, 116, + 116, 115, 115, 115, 115, 83, 82, 82, + 82, 65, 65, 65, 65, 65, 65, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 100, 99, 99, 99, 99, 99, 116, 116, + 116, 115, 115, 115, 114, 114, 82, 82, + 65, 65, 65, 65, 65, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 100, 99, 99, 99, 99, 99, 98, 97, + 97, 97, 97, 114, 114, 114, 114, 81, + 65, 65, 65, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 99, 99, 99, 99, 99, 98, 98, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 65, 64, 64, 64, 64, 9, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 100, + 99, 99, 99, 98, 98, 98, 98, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 96, 64, 64, 64, 202, 202, 202, 202, + 187, 187, 187, 187, 186, 186, 186, 100, + 99, 98, 98, 98, 98, 98, 98, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 99, + 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 97, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 98, + 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 98, + 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 238, 238, 238, 238, 238, 238, 238, 175, + 175, 220, 5, 5, 5, 5, 5, 5, + 5, 218, 218, 218, 218, 217, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 238, 238, 238, 238, 238, 238, 174, 174, + 174, 220, 220, 5, 5, 5, 5, 219, + 219, 218, 218, 218, 218, 217, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 238, 238, 238, 238, 174, 174, 174, 174, + 174, 174, 220, 220, 219, 219, 219, 219, + 219, 218, 218, 218, 218, 217, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 238, 238, 174, 174, 174, 174, 174, 174, + 174, 174, 220, 220, 219, 219, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 217, 216, 216, 216, 216, 215, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 220, 220, 219, 219, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 217, 216, 216, 216, 216, 215, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 200, 220, 219, 219, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 200, 200, 199, 219, 219, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 200, + 200, 200, 199, 199, 199, 219, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 200, + 199, 199, 199, 199, 199, 136, 219, 219, + 218, 218, 218, 218, 218, 217, 217, 217, + 217, 216, 216, 216, 216, 50, 50, 50, + 173, 173, 173, 173, 173, 173, 200, 199, + 199, 199, 199, 199, 199, 136, 13, 13, + 13, 13, 13, 218, 217, 217, 217, 217, + 216, 216, 51, 50, 50, 50, 50, 50, + 173, 173, 173, 173, 173, 199, 199, 199, + 199, 199, 199, 199, 136, 136, 13, 13, + 13, 13, 13, 13, 12, 12, 12, 217, + 51, 51, 50, 50, 50, 50, 50, 50, + 173, 173, 173, 173, 199, 199, 199, 199, + 199, 199, 199, 199, 135, 135, 13, 13, + 13, 13, 13, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 50, 50, + 3, 3, 173, 199, 199, 199, 199, 199, + 199, 199, 199, 135, 135, 135, 135, 13, + 13, 13, 12, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 49, 49, + 3, 3, 189, 189, 199, 199, 199, 199, + 199, 199, 135, 135, 135, 135, 135, 13, + 13, 12, 12, 12, 12, 12, 12, 12, + 50, 50, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 199, 199, 199, 199, + 199, 135, 135, 135, 135, 135, 134, 134, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 49, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 189, 199, 199, 199, + 135, 135, 135, 135, 134, 134, 134, 133, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 49, 49, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 189, 189, 199, 198, + 135, 135, 151, 151, 134, 134, 134, 133, + 31, 12, 12, 12, 12, 12, 11, 11, + 11, 49, 49, 49, 49, 49, 48, 48, + 189, 189, 189, 189, 189, 189, 189, 151, + 151, 151, 151, 150, 150, 150, 133, 133, + 31, 30, 30, 12, 12, 11, 11, 11, + 11, 49, 49, 49, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 151, + 151, 150, 150, 150, 150, 150, 133, 133, + 30, 30, 29, 29, 29, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 150, + 150, 150, 150, 150, 150, 149, 149, 149, + 116, 29, 29, 29, 28, 83, 83, 83, + 82, 82, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 150, 150, 149, 149, 116, + 116, 116, 29, 28, 28, 83, 83, 82, + 82, 82, 65, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 150, 149, 149, 116, 116, + 116, 115, 115, 115, 28, 83, 82, 82, + 82, 82, 65, 65, 65, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 187, 187, + 150, 150, 150, 149, 149, 149, 116, 116, + 116, 115, 115, 115, 114, 83, 82, 82, + 82, 65, 65, 65, 65, 65, 64, 64, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 150, 149, 149, 149, 116, 116, 116, + 115, 115, 115, 115, 114, 114, 82, 82, + 81, 65, 65, 65, 64, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 150, 149, 99, 116, 116, 116, 116, + 115, 115, 115, 114, 114, 114, 82, 81, + 81, 65, 64, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 99, 99, 99, 99, 98, 97, 97, + 97, 115, 114, 114, 114, 114, 113, 81, + 81, 64, 64, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 99, 99, 99, 99, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 113, 113, + 81, 64, 64, 64, 64, 9, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 99, 99, 98, 98, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 96, 96, + 112, 64, 64, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 98, 98, 98, 98, 98, 98, 97, 97, + 97, 97, 96, 96, 96, 96, 96, 96, + 96, 64, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 186, + 98, 98, 98, 98, 98, 97, 97, 97, + 97, 97, 96, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 186, + 98, 98, 98, 98, 98, 97, 97, 97, + 97, 96, 96, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 98, + 98, 98, 98, 98, 98, 97, 97, 97, + 97, 96, 96, 96, 96, 96, 96, 96, + 96, 202, 202, 202, 202, 202, 202, 202, + 238, 238, 238, 238, 238, 237, 237, 237, + 174, 174, 5, 5, 5, 5, 5, 5, + 218, 218, 218, 218, 217, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 238, 238, 238, 238, 237, 237, 174, 174, + 174, 174, 5, 5, 5, 5, 219, 219, + 218, 218, 218, 218, 217, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 238, 238, 238, 237, 174, 174, 174, 174, + 174, 174, 220, 219, 219, 219, 219, 219, + 218, 218, 218, 218, 217, 217, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 238, 238, 174, 174, 174, 174, 174, 174, + 174, 174, 220, 219, 219, 219, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 217, 216, 216, 216, 216, 215, 215, 215, + 238, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 219, 219, 219, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 217, 216, 216, 216, 216, 215, 215, 215, + 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 219, 219, 219, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 174, 199, 199, 199, 219, 219, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 199, 199, 199, 199, 199, 219, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 199, + 199, 199, 199, 199, 199, 199, 219, 218, + 218, 218, 218, 218, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 199, + 199, 199, 199, 199, 199, 199, 135, 13, + 13, 13, 218, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 50, 50, 50, 50, + 173, 173, 173, 173, 173, 173, 199, 199, + 199, 199, 199, 199, 199, 135, 135, 13, + 13, 13, 13, 12, 12, 12, 217, 216, + 216, 216, 50, 50, 50, 50, 50, 50, + 173, 173, 173, 173, 173, 199, 199, 199, + 199, 199, 199, 199, 135, 135, 135, 13, + 13, 13, 12, 12, 12, 12, 12, 12, + 50, 50, 50, 50, 50, 50, 49, 49, + 173, 173, 173, 173, 199, 199, 199, 199, + 199, 199, 199, 135, 135, 135, 135, 13, + 13, 12, 12, 12, 12, 12, 12, 12, + 11, 50, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 199, 199, 199, 199, 199, + 199, 198, 198, 135, 135, 135, 134, 134, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 49, 49, 49, 49, 49, 49, 49, + 3, 189, 189, 189, 199, 199, 199, 199, + 198, 198, 135, 135, 134, 134, 134, 134, + 12, 12, 12, 12, 12, 12, 11, 11, + 11, 49, 49, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 189, 199, 198, 198, + 198, 198, 135, 134, 134, 134, 134, 133, + 133, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 49, 49, 49, 49, 48, 48, + 189, 189, 189, 189, 189, 189, 198, 198, + 198, 135, 134, 134, 134, 134, 133, 133, + 133, 12, 12, 12, 12, 11, 11, 11, + 11, 11, 49, 49, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 198, 198, + 198, 150, 150, 150, 150, 133, 133, 133, + 133, 30, 29, 29, 11, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 150, + 150, 150, 150, 150, 150, 150, 133, 133, + 132, 29, 29, 29, 11, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 150, + 150, 150, 150, 150, 150, 149, 149, 149, + 132, 29, 29, 28, 28, 11, 11, 11, + 82, 82, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 188, + 150, 150, 150, 150, 149, 149, 149, 148, + 148, 115, 28, 28, 28, 27, 82, 82, + 82, 82, 82, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 187, 187, + 150, 150, 150, 149, 149, 149, 149, 148, + 148, 115, 115, 28, 27, 27, 82, 82, + 82, 82, 65, 65, 65, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 150, 150, 150, 149, 149, 149, 148, 148, + 115, 115, 115, 114, 114, 27, 82, 82, + 81, 81, 65, 64, 64, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 150, 149, 149, 149, 148, 148, 115, + 115, 115, 114, 114, 114, 114, 82, 81, + 81, 81, 64, 64, 64, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 149, 148, 116, 115, + 115, 115, 114, 114, 114, 114, 113, 81, + 81, 81, 64, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 99, 99, 98, 97, 97, 115, + 115, 114, 114, 114, 114, 113, 113, 81, + 81, 81, 64, 64, 64, 9, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 186, 99, 99, 98, 98, 97, 97, 97, + 97, 96, 96, 96, 113, 113, 113, 113, + 81, 64, 64, 64, 64, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 98, 98, 98, 98, 97, 97, 97, + 97, 96, 96, 96, 96, 96, 96, 112, + 112, 8, 64, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 98, 98, 98, 98, 97, 97, 97, + 97, 96, 96, 96, 96, 96, 96, 96, + 8, 8, 8, 202, 202, 202, 202, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 98, 98, 98, 97, 97, 97, 97, + 97, 96, 96, 96, 96, 96, 96, 96, + 8, 8, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 186, 186, 186, + 98, 98, 98, 98, 97, 97, 97, 97, + 96, 96, 96, 96, 96, 96, 96, 96, + 8, 8, 202, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 185, 185, 185, + 98, 98, 98, 98, 97, 97, 97, 97, + 96, 96, 96, 96, 96, 96, 96, 96, + 8, 8, 202, 202, 202, 202, 202, 202, + 237, 237, 237, 237, 237, 237, 237, 237, + 237, 174, 5, 5, 5, 5, 5, 218, + 218, 218, 218, 217, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 237, 237, 237, 237, 237, 237, 237, 174, + 174, 174, 5, 5, 5, 219, 219, 218, + 218, 218, 218, 217, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 237, 237, 237, 237, 237, 237, 174, 174, + 174, 174, 219, 219, 219, 219, 219, 218, + 218, 218, 218, 217, 217, 217, 217, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 237, 237, 237, 237, 174, 174, 174, 174, + 174, 174, 174, 219, 219, 219, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 217, + 216, 216, 216, 216, 215, 215, 215, 215, + 237, 237, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 219, 219, 219, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 217, + 216, 216, 216, 216, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 174, 174, 219, 219, 219, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 199, 199, 219, 219, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 199, 199, 199, 199, 219, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 199, 199, 199, 199, 199, 199, 218, 218, + 218, 218, 218, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 199, + 199, 199, 199, 199, 199, 198, 135, 13, + 13, 218, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 199, 199, + 199, 199, 199, 198, 198, 198, 135, 13, + 13, 13, 12, 12, 12, 217, 216, 216, + 216, 216, 216, 215, 50, 50, 49, 49, + 172, 172, 172, 172, 172, 199, 199, 199, + 199, 199, 198, 198, 198, 135, 135, 134, + 13, 12, 12, 12, 12, 12, 12, 12, + 11, 50, 49, 49, 49, 49, 49, 49, + 172, 172, 172, 172, 172, 199, 199, 199, + 198, 198, 198, 198, 198, 134, 134, 134, + 12, 12, 12, 12, 12, 12, 12, 11, + 11, 49, 49, 49, 49, 49, 49, 49, + 172, 172, 172, 172, 199, 199, 198, 198, + 198, 198, 198, 198, 134, 134, 134, 134, + 133, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 49, 49, 49, 49, 49, 49, + 189, 189, 189, 189, 199, 198, 198, 198, + 198, 198, 198, 198, 134, 134, 134, 133, + 133, 12, 12, 12, 12, 11, 11, 11, + 11, 11, 49, 49, 49, 49, 48, 48, + 189, 189, 189, 189, 198, 198, 198, 198, + 198, 198, 198, 134, 134, 134, 133, 133, + 133, 12, 12, 12, 12, 11, 11, 11, + 11, 11, 49, 49, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 198, 198, 198, + 198, 198, 134, 134, 134, 133, 133, 133, + 133, 132, 12, 12, 11, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 198, 198, + 198, 150, 150, 150, 150, 133, 133, 133, + 132, 132, 29, 11, 11, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 198, + 150, 150, 150, 150, 150, 133, 133, 132, + 132, 132, 29, 28, 11, 11, 11, 11, + 11, 11, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 150, + 150, 150, 150, 150, 149, 149, 149, 132, + 132, 132, 28, 28, 28, 11, 11, 11, + 11, 82, 48, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 187, 187, + 150, 150, 150, 149, 149, 149, 149, 148, + 148, 131, 131, 28, 27, 27, 27, 82, + 82, 82, 81, 48, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 150, 150, 150, 149, 149, 149, 148, 148, + 148, 147, 147, 27, 27, 27, 26, 82, + 82, 81, 81, 64, 64, 64, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 150, 149, 149, 149, 148, 148, 148, + 147, 147, 114, 114, 114, 26, 26, 81, + 81, 81, 81, 64, 64, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 149, 148, 148, 148, + 147, 114, 114, 114, 114, 113, 26, 81, + 81, 81, 81, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 148, 148, 148, 147, + 147, 114, 114, 114, 114, 113, 113, 81, + 81, 81, 64, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 186, 186, 149, 148, 148, 148, 147, 147, + 114, 114, 114, 114, 113, 113, 113, 112, + 81, 80, 64, 64, 64, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 98, 98, 97, 97, 97, 97, + 96, 96, 96, 113, 113, 113, 113, 112, + 112, 80, 64, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 98, 98, 97, 97, 97, 97, + 96, 96, 96, 96, 96, 113, 112, 112, + 8, 8, 8, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 98, 98, 97, 97, 97, 97, + 96, 96, 96, 96, 96, 96, 96, 8, + 8, 8, 8, 9, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 98, 98, 97, 97, 97, 97, 97, + 96, 96, 96, 96, 96, 96, 96, 8, + 8, 8, 8, 202, 202, 202, 202, 202, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 98, 97, 97, 97, 97, 96, + 96, 96, 96, 96, 96, 96, 96, 8, + 8, 8, 8, 202, 202, 202, 202, 202, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 98, 97, 97, 97, 97, 96, + 96, 96, 96, 96, 96, 96, 96, 8, + 8, 8, 8, 202, 202, 202, 202, 202, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 5, 5, 5, 5, 218, 218, + 218, 218, 217, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 174, 5, 5, 219, 219, 218, 218, + 218, 218, 217, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 236, 236, 236, 236, 236, 236, 236, 174, + 174, 174, 174, 219, 219, 219, 218, 218, + 218, 218, 217, 217, 217, 217, 217, 216, + 216, 216, 216, 216, 215, 215, 215, 215, + 236, 236, 236, 236, 236, 174, 174, 174, + 174, 174, 174, 219, 219, 218, 218, 218, + 218, 218, 217, 217, 217, 217, 217, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 236, 236, 236, 173, 173, 173, 173, 173, + 173, 173, 174, 219, 219, 218, 218, 218, + 218, 218, 217, 217, 217, 217, 217, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 219, 219, 218, 218, 218, + 218, 218, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 199, 199, 199, 218, 218, 218, + 218, 218, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 199, 199, 199, 199, 198, 218, 218, + 218, 218, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 215, + 173, 173, 173, 173, 173, 173, 173, 173, + 199, 199, 199, 199, 198, 198, 198, 218, + 218, 218, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 214, + 172, 172, 172, 172, 173, 173, 173, 199, + 199, 199, 198, 198, 198, 198, 198, 197, + 218, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 172, 172, 172, 172, 172, 172, 172, 199, + 198, 198, 198, 198, 198, 198, 197, 197, + 197, 12, 12, 12, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 49, + 172, 172, 172, 172, 172, 172, 199, 198, + 198, 198, 198, 198, 198, 197, 197, 197, + 197, 12, 12, 12, 12, 12, 12, 11, + 216, 216, 215, 49, 49, 49, 49, 49, + 172, 172, 172, 172, 172, 198, 198, 198, + 198, 198, 198, 198, 198, 197, 197, 197, + 133, 12, 12, 12, 12, 12, 11, 11, + 11, 11, 49, 49, 49, 49, 49, 49, + 172, 172, 172, 172, 172, 198, 198, 198, + 198, 198, 198, 198, 197, 197, 197, 133, + 133, 12, 12, 12, 12, 11, 11, 11, + 11, 11, 49, 49, 49, 49, 48, 48, + 172, 172, 172, 172, 198, 198, 198, 198, + 198, 198, 198, 197, 197, 197, 133, 133, + 133, 133, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 49, 48, 48, 48, 48, + 188, 188, 188, 188, 198, 198, 198, 198, + 198, 198, 197, 197, 197, 197, 133, 133, + 133, 132, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 198, 198, 198, + 198, 198, 197, 197, 197, 133, 133, 133, + 132, 132, 132, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 198, 198, + 198, 197, 197, 197, 133, 133, 133, 132, + 132, 132, 131, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 188, 198, + 197, 197, 150, 150, 133, 133, 132, 132, + 132, 132, 131, 11, 11, 11, 11, 11, + 11, 11, 10, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 187, 150, + 150, 150, 150, 150, 149, 149, 149, 132, + 132, 131, 131, 131, 11, 11, 11, 11, + 11, 10, 10, 48, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 150, 150, 150, 149, 149, 149, 148, 148, + 148, 131, 131, 131, 27, 27, 26, 10, + 10, 10, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 150, 150, 149, 149, 149, 148, 148, 148, + 147, 147, 147, 130, 27, 26, 26, 10, + 10, 10, 10, 80, 64, 64, 64, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 149, 148, 148, 148, + 147, 147, 147, 114, 26, 26, 26, 25, + 81, 81, 80, 80, 64, 64, 9, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 148, 148, 148, 147, + 147, 147, 114, 114, 113, 113, 25, 25, + 81, 80, 80, 64, 64, 64, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 186, 149, 149, 148, 148, 148, 147, 147, + 147, 147, 114, 114, 113, 113, 113, 81, + 80, 80, 80, 64, 64, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 149, 148, 148, 148, 147, 147, + 147, 114, 114, 113, 113, 113, 113, 112, + 80, 80, 80, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 148, 148, 148, 147, 147, 147, + 114, 114, 113, 113, 113, 113, 112, 112, + 112, 80, 80, 64, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 181, 97, 97, 97, 97, 96, + 96, 96, 96, 96, 113, 112, 112, 112, + 8, 8, 8, 8, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 182, 181, 97, 97, 97, 97, 96, + 96, 96, 96, 96, 96, 112, 112, 8, + 8, 8, 8, 8, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 181, 97, 97, 97, 97, 96, + 96, 96, 96, 96, 96, 96, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 97, 97, 96, 96, + 96, 96, 96, 96, 96, 96, 8, 8, + 8, 8, 8, 8, 202, 202, 202, 202, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 97, 97, 96, 96, + 96, 96, 96, 96, 96, 96, 8, 8, + 8, 8, 8, 8, 202, 202, 202, 202, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 5, 5, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 214, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 219, 219, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 214, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 174, 174, 219, 219, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 216, 216, 216, 215, 215, 215, 215, 214, + 236, 236, 236, 236, 236, 236, 236, 173, + 173, 173, 173, 219, 218, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 236, 236, 236, 236, 173, 173, 173, 173, + 173, 173, 173, 219, 218, 218, 218, 218, + 218, 217, 217, 217, 217, 217, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 236, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 218, 218, 218, 218, + 218, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 199, 198, 218, 218, 218, + 218, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 172, 172, 173, 173, 173, 173, 173, 173, + 173, 173, 198, 198, 198, 198, 218, 218, + 218, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 215, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 198, 198, 198, 198, 198, 198, 218, + 218, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 198, 198, 198, 198, 198, 198, 197, 197, + 197, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 198, + 198, 198, 198, 198, 198, 197, 197, 197, + 197, 197, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 198, + 198, 198, 198, 198, 198, 197, 197, 197, + 197, 196, 12, 12, 12, 12, 11, 216, + 216, 215, 215, 215, 215, 215, 49, 49, + 172, 172, 172, 172, 172, 172, 198, 198, + 198, 198, 198, 198, 197, 197, 197, 197, + 196, 196, 12, 12, 12, 11, 11, 11, + 11, 11, 11, 49, 49, 49, 48, 48, + 171, 171, 172, 172, 172, 198, 198, 198, + 198, 198, 198, 197, 197, 197, 197, 196, + 196, 196, 12, 12, 11, 11, 11, 11, + 11, 11, 11, 49, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 198, 198, 198, + 198, 198, 198, 197, 197, 197, 197, 196, + 196, 196, 132, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 171, 171, 171, 171, 198, 198, 198, 198, + 198, 198, 197, 197, 197, 197, 196, 196, + 196, 132, 132, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 198, 198, 198, + 198, 197, 197, 197, 197, 196, 196, 196, + 132, 132, 132, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 198, 198, 198, + 197, 197, 197, 197, 196, 196, 196, 132, + 132, 132, 131, 131, 11, 11, 11, 11, + 11, 11, 10, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 188, 198, 198, + 197, 197, 197, 196, 196, 196, 132, 132, + 132, 131, 131, 131, 11, 11, 11, 11, + 11, 10, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 197, + 197, 197, 197, 196, 196, 149, 132, 132, + 131, 131, 131, 131, 11, 11, 11, 10, + 10, 10, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 197, 150, 149, 149, 149, 148, 148, 148, + 131, 131, 131, 130, 130, 26, 26, 10, + 10, 10, 10, 10, 10, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 150, 149, 149, 149, 149, 148, 148, 148, + 147, 147, 147, 130, 130, 26, 26, 10, + 10, 10, 10, 10, 80, 64, 64, 9, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 149, 149, 149, 148, 148, 148, 147, + 147, 147, 146, 146, 146, 26, 25, 10, + 10, 10, 80, 80, 80, 64, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 186, 149, 149, 148, 148, 148, 147, 147, + 147, 147, 146, 146, 113, 25, 25, 24, + 24, 80, 80, 80, 80, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 149, 148, 148, 148, 147, 147, + 147, 146, 146, 113, 113, 113, 112, 24, + 24, 80, 80, 80, 64, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 148, 148, 148, 147, 147, 147, + 147, 146, 113, 113, 113, 113, 112, 112, + 7, 80, 80, 80, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 181, 148, 147, 147, 147, 147, + 146, 113, 113, 113, 113, 112, 112, 112, + 112, 8, 22, 22, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 182, 181, 181, 179, 147, 147, 96, + 96, 96, 113, 113, 112, 112, 112, 8, + 8, 8, 8, 8, 9, 9, 9, 9, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 181, 181, 179, 97, 96, 96, + 96, 96, 96, 96, 112, 112, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 96, 96, + 96, 96, 96, 96, 96, 8, 8, 8, + 8, 8, 8, 8, 8, 9, 9, 9, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 96, 96, + 96, 96, 96, 96, 96, 8, 8, 8, + 8, 8, 8, 8, 8, 202, 202, 202, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 96, 96, + 96, 96, 96, 96, 96, 8, 8, 8, + 8, 8, 8, 8, 8, 202, 202, 202, + 235, 235, 235, 235, 235, 235, 235, 234, + 234, 234, 234, 5, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 214, 214, + 235, 235, 235, 235, 235, 235, 234, 234, + 234, 234, 234, 219, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 214, 214, + 235, 235, 235, 235, 235, 234, 234, 234, + 234, 234, 228, 219, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 216, 216, 215, 215, 215, 215, 214, 214, + 235, 235, 235, 235, 234, 234, 234, 234, + 234, 228, 227, 227, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 235, 235, 235, 234, 234, 234, 173, 173, + 173, 173, 227, 227, 218, 218, 218, 218, + 217, 217, 217, 217, 217, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 235, 235, 173, 173, 173, 173, 173, 173, + 173, 173, 227, 226, 226, 218, 218, 218, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 226, 226, 226, 218, 218, 218, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 198, 198, 198, 225, 218, 218, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 215, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 198, 198, 198, 198, 198, 197, 197, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 198, 198, 198, 198, 198, 198, 197, 197, + 197, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 198, 198, 198, 198, 198, 197, 197, 197, + 197, 196, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 198, + 198, 198, 198, 198, 197, 197, 197, 197, + 197, 196, 196, 12, 12, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 171, 171, 171, 171, 172, 172, 198, 198, + 198, 198, 198, 197, 197, 197, 197, 197, + 196, 196, 196, 12, 11, 11, 11, 11, + 11, 11, 215, 215, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 171, 198, 198, + 198, 198, 198, 197, 197, 197, 197, 196, + 196, 196, 195, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 198, 198, 198, + 198, 198, 197, 197, 197, 197, 196, 196, + 196, 196, 195, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 198, 198, 198, + 198, 197, 197, 197, 197, 196, 196, 196, + 196, 195, 195, 11, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 198, 198, 198, + 197, 197, 197, 197, 197, 196, 196, 196, + 195, 195, 195, 131, 11, 11, 11, 11, + 11, 11, 11, 48, 48, 48, 48, 48, + 188, 188, 188, 188, 188, 198, 198, 198, + 197, 197, 197, 197, 196, 196, 196, 195, + 195, 195, 131, 131, 11, 11, 11, 11, + 11, 10, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 198, 197, + 197, 197, 197, 196, 196, 196, 195, 195, + 195, 131, 131, 131, 11, 11, 11, 11, + 10, 10, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 197, + 197, 197, 196, 196, 196, 196, 195, 195, + 195, 131, 131, 130, 130, 11, 10, 10, + 10, 10, 10, 10, 10, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 197, 196, 196, 196, 196, 195, 195, 195, + 131, 131, 130, 130, 130, 130, 10, 10, + 10, 10, 10, 10, 10, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 187, 196, 196, 196, 195, 148, 148, 147, + 147, 147, 130, 130, 130, 129, 10, 10, + 10, 10, 10, 10, 80, 80, 9, 9, + 187, 187, 187, 187, 186, 186, 186, 186, + 186, 149, 149, 148, 148, 148, 148, 147, + 147, 147, 146, 146, 146, 129, 25, 10, + 10, 10, 80, 80, 80, 80, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 149, 148, 148, 148, 147, 147, + 147, 146, 146, 146, 145, 145, 24, 24, + 24, 80, 80, 80, 80, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 148, 148, 148, 147, 147, 147, + 147, 146, 146, 145, 145, 145, 24, 24, + 7, 23, 80, 80, 22, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 181, 148, 147, 147, 147, 147, + 146, 146, 145, 145, 145, 112, 112, 112, + 23, 23, 22, 22, 22, 9, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 182, 181, 181, 147, 147, 147, 147, + 146, 145, 145, 145, 112, 112, 112, 112, + 8, 22, 22, 22, 21, 9, 9, 9, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 147, 145, + 145, 145, 145, 112, 112, 112, 112, 8, + 8, 8, 8, 21, 21, 21, 9, 9, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 179, 96, + 96, 96, 96, 112, 112, 112, 8, 8, + 8, 8, 8, 21, 21, 20, 9, 9, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 96, 96, 96, 96, 8, 8, 8, 8, + 8, 8, 8, 8, 20, 20, 19, 9, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 96, 96, 96, 96, 8, 8, 8, 8, + 8, 8, 8, 8, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 185, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 96, 96, 96, 96, 8, 8, 8, 8, + 8, 8, 8, 8, 19, 19, 19, 18, + 235, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 228, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 228, 228, 218, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 228, 228, 227, 227, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 216, 215, 215, 215, 215, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 234, + 228, 228, 227, 227, 227, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 228, + 228, 227, 227, 227, 226, 218, 218, 217, + 217, 217, 217, 217, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 234, 234, 234, 172, 172, 172, 172, 172, + 227, 227, 227, 226, 226, 226, 218, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 227, 227, 226, 226, 226, 225, 225, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 226, 226, 226, 225, 225, 225, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 215, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 226, 226, 225, 225, 225, 224, 224, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 172, 198, 198, 198, 225, 224, 224, 224, + 224, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 198, 198, 198, 198, 197, 197, 197, 197, + 197, 196, 196, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 172, 172, 198, + 198, 198, 198, 197, 197, 197, 197, 197, + 196, 196, 196, 196, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 198, + 198, 198, 198, 197, 197, 197, 197, 196, + 196, 196, 196, 195, 11, 11, 11, 11, + 11, 215, 215, 215, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 198, 198, + 198, 198, 197, 197, 197, 197, 197, 196, + 196, 196, 195, 195, 11, 11, 11, 11, + 11, 11, 11, 11, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 171, 198, 198, + 198, 197, 197, 197, 197, 197, 196, 196, + 196, 195, 195, 195, 11, 11, 11, 11, + 11, 11, 11, 11, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 171, 198, 198, + 197, 197, 197, 197, 197, 196, 196, 196, + 195, 195, 195, 194, 11, 11, 11, 11, + 11, 11, 11, 10, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 198, 198, 198, + 197, 197, 197, 197, 196, 196, 196, 196, + 195, 195, 194, 194, 194, 11, 11, 11, + 11, 11, 10, 10, 48, 48, 48, 48, + 187, 187, 187, 171, 171, 198, 198, 197, + 197, 197, 197, 196, 196, 196, 196, 195, + 195, 195, 194, 194, 194, 11, 11, 11, + 10, 10, 10, 10, 10, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 197, 197, + 197, 197, 197, 196, 196, 196, 195, 195, + 195, 194, 194, 194, 194, 11, 11, 10, + 10, 10, 10, 10, 10, 48, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 197, + 197, 197, 196, 196, 196, 195, 195, 195, + 195, 194, 194, 194, 130, 130, 10, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 187, 187, 187, 187, 187, 187, 187, 187, + 197, 196, 196, 196, 195, 195, 195, 195, + 194, 194, 194, 130, 130, 129, 10, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 187, 187, 187, 187, 186, 186, 186, 186, + 196, 196, 196, 196, 195, 195, 195, 194, + 194, 194, 130, 130, 129, 129, 10, 10, + 10, 10, 10, 10, 80, 80, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 196, 196, 195, 195, 195, 195, 147, + 147, 146, 146, 129, 129, 129, 128, 10, + 10, 10, 80, 80, 80, 80, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 195, 195, 195, 147, 147, 147, + 147, 146, 146, 145, 145, 145, 128, 24, + 7, 23, 23, 22, 22, 22, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 148, 148, 148, 147, 147, 147, + 146, 146, 145, 145, 145, 128, 128, 7, + 23, 23, 22, 22, 22, 21, 9, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 182, 181, 181, 147, 147, 147, 147, + 146, 145, 145, 145, 145, 144, 144, 23, + 23, 22, 22, 22, 21, 21, 21, 9, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 147, 145, + 145, 145, 145, 145, 144, 144, 112, 112, + 22, 22, 22, 21, 21, 21, 20, 9, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 179, 145, + 145, 145, 145, 144, 144, 112, 8, 8, + 8, 8, 21, 21, 21, 20, 20, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 145, 145, 144, 112, 8, 8, 8, + 8, 8, 21, 21, 20, 20, 19, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 112, 8, 8, 8, 8, + 8, 8, 8, 20, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 185, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 8, 8, 8, 8, 8, + 8, 8, 8, 20, 19, 19, 19, 18, + 185, 185, 185, 185, 185, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 8, 8, 8, 8, + 8, 8, 8, 19, 19, 19, 18, 18, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 229, 229, 228, 228, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 214, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 234, + 229, 229, 228, 228, 227, 218, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 214, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 234, 229, + 229, 228, 228, 227, 227, 227, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 216, + 215, 215, 215, 215, 214, 214, 214, 214, + 234, 234, 234, 234, 234, 234, 229, 229, + 228, 228, 227, 227, 227, 226, 217, 217, + 217, 217, 217, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 234, 234, 234, 234, 234, 229, 229, 228, + 228, 227, 227, 227, 226, 226, 226, 217, + 217, 217, 217, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 234, 234, 234, 234, 172, 229, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 217, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 215, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 172, 172, 172, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 172, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 198, 198, 225, 197, 197, 224, 224, 224, + 196, 196, 196, 195, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 198, 198, 197, 197, 197, 197, 197, 196, + 196, 196, 196, 195, 194, 11, 11, 11, + 215, 215, 215, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 198, + 198, 197, 197, 197, 197, 197, 196, 196, + 196, 196, 195, 195, 194, 11, 11, 11, + 11, 11, 11, 214, 214, 214, 48, 48, + 171, 171, 171, 171, 171, 171, 171, 198, + 197, 197, 197, 197, 197, 196, 196, 196, + 196, 195, 195, 194, 194, 11, 11, 11, + 11, 11, 11, 10, 48, 48, 48, 48, + 171, 171, 171, 171, 171, 171, 171, 198, + 197, 197, 197, 197, 197, 196, 196, 196, + 195, 195, 195, 194, 194, 11, 11, 11, + 11, 11, 10, 10, 10, 48, 48, 48, + 170, 171, 171, 171, 171, 171, 198, 197, + 197, 197, 197, 197, 196, 196, 196, 195, + 195, 195, 194, 194, 194, 194, 11, 11, + 10, 10, 10, 10, 10, 48, 48, 48, + 170, 170, 170, 171, 171, 169, 197, 197, + 197, 197, 197, 196, 196, 196, 195, 195, + 195, 194, 194, 194, 194, 193, 11, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 187, 187, 187, 187, 169, 169, 169, 197, + 197, 197, 196, 196, 196, 196, 195, 195, + 195, 194, 194, 194, 193, 193, 193, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 187, 187, 187, 187, 187, 187, 169, 197, + 197, 196, 196, 196, 196, 195, 195, 195, + 194, 194, 194, 194, 193, 193, 193, 10, + 10, 10, 10, 10, 10, 10, 10, 48, + 187, 187, 187, 187, 186, 186, 186, 167, + 197, 196, 196, 196, 195, 195, 195, 195, + 194, 194, 194, 193, 193, 193, 192, 10, + 10, 10, 10, 10, 10, 10, 80, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 167, 196, 196, 195, 195, 195, 195, 194, + 194, 194, 193, 193, 193, 192, 192, 10, + 10, 10, 10, 10, 22, 22, 22, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 196, 195, 195, 195, 195, 194, 194, + 194, 193, 193, 193, 129, 192, 192, 128, + 10, 23, 23, 22, 22, 22, 21, 9, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 166, 195, 195, 195, 195, 194, 194, + 193, 193, 193, 145, 145, 192, 128, 128, + 23, 23, 22, 22, 22, 21, 21, 21, + 186, 186, 186, 186, 186, 186, 186, 186, + 186, 182, 181, 195, 195, 147, 147, 193, + 193, 145, 145, 145, 145, 128, 128, 128, + 23, 22, 22, 22, 21, 21, 21, 20, + 186, 186, 186, 186, 186, 185, 185, 185, + 182, 182, 181, 181, 179, 147, 147, 145, + 145, 145, 145, 145, 144, 144, 144, 144, + 22, 22, 22, 21, 21, 21, 20, 20, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 179, 145, + 145, 145, 145, 145, 144, 144, 144, 144, + 22, 22, 21, 21, 21, 20, 20, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 145, 145, 145, 144, 144, 144, 144, 8, + 8, 21, 21, 21, 20, 20, 19, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 144, 144, 144, 144, 8, 8, + 8, 21, 21, 20, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 185, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 8, 8, 8, 8, + 8, 8, 20, 20, 19, 19, 19, 18, + 185, 185, 185, 185, 185, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 8, 8, 8, 8, + 8, 8, 20, 19, 19, 19, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 176, 8, 8, 8, + 8, 8, 19, 19, 19, 18, 18, 18, + 233, 233, 233, 233, 233, 233, 233, 233, + 229, 229, 228, 228, 228, 227, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 214, 214, 214, 214, 253, + 233, 233, 233, 233, 233, 233, 233, 229, + 229, 228, 228, 228, 227, 227, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 233, 233, 233, 233, 233, 233, 229, 229, + 228, 228, 228, 227, 227, 227, 217, 217, + 217, 217, 216, 216, 216, 216, 216, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 233, 233, 233, 233, 233, 229, 229, 228, + 228, 228, 227, 227, 227, 226, 226, 217, + 217, 217, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 233, 233, 233, 233, 229, 229, 228, 228, + 228, 227, 227, 227, 226, 226, 226, 217, + 217, 217, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 233, 233, 233, 229, 229, 228, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 225, + 217, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 233, 172, 172, 229, 228, 228, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 224, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 172, 172, 172, 172, 172, 228, 227, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 215, 214, 214, 214, 214, 214, + 171, 171, 172, 172, 172, 172, 227, 227, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 224, 216, 216, 216, 216, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 226, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 224, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 226, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 225, 225, 225, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 225, 225, 224, 224, 224, 224, 224, 224, + 224, 196, 195, 195, 194, 194, 11, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 198, 197, 197, 197, 197, 197, 196, 196, + 196, 195, 195, 194, 194, 194, 11, 11, + 11, 11, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 171, + 197, 197, 197, 197, 197, 196, 196, 196, + 196, 195, 195, 194, 194, 194, 11, 11, + 11, 11, 10, 10, 10, 48, 48, 48, + 170, 170, 171, 171, 171, 171, 171, 197, + 197, 197, 197, 197, 196, 196, 196, 196, + 195, 195, 194, 194, 194, 194, 11, 11, + 11, 10, 10, 10, 10, 48, 48, 48, + 170, 170, 170, 170, 171, 171, 169, 197, + 197, 197, 197, 196, 196, 196, 196, 195, + 195, 195, 194, 194, 194, 194, 193, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 170, 170, 170, 170, 169, 169, 169, 197, + 197, 197, 197, 196, 196, 196, 195, 195, + 195, 194, 194, 194, 194, 193, 193, 10, + 10, 10, 10, 10, 10, 10, 48, 48, + 170, 168, 168, 168, 169, 169, 169, 169, + 197, 197, 196, 196, 196, 195, 195, 195, + 194, 194, 194, 194, 193, 193, 193, 10, + 10, 10, 10, 10, 10, 10, 10, 48, + 168, 168, 168, 168, 169, 169, 169, 169, + 197, 196, 196, 196, 195, 195, 195, 195, + 194, 194, 194, 193, 193, 193, 193, 192, + 10, 10, 10, 10, 10, 10, 10, 48, + 186, 186, 186, 168, 168, 167, 167, 167, + 167, 196, 196, 196, 195, 195, 195, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 10, 10, 10, 10, 10, 22, 22, 21, + 186, 186, 186, 186, 186, 167, 167, 167, + 167, 167, 196, 195, 195, 195, 195, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 10, 10, 22, 22, 22, 21, 21, + 186, 186, 186, 186, 186, 186, 167, 167, + 167, 167, 195, 195, 195, 195, 194, 194, + 194, 193, 193, 193, 192, 192, 192, 192, + 192, 23, 22, 22, 22, 21, 21, 21, + 186, 186, 186, 186, 186, 186, 186, 166, + 166, 166, 166, 195, 195, 194, 194, 194, + 193, 193, 193, 193, 192, 192, 192, 128, + 128, 22, 22, 22, 21, 21, 21, 20, + 186, 186, 186, 186, 186, 185, 185, 166, + 166, 166, 181, 181, 195, 194, 194, 193, + 193, 193, 145, 145, 192, 128, 128, 128, + 22, 22, 22, 21, 21, 21, 20, 20, + 185, 185, 185, 185, 185, 185, 185, 185, + 182, 182, 181, 181, 179, 179, 163, 193, + 145, 145, 145, 145, 144, 144, 144, 144, + 22, 22, 21, 21, 21, 20, 20, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 163, 163, + 145, 145, 145, 144, 144, 144, 144, 144, + 22, 21, 21, 21, 20, 20, 19, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 144, 144, 144, 144, 144, 144, + 21, 21, 21, 20, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 185, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 144, 144, 144, 144, 8, + 21, 21, 20, 20, 19, 19, 19, 18, + 185, 185, 185, 185, 185, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 176, 8, 8, 8, + 8, 20, 20, 19, 19, 19, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 176, 8, 8, 8, + 8, 20, 19, 19, 19, 18, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 8, + 8, 19, 19, 19, 18, 18, 18, 17, + 233, 232, 232, 232, 232, 232, 232, 229, + 229, 229, 228, 228, 228, 227, 217, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 214, 214, 214, 214, 253, 253, + 232, 232, 232, 232, 232, 232, 229, 229, + 229, 228, 228, 228, 227, 227, 227, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 253, + 232, 232, 232, 232, 232, 229, 229, 229, + 228, 228, 228, 227, 227, 227, 226, 217, + 217, 216, 216, 216, 216, 216, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 232, 232, 232, 232, 229, 229, 229, 228, + 228, 228, 227, 227, 227, 226, 226, 226, + 217, 216, 216, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 232, 232, 232, 229, 229, 229, 228, 228, + 228, 227, 227, 227, 226, 226, 226, 225, + 217, 216, 216, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 232, 232, 229, 229, 229, 228, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 225, + 225, 216, 216, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 232, 229, 229, 229, 228, 228, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 224, 216, 216, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 229, 228, 228, 228, 227, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 224, 216, 216, 216, 215, 215, 215, + 215, 215, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 227, 227, 227, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 224, 224, 216, 216, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 227, 226, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 224, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 226, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 224, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 226, + 225, 225, 225, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 171, 225, + 225, 225, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 195, 194, 194, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 170, 171, 171, 171, 171, 171, 171, 171, + 225, 224, 224, 224, 224, 224, 224, 224, + 224, 195, 195, 194, 194, 194, 194, 11, + 11, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 171, 171, 171, 171, 171, + 224, 224, 224, 224, 224, 224, 224, 196, + 195, 195, 194, 194, 194, 194, 194, 11, + 11, 10, 10, 10, 10, 214, 214, 214, + 170, 170, 170, 170, 170, 171, 171, 169, + 197, 197, 197, 197, 196, 196, 196, 195, + 195, 195, 194, 194, 194, 194, 193, 193, + 10, 10, 10, 10, 10, 10, 48, 48, + 170, 170, 170, 170, 170, 169, 169, 169, + 197, 197, 197, 196, 196, 196, 196, 195, + 195, 194, 194, 194, 194, 193, 193, 193, + 10, 10, 10, 10, 10, 10, 10, 48, + 170, 170, 170, 169, 169, 169, 169, 169, + 169, 197, 196, 196, 196, 196, 195, 195, + 195, 194, 194, 194, 193, 193, 193, 193, + 10, 10, 10, 10, 10, 10, 10, 48, + 168, 168, 168, 168, 169, 169, 169, 169, + 169, 196, 196, 196, 196, 195, 195, 195, + 194, 194, 194, 194, 193, 193, 193, 192, + 192, 10, 10, 10, 10, 10, 10, 10, + 168, 168, 168, 168, 169, 169, 169, 169, + 167, 196, 196, 196, 195, 195, 195, 194, + 194, 194, 194, 193, 193, 193, 192, 192, + 192, 10, 10, 10, 10, 10, 22, 21, + 168, 168, 168, 168, 168, 167, 167, 167, + 167, 167, 196, 195, 195, 195, 195, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 192, 192, 10, 10, 22, 22, 21, 21, + 168, 168, 168, 168, 167, 167, 167, 167, + 167, 167, 167, 195, 195, 195, 194, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 192, 22, 22, 22, 21, 21, 21, + 186, 186, 186, 186, 167, 167, 167, 167, + 167, 167, 167, 195, 195, 195, 194, 194, + 193, 193, 193, 193, 192, 192, 192, 192, + 192, 192, 22, 22, 21, 21, 21, 20, + 186, 186, 186, 186, 166, 166, 166, 166, + 166, 166, 166, 195, 195, 194, 194, 193, + 193, 193, 193, 192, 192, 192, 192, 192, + 128, 22, 22, 21, 21, 21, 20, 20, + 185, 185, 185, 185, 185, 166, 166, 166, + 166, 166, 166, 181, 163, 163, 193, 193, + 193, 193, 193, 192, 192, 192, 192, 128, + 128, 22, 21, 21, 21, 20, 20, 19, + 185, 185, 185, 185, 185, 185, 185, 164, + 182, 182, 181, 181, 179, 163, 163, 163, + 193, 145, 145, 192, 144, 144, 144, 144, + 22, 21, 21, 21, 20, 20, 19, 19, + 185, 185, 185, 185, 185, 185, 185, 182, + 182, 182, 181, 181, 179, 163, 163, 163, + 163, 145, 145, 144, 144, 144, 144, 144, + 21, 21, 21, 20, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 185, 183, 182, + 182, 182, 181, 181, 179, 179, 163, 163, + 177, 176, 176, 144, 144, 144, 144, 144, + 21, 21, 20, 20, 19, 19, 19, 18, + 185, 185, 185, 185, 185, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 144, 144, 144, 21, + 21, 20, 20, 19, 19, 19, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 179, 177, + 177, 176, 176, 176, 176, 176, 8, 8, + 20, 20, 19, 19, 19, 18, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 20, 19, 19, 19, 18, 18, 18, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 19, 18, 18, 18, 17, 17, + 232, 232, 232, 232, 232, 230, 230, 229, + 229, 229, 228, 228, 228, 227, 227, 217, + 216, 216, 216, 216, 216, 215, 215, 215, + 215, 214, 214, 214, 214, 253, 253, 253, + 232, 232, 232, 232, 230, 230, 229, 229, + 229, 228, 228, 228, 227, 227, 227, 226, + 216, 216, 216, 216, 216, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 253, 253, + 232, 232, 232, 230, 230, 229, 229, 229, + 228, 228, 228, 227, 227, 227, 226, 226, + 216, 216, 216, 216, 216, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 253, + 232, 232, 230, 230, 229, 229, 229, 228, + 228, 228, 227, 227, 227, 226, 226, 226, + 216, 216, 216, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 232, 230, 230, 229, 229, 229, 228, 228, + 228, 227, 227, 227, 226, 226, 226, 225, + 225, 216, 216, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 230, 230, 229, 229, 229, 228, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 225, + 225, 216, 216, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 230, 229, 229, 229, 228, 228, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 224, 224, 216, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 229, 229, 229, 228, 228, 228, 227, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 224, 224, 216, 215, 215, 215, 215, + 215, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 228, 228, 227, 227, 227, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 224, 224, 216, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 227, 227, 226, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 224, 224, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 226, 226, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 171, 171, 226, 226, + 225, 225, 225, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 171, 171, 171, 171, 171, 225, + 225, 225, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 194, 194, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 171, 171, 171, 225, + 225, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 194, 194, 194, 194, 194, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 170, 225, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 195, 194, 194, 194, 194, 194, 193, + 193, 10, 10, 10, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 169, 169, + 224, 224, 224, 224, 224, 224, 224, 195, + 195, 194, 194, 194, 194, 194, 193, 193, + 193, 10, 10, 10, 10, 10, 10, 48, + 170, 170, 170, 170, 169, 169, 169, 169, + 169, 224, 224, 224, 196, 196, 195, 195, + 195, 194, 194, 194, 194, 193, 193, 193, + 192, 10, 10, 10, 10, 10, 10, 48, + 170, 170, 168, 169, 169, 169, 169, 169, + 169, 169, 196, 196, 196, 195, 195, 195, + 194, 194, 194, 194, 193, 193, 193, 193, + 192, 192, 10, 10, 10, 10, 10, 10, + 168, 168, 168, 168, 169, 169, 169, 169, + 169, 169, 196, 196, 196, 195, 195, 195, + 194, 194, 194, 193, 193, 193, 193, 192, + 192, 192, 10, 10, 10, 10, 10, 21, + 168, 168, 168, 168, 169, 169, 169, 169, + 167, 167, 196, 196, 195, 195, 195, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 192, 192, 192, 10, 10, 22, 21, 21, + 168, 168, 168, 168, 168, 167, 167, 167, + 167, 167, 167, 195, 195, 195, 194, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 192, 192, 22, 22, 21, 21, 21, + 168, 168, 168, 168, 167, 167, 167, 167, + 167, 167, 167, 195, 195, 195, 194, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 192, 22, 22, 21, 21, 21, 20, + 165, 165, 165, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 195, 194, 194, 194, + 193, 193, 193, 193, 192, 192, 192, 192, + 192, 192, 22, 21, 21, 21, 20, 20, + 165, 165, 165, 165, 166, 166, 166, 166, + 166, 166, 166, 166, 163, 194, 194, 193, + 193, 193, 193, 192, 192, 192, 192, 192, + 192, 22, 21, 21, 21, 20, 20, 19, + 165, 165, 165, 165, 165, 166, 166, 166, + 166, 166, 166, 181, 163, 163, 163, 193, + 193, 193, 192, 192, 192, 192, 192, 192, + 128, 21, 21, 21, 20, 20, 19, 19, + 185, 185, 185, 185, 165, 164, 164, 164, + 164, 182, 181, 181, 163, 163, 163, 163, + 163, 193, 192, 192, 192, 144, 144, 144, + 144, 21, 21, 20, 20, 19, 19, 19, + 185, 185, 185, 185, 185, 164, 164, 164, + 182, 182, 181, 181, 179, 163, 163, 163, + 163, 163, 176, 144, 144, 144, 144, 144, + 21, 21, 20, 20, 19, 19, 19, 18, + 185, 185, 185, 185, 185, 183, 183, 182, + 182, 182, 181, 181, 179, 163, 163, 163, + 163, 176, 176, 176, 144, 144, 144, 144, + 21, 20, 20, 19, 19, 19, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 182, 181, 181, 179, 179, 163, 163, + 177, 176, 176, 176, 176, 144, 144, 21, + 20, 20, 19, 19, 19, 18, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 20, 19, 19, 19, 18, 18, 18, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 19, 18, 18, 18, 17, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 18, 18, 18, 17, 17, 17, + 249, 231, 231, 231, 230, 230, 230, 229, + 229, 229, 228, 228, 228, 227, 227, 227, + 216, 216, 216, 216, 215, 215, 215, 215, + 214, 214, 214, 214, 253, 253, 253, 253, + 231, 231, 231, 230, 230, 230, 229, 229, + 229, 228, 228, 228, 227, 227, 227, 226, + 216, 216, 216, 216, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 253, 253, 253, + 231, 231, 230, 230, 230, 229, 229, 229, + 228, 228, 228, 227, 227, 227, 226, 226, + 226, 216, 216, 216, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 253, 253, + 231, 230, 230, 230, 229, 229, 229, 228, + 228, 228, 227, 227, 227, 226, 226, 226, + 225, 216, 216, 215, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 253, + 230, 230, 230, 229, 229, 229, 228, 228, + 228, 227, 227, 227, 226, 226, 226, 225, + 225, 216, 216, 215, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 230, 230, 229, 229, 229, 228, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 225, + 225, 224, 216, 215, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 230, 229, 229, 229, 228, 228, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 224, 224, 224, 215, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 229, 229, 229, 228, 228, 228, 227, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 224, 224, 215, 215, 215, 215, 215, + 214, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 228, 228, 228, 227, 227, 227, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 224, 224, 224, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 171, 171, 171, 171, 227, 227, 227, 226, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 224, 224, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 171, 171, 171, 171, 227, 226, 226, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 171, 171, 171, 226, 226, + 225, 225, 225, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 226, 225, + 225, 225, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 194, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 170, 225, + 225, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 194, 194, 194, 193, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 170, 225, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 194, 194, 194, 194, 193, 193, + 193, 10, 10, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 169, 169, 169, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 194, 194, 194, 194, 193, 193, 193, + 193, 192, 10, 10, 10, 10, 10, 214, + 170, 170, 170, 170, 169, 169, 169, 169, + 169, 224, 224, 224, 224, 224, 224, 195, + 194, 194, 194, 194, 194, 193, 193, 193, + 192, 192, 10, 10, 10, 10, 10, 10, + 170, 168, 168, 169, 169, 169, 169, 169, + 169, 169, 224, 224, 224, 195, 195, 195, + 194, 194, 194, 194, 193, 193, 193, 192, + 192, 192, 192, 10, 10, 10, 10, 10, + 168, 168, 168, 168, 169, 169, 169, 169, + 169, 169, 169, 196, 195, 195, 195, 194, + 194, 194, 194, 193, 193, 193, 193, 192, + 192, 192, 192, 10, 10, 10, 21, 21, + 168, 168, 168, 168, 169, 169, 169, 169, + 167, 167, 167, 195, 195, 195, 195, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 192, 192, 192, 192, 22, 21, 21, 21, + 168, 168, 168, 168, 168, 167, 167, 167, + 167, 167, 167, 167, 195, 195, 194, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 192, 192, 22, 21, 21, 21, 20, + 168, 168, 168, 168, 167, 167, 167, 167, + 167, 167, 167, 167, 195, 194, 194, 194, + 193, 193, 193, 193, 192, 192, 192, 192, + 192, 192, 192, 21, 21, 21, 20, 20, + 165, 165, 165, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 194, 194, 193, + 193, 193, 193, 193, 192, 192, 192, 192, + 192, 192, 21, 21, 21, 20, 20, 19, + 165, 165, 165, 165, 166, 166, 166, 166, + 166, 166, 166, 166, 163, 163, 163, 193, + 193, 193, 193, 192, 192, 192, 192, 192, + 192, 192, 21, 21, 20, 20, 19, 19, + 165, 165, 165, 165, 165, 166, 166, 166, + 166, 166, 166, 181, 163, 163, 163, 163, + 193, 193, 192, 192, 192, 192, 192, 192, + 192, 21, 21, 20, 20, 19, 19, 19, + 165, 165, 165, 165, 165, 164, 164, 164, + 164, 164, 181, 181, 163, 163, 163, 163, + 163, 163, 192, 192, 192, 192, 192, 144, + 21, 21, 20, 20, 19, 19, 19, 18, + 165, 165, 165, 165, 164, 164, 164, 164, + 164, 182, 181, 181, 163, 163, 163, 163, + 163, 163, 176, 192, 144, 144, 144, 144, + 21, 20, 20, 19, 19, 19, 18, 18, + 184, 184, 184, 184, 164, 164, 164, 164, + 182, 182, 181, 181, 179, 163, 163, 163, + 163, 176, 176, 176, 176, 144, 144, 144, + 20, 20, 19, 19, 19, 18, 18, 18, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 163, 163, 163, + 163, 176, 176, 176, 176, 160, 160, 160, + 20, 19, 19, 19, 18, 18, 18, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 163, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 19, 18, 18, 18, 17, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 179, 177, 177, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 18, 18, 18, 17, 17, 17, + 251, 184, 184, 184, 183, 183, 183, 182, + 180, 180, 181, 178, 178, 179, 177, 177, + 177, 176, 176, 176, 160, 160, 160, 160, + 160, 160, 18, 18, 17, 17, 17, 16, + 249, 249, 231, 231, 230, 230, 230, 229, + 229, 229, 228, 228, 228, 227, 227, 227, + 216, 216, 216, 215, 215, 215, 215, 214, + 214, 214, 214, 253, 253, 253, 253, 253, + 249, 231, 231, 230, 230, 230, 229, 229, + 229, 228, 228, 228, 227, 227, 227, 226, + 226, 216, 216, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 253, 253, 253, 253, + 231, 231, 230, 230, 230, 229, 229, 229, + 228, 228, 228, 227, 227, 227, 226, 226, + 226, 216, 216, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 253, 253, 253, + 231, 230, 230, 230, 229, 229, 229, 228, + 228, 228, 227, 227, 227, 226, 226, 226, + 225, 225, 215, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 253, 253, + 230, 230, 230, 229, 229, 229, 228, 228, + 228, 227, 227, 227, 226, 226, 226, 225, + 225, 225, 215, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 253, + 230, 230, 229, 229, 229, 228, 228, 228, + 227, 227, 227, 226, 226, 226, 225, 225, + 225, 224, 224, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 230, 229, 229, 229, 228, 228, 228, 227, + 227, 227, 226, 226, 226, 225, 225, 225, + 224, 224, 224, 215, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 229, 229, 229, 228, 228, 228, 227, 227, + 227, 226, 226, 226, 225, 225, 225, 224, + 224, 224, 224, 224, 215, 215, 215, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 229, 229, 228, 228, 228, 227, 227, 227, + 226, 226, 226, 225, 225, 225, 224, 224, + 224, 224, 224, 224, 215, 215, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 171, 228, 227, 227, 227, 226, + 226, 226, 225, 225, 225, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 227, 227, 226, 226, + 226, 225, 225, 225, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 215, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 226, 226, 226, + 225, 225, 225, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 226, 225, + 225, 225, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 170, 225, + 225, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 194, 194, 193, + 214, 214, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 170, 169, 169, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 194, 194, 194, 193, 193, + 193, 192, 214, 214, 214, 214, 214, 214, + 170, 170, 170, 170, 170, 169, 169, 169, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 194, 194, 194, 193, 193, 193, + 193, 192, 192, 10, 10, 10, 214, 214, + 170, 170, 170, 169, 169, 169, 169, 169, + 169, 224, 224, 224, 224, 224, 224, 224, + 194, 194, 194, 194, 193, 193, 193, 193, + 192, 192, 192, 192, 10, 10, 10, 10, + 168, 168, 168, 169, 169, 169, 169, 169, + 169, 169, 224, 224, 224, 224, 224, 194, + 194, 194, 194, 193, 193, 193, 193, 192, + 192, 192, 192, 192, 10, 10, 10, 21, + 168, 168, 168, 168, 169, 169, 169, 169, + 169, 169, 169, 224, 224, 195, 195, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 192, 192, 192, 192, 192, 21, 21, 21, + 168, 168, 168, 168, 169, 169, 169, 169, + 167, 167, 167, 167, 195, 195, 194, 194, + 194, 194, 193, 193, 193, 193, 192, 192, + 192, 192, 192, 192, 21, 21, 21, 20, + 168, 168, 168, 168, 168, 167, 167, 167, + 167, 167, 167, 167, 167, 195, 194, 194, + 194, 193, 193, 193, 193, 192, 192, 192, + 192, 192, 192, 192, 21, 21, 20, 20, + 168, 168, 168, 168, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 194, 194, 194, + 193, 193, 193, 193, 192, 192, 192, 192, + 192, 192, 192, 21, 21, 20, 20, 19, + 165, 165, 165, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 194, 194, 193, + 193, 193, 193, 192, 192, 192, 192, 192, + 192, 192, 21, 21, 20, 20, 19, 19, + 165, 165, 165, 165, 166, 166, 166, 166, + 166, 166, 166, 166, 163, 163, 163, 163, + 193, 193, 193, 192, 192, 192, 192, 192, + 192, 192, 21, 20, 20, 19, 19, 19, + 165, 165, 165, 165, 165, 166, 166, 166, + 166, 166, 166, 166, 163, 163, 163, 163, + 163, 193, 192, 192, 192, 192, 192, 192, + 192, 21, 20, 20, 19, 19, 19, 18, + 165, 165, 165, 165, 165, 164, 164, 164, + 164, 164, 164, 163, 163, 163, 163, 163, + 163, 163, 192, 192, 192, 192, 192, 192, + 21, 20, 20, 19, 19, 19, 18, 18, + 165, 165, 165, 165, 164, 164, 164, 164, + 164, 164, 181, 181, 163, 163, 163, 163, + 163, 163, 176, 176, 192, 144, 144, 144, + 20, 20, 19, 19, 19, 18, 18, 18, + 165, 165, 165, 164, 164, 164, 164, 164, + 164, 181, 181, 181, 163, 163, 163, 163, + 163, 163, 176, 176, 176, 160, 160, 160, + 20, 19, 19, 19, 18, 18, 18, 17, + 184, 184, 184, 184, 164, 164, 164, 182, + 182, 181, 181, 181, 179, 163, 163, 163, + 163, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 19, 18, 18, 18, 17, 17, + 184, 184, 184, 184, 183, 183, 183, 182, + 182, 181, 181, 181, 179, 163, 163, 163, + 177, 176, 176, 176, 176, 160, 160, 160, + 160, 19, 18, 18, 18, 17, 17, 17, + 251, 184, 184, 184, 183, 183, 183, 182, + 180, 180, 181, 178, 178, 162, 163, 177, + 177, 176, 176, 176, 160, 160, 160, 160, + 160, 160, 18, 18, 17, 17, 17, 16, + 251, 251, 184, 184, 183, 183, 183, 180, + 180, 180, 180, 178, 178, 162, 162, 177, + 161, 176, 176, 176, 160, 160, 160, 160, + 160, 160, 18, 17, 17, 17, 16, 16, +}; diff --git a/Magic2/AlphaPalette.cpp b/Magic2/AlphaPalette.cpp index 7f7c2e1..7142de0 100644 --- a/Magic2/AlphaPalette.cpp +++ b/Magic2/AlphaPalette.cpp @@ -1,260 +1,293 @@ -#include "stdafx.h" - -PALETTEENTRY standard_palette[256] = { - { 0, 0, 0, 0 }, - { 128, 0, 0, 0 }, - { 0, 128, 0, 0 }, - { 128, 128, 0, 0 }, - { 0, 0, 128, 0 }, - { 128, 0, 128, 0 }, - { 0, 128, 128, 0 }, - { 192, 192, 192, 0 }, - { 192, 220, 192, 0 }, - { 166, 202, 240, 0 }, - { 186, 172, 189, 0 }, - { 167, 147, 172, 0 }, - { 143, 129, 148, 0 }, - { 122, 107, 126, 0 }, - { 100, 87, 104, 0 }, - { 55, 49, 57, 0 }, - { 247, 247, 247, 0 }, - { 240, 240, 240, 0 }, - { 232, 232, 232, 0 }, - { 225, 225, 225, 0 }, - { 217, 217, 217, 0 }, - { 210, 210, 210, 0 }, - { 202, 202, 202, 0 }, - { 195, 195, 195, 0 }, - { 188, 188, 188, 0 }, - { 180, 180, 180, 0 }, - { 173, 173, 173, 0 }, - { 165, 165, 165, 0 }, - { 158, 158, 158, 0 }, - { 150, 150, 150, 0 }, - { 143, 143, 143, 0 }, - { 136, 136, 136, 0 }, - { 128, 128, 128, 0 }, - { 121, 121, 121, 0 }, - { 113, 113, 113, 0 }, - { 106, 106, 106, 0 }, - { 98, 98, 98, 0 }, - { 91, 91, 91, 0 }, - { 83, 83, 83, 0 }, - { 76, 76, 76, 0 }, - { 69, 69, 69, 0 }, - { 61, 61, 61, 0 }, - { 54, 54, 54, 0 }, - { 42, 42, 42, 0 }, - { 31, 31, 31, 0 }, - { 21, 21, 21, 0 }, - { 10, 10, 10, 0 }, - { 5, 5, 5, 0 }, - { 149, 149, 234, 0 }, - { 134, 134, 227, 0 }, - { 117, 117, 223, 0 }, - { 104, 104, 215, 0 }, - { 87, 87, 210, 0 }, - { 70, 70, 206, 0 }, - { 49, 49, 185, 0 }, - { 45, 45, 168, 0 }, - { 36, 36, 134, 0 }, - { 31, 31, 118, 0 }, - { 27, 27, 101, 0 }, - { 22, 22, 84, 0 }, - { 18, 18, 67, 0 }, - { 13, 13, 51, 0 }, - { 9, 9, 34, 0 }, - { 4, 4, 17, 0 }, - { 159, 191, 223, 0 }, - { 143, 181, 218, 0 }, - { 128, 170, 213, 0 }, - { 112, 159, 207, 0 }, - { 96, 149, 202, 0 }, - { 85, 138, 191, 0 }, - { 69, 128, 186, 0 }, - { 68, 117, 166, 0 }, - { 62, 106, 151, 0 }, - { 55, 96, 136, 0 }, - { 53, 85, 117, 0 }, - { 47, 74, 102, 0 }, - { 43, 64, 85, 0 }, - { 35, 53, 71, 0 }, - { 29, 43, 56, 0 }, - { 21, 32, 43, 0 }, - { 184, 190, 199, 0 }, - { 171, 182, 190, 0 }, - { 159, 169, 181, 0 }, - { 148, 162, 171, 0 }, - { 136, 150, 162, 0 }, - { 123, 138, 153, 0 }, - { 112, 128, 143, 0 }, - { 102, 118, 132, 0 }, - { 92, 105, 120, 0 }, - { 86, 97, 105, 0 }, - { 77, 85, 94, 0 }, - { 67, 74, 82, 0 }, - { 57, 66, 70, 0 }, - { 48, 53, 58, 0 }, - { 38, 44, 47, 0 }, - { 29, 32, 35, 0 }, - { 154, 228, 154, 0 }, - { 137, 224, 137, 0 }, - { 120, 220, 120, 0 }, - { 112, 207, 112, 0 }, - { 96, 202, 96, 0 }, - { 80, 197, 80, 0 }, - { 64, 191, 64, 0 }, - { 58, 175, 77, 0 }, - { 53, 159, 67, 0 }, - { 48, 143, 63, 0 }, - { 43, 128, 64, 0 }, - { 37, 112, 56, 0 }, - { 32, 96, 50, 0 }, - { 27, 80, 43, 0 }, - { 21, 64, 33, 0 }, - { 16, 48, 27, 0 }, - { 186, 204, 179, 0 }, - { 175, 194, 167, 0 }, - { 164, 184, 156, 0 }, - { 152, 174, 145, 0 }, - { 140, 167, 131, 0 }, - { 130, 157, 119, 0 }, - { 119, 148, 107, 0 }, - { 111, 136, 98, 0 }, - { 99, 124, 88, 0 }, - { 88, 112, 80, 0 }, - { 81, 97, 73, 0 }, - { 70, 84, 65, 0 }, - { 61, 73, 54, 0 }, - { 51, 61, 46, 0 }, - { 40, 48, 37, 0 }, - { 30, 36, 28, 0 }, - { 209, 191, 173, 0 }, - { 202, 181, 159, 0 }, - { 191, 170, 149, 0 }, - { 183, 159, 136, 0 }, - { 175, 149, 122, 0 }, - { 167, 138, 109, 0 }, - { 159, 128, 96, 0 }, - { 147, 117, 87, 0 }, - { 129, 106, 84, 0 }, - { 116, 96, 75, 0 }, - { 103, 85, 67, 0 }, - { 90, 73, 58, 0 }, - { 78, 64, 50, 0 }, - { 64, 53, 43, 0 }, - { 51, 43, 34, 0 }, - { 38, 32, 26, 0 }, - { 209, 196, 173, 0 }, - { 202, 186, 159, 0 }, - { 191, 175, 149, 0 }, - { 183, 169, 136, 0 }, - { 175, 159, 122, 0 }, - { 167, 150, 109, 0 }, - { 159, 140, 96, 0 }, - { 143, 128, 90, 0 }, - { 131, 119, 82, 0 }, - { 116, 106, 75, 0 }, - { 103, 95, 67, 0 }, - { 90, 83, 58, 0 }, - { 78, 70, 50, 0 }, - { 64, 60, 43, 0 }, - { 51, 48, 34, 0 }, - { 38, 36, 26, 0 }, - { 255, 255, 170, 0 }, - { 255, 255, 128, 0 }, - { 255, 244, 106, 0 }, - { 249, 232, 113, 0 }, - { 255, 213, 43, 0 }, - { 255, 197, 21, 0 }, - { 255, 186, 43, 0 }, - { 255, 175, 43, 0 }, - { 255, 150, 21, 0 }, - { 255, 143, 32, 0 }, - { 244, 111, 11, 0 }, - { 215, 92, 19, 0 }, - { 190, 72, 22, 0 }, - { 168, 60, 23, 0 }, - { 146, 39, 24, 0 }, - { 128, 27, 21, 0 }, - { 244, 244, 138, 0 }, - { 242, 242, 119, 0 }, - { 248, 248, 92, 0 }, - { 240, 240, 100, 0 }, - { 247, 247, 72, 0 }, - { 239, 239, 80, 0 }, - { 237, 237, 61, 0 }, - { 236, 236, 40, 0 }, - { 235, 235, 20, 0 }, - { 215, 215, 19, 0 }, - { 194, 194, 18, 0 }, - { 175, 175, 16, 0 }, - { 156, 156, 14, 0 }, - { 136, 136, 13, 0 }, - { 117, 117, 11, 0 }, - { 98, 98, 9, 0 }, - { 215, 183, 168, 0 }, - { 211, 170, 150, 0 }, - { 205, 157, 135, 0 }, - { 199, 148, 120, 0 }, - { 193, 135, 104, 0 }, - { 187, 123, 89, 0 }, - { 174, 109, 70, 0 }, - { 151, 96, 62, 0 }, - { 128, 83, 53, 0 }, - { 105, 68, 44, 0 }, - { 143, 239, 239, 0 }, - { 124, 237, 237, 0 }, - { 106, 234, 234, 0 }, - { 87, 232, 232, 0 }, - { 70, 227, 227, 0 }, - { 47, 230, 230, 0 }, - { 32, 223, 223, 0 }, - { 29, 205, 205, 0 }, - { 26, 176, 176, 0 }, - { 20, 150, 150, 0 }, - { 17, 121, 121, 0 }, - { 13, 94, 94, 0 }, - { 223, 32, 223, 0 }, - { 204, 30, 204, 0 }, - { 186, 27, 186, 0 }, - { 168, 23, 168, 0 }, - { 149, 21, 149, 0 }, - { 131, 18, 131, 0 }, - { 112, 16, 112, 0 }, - { 94, 13, 94, 0 }, - { 74, 11, 74, 0 }, - { 56, 7, 56, 0 }, - { 249, 91, 91, 0 }, - { 248, 80, 80, 0 }, - { 247, 68, 68, 0 }, - { 247, 55, 55, 0 }, - { 247, 43, 43, 0 }, - { 245, 31, 31, 0 }, - { 244, 19, 19, 0 }, - { 240, 11, 11, 0 }, - { 228, 10, 10, 0 }, - { 217, 9, 9, 0 }, - { 204, 9, 9, 0 }, - { 192, 7, 7, 0 }, - { 180, 7, 7, 0 }, - { 168, 6, 6, 0 }, - { 156, 5, 5, 0 }, - { 145, 4, 4, 0 }, - { 131, 5, 5, 0 }, - { 118, 5, 5, 0 }, - { 106, 4, 4, 0 }, - { 94, 4, 4, 0 }, - { 80, 5, 5, 0 }, - { 66, 6, 6, 0 }, - { 53, 6, 6, 0 }, - { 41, 5, 5, 0 }, - { 128, 128, 128, 0 }, - { 255, 0, 0, 0 }, - { 0, 255, 0, 0 }, - { 255, 255, 0, 0 }, - { 0, 0, 255, 0 }, - { 255, 0, 255, 0 }, - { 0, 255, 255, 0 }, - { 255, 255, 255, 0 }, -}; +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: AlphaPalette.cpp + AUTHOR: John DiCamillo +*/ + +#include "stdafx.h" + +PALETTEENTRY standard_palette[256] = { + { 0, 0, 0, 0 }, + { 128, 0, 0, 0 }, + { 0, 128, 0, 0 }, + { 128, 128, 0, 0 }, + { 0, 0, 128, 0 }, + { 128, 0, 128, 0 }, + { 0, 128, 128, 0 }, + { 192, 192, 192, 0 }, + { 192, 220, 192, 0 }, + { 166, 202, 240, 0 }, + { 186, 172, 189, 0 }, + { 167, 147, 172, 0 }, + { 143, 129, 148, 0 }, + { 122, 107, 126, 0 }, + { 100, 87, 104, 0 }, + { 55, 49, 57, 0 }, + { 247, 247, 247, 0 }, + { 240, 240, 240, 0 }, + { 232, 232, 232, 0 }, + { 225, 225, 225, 0 }, + { 217, 217, 217, 0 }, + { 210, 210, 210, 0 }, + { 202, 202, 202, 0 }, + { 195, 195, 195, 0 }, + { 188, 188, 188, 0 }, + { 180, 180, 180, 0 }, + { 173, 173, 173, 0 }, + { 165, 165, 165, 0 }, + { 158, 158, 158, 0 }, + { 150, 150, 150, 0 }, + { 143, 143, 143, 0 }, + { 136, 136, 136, 0 }, + { 128, 128, 128, 0 }, + { 121, 121, 121, 0 }, + { 113, 113, 113, 0 }, + { 106, 106, 106, 0 }, + { 98, 98, 98, 0 }, + { 91, 91, 91, 0 }, + { 83, 83, 83, 0 }, + { 76, 76, 76, 0 }, + { 69, 69, 69, 0 }, + { 61, 61, 61, 0 }, + { 54, 54, 54, 0 }, + { 42, 42, 42, 0 }, + { 31, 31, 31, 0 }, + { 21, 21, 21, 0 }, + { 10, 10, 10, 0 }, + { 5, 5, 5, 0 }, + { 149, 149, 234, 0 }, + { 134, 134, 227, 0 }, + { 117, 117, 223, 0 }, + { 104, 104, 215, 0 }, + { 87, 87, 210, 0 }, + { 70, 70, 206, 0 }, + { 49, 49, 185, 0 }, + { 45, 45, 168, 0 }, + { 36, 36, 134, 0 }, + { 31, 31, 118, 0 }, + { 27, 27, 101, 0 }, + { 22, 22, 84, 0 }, + { 18, 18, 67, 0 }, + { 13, 13, 51, 0 }, + { 9, 9, 34, 0 }, + { 4, 4, 17, 0 }, + { 159, 191, 223, 0 }, + { 143, 181, 218, 0 }, + { 128, 170, 213, 0 }, + { 112, 159, 207, 0 }, + { 96, 149, 202, 0 }, + { 85, 138, 191, 0 }, + { 69, 128, 186, 0 }, + { 68, 117, 166, 0 }, + { 62, 106, 151, 0 }, + { 55, 96, 136, 0 }, + { 53, 85, 117, 0 }, + { 47, 74, 102, 0 }, + { 43, 64, 85, 0 }, + { 35, 53, 71, 0 }, + { 29, 43, 56, 0 }, + { 21, 32, 43, 0 }, + { 184, 190, 199, 0 }, + { 171, 182, 190, 0 }, + { 159, 169, 181, 0 }, + { 148, 162, 171, 0 }, + { 136, 150, 162, 0 }, + { 123, 138, 153, 0 }, + { 112, 128, 143, 0 }, + { 102, 118, 132, 0 }, + { 92, 105, 120, 0 }, + { 86, 97, 105, 0 }, + { 77, 85, 94, 0 }, + { 67, 74, 82, 0 }, + { 57, 66, 70, 0 }, + { 48, 53, 58, 0 }, + { 38, 44, 47, 0 }, + { 29, 32, 35, 0 }, + { 154, 228, 154, 0 }, + { 137, 224, 137, 0 }, + { 120, 220, 120, 0 }, + { 112, 207, 112, 0 }, + { 96, 202, 96, 0 }, + { 80, 197, 80, 0 }, + { 64, 191, 64, 0 }, + { 58, 175, 77, 0 }, + { 53, 159, 67, 0 }, + { 48, 143, 63, 0 }, + { 43, 128, 64, 0 }, + { 37, 112, 56, 0 }, + { 32, 96, 50, 0 }, + { 27, 80, 43, 0 }, + { 21, 64, 33, 0 }, + { 16, 48, 27, 0 }, + { 186, 204, 179, 0 }, + { 175, 194, 167, 0 }, + { 164, 184, 156, 0 }, + { 152, 174, 145, 0 }, + { 140, 167, 131, 0 }, + { 130, 157, 119, 0 }, + { 119, 148, 107, 0 }, + { 111, 136, 98, 0 }, + { 99, 124, 88, 0 }, + { 88, 112, 80, 0 }, + { 81, 97, 73, 0 }, + { 70, 84, 65, 0 }, + { 61, 73, 54, 0 }, + { 51, 61, 46, 0 }, + { 40, 48, 37, 0 }, + { 30, 36, 28, 0 }, + { 209, 191, 173, 0 }, + { 202, 181, 159, 0 }, + { 191, 170, 149, 0 }, + { 183, 159, 136, 0 }, + { 175, 149, 122, 0 }, + { 167, 138, 109, 0 }, + { 159, 128, 96, 0 }, + { 147, 117, 87, 0 }, + { 129, 106, 84, 0 }, + { 116, 96, 75, 0 }, + { 103, 85, 67, 0 }, + { 90, 73, 58, 0 }, + { 78, 64, 50, 0 }, + { 64, 53, 43, 0 }, + { 51, 43, 34, 0 }, + { 38, 32, 26, 0 }, + { 209, 196, 173, 0 }, + { 202, 186, 159, 0 }, + { 191, 175, 149, 0 }, + { 183, 169, 136, 0 }, + { 175, 159, 122, 0 }, + { 167, 150, 109, 0 }, + { 159, 140, 96, 0 }, + { 143, 128, 90, 0 }, + { 131, 119, 82, 0 }, + { 116, 106, 75, 0 }, + { 103, 95, 67, 0 }, + { 90, 83, 58, 0 }, + { 78, 70, 50, 0 }, + { 64, 60, 43, 0 }, + { 51, 48, 34, 0 }, + { 38, 36, 26, 0 }, + { 255, 255, 170, 0 }, + { 255, 255, 128, 0 }, + { 255, 244, 106, 0 }, + { 249, 232, 113, 0 }, + { 255, 213, 43, 0 }, + { 255, 197, 21, 0 }, + { 255, 186, 43, 0 }, + { 255, 175, 43, 0 }, + { 255, 150, 21, 0 }, + { 255, 143, 32, 0 }, + { 244, 111, 11, 0 }, + { 215, 92, 19, 0 }, + { 190, 72, 22, 0 }, + { 168, 60, 23, 0 }, + { 146, 39, 24, 0 }, + { 128, 27, 21, 0 }, + { 244, 244, 138, 0 }, + { 242, 242, 119, 0 }, + { 248, 248, 92, 0 }, + { 240, 240, 100, 0 }, + { 247, 247, 72, 0 }, + { 239, 239, 80, 0 }, + { 237, 237, 61, 0 }, + { 236, 236, 40, 0 }, + { 235, 235, 20, 0 }, + { 215, 215, 19, 0 }, + { 194, 194, 18, 0 }, + { 175, 175, 16, 0 }, + { 156, 156, 14, 0 }, + { 136, 136, 13, 0 }, + { 117, 117, 11, 0 }, + { 98, 98, 9, 0 }, + { 215, 183, 168, 0 }, + { 211, 170, 150, 0 }, + { 205, 157, 135, 0 }, + { 199, 148, 120, 0 }, + { 193, 135, 104, 0 }, + { 187, 123, 89, 0 }, + { 174, 109, 70, 0 }, + { 151, 96, 62, 0 }, + { 128, 83, 53, 0 }, + { 105, 68, 44, 0 }, + { 143, 239, 239, 0 }, + { 124, 237, 237, 0 }, + { 106, 234, 234, 0 }, + { 87, 232, 232, 0 }, + { 70, 227, 227, 0 }, + { 47, 230, 230, 0 }, + { 32, 223, 223, 0 }, + { 29, 205, 205, 0 }, + { 26, 176, 176, 0 }, + { 20, 150, 150, 0 }, + { 17, 121, 121, 0 }, + { 13, 94, 94, 0 }, + { 223, 32, 223, 0 }, + { 204, 30, 204, 0 }, + { 186, 27, 186, 0 }, + { 168, 23, 168, 0 }, + { 149, 21, 149, 0 }, + { 131, 18, 131, 0 }, + { 112, 16, 112, 0 }, + { 94, 13, 94, 0 }, + { 74, 11, 74, 0 }, + { 56, 7, 56, 0 }, + { 249, 91, 91, 0 }, + { 248, 80, 80, 0 }, + { 247, 68, 68, 0 }, + { 247, 55, 55, 0 }, + { 247, 43, 43, 0 }, + { 245, 31, 31, 0 }, + { 244, 19, 19, 0 }, + { 240, 11, 11, 0 }, + { 228, 10, 10, 0 }, + { 217, 9, 9, 0 }, + { 204, 9, 9, 0 }, + { 192, 7, 7, 0 }, + { 180, 7, 7, 0 }, + { 168, 6, 6, 0 }, + { 156, 5, 5, 0 }, + { 145, 4, 4, 0 }, + { 131, 5, 5, 0 }, + { 118, 5, 5, 0 }, + { 106, 4, 4, 0 }, + { 94, 4, 4, 0 }, + { 80, 5, 5, 0 }, + { 66, 6, 6, 0 }, + { 53, 6, 6, 0 }, + { 41, 5, 5, 0 }, + { 128, 128, 128, 0 }, + { 255, 0, 0, 0 }, + { 0, 255, 0, 0 }, + { 255, 255, 0, 0 }, + { 0, 0, 255, 0 }, + { 255, 0, 255, 0 }, + { 0, 255, 255, 0 }, + { 255, 255, 255, 0 }, +}; diff --git a/Magic2/Command.cpp b/Magic2/Command.cpp index 0b52082..ce199b6 100644 --- a/Magic2/Command.cpp +++ b/Magic2/Command.cpp @@ -1,52 +1,76 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2005. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Command.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Base class (interface) for command pattern. A - command encapsulates a single editing operation - that may be performed on a document. Each command - may be done or undone multiple times. The specialized - implementations for each type of operation are re- - sponsible for providing a means to return the model - to the prior state. -*/ - -#include "stdafx.h" -#include "Command.h" - -// +--------------------------------------------------------------------+ - -void Print(const char* msg, ...); - -// +--------------------------------------------------------------------+ - -Command::Command(const char* n, MagicDoc* d) - : name(n), document(d) -{ -} - -Command::~Command() -{ - document = 0; -} - -// +--------------------------------------------------------------------+ - -void -Command::Do() -{ - Print("WARNING: Command::Do() called for '%s'\n", name.data()); -} - -void -Command::Undo() -{ - Print("WARNING: Command::Undo() called for '%s'\n", name.data()); -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Command.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Base class (interface) for command pattern. A + command encapsulates a single editing operation + that may be performed on a document. Each command + may be done or undone multiple times. The specialized + implementations for each type of operation are re- + sponsible for providing a means to return the model + to the prior state. +*/ + +#include "stdafx.h" +#include "Command.h" + +// +--------------------------------------------------------------------+ + +void Print(const char* msg, ...); + +// +--------------------------------------------------------------------+ + +Command::Command(const char* n, MagicDoc* d) + : name(n), document(d) +{ +} + +Command::~Command() +{ + document = 0; +} + +// +--------------------------------------------------------------------+ + +void +Command::Do() +{ + Print("WARNING: Command::Do() called for '%s'\n", name.data()); +} + +void +Command::Undo() +{ + Print("WARNING: Command::Undo() called for '%s'\n", name.data()); +} diff --git a/Magic2/Command.h b/Magic2/Command.h index 30f568e..f35e237 100644 --- a/Magic2/Command.h +++ b/Magic2/Command.h @@ -1,55 +1,79 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2005. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Command.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Base class (interface) for command pattern. A - command encapsulates a single editing operation - that may be performed on a document. Each command - may be done or undone multiple times. The specialized - implementations for each type of operation are re- - sponsible for providing a means to return the model - to the prior state. -*/ - -#ifndef Command_h -#define Command_h - -#include "Text.h" - -// +--------------------------------------------------------------------+ - -class MagicDoc; -class Solid; -class Model; - -// +--------------------------------------------------------------------+ - -class Command -{ -public: - static const char* TYPENAME() { return "Command"; } - - Command(const char* name, MagicDoc* document); - virtual ~Command(); - - // operations - virtual void Do(); - virtual void Undo(); - - const char* Name() const { return name; } - -protected: - Text name; - MagicDoc* document; -}; - -// +--------------------------------------------------------------------+ - -#endif Command_h +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Command.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Base class (interface) for command pattern. A + command encapsulates a single editing operation + that may be performed on a document. Each command + may be done or undone multiple times. The specialized + implementations for each type of operation are re- + sponsible for providing a means to return the model + to the prior state. +*/ + +#ifndef Command_h +#define Command_h + +#include "Text.h" + +// +--------------------------------------------------------------------+ + +class MagicDoc; +class Solid; +class Model; + +// +--------------------------------------------------------------------+ + +class Command +{ +public: + static const char* TYPENAME() { return "Command"; } + + Command(const char* name, MagicDoc* document); + virtual ~Command(); + + // operations + virtual void Do(); + virtual void Undo(); + + const char* Name() const { return name; } + +protected: + Text name; + MagicDoc* document; +}; + +// +--------------------------------------------------------------------+ + +#endif Command_h diff --git a/Magic2/ContentBundle.cpp b/Magic2/ContentBundle.cpp index b489cf8..7d0e250 100644 --- a/Magic2/ContentBundle.cpp +++ b/Magic2/ContentBundle.cpp @@ -1,137 +1,161 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2006. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: ContentBundle.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Chained collection of localized strings -*/ - -#include "MemDebug.h" -#include "ContentBundle.h" -#include "DataLoader.h" - -void Print(const char* fmt, ...); - -// +--------------------------------------------------------------------+ - -ContentBundle::ContentBundle(const char* bundle, Locale* locale) -{ - Text file = FindFile(bundle, locale); - if (file.length() > 0) { - LoadBundle(file); - } -} - -// +--------------------------------------------------------------------+ - -ContentBundle::~ContentBundle() -{ -} - -// +--------------------------------------------------------------------+ - -Text -ContentBundle::GetText(const char* key) const -{ - return values.find(key, Text(key)); -} - -// +--------------------------------------------------------------------+ - -Text -ContentBundle::FindFile(const char* bundle, Locale* locale) -{ - Text result; - Text basename = Text(bundle); - DataLoader* loader = DataLoader::GetLoader(); - - if (loader && bundle) { - if (locale) { - result = basename + locale->GetFullCode() + ".txt"; - - if (loader->FindFile(result)) - return result; - - result = basename + "_" + locale->GetLanguage() + ".txt"; - - if (loader->FindFile(result)) - return result; - } - - result = basename + ".txt"; - - if (loader->FindFile(result)) - return result; - } - - return Text(); -} - -// +--------------------------------------------------------------------+ - -void -ContentBundle::LoadBundle(const char* filename) -{ - DataLoader* loader = DataLoader::GetLoader(); - if (loader && filename && *filename) { - BYTE* buffer = 0; - loader->LoadBuffer(filename, buffer, true, true); - if (buffer && *buffer) { - char key[1024]; - char val[2048]; - char* p = (char*) buffer; - int s = 0, ik = 0, iv = 0; - - key[0] = 0; - val[0] = 0; - - while (*p) { - if (*p == '=') { - s = 1; - } - else if (*p == '\n' || *p == '\r') { - if (key[0] && val[0]) - values.insert(Text(key).trim(), Text(val).trim()); - - ZeroMemory(key, 1024); - ZeroMemory(val, 2048); - s = 0; - ik = 0; - iv = 0; - } - else if (s == 0) { - if (!key[0]) { - if (*p == '#') { - s = -1; // comment - } - else if (!isspace(*p)) { - key[ik++] = *p; - } - } - else { - key[ik++] = *p; - } - } - else if (s == 1) { - if (!isspace(*p)) { - s = 2; - val[iv++] = *p; - } - } - else if (s == 2) { - val[iv++] = *p; - } - - p++; - } - - loader->ReleaseBuffer(buffer); - } - } -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: ContentBundle.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Chained collection of localized strings +*/ + +#include "MemDebug.h" +#include "ContentBundle.h" +#include "DataLoader.h" + +void Print(const char* fmt, ...); + +// +--------------------------------------------------------------------+ + +ContentBundle::ContentBundle(const char* bundle, Locale* locale) +{ + Text file = FindFile(bundle, locale); + if (file.length() > 0) { + LoadBundle(file); + } +} + +// +--------------------------------------------------------------------+ + +ContentBundle::~ContentBundle() +{ +} + +// +--------------------------------------------------------------------+ + +Text +ContentBundle::GetText(const char* key) const +{ + return values.find(key, Text(key)); +} + +// +--------------------------------------------------------------------+ + +Text +ContentBundle::FindFile(const char* bundle, Locale* locale) +{ + Text result; + Text basename = Text(bundle); + DataLoader* loader = DataLoader::GetLoader(); + + if (loader && bundle) { + if (locale) { + result = basename + locale->GetFullCode() + ".txt"; + + if (loader->FindFile(result)) + return result; + + result = basename + "_" + locale->GetLanguage() + ".txt"; + + if (loader->FindFile(result)) + return result; + } + + result = basename + ".txt"; + + if (loader->FindFile(result)) + return result; + } + + return Text(); +} + +// +--------------------------------------------------------------------+ + +void +ContentBundle::LoadBundle(const char* filename) +{ + DataLoader* loader = DataLoader::GetLoader(); + if (loader && filename && *filename) { + BYTE* buffer = 0; + loader->LoadBuffer(filename, buffer, true, true); + if (buffer && *buffer) { + char key[1024]; + char val[2048]; + char* p = (char*) buffer; + int s = 0, ik = 0, iv = 0; + + key[0] = 0; + val[0] = 0; + + while (*p) { + if (*p == '=') { + s = 1; + } + else if (*p == '\n' || *p == '\r') { + if (key[0] && val[0]) + values.insert(Text(key).trim(), Text(val).trim()); + + ZeroMemory(key, 1024); + ZeroMemory(val, 2048); + s = 0; + ik = 0; + iv = 0; + } + else if (s == 0) { + if (!key[0]) { + if (*p == '#') { + s = -1; // comment + } + else if (!isspace(*p)) { + key[ik++] = *p; + } + } + else { + key[ik++] = *p; + } + } + else if (s == 1) { + if (!isspace(*p)) { + s = 2; + val[iv++] = *p; + } + } + else if (s == 2) { + val[iv++] = *p; + } + + p++; + } + + loader->ReleaseBuffer(buffer); + } + } +} diff --git a/Magic2/ContentBundle.h b/Magic2/ContentBundle.h index 4848716..d75a817 100644 --- a/Magic2/ContentBundle.h +++ b/Magic2/ContentBundle.h @@ -1,48 +1,72 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2006. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: ContentBundle.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Chained collection of localized strings -*/ - -#ifndef ContentBundle_h -#define ContentBundle_h - -#include "Types.h" -#include "Dictionary.h" -#include "Text.h" -#include "Locale_ss.h" - -// +--------------------------------------------------------------------+ - -class ContentBundle -{ -public: - static const char* TYPENAME() { return "ContentBundle"; } - - ContentBundle(const char* bundle, Locale* locale); - virtual ~ContentBundle(); - - int operator == (const ContentBundle& that) const { return this == &that; } - - const Text& GetName() const { return name; } - Text GetText(const char* key) const; - bool IsLoaded() const { return !values.isEmpty(); } - -protected: - void LoadBundle(const char* filename); - Text FindFile(const char* bundle, Locale* locale); - - Text name; - Dictionary values; -}; - -#endif ContentBundle_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: ContentBundle.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Chained collection of localized strings +*/ + +#ifndef ContentBundle_h +#define ContentBundle_h + +#include "Types.h" +#include "Dictionary.h" +#include "Text.h" +#include "Locale_ss.h" + +// +--------------------------------------------------------------------+ + +class ContentBundle +{ +public: + static const char* TYPENAME() { return "ContentBundle"; } + + ContentBundle(const char* bundle, Locale* locale); + virtual ~ContentBundle(); + + int operator == (const ContentBundle& that) const { return this == &that; } + + const Text& GetName() const { return name; } + Text GetText(const char* key) const; + bool IsLoaded() const { return !values.isEmpty(); } + +protected: + void LoadBundle(const char* filename); + Text FindFile(const char* bundle, Locale* locale); + + Text name; + Dictionary values; +}; + +#endif ContentBundle_h + diff --git a/Magic2/Editor.cpp b/Magic2/Editor.cpp index cfaf40d..24ac589 100644 --- a/Magic2/Editor.cpp +++ b/Magic2/Editor.cpp @@ -1,412 +1,436 @@ -/* Project MAGIC - John DiCamillo Software Consulting - Copyright © 1994-1997. All Rights Reserved. - - SUBSYSTEM: Magic.exe Application - FILE: Editor.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Source file for implementation of Selector -*/ - - -#include "stdafx.h" -#include "Editor.h" -#include "MagicDoc.h" -#include "ModelView.h" -#include "Selection.h" - -// +----------------------------------------------------------------------+ - - -static float project_u(Vec3& v, int style) -{ - switch (style) { - case 0: return v.x; // PLAN - case 1: return v.x; // FRONT - case 2: return v.z; // SIDE - } - - return v.x; -} - -static float project_v(Vec3& v, int style) -{ - switch (style) { - case 0: return -v.y; // PLAN - case 1: return -v.z; // FRONT - case 2: return -v.y; // SIDE - } - - return -v.y; -} - -static float project_u_cylindrical(Vec3& v, int axis) -{ - float t = 0.0f; - - switch (axis) { - // PLAN - case 0: if (v.x == 0) - return 0.0f; - t = v.y/v.x; - return (float) atan(t); - - // FRONT - case 1: if (v.x == 0) - return 0.0f; - t = v.z/v.x; - return (float) atan(t); - - // SIDE - case 2: return (float) atan2(v.z, v.y); // SIDE - } - - return project_u(v, axis); -} - -static float project_v_cylindrical(Vec3& v, int axis) -{ - switch (axis) { - case 0: return v.z; // PLAN - case 1: return v.y; // FRONT - case 2: return v.x; // SIDE - } - - return project_v(v, axis); -} - -void -Editor::ApplyMaterial(Material* material, List& polys, - int mapping, int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate) -{ - // save state: - EditCommand* command = new EditCommand("ApplyMaterial", document); - document->Exec(command); - - // do the job: - if (mapping == MAP_CYLINDRICAL) { - ApplyMaterialCylindrical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate); - return; - } - - if (mapping == MAP_SPHERICAL) { - ApplyMaterialSpherical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate); - return; - } - - VertexSet* vset = polys.first()->vertex_set; - - Vec3* loc = vset->loc; - float min_u = 100000.0f, max_u = -100000.0f; - float min_v = 100000.0f, max_v = -100000.0f; - - ListIter iter = polys; - - // compute range and scale: - if (mapping == MAP_PLANAR) { - while (++iter) { - Poly* poly = iter.value(); - for (int i = 0; i < poly->nverts; i++) { - int v = poly->verts[i]; - - float u0 = project_u(loc[v], axis); - float v0 = project_v(loc[v], axis); - - if (u0 < min_u) min_u = u0; - if (v0 < min_v) min_v = v0; - if (u0 > max_u) max_u = u0; - if (v0 > max_v) max_v = v0; - } - } - } - - float base_u = 0.0f; - float base_v = 0.0f; - - if (max_u != min_u) base_u = 1.0f / (max_u - min_u); - if (max_v != min_v) base_v = 1.0f / (max_v - min_v); - - iter.reset(); - - // assign texture id and coordinates: - while (++iter) { - Poly* poly = iter.value(); - - poly->material = material; - - if (mapping == MAP_NONE) - continue; - - for (int i = 0; i < poly->nverts; i++) { - int v = poly->verts[i]; - - // planar projection - if (mapping == MAP_PLANAR) { - if (!rotate) { - if (mirror) - vset->tu[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u; - else - vset->tu[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u; - - if (flip) - vset->tv[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v; - else - vset->tv[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v; - } - else { - if (!mirror) - vset->tv[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u; - else - vset->tv[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u; - - if (flip) - vset->tu[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v; - else - vset->tu[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v; - } - } - - // stretch to fit - else if (mapping == MAP_STRETCH) { - if (scale_u < 0.001) scale_u = 1; - if (scale_v < 0.001) scale_v = 1; - - if (!rotate) { - if (mirror) - vset->tu[v] = scale_u * (float) (i < 1 || i > 2); - else - vset->tu[v] = scale_u * (float) (i > 0 && i < 3); - - if (flip) - vset->tv[v] = scale_v * (float) (i <= 1); - else - vset->tv[v] = scale_v * (float) (i > 1); - } - else { - if (!mirror) - vset->tv[v] = scale_v * (float) (i < 1 || i > 2); - else - vset->tv[v] = scale_v * (float) (i > 0 && i < 3); - - if (flip) - vset->tu[v] = scale_u * (float) (i <= 1); - else - vset->tu[v] = scale_u * (float) (i > 1); - } - } - } - } - - Resegment(); -} - -void -Editor::ApplyMaterialCylindrical(Material* material, List& polys, - int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate) -{ - VertexSet* vset = polys.first()->vertex_set; - - Vec3* loc = vset->loc; - float min_u = 100000.0f, max_u = -100000.0f; - float min_v = 100000.0f, max_v = -100000.0f; - - ListIter iter = polys; - - // compute range and scale: - while (++iter) { - Poly* poly = iter.value(); - for (int i = 0; i < poly->nverts; i++) { - int v = poly->verts[i]; - - float u0 = project_u_cylindrical(loc[v], axis); - float v0 = project_v_cylindrical(loc[v], axis); - - if (u0 < min_u) min_u = u0; - if (v0 < min_v) min_v = v0; - if (u0 > max_u) max_u = u0; - if (v0 > max_v) max_v = v0; - } - } - - float base_u = 0.0f; - float base_v = 0.0f; - - if (max_u != min_u) base_u = 1.0f / (max_u - min_u); - if (max_v != min_v) base_v = 1.0f / (max_v - min_v); - - iter.reset(); - - // assign texture id and coordinates: - while (++iter) { - Poly* poly = iter.value(); - - poly->material = material; - - for (int i = 0; i < poly->nverts; i++) { - int v = poly->verts[i]; - float u0 = project_u_cylindrical(loc[v], axis); - float v0 = project_v_cylindrical(loc[v], axis); - - if (!rotate) { - if (mirror) - vset->tu[v] = (1.0f - base_u * (u0 - min_u)) * scale_u; - else - vset->tu[v] = (u0 - min_u) * scale_u * base_u; - - if (flip) - vset->tv[v] = (1.0f - base_v * (v0 - min_v)) * scale_v; - else - vset->tv[v] = (v0 - min_v) * scale_v * base_v; - } - else { - if (!mirror) - vset->tv[v] = (1.0f - base_u * (u0 - min_u)) * scale_u; - else - vset->tv[v] = (u0 - min_u) * scale_u * base_u; - - if (flip) - vset->tu[v] = (1.0f - base_v * (v0 - min_v)) * scale_v; - else - vset->tu[v] = (v0 - min_v) * scale_v * base_v; - } - } - } - - Resegment(); -} - -void -Editor::ApplyMaterialSpherical(Material* material, List& polys, - int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate) -{ -} - -// +----------------------------------------------------------------------+ - -static int mcomp(const void* a, const void* b) -{ - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; - - if (pa->sortval == pb->sortval) - return 0; - - if (pa->sortval < pb->sortval) - return -1; - - return 1; -} - -void -Editor::Resegment() -{ - if (model) { - ListIter iter = model->GetSurfaces(); - while (++iter) { - Surface* surface = iter.value(); - Poly* polys = surface->GetPolys(); - int npolys = surface->NumPolys(); - - for (int n = 0; n < npolys; n++) { - Poly* p = polys + n; - Material* m = p->material; - int sortval = model->GetMaterials().index(m) + 1; - - if (p->sortval != sortval) - p->sortval = sortval; - } - - // destroy the old segments and video data: - VideoPrivateData* video_data = surface->GetVideoPrivateData(); - surface->SetVideoPrivateData(0); - surface->GetSegments().destroy(); - - delete video_data; - - // sort the polys by material index: - qsort((void*) polys, npolys, sizeof(Poly), mcomp); - - // create new cohesive segments: - Segment* segment = 0; - - for (int n = 0; n < npolys; n++) { - if (segment && segment->material == polys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new Segment; - - segment->npolys = 1; - segment->polys = polys + n; - segment->material = segment->polys->material; - - surface->GetSegments().append(segment); - } - } - } - } -} - - -// +----------------------------------------------------------------------+ -// +----------------------------------------------------------------------+ -// +----------------------------------------------------------------------+ - -EditCommand::EditCommand(const char* n, MagicDoc* d) - : Command(n, d), model1(0), model2(0) -{ -} - -EditCommand::~EditCommand() -{ - delete model1; - delete model2; -} - -// +----------------------------------------------------------------------+ - -void -EditCommand::Do() -{ - if (document) { - Solid* solid = document->GetSolid(); - - // first application: - if (!model2) { - if (!model1) - model1 = new Model(*solid->GetModel()); - } - // re-do: - else { - solid->GetModel()->operator=(*model2); - } - } -} - -// +----------------------------------------------------------------------+ - -void -EditCommand::Undo() -{ - if (document && model1) { - Solid* solid = document->GetSolid(); - - // save current state for later re-do: - if (!model2) - model2 = new Model(*solid->GetModel()); - - solid->GetModel()->operator=(*model1); - } -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe Application + FILE: Editor.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Source file for implementation of Selector +*/ + + +#include "stdafx.h" +#include "Editor.h" +#include "MagicDoc.h" +#include "ModelView.h" +#include "Selection.h" + +// +----------------------------------------------------------------------+ + + +static float project_u(Vec3& v, int style) +{ + switch (style) { + case 0: return v.x; // PLAN + case 1: return v.x; // FRONT + case 2: return v.z; // SIDE + } + + return v.x; +} + +static float project_v(Vec3& v, int style) +{ + switch (style) { + case 0: return -v.y; // PLAN + case 1: return -v.z; // FRONT + case 2: return -v.y; // SIDE + } + + return -v.y; +} + +static float project_u_cylindrical(Vec3& v, int axis) +{ + float t = 0.0f; + + switch (axis) { + // PLAN + case 0: if (v.x == 0) + return 0.0f; + t = v.y/v.x; + return (float) atan(t); + + // FRONT + case 1: if (v.x == 0) + return 0.0f; + t = v.z/v.x; + return (float) atan(t); + + // SIDE + case 2: return (float) atan2(v.z, v.y); // SIDE + } + + return project_u(v, axis); +} + +static float project_v_cylindrical(Vec3& v, int axis) +{ + switch (axis) { + case 0: return v.z; // PLAN + case 1: return v.y; // FRONT + case 2: return v.x; // SIDE + } + + return project_v(v, axis); +} + +void +Editor::ApplyMaterial(Material* material, List& polys, + int mapping, int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate) +{ + // save state: + EditCommand* command = new EditCommand("ApplyMaterial", document); + document->Exec(command); + + // do the job: + if (mapping == MAP_CYLINDRICAL) { + ApplyMaterialCylindrical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate); + return; + } + + if (mapping == MAP_SPHERICAL) { + ApplyMaterialSpherical(material, polys, axis, scale_u, scale_v, flip, mirror, rotate); + return; + } + + VertexSet* vset = polys.first()->vertex_set; + + Vec3* loc = vset->loc; + float min_u = 100000.0f, max_u = -100000.0f; + float min_v = 100000.0f, max_v = -100000.0f; + + ListIter iter = polys; + + // compute range and scale: + if (mapping == MAP_PLANAR) { + while (++iter) { + Poly* poly = iter.value(); + for (int i = 0; i < poly->nverts; i++) { + int v = poly->verts[i]; + + float u0 = project_u(loc[v], axis); + float v0 = project_v(loc[v], axis); + + if (u0 < min_u) min_u = u0; + if (v0 < min_v) min_v = v0; + if (u0 > max_u) max_u = u0; + if (v0 > max_v) max_v = v0; + } + } + } + + float base_u = 0.0f; + float base_v = 0.0f; + + if (max_u != min_u) base_u = 1.0f / (max_u - min_u); + if (max_v != min_v) base_v = 1.0f / (max_v - min_v); + + iter.reset(); + + // assign texture id and coordinates: + while (++iter) { + Poly* poly = iter.value(); + + poly->material = material; + + if (mapping == MAP_NONE) + continue; + + for (int i = 0; i < poly->nverts; i++) { + int v = poly->verts[i]; + + // planar projection + if (mapping == MAP_PLANAR) { + if (!rotate) { + if (mirror) + vset->tu[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u; + else + vset->tu[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u; + + if (flip) + vset->tv[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v; + else + vset->tv[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v; + } + else { + if (!mirror) + vset->tv[v] = (1.0f - base_u * (project_u(loc[v], axis) - min_u)) * scale_u; + else + vset->tv[v] = (project_u(loc[v], axis) - min_u) * scale_u * base_u; + + if (flip) + vset->tu[v] = (1.0f - base_v * (project_v(loc[v], axis) - min_v)) * scale_v; + else + vset->tu[v] = (project_v(loc[v], axis) - min_v) * scale_v * base_v; + } + } + + // stretch to fit + else if (mapping == MAP_STRETCH) { + if (scale_u < 0.001) scale_u = 1; + if (scale_v < 0.001) scale_v = 1; + + if (!rotate) { + if (mirror) + vset->tu[v] = scale_u * (float) (i < 1 || i > 2); + else + vset->tu[v] = scale_u * (float) (i > 0 && i < 3); + + if (flip) + vset->tv[v] = scale_v * (float) (i <= 1); + else + vset->tv[v] = scale_v * (float) (i > 1); + } + else { + if (!mirror) + vset->tv[v] = scale_v * (float) (i < 1 || i > 2); + else + vset->tv[v] = scale_v * (float) (i > 0 && i < 3); + + if (flip) + vset->tu[v] = scale_u * (float) (i <= 1); + else + vset->tu[v] = scale_u * (float) (i > 1); + } + } + } + } + + Resegment(); +} + +void +Editor::ApplyMaterialCylindrical(Material* material, List& polys, + int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate) +{ + VertexSet* vset = polys.first()->vertex_set; + + Vec3* loc = vset->loc; + float min_u = 100000.0f, max_u = -100000.0f; + float min_v = 100000.0f, max_v = -100000.0f; + + ListIter iter = polys; + + // compute range and scale: + while (++iter) { + Poly* poly = iter.value(); + for (int i = 0; i < poly->nverts; i++) { + int v = poly->verts[i]; + + float u0 = project_u_cylindrical(loc[v], axis); + float v0 = project_v_cylindrical(loc[v], axis); + + if (u0 < min_u) min_u = u0; + if (v0 < min_v) min_v = v0; + if (u0 > max_u) max_u = u0; + if (v0 > max_v) max_v = v0; + } + } + + float base_u = 0.0f; + float base_v = 0.0f; + + if (max_u != min_u) base_u = 1.0f / (max_u - min_u); + if (max_v != min_v) base_v = 1.0f / (max_v - min_v); + + iter.reset(); + + // assign texture id and coordinates: + while (++iter) { + Poly* poly = iter.value(); + + poly->material = material; + + for (int i = 0; i < poly->nverts; i++) { + int v = poly->verts[i]; + float u0 = project_u_cylindrical(loc[v], axis); + float v0 = project_v_cylindrical(loc[v], axis); + + if (!rotate) { + if (mirror) + vset->tu[v] = (1.0f - base_u * (u0 - min_u)) * scale_u; + else + vset->tu[v] = (u0 - min_u) * scale_u * base_u; + + if (flip) + vset->tv[v] = (1.0f - base_v * (v0 - min_v)) * scale_v; + else + vset->tv[v] = (v0 - min_v) * scale_v * base_v; + } + else { + if (!mirror) + vset->tv[v] = (1.0f - base_u * (u0 - min_u)) * scale_u; + else + vset->tv[v] = (u0 - min_u) * scale_u * base_u; + + if (flip) + vset->tu[v] = (1.0f - base_v * (v0 - min_v)) * scale_v; + else + vset->tu[v] = (v0 - min_v) * scale_v * base_v; + } + } + } + + Resegment(); +} + +void +Editor::ApplyMaterialSpherical(Material* material, List& polys, + int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate) +{ +} + +// +----------------------------------------------------------------------+ + +static int mcomp(const void* a, const void* b) +{ + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; + + if (pa->sortval == pb->sortval) + return 0; + + if (pa->sortval < pb->sortval) + return -1; + + return 1; +} + +void +Editor::Resegment() +{ + if (model) { + ListIter iter = model->GetSurfaces(); + while (++iter) { + Surface* surface = iter.value(); + Poly* polys = surface->GetPolys(); + int npolys = surface->NumPolys(); + + for (int n = 0; n < npolys; n++) { + Poly* p = polys + n; + Material* m = p->material; + int sortval = model->GetMaterials().index(m) + 1; + + if (p->sortval != sortval) + p->sortval = sortval; + } + + // destroy the old segments and video data: + VideoPrivateData* video_data = surface->GetVideoPrivateData(); + surface->SetVideoPrivateData(0); + surface->GetSegments().destroy(); + + delete video_data; + + // sort the polys by material index: + qsort((void*) polys, npolys, sizeof(Poly), mcomp); + + // create new cohesive segments: + Segment* segment = 0; + + for (int n = 0; n < npolys; n++) { + if (segment && segment->material == polys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new Segment; + + segment->npolys = 1; + segment->polys = polys + n; + segment->material = segment->polys->material; + + surface->GetSegments().append(segment); + } + } + } + } +} + + +// +----------------------------------------------------------------------+ +// +----------------------------------------------------------------------+ +// +----------------------------------------------------------------------+ + +EditCommand::EditCommand(const char* n, MagicDoc* d) + : Command(n, d), model1(0), model2(0) +{ +} + +EditCommand::~EditCommand() +{ + delete model1; + delete model2; +} + +// +----------------------------------------------------------------------+ + +void +EditCommand::Do() +{ + if (document) { + Solid* solid = document->GetSolid(); + + // first application: + if (!model2) { + if (!model1) + model1 = new Model(*solid->GetModel()); + } + // re-do: + else { + solid->GetModel()->operator=(*model2); + } + } +} + +// +----------------------------------------------------------------------+ + +void +EditCommand::Undo() +{ + if (document && model1) { + Solid* solid = document->GetSolid(); + + // save current state for later re-do: + if (!model2) + model2 = new Model(*solid->GetModel()); + + solid->GetModel()->operator=(*model1); + } +} + diff --git a/Magic2/Editor.h b/Magic2/Editor.h index c0326e2..b8cba52 100644 --- a/Magic2/Editor.h +++ b/Magic2/Editor.h @@ -1,84 +1,108 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Editor.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Classes for rendering solid meshes of polygons -*/ - -#ifndef Editor_h -#define Editor_h - -#include "MagicDoc.h" -#include "Command.h" -#include "Polygon.h" -#include "Solid.h" -#include "Video.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -class Selection; -class ModelView; - -// +--------------------------------------------------------------------+ - -class Editor -{ -public: - Editor(MagicDoc* doc) : document(doc), model(0) { } - - // accessors / mutators - void UseModel(Model* m) { model = m; } - Model* GetModel() const { return model; } - - // operations - - enum { MAP_NONE, MAP_PLANAR, MAP_CYLINDRICAL, MAP_SPHERICAL, MAP_STRETCH }; - - void ApplyMaterial(Material* material, List& polys, - int mapping, int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate); - - void ApplyMaterialCylindrical(Material* material, List& polys, - int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate); - - void ApplyMaterialSpherical(Material* material, List& polys, - int axis, float scale_u, float scale_v, - int flip, int mirror, int rotate); - - - void Resegment(); - -protected: - MagicDoc* document; - Model* model; -}; - -// +--------------------------------------------------------------------+ - -class EditCommand : public Command -{ -public: - EditCommand(const char* name, MagicDoc* doc); - virtual ~EditCommand(); - - virtual void Do(); - virtual void Undo(); - -private: - Model* model1; - Model* model2; -}; - -// +--------------------------------------------------------------------+ - -#endif Editor_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Editor.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Classes for rendering solid meshes of polygons +*/ + +#ifndef Editor_h +#define Editor_h + +#include "MagicDoc.h" +#include "Command.h" +#include "Polygon.h" +#include "Solid.h" +#include "Video.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +class Selection; +class ModelView; + +// +--------------------------------------------------------------------+ + +class Editor +{ +public: + Editor(MagicDoc* doc) : document(doc), model(0) { } + + // accessors / mutators + void UseModel(Model* m) { model = m; } + Model* GetModel() const { return model; } + + // operations + + enum { MAP_NONE, MAP_PLANAR, MAP_CYLINDRICAL, MAP_SPHERICAL, MAP_STRETCH }; + + void ApplyMaterial(Material* material, List& polys, + int mapping, int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate); + + void ApplyMaterialCylindrical(Material* material, List& polys, + int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate); + + void ApplyMaterialSpherical(Material* material, List& polys, + int axis, float scale_u, float scale_v, + int flip, int mirror, int rotate); + + + void Resegment(); + +protected: + MagicDoc* document; + Model* model; +}; + +// +--------------------------------------------------------------------+ + +class EditCommand : public Command +{ +public: + EditCommand(const char* name, MagicDoc* doc); + virtual ~EditCommand(); + + virtual void Do(); + virtual void Undo(); + +private: + Model* model1; + Model* model2; +}; + +// +--------------------------------------------------------------------+ + +#endif Editor_h + diff --git a/Magic2/Grid.cpp b/Magic2/Grid.cpp index 3499591..133f26c 100644 --- a/Magic2/Grid.cpp +++ b/Magic2/Grid.cpp @@ -1,346 +1,370 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Grid.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the Grid class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MagicDoc.h" -#include "Grid.h" - -#include "ActiveWindow.h" -#include "Color.h" -#include "Polygon.h" -#include "Scene.h" -#include "Screen.h" -#include "Solid.h" -#include "Video.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -const int MAJOR_COUNT = 64; - -// +--------------------------------------------------------------------+ - -Grid::Grid() - : x_major(0), y_major(0), x_minor(0), y_minor(0), - bmp_plan(0), bmp_front(0), bmp_side(0) -{ - strcpy(name, "Grid"); - - plane = GRID_XZ; // plan - - show = true; - show_ref = true; - snap = true; - minor = true; - - x_size = 4; - y_size = 4; - x_skip = 4; - y_skip = 4; - - x_major = new Vec3[2*MAJOR_COUNT]; - y_major = new Vec3[2*MAJOR_COUNT]; -} - -Grid::~Grid() -{ - delete [] x_major; - delete [] y_major; - delete [] x_minor; - delete [] y_minor; -} - -// +--------------------------------------------------------------------+ - -const char* -Grid::GetReferencePlan() const -{ - if (bmp_plan) - return bmp_plan->GetFilename(); - - return ""; -} - -void -Grid::SetReferencePlan(const char* fname) -{ - bmp_plan = 0; - - if (fname && *fname) - LoadTexture(fname, bmp_plan); -} - -// +--------------------------------------------------------------------+ - -const char* -Grid::GetReferenceFront() const -{ - if (bmp_front) - return bmp_front->GetFilename(); - - return ""; -} - -void -Grid::SetReferenceFront(const char* fname) -{ - bmp_front = 0; - - if (fname && *fname) - LoadTexture(fname, bmp_front); -} - -// +--------------------------------------------------------------------+ - -const char* -Grid::GetReferenceSide() const -{ - if (bmp_side) - return bmp_side->GetFilename(); - - return ""; -} - -void -Grid::SetReferenceSide(const char* fname) -{ - bmp_side = 0; - - if (fname && *fname) - LoadTexture(fname, bmp_side); -} - -// +--------------------------------------------------------------------+ - -void -Grid::Render(Video* video, DWORD flags) -{ - Vec3 origin[4]; - - for (int i = 0; i < 4; i++) - origin[i] = loc; - - const float EXTENT = (float) MAJOR_COUNT * 64.0f; - - switch (plane) { - case GRID_XY: // FRONT - origin[0].x += -EXTENT; - origin[1].x += EXTENT; - origin[2].y += -EXTENT; - origin[3].y += EXTENT; - - for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { - float x = (float) (i-MAJOR_COUNT) * 64.0f; - float y = (float) (i-MAJOR_COUNT) * 64.0f; - - x_major[i ] = loc + Vec3(x, -EXTENT, 0.0f); - x_major[i+1] = loc + Vec3(x, EXTENT, 0.0f); - y_major[i ] = loc + Vec3(-EXTENT, y, 0.0f); - y_major[i+1] = loc + Vec3( EXTENT, y, 0.0f); - } - - break; - - case GRID_XZ: // PLAN - origin[0].x += -EXTENT; - origin[1].x += EXTENT; - origin[2].z += -EXTENT; - origin[3].z += EXTENT; - - for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { - float x = (float) (i-MAJOR_COUNT) * 64.0f; - float z = (float) (i-MAJOR_COUNT) * 64.0f; - - x_major[i ] = loc + Vec3(x, 0.0f, -EXTENT); - x_major[i+1] = loc + Vec3(x, 0.0f, EXTENT); - y_major[i ] = loc + Vec3(-EXTENT, 0.0f, z); - y_major[i+1] = loc + Vec3( EXTENT, 0.0f, z); - } - - break; - - case GRID_YZ: // SIDE - origin[0].y += -EXTENT; - origin[1].y += EXTENT; - origin[2].z += -EXTENT; - origin[3].z += EXTENT; - - for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { - float y = (float) (i-MAJOR_COUNT) * 64.0f; - float z = (float) (i-MAJOR_COUNT) * 64.0f; - - x_major[i ] = loc + Vec3(0.0f, y, -EXTENT); - x_major[i+1] = loc + Vec3(0.0f, y, EXTENT); - y_major[i ] = loc + Vec3(0.0f, -EXTENT, z); - y_major[i+1] = loc + Vec3(0.0f, EXTENT, z); - } - - break; - } - - RenderReference(video); - - video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); - video->SetRenderState(Video::LIGHTING_ENABLE, FALSE); - video->SetRenderState(Video::Z_ENABLE, TRUE); - video->SetRenderState(Video::Z_WRITE_ENABLE, TRUE); - - video->DrawLines(MAJOR_COUNT, x_major, Color::Gray, 1); - video->DrawLines(MAJOR_COUNT, y_major, Color::Gray, 1); - video->DrawLines( 2, origin, Color::DarkGray, 1); -} - -// +--------------------------------------------------------------------+ - -void -Grid::RenderReference(Video* video) -{ - if (!show_ref) return; - - Bitmap* bmp = 0; - - switch (plane) { - case GRID_XY: bmp = bmp_front; break; - case GRID_XZ: bmp = bmp_plan; break; - case GRID_YZ: bmp = bmp_side; break; - } - - if (!bmp) return; - - Material mtl; - VertexSet vset(4); - Poly poly; - Vec3 nrm; - - float vx = (float) bmp->Width(); - float vy = (float) bmp->Height(); - float vz = -100.0f; - - if (vx <= 256 || vy <= 256) { - vx *= 2.0f; - vy *= 2.0f; - } - - switch (plane) { - case GRID_XY: // FRONT - nrm = Vec3(0.0f, 0.0f, 1.0f); - vset.loc[0] = loc + Vec3(-vx, -vy, vz); - vset.loc[1] = loc + Vec3( vx, -vy, vz); - vset.loc[2] = loc + Vec3( vx, vy, vz); - vset.loc[3] = loc + Vec3(-vx, vy, vz); - break; - - case GRID_XZ: // PLAN - nrm = Vec3(0.0f, 1.0f, 0.0f); - vset.loc[0] = loc + Vec3(-vx, vz, vy); - vset.loc[1] = loc + Vec3( vx, vz, vy); - vset.loc[2] = loc + Vec3( vx, vz, -vy); - vset.loc[3] = loc + Vec3(-vx, vz, -vy); - break; - - case GRID_YZ: // SIDE - nrm = Vec3(1.0f, 0.0f, 0.0f); - vset.loc[0] = loc + Vec3( vz, -vx, -vy); - vset.loc[1] = loc + Vec3( vz, vx, -vy); - vset.loc[2] = loc + Vec3( vz, vx, vy); - vset.loc[3] = loc + Vec3( vz, -vx, vy); - break; - - default: - return; - } - - mtl.Ka = Color::White; - mtl.Kd = Color::Black; - mtl.tex_diffuse = bmp; - - vset.nrm[0] = nrm; - vset.nrm[1] = nrm; - vset.nrm[2] = nrm; - vset.nrm[3] = nrm; - - vset.tu[0] = 0.0f; - vset.tv[0] = 0.0f; - vset.tu[1] = 1.0f; - vset.tv[1] = 0.0f; - vset.tu[2] = 1.0f; - vset.tv[2] = 1.0f; - vset.tu[3] = 0.0f; - vset.tv[3] = 1.0f; - - poly.nverts = 4; - poly.verts[0] = 0; - poly.verts[1] = 1; - poly.verts[2] = 2; - poly.verts[3] = 3; - poly.material = &mtl; - poly.vertex_set = &vset; - - video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); - video->SetRenderState(Video::LIGHTING_ENABLE, TRUE); - video->SetRenderState(Video::Z_ENABLE, FALSE); - video->SetRenderState(Video::Z_WRITE_ENABLE, FALSE); - video->SetAmbient(Color::White); - - video->DrawPolys(1, &poly); -} - -// +----------------------------------------------------------------------+ - -CPoint& -Grid::Snap(CPoint& p) -{ - p.x = snapto(p.x, x_size); - p.y = snapto(p.y, y_size); - - return p; -} - -// +----------------------------------------------------------------------+ - -int -Grid::snapto(int i, int dim) -{ - if (!snap) - return i; - - int n = i + dim/2; - int m = n % dim; - - return (n - m); -} - -// +----------------------------------------------------------------------+ - -void -Grid::SetSize(int x, int y) -{ - x_size = x; - y_size = y ? y : x; -} - -// +----------------------------------------------------------------------+ - -void -Grid::SetSkip(int x, int y) -{ - x_skip = x; - y_skip = y ? y : x; -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Grid.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the Grid class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "Grid.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Polygon.h" +#include "Scene.h" +#include "Screen.h" +#include "Solid.h" +#include "Video.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +const int MAJOR_COUNT = 64; + +// +--------------------------------------------------------------------+ + +Grid::Grid() + : x_major(0), y_major(0), x_minor(0), y_minor(0), + bmp_plan(0), bmp_front(0), bmp_side(0) +{ + strcpy(name, "Grid"); + + plane = GRID_XZ; // plan + + show = true; + show_ref = true; + snap = true; + minor = true; + + x_size = 4; + y_size = 4; + x_skip = 4; + y_skip = 4; + + x_major = new Vec3[2*MAJOR_COUNT]; + y_major = new Vec3[2*MAJOR_COUNT]; +} + +Grid::~Grid() +{ + delete [] x_major; + delete [] y_major; + delete [] x_minor; + delete [] y_minor; +} + +// +--------------------------------------------------------------------+ + +const char* +Grid::GetReferencePlan() const +{ + if (bmp_plan) + return bmp_plan->GetFilename(); + + return ""; +} + +void +Grid::SetReferencePlan(const char* fname) +{ + bmp_plan = 0; + + if (fname && *fname) + LoadTexture(fname, bmp_plan); +} + +// +--------------------------------------------------------------------+ + +const char* +Grid::GetReferenceFront() const +{ + if (bmp_front) + return bmp_front->GetFilename(); + + return ""; +} + +void +Grid::SetReferenceFront(const char* fname) +{ + bmp_front = 0; + + if (fname && *fname) + LoadTexture(fname, bmp_front); +} + +// +--------------------------------------------------------------------+ + +const char* +Grid::GetReferenceSide() const +{ + if (bmp_side) + return bmp_side->GetFilename(); + + return ""; +} + +void +Grid::SetReferenceSide(const char* fname) +{ + bmp_side = 0; + + if (fname && *fname) + LoadTexture(fname, bmp_side); +} + +// +--------------------------------------------------------------------+ + +void +Grid::Render(Video* video, DWORD flags) +{ + Vec3 origin[4]; + + for (int i = 0; i < 4; i++) + origin[i] = loc; + + const float EXTENT = (float) MAJOR_COUNT * 64.0f; + + switch (plane) { + case GRID_XY: // FRONT + origin[0].x += -EXTENT; + origin[1].x += EXTENT; + origin[2].y += -EXTENT; + origin[3].y += EXTENT; + + for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { + float x = (float) (i-MAJOR_COUNT) * 64.0f; + float y = (float) (i-MAJOR_COUNT) * 64.0f; + + x_major[i ] = loc + Vec3(x, -EXTENT, 0.0f); + x_major[i+1] = loc + Vec3(x, EXTENT, 0.0f); + y_major[i ] = loc + Vec3(-EXTENT, y, 0.0f); + y_major[i+1] = loc + Vec3( EXTENT, y, 0.0f); + } + + break; + + case GRID_XZ: // PLAN + origin[0].x += -EXTENT; + origin[1].x += EXTENT; + origin[2].z += -EXTENT; + origin[3].z += EXTENT; + + for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { + float x = (float) (i-MAJOR_COUNT) * 64.0f; + float z = (float) (i-MAJOR_COUNT) * 64.0f; + + x_major[i ] = loc + Vec3(x, 0.0f, -EXTENT); + x_major[i+1] = loc + Vec3(x, 0.0f, EXTENT); + y_major[i ] = loc + Vec3(-EXTENT, 0.0f, z); + y_major[i+1] = loc + Vec3( EXTENT, 0.0f, z); + } + + break; + + case GRID_YZ: // SIDE + origin[0].y += -EXTENT; + origin[1].y += EXTENT; + origin[2].z += -EXTENT; + origin[3].z += EXTENT; + + for (int i = 0; i < 2*MAJOR_COUNT; i += 2) { + float y = (float) (i-MAJOR_COUNT) * 64.0f; + float z = (float) (i-MAJOR_COUNT) * 64.0f; + + x_major[i ] = loc + Vec3(0.0f, y, -EXTENT); + x_major[i+1] = loc + Vec3(0.0f, y, EXTENT); + y_major[i ] = loc + Vec3(0.0f, -EXTENT, z); + y_major[i+1] = loc + Vec3(0.0f, EXTENT, z); + } + + break; + } + + RenderReference(video); + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + video->SetRenderState(Video::LIGHTING_ENABLE, FALSE); + video->SetRenderState(Video::Z_ENABLE, TRUE); + video->SetRenderState(Video::Z_WRITE_ENABLE, TRUE); + + video->DrawLines(MAJOR_COUNT, x_major, Color::Gray, 1); + video->DrawLines(MAJOR_COUNT, y_major, Color::Gray, 1); + video->DrawLines( 2, origin, Color::DarkGray, 1); +} + +// +--------------------------------------------------------------------+ + +void +Grid::RenderReference(Video* video) +{ + if (!show_ref) return; + + Bitmap* bmp = 0; + + switch (plane) { + case GRID_XY: bmp = bmp_front; break; + case GRID_XZ: bmp = bmp_plan; break; + case GRID_YZ: bmp = bmp_side; break; + } + + if (!bmp) return; + + Material mtl; + VertexSet vset(4); + Poly poly; + Vec3 nrm; + + float vx = (float) bmp->Width(); + float vy = (float) bmp->Height(); + float vz = -100.0f; + + if (vx <= 256 || vy <= 256) { + vx *= 2.0f; + vy *= 2.0f; + } + + switch (plane) { + case GRID_XY: // FRONT + nrm = Vec3(0.0f, 0.0f, 1.0f); + vset.loc[0] = loc + Vec3(-vx, -vy, vz); + vset.loc[1] = loc + Vec3( vx, -vy, vz); + vset.loc[2] = loc + Vec3( vx, vy, vz); + vset.loc[3] = loc + Vec3(-vx, vy, vz); + break; + + case GRID_XZ: // PLAN + nrm = Vec3(0.0f, 1.0f, 0.0f); + vset.loc[0] = loc + Vec3(-vx, vz, vy); + vset.loc[1] = loc + Vec3( vx, vz, vy); + vset.loc[2] = loc + Vec3( vx, vz, -vy); + vset.loc[3] = loc + Vec3(-vx, vz, -vy); + break; + + case GRID_YZ: // SIDE + nrm = Vec3(1.0f, 0.0f, 0.0f); + vset.loc[0] = loc + Vec3( vz, -vx, -vy); + vset.loc[1] = loc + Vec3( vz, vx, -vy); + vset.loc[2] = loc + Vec3( vz, vx, vy); + vset.loc[3] = loc + Vec3( vz, -vx, vy); + break; + + default: + return; + } + + mtl.Ka = Color::White; + mtl.Kd = Color::Black; + mtl.tex_diffuse = bmp; + + vset.nrm[0] = nrm; + vset.nrm[1] = nrm; + vset.nrm[2] = nrm; + vset.nrm[3] = nrm; + + vset.tu[0] = 0.0f; + vset.tv[0] = 0.0f; + vset.tu[1] = 1.0f; + vset.tv[1] = 0.0f; + vset.tu[2] = 1.0f; + vset.tv[2] = 1.0f; + vset.tu[3] = 0.0f; + vset.tv[3] = 1.0f; + + poly.nverts = 4; + poly.verts[0] = 0; + poly.verts[1] = 1; + poly.verts[2] = 2; + poly.verts[3] = 3; + poly.material = &mtl; + poly.vertex_set = &vset; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + video->SetRenderState(Video::LIGHTING_ENABLE, TRUE); + video->SetRenderState(Video::Z_ENABLE, FALSE); + video->SetRenderState(Video::Z_WRITE_ENABLE, FALSE); + video->SetAmbient(Color::White); + + video->DrawPolys(1, &poly); +} + +// +----------------------------------------------------------------------+ + +CPoint& +Grid::Snap(CPoint& p) +{ + p.x = snapto(p.x, x_size); + p.y = snapto(p.y, y_size); + + return p; +} + +// +----------------------------------------------------------------------+ + +int +Grid::snapto(int i, int dim) +{ + if (!snap) + return i; + + int n = i + dim/2; + int m = n % dim; + + return (n - m); +} + +// +----------------------------------------------------------------------+ + +void +Grid::SetSize(int x, int y) +{ + x_size = x; + y_size = y ? y : x; +} + +// +----------------------------------------------------------------------+ + +void +Grid::SetSkip(int x, int y) +{ + x_skip = x; + y_skip = y ? y : x; +} + diff --git a/Magic2/Grid.h b/Magic2/Grid.h index 93c0201..7e0491c 100644 --- a/Magic2/Grid.h +++ b/Magic2/Grid.h @@ -1,81 +1,105 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Grid.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the Grid class -*/ - - -#ifndef Grid_h -#define Grid_h - -#include "Bitmap.h" -#include "Graphic.h" - -// +--------------------------------------------------------------------+ - -class Grid : public Graphic -{ -public: - enum PLANE { GRID_XY, GRID_XZ, GRID_YZ }; - - Grid(); - virtual ~Grid(); - - CPoint& Snap(CPoint& p); - - bool IsSnap() const { return snap; } - bool IsShow() const { return show; } - void SetSnap(bool s) { snap = s; } - void SetShow(bool s) { show = s; } - void SetSize(int x, int y = 0); - void SetSkip(int x, int y = 0); - void ShowMinor(bool show) { minor = show; } - void ShowPlane(int p) { plane = p; } - void ShowReference(bool show) { show_ref = show; } - - const char* GetReferencePlan() const; - void SetReferencePlan(const char* fname); - const char* GetReferenceFront() const; - void SetReferenceFront(const char* fname); - const char* GetReferenceSide() const; - void SetReferenceSide(const char* fname); - - int GetSize() const { return x_size; } - - // operations - virtual void Render(Video* video, DWORD flags); - virtual void RenderReference(Video* video); - -protected: - int snapto(int i, int dim); - - bool show; - bool show_ref; - bool snap; - bool minor; - - int x_size, y_size; - int x_skip, y_skip; - int plane; - - Vec3* x_major; - Vec3* x_minor; - Vec3* y_major; - Vec3* y_minor; - - Bitmap* bmp_plan; - Bitmap* bmp_front; - Bitmap* bmp_side; -}; - -// +--------------------------------------------------------------------+ - -#endif Grid_h +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Grid.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the Grid class +*/ + + +#ifndef Grid_h +#define Grid_h + +#include "Bitmap.h" +#include "Graphic.h" + +// +--------------------------------------------------------------------+ + +class Grid : public Graphic +{ +public: + enum PLANE { GRID_XY, GRID_XZ, GRID_YZ }; + + Grid(); + virtual ~Grid(); + + CPoint& Snap(CPoint& p); + + bool IsSnap() const { return snap; } + bool IsShow() const { return show; } + void SetSnap(bool s) { snap = s; } + void SetShow(bool s) { show = s; } + void SetSize(int x, int y = 0); + void SetSkip(int x, int y = 0); + void ShowMinor(bool show) { minor = show; } + void ShowPlane(int p) { plane = p; } + void ShowReference(bool show) { show_ref = show; } + + const char* GetReferencePlan() const; + void SetReferencePlan(const char* fname); + const char* GetReferenceFront() const; + void SetReferenceFront(const char* fname); + const char* GetReferenceSide() const; + void SetReferenceSide(const char* fname); + + int GetSize() const { return x_size; } + + // operations + virtual void Render(Video* video, DWORD flags); + virtual void RenderReference(Video* video); + +protected: + int snapto(int i, int dim); + + bool show; + bool show_ref; + bool snap; + bool minor; + + int x_size, y_size; + int x_skip, y_skip; + int plane; + + Vec3* x_major; + Vec3* x_minor; + Vec3* y_major; + Vec3* y_minor; + + Bitmap* bmp_plan; + Bitmap* bmp_front; + Bitmap* bmp_side; +}; + +// +--------------------------------------------------------------------+ + +#endif Grid_h diff --git a/Magic2/GridProps.cpp b/Magic2/GridProps.cpp index d375ea9..89ff991 100644 --- a/Magic2/GridProps.cpp +++ b/Magic2/GridProps.cpp @@ -1,126 +1,150 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: GridProps.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Grid Properties Dialog implementation file -*/ - - -#include "stdafx.h" -#include "Magic.h" -#include "GridProps.h" -#include "Grid.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// +--------------------------------------------------------------------+ -// GridProps dialog -// +--------------------------------------------------------------------+ - -GridProps::GridProps(Grid* g, CWnd* pParent /*=NULL*/) - : CDialog(GridProps::IDD, pParent), grid(g) -{ - //{{AFX_DATA_INIT(GridProps) - mGridShow = grid->IsShow(); - mGridSnap = grid->IsSnap(); - mReferencePlan = grid->GetReferencePlan(); - mReferenceFront = grid->GetReferenceFront(); - mReferenceSide = grid->GetReferenceSide(); - mGridSize = grid->GetSize(); - //}}AFX_DATA_INIT -} - -static const char* C(CString& str) -{ - static char buf[512]; - int i; - for (i = 0; i < str.GetLength(); i++) - buf[i] = (char) str.GetAt(i); - buf[i] = 0; - - return buf; -} - -void GridProps::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(GridProps) - DDX_Check(pDX, IDC_GRID_SHOW, mGridShow); - DDX_Check(pDX, IDC_GRID_SNAP, mGridSnap); - DDX_Text(pDX, IDC_REFERENCE_PLAN, mReferencePlan); - DDX_Text(pDX, IDC_REFERENCE_FRONT, mReferenceFront); - DDX_Text(pDX, IDC_REFERENCE_SIDE, mReferenceSide); - DDX_Text(pDX, IDC_GRID_SIZE, mGridSize); - DDV_MinMaxInt(pDX, mGridSize, 1, 64); - //}}AFX_DATA_MAP - - // if saving, write the values back to the grid - if (pDX->m_bSaveAndValidate) { - grid->SetSnap(mGridSnap ? true : false); - grid->SetShow(mGridShow ? true : false); - grid->SetSize(mGridSize); - - grid->SetReferencePlan(C(mReferencePlan)); - grid->SetReferenceFront(C(mReferenceFront)); - grid->SetReferenceSide(C(mReferenceSide)); - } -} - - -BEGIN_MESSAGE_MAP(GridProps, CDialog) - //{{AFX_MSG_MAP(GridProps) - ON_BN_CLICKED(IDC_FILE_PLAN, OnFilePlan) - ON_BN_CLICKED(IDC_FILE_FRONT, OnFileFront) - ON_BN_CLICKED(IDC_FILE_SIDE, OnFileSide) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ - -static void OnImageFile(CString& strImageFile) -{ - char filename[512]; - filename[0] = '\0'; - CFileDialog ofd(TRUE, "pcx"); - - ofd.m_ofn.lpstrFilter = "PCX Files\0*.pcx\0All Files\0*.*\0\0"; - ofd.m_ofn.lpstrFile = filename; - ofd.m_ofn.nMaxFile = sizeof(filename); - - if (ofd.DoModal() != IDOK) - return; - - char tex_name[512]; - sprintf(tex_name, "%s", ofd.GetFileName().GetBuffer(0)); - - strImageFile = tex_name; -} - -void GridProps::OnFilePlan() -{ - OnImageFile(mReferencePlan); - UpdateData(FALSE); -} - -void GridProps::OnFileFront() -{ - OnImageFile(mReferenceFront); - UpdateData(FALSE); -} - -void GridProps::OnFileSide() -{ - OnImageFile(mReferenceSide); - UpdateData(FALSE); -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: GridProps.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Grid Properties Dialog implementation file +*/ + + +#include "stdafx.h" +#include "Magic.h" +#include "GridProps.h" +#include "Grid.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ +// GridProps dialog +// +--------------------------------------------------------------------+ + +GridProps::GridProps(Grid* g, CWnd* pParent /*=NULL*/) + : CDialog(GridProps::IDD, pParent), grid(g) +{ + //{{AFX_DATA_INIT(GridProps) + mGridShow = grid->IsShow(); + mGridSnap = grid->IsSnap(); + mReferencePlan = grid->GetReferencePlan(); + mReferenceFront = grid->GetReferenceFront(); + mReferenceSide = grid->GetReferenceSide(); + mGridSize = grid->GetSize(); + //}}AFX_DATA_INIT +} + +static const char* C(CString& str) +{ + static char buf[512]; + int i; + for (i = 0; i < str.GetLength(); i++) + buf[i] = (char) str.GetAt(i); + buf[i] = 0; + + return buf; +} + +void GridProps::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(GridProps) + DDX_Check(pDX, IDC_GRID_SHOW, mGridShow); + DDX_Check(pDX, IDC_GRID_SNAP, mGridSnap); + DDX_Text(pDX, IDC_REFERENCE_PLAN, mReferencePlan); + DDX_Text(pDX, IDC_REFERENCE_FRONT, mReferenceFront); + DDX_Text(pDX, IDC_REFERENCE_SIDE, mReferenceSide); + DDX_Text(pDX, IDC_GRID_SIZE, mGridSize); + DDV_MinMaxInt(pDX, mGridSize, 1, 64); + //}}AFX_DATA_MAP + + // if saving, write the values back to the grid + if (pDX->m_bSaveAndValidate) { + grid->SetSnap(mGridSnap ? true : false); + grid->SetShow(mGridShow ? true : false); + grid->SetSize(mGridSize); + + grid->SetReferencePlan(C(mReferencePlan)); + grid->SetReferenceFront(C(mReferenceFront)); + grid->SetReferenceSide(C(mReferenceSide)); + } +} + + +BEGIN_MESSAGE_MAP(GridProps, CDialog) + //{{AFX_MSG_MAP(GridProps) + ON_BN_CLICKED(IDC_FILE_PLAN, OnFilePlan) + ON_BN_CLICKED(IDC_FILE_FRONT, OnFileFront) + ON_BN_CLICKED(IDC_FILE_SIDE, OnFileSide) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +static void OnImageFile(CString& strImageFile) +{ + char filename[512]; + filename[0] = '\0'; + CFileDialog ofd(TRUE, "pcx"); + + ofd.m_ofn.lpstrFilter = "PCX Files\0*.pcx\0All Files\0*.*\0\0"; + ofd.m_ofn.lpstrFile = filename; + ofd.m_ofn.nMaxFile = sizeof(filename); + + if (ofd.DoModal() != IDOK) + return; + + char tex_name[512]; + sprintf(tex_name, "%s", ofd.GetFileName().GetBuffer(0)); + + strImageFile = tex_name; +} + +void GridProps::OnFilePlan() +{ + OnImageFile(mReferencePlan); + UpdateData(FALSE); +} + +void GridProps::OnFileFront() +{ + OnImageFile(mReferenceFront); + UpdateData(FALSE); +} + +void GridProps::OnFileSide() +{ + OnImageFile(mReferenceSide); + UpdateData(FALSE); +} diff --git a/Magic2/GridProps.h b/Magic2/GridProps.h index c2dd77a..e5412e9 100644 --- a/Magic2/GridProps.h +++ b/Magic2/GridProps.h @@ -1,69 +1,93 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: GridProps.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Grid Properties Dialog interface file -*/ - -#if !defined(AFX_GRIDPROPS_H__79C78890_ABB9_4789_BFFC_29617CAC606E__INCLUDED_) -#define AFX_GRIDPROPS_H__79C78890_ABB9_4789_BFFC_29617CAC606E__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -// +--------------------------------------------------------------------+ -// GridProps dialog -// +--------------------------------------------------------------------+ - -class Grid; - -class GridProps : public CDialog -{ -// Construction -public: - GridProps(Grid* g, CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(GridProps) - enum { IDD = IDD_GRIDPROPS }; - BOOL mGridShow; - BOOL mGridSnap; - CString mReferencePlan; - CString mReferenceFront; - CString mReferenceSide; - int mGridSize; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(GridProps) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - Grid* grid; - - // Generated message map functions - //{{AFX_MSG(GridProps) - afx_msg void OnFilePlan(); - afx_msg void OnFileFront(); - afx_msg void OnFileSide(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: GridProps.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Grid Properties Dialog interface file +*/ + +#if !defined(AFX_GRIDPROPS_H__79C78890_ABB9_4789_BFFC_29617CAC606E__INCLUDED_) +#define AFX_GRIDPROPS_H__79C78890_ABB9_4789_BFFC_29617CAC606E__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// +--------------------------------------------------------------------+ +// GridProps dialog +// +--------------------------------------------------------------------+ + +class Grid; + +class GridProps : public CDialog +{ +// Construction +public: + GridProps(Grid* g, CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(GridProps) + enum { IDD = IDD_GRIDPROPS }; + BOOL mGridShow; + BOOL mGridSnap; + CString mReferencePlan; + CString mReferenceFront; + CString mReferenceSide; + int mGridSize; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(GridProps) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + Grid* grid; + + // Generated message map functions + //{{AFX_MSG(GridProps) + afx_msg void OnFilePlan(); + afx_msg void OnFileFront(); + afx_msg void OnFileSide(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif diff --git a/Magic2/Locale_ss.cpp b/Magic2/Locale_ss.cpp index 9a87650..d079791 100644 --- a/Magic2/Locale_ss.cpp +++ b/Magic2/Locale_ss.cpp @@ -1,237 +1,261 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2006. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: Locale.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - 3D Locale (Polygon) Object -*/ - -#include "MemDebug.h" -#include "Locale_ss.h" - -void Print(const char* fmt, ...); - -// +--------------------------------------------------------------------+ - -static List locales; - -// +--------------------------------------------------------------------+ - -Locale::Locale(const char* l, const char* c, const char* v) -{ - ZeroMemory(this, sizeof(Locale)); - if (l && *l) { - strncpy_s(language, l, 6); - char* p = language; - while (*p) { - *p = tolower(*p); - p++; - } - } - - if (c && *c) { - strncpy_s(country, c, 6); - char* p = country; - while (*p) { - *p = toupper(*p); - p++; - } - } - - if (v && *v) { - strncpy_s(variant, v, 6); - char* p = variant; - while (*p) { - *p = tolower(*p); - p++; - } - } - - locales.append(this); -} - -// +--------------------------------------------------------------------+ - -Locale::~Locale() -{ - locales.remove(this); -} - -// +--------------------------------------------------------------------+ - -int -Locale::operator == (const Locale& that) const -{ - if (this == &that) return 1; - - return !_stricmp(language, that.language) && - !_stricmp(country, that.country) && - !_stricmp(variant, that.variant); -} - -// +--------------------------------------------------------------------+ - -Locale* -Locale::ParseLocale(const char* str) -{ - if (str && *str) { - int i = 0; - char s1[4]; - char s2[4]; - char s3[4]; - - while (*str && *str != '_' && i < 3) { - s1[i] = *str++; - i++; - } - s1[i] = 0; - i = 0; - - if (*str == '_') - str++; - - while (*str && *str != '_' && i < 3) { - s2[i] = *str++; - i++; - } - s2[i] = 0; - i = 0; - - if (*str == '_') - str++; - - while (*str && *str != '_' && i < 3) { - s3[i] = *str++; - i++; - } - s3[i] = 0; - i = 0; - - return CreateLocale(s1, s2, s3); - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -Locale* -Locale::CreateLocale(const char* l, const char* c, const char* v) -{ - ListIter iter = locales; - while (++iter) { - Locale* loc = iter.value(); - if (!_stricmp(l, loc->GetLanguage())) { - if (c && *c) { - if (!_stricmp(c, loc->GetCountry())) { - if (v && *v) { - if (!_stricmp(v, loc->GetVariant())) { - return loc; - } - } - else { - return loc; - } - } - } - else { - return loc; - } - } - } - - if (l[0]) { - if (c[0]) { - if (v[0]) { - return new(__FILE__,__LINE__) Locale(l, c, v); - } - return new(__FILE__,__LINE__) Locale(l, c); - } - return new(__FILE__,__LINE__) Locale(l); - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -const List& -Locale::GetAllLocales() -{ - return locales; -} - -// +--------------------------------------------------------------------+ - -const Text -Locale::GetFullCode() const -{ - Text result = language; - if (*country) { - result.append("_"); - result.append(country); - - if (*variant) { - result.append("_"); - result.append(variant); - } - } - return result; -} - -// +--------------------------------------------------------------------+ - -static const char* languages[] = { - "en", "English", - "fr", "French", - "de", "German", - "it", "Italian", - "pt", "Portuguese", - "ru", "Russian", - "es", "Spanish" -}; - -static const char* countries[] = { - "US", "USA", - "CA", "Canada", - "FR", "France", - "DE", "Germany", - "IT", "Italy", - "PT", "Portugal", - "RU", "Russia", - "ES", "Spain", - "UK", "United Kingdom" -}; - -const Text -Locale::GetDisplayName() const -{ - Text result; - if (*language) { - for (int i = 0; i < 14; i += 2) { - if (!_stricmp(language, languages[i])) { - result = languages[i+1]; - break; - } - } - - if (*country) { - for (int i = 0; i < 18; i += 2) { - if (!_stricmp(country, countries[i])) { - result.append(" - "); - result.append(countries[i+1]); - break; - } - } - } - - } - return result; -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: Locale.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + 3D Locale (Polygon) Object +*/ + +#include "MemDebug.h" +#include "Locale_ss.h" + +void Print(const char* fmt, ...); + +// +--------------------------------------------------------------------+ + +static List locales; + +// +--------------------------------------------------------------------+ + +Locale::Locale(const char* l, const char* c, const char* v) +{ + ZeroMemory(this, sizeof(Locale)); + if (l && *l) { + strncpy_s(language, l, 6); + char* p = language; + while (*p) { + *p = tolower(*p); + p++; + } + } + + if (c && *c) { + strncpy_s(country, c, 6); + char* p = country; + while (*p) { + *p = toupper(*p); + p++; + } + } + + if (v && *v) { + strncpy_s(variant, v, 6); + char* p = variant; + while (*p) { + *p = tolower(*p); + p++; + } + } + + locales.append(this); +} + +// +--------------------------------------------------------------------+ + +Locale::~Locale() +{ + locales.remove(this); +} + +// +--------------------------------------------------------------------+ + +int +Locale::operator == (const Locale& that) const +{ + if (this == &that) return 1; + + return !_stricmp(language, that.language) && + !_stricmp(country, that.country) && + !_stricmp(variant, that.variant); +} + +// +--------------------------------------------------------------------+ + +Locale* +Locale::ParseLocale(const char* str) +{ + if (str && *str) { + int i = 0; + char s1[4]; + char s2[4]; + char s3[4]; + + while (*str && *str != '_' && i < 3) { + s1[i] = *str++; + i++; + } + s1[i] = 0; + i = 0; + + if (*str == '_') + str++; + + while (*str && *str != '_' && i < 3) { + s2[i] = *str++; + i++; + } + s2[i] = 0; + i = 0; + + if (*str == '_') + str++; + + while (*str && *str != '_' && i < 3) { + s3[i] = *str++; + i++; + } + s3[i] = 0; + i = 0; + + return CreateLocale(s1, s2, s3); + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +Locale* +Locale::CreateLocale(const char* l, const char* c, const char* v) +{ + ListIter iter = locales; + while (++iter) { + Locale* loc = iter.value(); + if (!_stricmp(l, loc->GetLanguage())) { + if (c && *c) { + if (!_stricmp(c, loc->GetCountry())) { + if (v && *v) { + if (!_stricmp(v, loc->GetVariant())) { + return loc; + } + } + else { + return loc; + } + } + } + else { + return loc; + } + } + } + + if (l[0]) { + if (c[0]) { + if (v[0]) { + return new(__FILE__,__LINE__) Locale(l, c, v); + } + return new(__FILE__,__LINE__) Locale(l, c); + } + return new(__FILE__,__LINE__) Locale(l); + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +const List& +Locale::GetAllLocales() +{ + return locales; +} + +// +--------------------------------------------------------------------+ + +const Text +Locale::GetFullCode() const +{ + Text result = language; + if (*country) { + result.append("_"); + result.append(country); + + if (*variant) { + result.append("_"); + result.append(variant); + } + } + return result; +} + +// +--------------------------------------------------------------------+ + +static const char* languages[] = { + "en", "English", + "fr", "French", + "de", "German", + "it", "Italian", + "pt", "Portuguese", + "ru", "Russian", + "es", "Spanish" +}; + +static const char* countries[] = { + "US", "USA", + "CA", "Canada", + "FR", "France", + "DE", "Germany", + "IT", "Italy", + "PT", "Portugal", + "RU", "Russia", + "ES", "Spain", + "UK", "United Kingdom" +}; + +const Text +Locale::GetDisplayName() const +{ + Text result; + if (*language) { + for (int i = 0; i < 14; i += 2) { + if (!_stricmp(language, languages[i])) { + result = languages[i+1]; + break; + } + } + + if (*country) { + for (int i = 0; i < 18; i += 2) { + if (!_stricmp(country, countries[i])) { + result.append(" - "); + result.append(countries[i+1]); + break; + } + } + } + + } + return result; +} + diff --git a/Magic2/Locale_ss.h b/Magic2/Locale_ss.h index 551c379..29c12cf 100644 --- a/Magic2/Locale_ss.h +++ b/Magic2/Locale_ss.h @@ -1,53 +1,77 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2006. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: Locale.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Description of locale by ISO language, country, and variant -*/ - -#ifndef Locale_h -#define Locale_h - -#include "List.h" -#include "Text.h" - -// +--------------------------------------------------------------------+ - -class Locale -{ -public: - static const char* TYPENAME() { return "Locale"; } - - Locale(const char* language, const char* country=0, const char* variant=0); - ~Locale(); - - int operator == (const Locale& that) const; - - // Operations: - static const List& GetAllLocales(); - static Locale* ParseLocale(const char* str); - - // Property accessors: - const char* GetLanguage() const { return language; } - const char* GetCountry() const { return country; } - const char* GetVariant() const { return variant; } - const Text GetFullCode() const; - const Text GetDisplayName() const; - - -protected: - static Locale* CreateLocale(const char* language, const char* country=0, const char* variant=0); - char language[8]; - char country[8]; - char variant[8]; -}; - -#endif Locale_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: Locale.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Description of locale by ISO language, country, and variant +*/ + +#ifndef Locale_h +#define Locale_h + +#include "List.h" +#include "Text.h" + +// +--------------------------------------------------------------------+ + +class Locale +{ +public: + static const char* TYPENAME() { return "Locale"; } + + Locale(const char* language, const char* country=0, const char* variant=0); + ~Locale(); + + int operator == (const Locale& that) const; + + // Operations: + static const List& GetAllLocales(); + static Locale* ParseLocale(const char* str); + + // Property accessors: + const char* GetLanguage() const { return language; } + const char* GetCountry() const { return country; } + const char* GetVariant() const { return variant; } + const Text GetFullCode() const; + const Text GetDisplayName() const; + + +protected: + static Locale* CreateLocale(const char* language, const char* country=0, const char* variant=0); + char language[8]; + char country[8]; + char variant[8]; +}; + +#endif Locale_h + diff --git a/Magic2/M3DS.cpp b/Magic2/M3DS.cpp index 21ac41a..f5b5fc5 100644 --- a/Magic2/M3DS.cpp +++ b/Magic2/M3DS.cpp @@ -1,263 +1,287 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFile3DS.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for 3DStudio MAX 3DS format models -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "ModelFile3DS.h" - -#include "Bitmap.h" -#include "Polygon.h" -#include "Text.h" -#include "List.h" -#include "ArrayList.h" - -// +--------------------------------------------------------------------+ - -struct Chunk -{ - WORD id; - DWORD len; - BYTE* start; - - List chunks; -}; - -// +--------------------------------------------------------------------+ - -struct Vec2 -{ - float u,v; -}; - -struct Triangle -{ - WORD a,b,c; -}; - -struct Triangle2 -{ - Vec3 vloc[3]; - Vec3 vnrm[3]; - Vec2 vtex[3]; - Vec3 fnrm; - DWORD mtl_id; -}; - -struct TextureMap -{ - char fname[256]; - float strength; - float u_scale; - float v_scale; - float u_offset; - float v_offset; - float angle; -}; - -// +--------------------------------------------------------------------+ - -class Object3DS -{ -public: - Object3DS(); - virtual ~Object3DS(); - - virtual const char* GetName(); - virtual bool IsObject(const char* name); - -protected: - Text name; -}; - -// +--------------------------------------------------------------------+ - -class Material3DS : public Object3DS -{ -public: - Material3DS(); - virtual ~Material3DS(); - - DWORD GetID(); - TextureMap& GetTextureMap1(); - TextureMap& GetTextureMap2(); - TextureMap& GetOpacityMap(); - TextureMap& GetSpecularMap(); - TextureMap& GetBumpMap(); - TextureMap& GetReflectionMap(); - ColorValue GetAmbientColor(); - ColorValue GetDiffuseColor(); - ColorValue GetSpecularColor(); - float GetShininess(); - float GetTransparency(); - DWORD GetShadingType(); - - // this methods should not be used by the "user", they're used internally to fill the class - // with valid data when reading from file. If you're about to add an importer for another format you'LL - // have to use these methods - - void SetID(DWORD value); - void SetAmbientColor(const ColorValue &color); - void SetDiffuseColor(const ColorValue &color); - void SetSpecularColor(const ColorValue &color); - void SetShininess(float value); - void SetTransparency(float value); - void SetShadingType(DWORD shading); - -protected: - int id; - TextureMap texMap1; - TextureMap texMap2; - TextureMap opacMap; - TextureMap refTextureMap; - TextureMap bumpMap; - TextureMap specMap; - ColorValue ambient; - ColorValue diffuse; - ColorValue specular; - float shininess; - float transparency; - DWORD shading; -}; - -// +--------------------------------------------------------------------+ - -class Mesh3DS : public Object3DS -{ -public: - Mesh3DS(); - virtual ~Mesh3DS(); - - void Clear(); - - DWORD GetVertexCount(); - void SetVertexArraySize(DWORD value); - DWORD GetTriangleCount(); - void SetTriangleArraySize(DWORD value); - - const Vec3& GetVertex(DWORD index); - const Vec3& GetNormal(DWORD index); - const Vec2& GetUV(DWORD index); - const Vec3& GetTangent(DWORD index); - const Vec3& GetBinormal(DWORD index); - - void SetVertex(const Vec3 &vec, DWORD index); - void SetNormal(const Vec3 &vec, DWORD index); - void SetUV(const Vec2 &vec, DWORD index); - void SetTangent(const Vec3 &vec, DWORD index); - void SetBinormal(const Vec3 &vec, DWORD index); - - const Triangle& GetTriangle(DWORD index); - Triangle2 GetTriangle2(DWORD index); - - Matrix& GetMatrix(); - void SetMatrix(Matrix& m); - void Optimize(int level); - - DWORD GetMaterial(DWORD index); - DWORD AddMaterial(DWORD id); - DWORD GetMaterialCount(); - -protected: - // the vertices, normals, etc. - List vertices; - List normals; - List binormals; - List tangents; - List uv; - - // triangles - List triangles; - - // the transformation matrix. - Matrix matrix; - - // the material ID array - ArrayList materials; - - void CalcNormals(bool useSmoothingGroups); - void CalcTextureSpace(); - - void TransformVertices(); -}; - - -// +--------------------------------------------------------------------+ -// +--------------------------------------------------------------------+ -// +--------------------------------------------------------------------+ - -ModelFile3DS::ModelFile3DS(const char* fname) - : ModelFile(fname) -{ -} - -ModelFile3DS::~ModelFile3DS() -{ -} - -// +--------------------------------------------------------------------+ - -static int mcomp(const void* a, const void* b) -{ - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; - - if (pa->sortval == pb->sortval) - return 0; - - if (pa->sortval < pb->sortval) - return 1; - - return -1; -} - -bool -ModelFile3DS::Load(Model* m, double scale) -{ - if (m && scale > 0 && strlen(filename) > 0) { - ModelFile::Load(m, scale); - - FILE* fp = fopen(filename, "rb"); - fclose(fp); - - m->Normalize(); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -ModelFile3DS::Save(Model* m) -{ - if (m) { - ModelFile::Save(m); - - FILE* f = fopen(filename, "w"); - if (!f) { - ::MessageBox(0, "Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); - return false; - } - - fclose(f); - - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFile3DS.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for 3DStudio MAX 3DS format models +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "ModelFile3DS.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "Text.h" +#include "List.h" +#include "ArrayList.h" + +// +--------------------------------------------------------------------+ + +struct Chunk +{ + WORD id; + DWORD len; + BYTE* start; + + List chunks; +}; + +// +--------------------------------------------------------------------+ + +struct Vec2 +{ + float u,v; +}; + +struct Triangle +{ + WORD a,b,c; +}; + +struct Triangle2 +{ + Vec3 vloc[3]; + Vec3 vnrm[3]; + Vec2 vtex[3]; + Vec3 fnrm; + DWORD mtl_id; +}; + +struct TextureMap +{ + char fname[256]; + float strength; + float u_scale; + float v_scale; + float u_offset; + float v_offset; + float angle; +}; + +// +--------------------------------------------------------------------+ + +class Object3DS +{ +public: + Object3DS(); + virtual ~Object3DS(); + + virtual const char* GetName(); + virtual bool IsObject(const char* name); + +protected: + Text name; +}; + +// +--------------------------------------------------------------------+ + +class Material3DS : public Object3DS +{ +public: + Material3DS(); + virtual ~Material3DS(); + + DWORD GetID(); + TextureMap& GetTextureMap1(); + TextureMap& GetTextureMap2(); + TextureMap& GetOpacityMap(); + TextureMap& GetSpecularMap(); + TextureMap& GetBumpMap(); + TextureMap& GetReflectionMap(); + ColorValue GetAmbientColor(); + ColorValue GetDiffuseColor(); + ColorValue GetSpecularColor(); + float GetShininess(); + float GetTransparency(); + DWORD GetShadingType(); + + // this methods should not be used by the "user", they're used internally to fill the class + // with valid data when reading from file. If you're about to add an importer for another format you'LL + // have to use these methods + + void SetID(DWORD value); + void SetAmbientColor(const ColorValue &color); + void SetDiffuseColor(const ColorValue &color); + void SetSpecularColor(const ColorValue &color); + void SetShininess(float value); + void SetTransparency(float value); + void SetShadingType(DWORD shading); + +protected: + int id; + TextureMap texMap1; + TextureMap texMap2; + TextureMap opacMap; + TextureMap refTextureMap; + TextureMap bumpMap; + TextureMap specMap; + ColorValue ambient; + ColorValue diffuse; + ColorValue specular; + float shininess; + float transparency; + DWORD shading; +}; + +// +--------------------------------------------------------------------+ + +class Mesh3DS : public Object3DS +{ +public: + Mesh3DS(); + virtual ~Mesh3DS(); + + void Clear(); + + DWORD GetVertexCount(); + void SetVertexArraySize(DWORD value); + DWORD GetTriangleCount(); + void SetTriangleArraySize(DWORD value); + + const Vec3& GetVertex(DWORD index); + const Vec3& GetNormal(DWORD index); + const Vec2& GetUV(DWORD index); + const Vec3& GetTangent(DWORD index); + const Vec3& GetBinormal(DWORD index); + + void SetVertex(const Vec3 &vec, DWORD index); + void SetNormal(const Vec3 &vec, DWORD index); + void SetUV(const Vec2 &vec, DWORD index); + void SetTangent(const Vec3 &vec, DWORD index); + void SetBinormal(const Vec3 &vec, DWORD index); + + const Triangle& GetTriangle(DWORD index); + Triangle2 GetTriangle2(DWORD index); + + Matrix& GetMatrix(); + void SetMatrix(Matrix& m); + void Optimize(int level); + + DWORD GetMaterial(DWORD index); + DWORD AddMaterial(DWORD id); + DWORD GetMaterialCount(); + +protected: + // the vertices, normals, etc. + List vertices; + List normals; + List binormals; + List tangents; + List uv; + + // triangles + List triangles; + + // the transformation matrix. + Matrix matrix; + + // the material ID array + ArrayList materials; + + void CalcNormals(bool useSmoothingGroups); + void CalcTextureSpace(); + + void TransformVertices(); +}; + + +// +--------------------------------------------------------------------+ +// +--------------------------------------------------------------------+ +// +--------------------------------------------------------------------+ + +ModelFile3DS::ModelFile3DS(const char* fname) + : ModelFile(fname) +{ +} + +ModelFile3DS::~ModelFile3DS() +{ +} + +// +--------------------------------------------------------------------+ + +static int mcomp(const void* a, const void* b) +{ + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; + + if (pa->sortval == pb->sortval) + return 0; + + if (pa->sortval < pb->sortval) + return 1; + + return -1; +} + +bool +ModelFile3DS::Load(Model* m, double scale) +{ + if (m && scale > 0 && strlen(filename) > 0) { + ModelFile::Load(m, scale); + + FILE* fp = fopen(filename, "rb"); + fclose(fp); + + m->Normalize(); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +ModelFile3DS::Save(Model* m) +{ + if (m) { + ModelFile::Save(m); + + FILE* f = fopen(filename, "w"); + if (!f) { + ::MessageBox(0, "Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); + return false; + } + + fclose(f); + + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ diff --git a/Magic2/M3DS.h b/Magic2/M3DS.h index b60ff71..f9b002a 100644 --- a/Magic2/M3DS.h +++ b/Magic2/M3DS.h @@ -1,329 +1,353 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: M3DS.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Window class -*/ - -// parts copyright (c) 2001-2002 Lev Povalahev - -#ifndef M3DS_H -#define M3DS_H - -#include "List.h" - -// +--------------------------------------------------------------------+ - -struct Chunk -{ - WORD id; - DWORD len; - BYTE* start; - - List chunks; -}; - -// +--------------------------------------------------------------------+ - -struct LTriangle -{ - WORD a,b,c; -}; - -struct LTriangle2 -{ - Point vertices[3]; - Vec3 vertexNormals[3]; - LVector2 textureCoords[3]; - Vec3 faceNormal; - DWORD materialId; -}; - -struct TextureMap -{ - char fname[256]; - float strength; - float u_scale; - float v_scale; - float u_offset; - float v_offset; - float angle; -}; - -// +--------------------------------------------------------------------+ - -class LObject -{ -public: - LObject(); - virtual ~LObject(); - - virtual const char* GetName(); - virtual bool IsObject(const const char* name); - -protected: - Text name; -}; - -// +--------------------------------------------------------------------+ - -class LMaterial : public LObject -{ -public: - LMaterial(); - virtual ~LMaterial(); - - DWORD GetID(); - TextureMap& GetTextureMap1(); - TextureMap& GetTextureMap2(); - TextureMap& GetOpacityMap(); - TextureMap& GetSpecularMap(); - TextureMap& GetBumpMap(); - TextureMap& GetReflectionMap(); - ColorValue GetAmbientColor(); - ColorValue GetDiffuseColor(); - ColorValue GetSpecularColor(); - float GetShininess(); - float GetTransparency(); - DWORD GetShadingType(); - - // this methods should not be used by the "user", they're used internally to fill the class - // with valid data when reading from file. If you're about to add an importer for another format you'LL - // have to use these methods - - void SetID(DWORD value); - void SetAmbientColor(const ColorValue &color); - void SetDiffuseColor(const ColorValue &color); - void SetSpecularColor(const ColorValue &color); - void SetShininess(float value); - void SetTransparency(float value); - void SetShadingType(DWORD shading); - -protected: - int id; - TextureMap texMap1; - TextureMap texMap2; - TextureMap opacMap; - TextureMap refTextureMap; - TextureMap bumpMap; - TextureMap specMap; - ColorValue ambient; - ColorValue diffuse; - ColorValue specular; - float shininess; - float transparency; - DWORD shading; -}; - -// +--------------------------------------------------------------------+ - -class LMesh : public LObject -{ -public: - LMesh(); - virtual ~LMesh(); - - void Clear(); - - DWORD GetVertexCount(); - void SetVertexArraySize(DWORD value); - DWORD GetTriangleCount(); - void SetTriangleArraySize(DWORD value); - - // returns given vertex - const LVector4& GetVertex(DWORD index); - // returns the given normal - const LVector3& GetNormal(DWORD index); - // returns the given texture coordinates vector - const LVector2& GetUV(DWORD index); - // returns the pointer to the array of tangents - const LVector3& GetTangent(DWORD index); - // returns the pointer to the array of binormals - const LVector3& GetBinormal(DWORD index); - // sets the vertex at a given index to "vec" - for internal use - void SetVertex(const LVector4 &vec, DWORD index); - // sets the normal at a given index to "vec" - for internal use - void SetNormal(const LVector3 &vec, DWORD index); - // sets the texture coordinates vector at a given index to "vec" - for internal use - void SetUV(const LVector2 &vec, DWORD index); - // sets the tangent at a given index to "vec" - for internal use - void SetTangent(const LVector3 &vec, DWORD index); - // sets the binormal at a given index to "vec" - for internal use - void SetBinormal(const LVector3 &vec, DWORD index); - // returns the triangle with a given index - const LTriangle& GetTriangle(DWORD index); - // returns the triangle with a given index, see LTriangle2 structure description - LTriangle2 GetTriangle2(DWORD index); - // returns the mesh matrix, should be identity matrix after loading - LMatrix4 GetMatrix(); - // sets the mesh matrix to a given matrix - for internal use - void SetMatrix(LMatrix4 m); - // optimizises the mesh using a given optimization level - void Optimize(LOptimizationLevel value); - // sets an internal triangle structure with index "index" - for internal use only - void SetTri(const LTri &tri, DWORD index); - // returns the pointer to the internal triangle structure - for internal use only - LTri& GetTri(DWORD index); - // returns the material id with a given index for the mesh - DWORD GetMaterial(DWORD index); - // adds a material to the mesh and returns its index - for internal use - DWORD AddMaterial(DWORD id); - // returns the number of materials used in the mesh - DWORD GetMaterialCount(); -protected: - // the vertices, normals, etc. - List vertices; - List normals; - List binormals; - List tangents; - List uv; - - // triangles - List triangles; - - //used internally - List tris; - - // the transformation matrix. - Matrix matrix; - - // the material ID array - List materials; - - // calculates the normals, either using the smoothing groups information or not - void CalcNormals(bool useSmoothingGroups); - // calculates the texture(tangent) space for each vertex - void CalcTextureSpace(); - // transforms the vertices by the mesh matrix - void TransformVertices(); -}; - -//------------------------------------------------ - -class LImporter -{ -public: - // the default constructor - LImporter(); - // the destructor - virtual ~LImporter(); - // reads the model from a file, must be overriden by the child classes - virtual bool LoadFile(const char *filename) = 0; - // returns the number of meshes in the scene - DWORD GetMeshCount(); - // returns the number of lights in the scene - DWORD GetLightCount(); - // returns the number of materials in the scene - DWORD GetMaterialCount(); - // returns a pointer to a mesh - LMesh& GetMesh(DWORD index); - // returns a pointer to a light at a given index - LLight& GetLight(DWORD index); - // returns the pointer to the material - LMaterial& GetMaterial(DWORD index); - // returns the pointer to the material with a given name, or NULL if the material was not found - LMaterial* FindMaterial(const Text &name); - // returns the pointer to the mesh with a given name, or NULL if the mesh with such name - // is not present in the scene - LMesh* FindMesh(const Text &name); - // returns the pointer to the light with a given name, or NULL if not found - LLight* FindLight(const Text &name); - // sets the optimization level to a given value - void SetOptimizationLevel(LOptimizationLevel value); - // returns the current optimization level - LOptimizationLevel GetOptimizationLevel(); -protected: - // the lights found in the scene - List lights; - // triangular meshes - List meshes; - // the materials in the scene - List materials; - // level of optimization to perform on the meshes - LOptimizationLevel optLevel; - // clears all data. - virtual void Clear(); -}; -//------------------------------------------------ - -class L3DS : public LImporter -{ -public: - // the default contructor - L3DS(); - // constructs the object and loads the file - L3DS(const char *filename); - // destructor - virtual ~L3DS(); - // load 3ds file - virtual bool LoadFile(const char *filename); -protected: - // used internally for reading - char objName[100]; - // true if end of file is reached - bool eof; - // buffer for loading, used for speedup - unsigned char *buffer; - // the size of the buffer - DWORD bufferSize; - // the current cursor position in the buffer - DWORD pos; - - // reads a short value from the buffer - short ReadShort(); - // reads an int value from the buffer - int ReadInt(); - // reads a char from the buffer - char ReadChar(); - //reada a floatvalue from the buffer - float ReadFloat(); - //reads an unsigned byte from the buffer - byte ReadByte(); - //reads an asciiz string - int ReadASCIIZ(char *buf, int max_count); - // seek wihtin the buffer - void Seek(int offset, int origin); - // returns the position of the cursor - DWORD Pos(); - - // read the chunk and return it. - LChunk ReadChunk(); - // read until given chunk is found - bool FindChunk(LChunk &target, const LChunk &parent); - // skip to the end of chunk "chunk" - void SkipChunk(const LChunk &chunk); - // goes to the beginning of the data in teh given chunk - void GotoChunk(const LChunk &chunk); - - // the function read the color chunk (any of the color chunks) - ColorValue ReadColor(const LChunk &chunk); - // the function that read the percentage chunk and returns a float from 0 to 1 - float ReadPercentage(const LChunk &chunk); - // this is where 3ds file is being read - bool Read3DS(); - // read a light chunk - void ReadLight(const LChunk &parent); - // read a trimesh chunk - void ReadMesh(const LChunk &parent); - // reads the face list, face materials, smoothing groups... and fill rthe information into the mesh - void ReadFaceList(const LChunk &chunk, LMesh &mesh); - // reads the material - void ReadMaterial(const LChunk &parent); - // reads the map info and fills the given map with this information - void ReadMap(const LChunk &chunk, TextureMap& map); - // reads keyframer data of the OBJECT_NODE_TAG chunk - void ReadKeyframeData(const LChunk &parent); - // reads the keyheader structure from the current offset and returns the frame number - long ReadKeyheader(); -}; - -//--------------------------------------------------------- - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: M3DS.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Window class +*/ + +// parts copyright (c) 2001-2002 Lev Povalahev + +#ifndef M3DS_H +#define M3DS_H + +#include "List.h" + +// +--------------------------------------------------------------------+ + +struct Chunk +{ + WORD id; + DWORD len; + BYTE* start; + + List chunks; +}; + +// +--------------------------------------------------------------------+ + +struct LTriangle +{ + WORD a,b,c; +}; + +struct LTriangle2 +{ + Point vertices[3]; + Vec3 vertexNormals[3]; + LVector2 textureCoords[3]; + Vec3 faceNormal; + DWORD materialId; +}; + +struct TextureMap +{ + char fname[256]; + float strength; + float u_scale; + float v_scale; + float u_offset; + float v_offset; + float angle; +}; + +// +--------------------------------------------------------------------+ + +class LObject +{ +public: + LObject(); + virtual ~LObject(); + + virtual const char* GetName(); + virtual bool IsObject(const const char* name); + +protected: + Text name; +}; + +// +--------------------------------------------------------------------+ + +class LMaterial : public LObject +{ +public: + LMaterial(); + virtual ~LMaterial(); + + DWORD GetID(); + TextureMap& GetTextureMap1(); + TextureMap& GetTextureMap2(); + TextureMap& GetOpacityMap(); + TextureMap& GetSpecularMap(); + TextureMap& GetBumpMap(); + TextureMap& GetReflectionMap(); + ColorValue GetAmbientColor(); + ColorValue GetDiffuseColor(); + ColorValue GetSpecularColor(); + float GetShininess(); + float GetTransparency(); + DWORD GetShadingType(); + + // this methods should not be used by the "user", they're used internally to fill the class + // with valid data when reading from file. If you're about to add an importer for another format you'LL + // have to use these methods + + void SetID(DWORD value); + void SetAmbientColor(const ColorValue &color); + void SetDiffuseColor(const ColorValue &color); + void SetSpecularColor(const ColorValue &color); + void SetShininess(float value); + void SetTransparency(float value); + void SetShadingType(DWORD shading); + +protected: + int id; + TextureMap texMap1; + TextureMap texMap2; + TextureMap opacMap; + TextureMap refTextureMap; + TextureMap bumpMap; + TextureMap specMap; + ColorValue ambient; + ColorValue diffuse; + ColorValue specular; + float shininess; + float transparency; + DWORD shading; +}; + +// +--------------------------------------------------------------------+ + +class LMesh : public LObject +{ +public: + LMesh(); + virtual ~LMesh(); + + void Clear(); + + DWORD GetVertexCount(); + void SetVertexArraySize(DWORD value); + DWORD GetTriangleCount(); + void SetTriangleArraySize(DWORD value); + + // returns given vertex + const LVector4& GetVertex(DWORD index); + // returns the given normal + const LVector3& GetNormal(DWORD index); + // returns the given texture coordinates vector + const LVector2& GetUV(DWORD index); + // returns the pointer to the array of tangents + const LVector3& GetTangent(DWORD index); + // returns the pointer to the array of binormals + const LVector3& GetBinormal(DWORD index); + // sets the vertex at a given index to "vec" - for internal use + void SetVertex(const LVector4 &vec, DWORD index); + // sets the normal at a given index to "vec" - for internal use + void SetNormal(const LVector3 &vec, DWORD index); + // sets the texture coordinates vector at a given index to "vec" - for internal use + void SetUV(const LVector2 &vec, DWORD index); + // sets the tangent at a given index to "vec" - for internal use + void SetTangent(const LVector3 &vec, DWORD index); + // sets the binormal at a given index to "vec" - for internal use + void SetBinormal(const LVector3 &vec, DWORD index); + // returns the triangle with a given index + const LTriangle& GetTriangle(DWORD index); + // returns the triangle with a given index, see LTriangle2 structure description + LTriangle2 GetTriangle2(DWORD index); + // returns the mesh matrix, should be identity matrix after loading + LMatrix4 GetMatrix(); + // sets the mesh matrix to a given matrix - for internal use + void SetMatrix(LMatrix4 m); + // optimizises the mesh using a given optimization level + void Optimize(LOptimizationLevel value); + // sets an internal triangle structure with index "index" - for internal use only + void SetTri(const LTri &tri, DWORD index); + // returns the pointer to the internal triangle structure - for internal use only + LTri& GetTri(DWORD index); + // returns the material id with a given index for the mesh + DWORD GetMaterial(DWORD index); + // adds a material to the mesh and returns its index - for internal use + DWORD AddMaterial(DWORD id); + // returns the number of materials used in the mesh + DWORD GetMaterialCount(); +protected: + // the vertices, normals, etc. + List vertices; + List normals; + List binormals; + List tangents; + List uv; + + // triangles + List triangles; + + //used internally + List tris; + + // the transformation matrix. + Matrix matrix; + + // the material ID array + List materials; + + // calculates the normals, either using the smoothing groups information or not + void CalcNormals(bool useSmoothingGroups); + // calculates the texture(tangent) space for each vertex + void CalcTextureSpace(); + // transforms the vertices by the mesh matrix + void TransformVertices(); +}; + +//------------------------------------------------ + +class LImporter +{ +public: + // the default constructor + LImporter(); + // the destructor + virtual ~LImporter(); + // reads the model from a file, must be overriden by the child classes + virtual bool LoadFile(const char *filename) = 0; + // returns the number of meshes in the scene + DWORD GetMeshCount(); + // returns the number of lights in the scene + DWORD GetLightCount(); + // returns the number of materials in the scene + DWORD GetMaterialCount(); + // returns a pointer to a mesh + LMesh& GetMesh(DWORD index); + // returns a pointer to a light at a given index + LLight& GetLight(DWORD index); + // returns the pointer to the material + LMaterial& GetMaterial(DWORD index); + // returns the pointer to the material with a given name, or NULL if the material was not found + LMaterial* FindMaterial(const Text &name); + // returns the pointer to the mesh with a given name, or NULL if the mesh with such name + // is not present in the scene + LMesh* FindMesh(const Text &name); + // returns the pointer to the light with a given name, or NULL if not found + LLight* FindLight(const Text &name); + // sets the optimization level to a given value + void SetOptimizationLevel(LOptimizationLevel value); + // returns the current optimization level + LOptimizationLevel GetOptimizationLevel(); +protected: + // the lights found in the scene + List lights; + // triangular meshes + List meshes; + // the materials in the scene + List materials; + // level of optimization to perform on the meshes + LOptimizationLevel optLevel; + // clears all data. + virtual void Clear(); +}; +//------------------------------------------------ + +class L3DS : public LImporter +{ +public: + // the default contructor + L3DS(); + // constructs the object and loads the file + L3DS(const char *filename); + // destructor + virtual ~L3DS(); + // load 3ds file + virtual bool LoadFile(const char *filename); +protected: + // used internally for reading + char objName[100]; + // true if end of file is reached + bool eof; + // buffer for loading, used for speedup + unsigned char *buffer; + // the size of the buffer + DWORD bufferSize; + // the current cursor position in the buffer + DWORD pos; + + // reads a short value from the buffer + short ReadShort(); + // reads an int value from the buffer + int ReadInt(); + // reads a char from the buffer + char ReadChar(); + //reada a floatvalue from the buffer + float ReadFloat(); + //reads an unsigned byte from the buffer + byte ReadByte(); + //reads an asciiz string + int ReadASCIIZ(char *buf, int max_count); + // seek wihtin the buffer + void Seek(int offset, int origin); + // returns the position of the cursor + DWORD Pos(); + + // read the chunk and return it. + LChunk ReadChunk(); + // read until given chunk is found + bool FindChunk(LChunk &target, const LChunk &parent); + // skip to the end of chunk "chunk" + void SkipChunk(const LChunk &chunk); + // goes to the beginning of the data in teh given chunk + void GotoChunk(const LChunk &chunk); + + // the function read the color chunk (any of the color chunks) + ColorValue ReadColor(const LChunk &chunk); + // the function that read the percentage chunk and returns a float from 0 to 1 + float ReadPercentage(const LChunk &chunk); + // this is where 3ds file is being read + bool Read3DS(); + // read a light chunk + void ReadLight(const LChunk &parent); + // read a trimesh chunk + void ReadMesh(const LChunk &parent); + // reads the face list, face materials, smoothing groups... and fill rthe information into the mesh + void ReadFaceList(const LChunk &chunk, LMesh &mesh); + // reads the material + void ReadMaterial(const LChunk &parent); + // reads the map info and fills the given map with this information + void ReadMap(const LChunk &chunk, TextureMap& map); + // reads keyframer data of the OBJECT_NODE_TAG chunk + void ReadKeyframeData(const LChunk &parent); + // reads the keyheader structure from the current offset and returns the frame number + long ReadKeyheader(); +}; + +//--------------------------------------------------------- + #endif \ No newline at end of file diff --git a/Magic2/Magic.cpp b/Magic2/Magic.cpp index d9d626a..f1bc859 100644 --- a/Magic2/Magic.cpp +++ b/Magic2/Magic.cpp @@ -1,202 +1,226 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Magic.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the main application class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MainFrm.h" -#include "MagicDoc.h" -#include "MagicView.h" - -#include "MachineInfo.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// +--------------------------------------------------------------------+ - -BEGIN_MESSAGE_MAP(Magic, CWinApp) - //{{AFX_MSG_MAP(Magic) - ON_COMMAND(ID_APP_ABOUT, OnAppAbout) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP - // Standard file based document commands - ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) - ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) - // Standard print setup command - ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ - -extern FILE* ErrLog; -extern int VD3D_describe_things; -void Print(const char* msg, ...); - -static void PrintLogHeader() -{ - ErrLog = fopen("errlog.txt", "w"); - Print("+====================================================================+\n"); - Print("| Magic 2.0 |\n"); - - VD3D_describe_things = 4; - MachineInfo::DescribeMachine(); -} - -// +--------------------------------------------------------------------+ - -Magic::Magic() -{ - PrintLogHeader(); -} - -Magic::~Magic() -{ - Print("+====================================================================+\n"); - Print(" END OF LINE.\n"); - - fclose(ErrLog); -} - -// +--------------------------------------------------------------------+ -// -// The one and only Magic object - -Magic theApp; - -// +--------------------------------------------------------------------+ -// -// Magic initialization - -BOOL Magic::InitInstance() -{ - AfxEnableControlContainer(); - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -//#ifdef _AFXDLL -// Enable3dControls(); // Call this when using MFC in a shared DLL -//#else -// Enable3dControlsStatic(); // Call this when linking to MFC statically -//#endif - - // Change the registry key under which our settings are stored. - // TODO: You should modify this string to be something appropriate - // such as the name of your company or organization. - SetRegistryKey(_T("Local AppWizard-Generated Applications")); - - LoadStdProfileSettings(); // Load standard INI file options (including MRU) - - // Register the application's document templates. Document templates - // serve as the connection between documents, frame windows and views. - - CSingleDocTemplate* pDocTemplate; - pDocTemplate = new CSingleDocTemplate( - IDR_MAINFRAME, - RUNTIME_CLASS(MagicDoc), - RUNTIME_CLASS(MainFrame), // main SDI frame window - RUNTIME_CLASS(MagicView)); - AddDocTemplate(pDocTemplate); - - // Parse command line for standard shell commands, DDE, file open - CCommandLineInfo cmdInfo; - ParseCommandLine(cmdInfo); - - // Dispatch commands specified on the command line - if (!ProcessShellCommand(cmdInfo)) - return FALSE; - - // The one and only window has been initialized, so show and update it. - m_pMainWnd->ShowWindow(SW_SHOW); - m_pMainWnd->UpdateWindow(); - - return TRUE; -} - - -// +--------------------------------------------------------------------+ -// -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - // No message handlers - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - // No message handlers - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// App command to run the dialog -void Magic::OnAppAbout() -{ - CAboutDlg aboutDlg; - aboutDlg.DoModal(); -} - -// +--------------------------------------------------------------------+ -// -// Magic message handlers - -BOOL Magic::OnIdle(LONG lCount) -{ - CWinApp::OnIdle(lCount); - - if (!app_active) - Sleep(50); - - m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_RENDER); - return TRUE; // always request more time -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Magic.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the main application class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MainFrm.h" +#include "MagicDoc.h" +#include "MagicView.h" + +#include "MachineInfo.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ + +BEGIN_MESSAGE_MAP(Magic, CWinApp) + //{{AFX_MSG_MAP(Magic) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +extern FILE* ErrLog; +extern int VD3D_describe_things; +void Print(const char* msg, ...); + +static void PrintLogHeader() +{ + ErrLog = fopen("errlog.txt", "w"); + Print("+====================================================================+\n"); + Print("| Magic 2.0 |\n"); + + VD3D_describe_things = 4; + MachineInfo::DescribeMachine(); +} + +// +--------------------------------------------------------------------+ + +Magic::Magic() +{ + PrintLogHeader(); +} + +Magic::~Magic() +{ + Print("+====================================================================+\n"); + Print(" END OF LINE.\n"); + + fclose(ErrLog); +} + +// +--------------------------------------------------------------------+ +// +// The one and only Magic object + +Magic theApp; + +// +--------------------------------------------------------------------+ +// +// Magic initialization + +BOOL Magic::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +//#ifdef _AFXDLL +// Enable3dControls(); // Call this when using MFC in a shared DLL +//#else +// Enable3dControlsStatic(); // Call this when linking to MFC statically +//#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(MagicDoc), + RUNTIME_CLASS(MainFrame), // main SDI frame window + RUNTIME_CLASS(MagicView)); + AddDocTemplate(pDocTemplate); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // The one and only window has been initialized, so show and update it. + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->UpdateWindow(); + + return TRUE; +} + + +// +--------------------------------------------------------------------+ +// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void Magic::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +// +--------------------------------------------------------------------+ +// +// Magic message handlers + +BOOL Magic::OnIdle(LONG lCount) +{ + CWinApp::OnIdle(lCount); + + if (!app_active) + Sleep(50); + + m_pMainWnd->SendMessage(WM_COMMAND, ID_VIEW_RENDER); + return TRUE; // always request more time +} diff --git a/Magic2/Magic.h b/Magic2/Magic.h index 07318b1..8320542 100644 --- a/Magic2/Magic.h +++ b/Magic2/Magic.h @@ -1,63 +1,87 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Magic.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the main application class -*/ - - -#if !defined(AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_) -#define AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - - -class Magic : public CWinApp -{ -public: - Magic(); - virtual ~Magic(); - - bool AppActivated() const { return app_active; } - void SetAppActivated(bool a) { app_active = a; } - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(Magic) - public: - virtual BOOL InitInstance(); - virtual BOOL OnIdle(LONG lCount); - //}}AFX_VIRTUAL - -// Implementation - //{{AFX_MSG(Magic) - afx_msg void OnAppAbout(); - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -private: - bool app_active; -}; - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_) +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Magic.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the main application class +*/ + + +#if !defined(AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_) +#define AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + + +class Magic : public CWinApp +{ +public: + Magic(); + virtual ~Magic(); + + bool AppActivated() const { return app_active; } + void SetAppActivated(bool a) { app_active = a; } + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(Magic) + public: + virtual BOOL InitInstance(); + virtual BOOL OnIdle(LONG lCount); + //}}AFX_VIRTUAL + +// Implementation + //{{AFX_MSG(Magic) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + bool app_active; +}; + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAGIC_H__E61FB5C3_42B6_42D1_BEFA_17F0B038E33B__INCLUDED_) diff --git a/Magic2/MagicDoc.cpp b/Magic2/MagicDoc.cpp index 7b8e6f8..f0c7929 100644 --- a/Magic2/MagicDoc.cpp +++ b/Magic2/MagicDoc.cpp @@ -1,615 +1,639 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MagicDoc.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the MagicDoc class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MagicDoc.h" -#include "ModelFileMAG.h" -#include "ModelFileOBJ.h" -#include "ModelFile3DS.h" -#include "Selection.h" -#include "Selector.h" -#include "Editor.h" -#include "Command.h" - -#include "Bitmap.h" -#include "Color.h" -#include "D3DXImage.h" -#include "Geometry.h" -#include "Pcx.h" -#include "Polygon.h" -#include "Solid.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// +--------------------------------------------------------------------+ - -IMPLEMENT_DYNCREATE(MagicDoc, CDocument) - -BEGIN_MESSAGE_MAP(MagicDoc, CDocument) - //{{AFX_MSG_MAP(MagicDoc) - ON_COMMAND(ID_SURFACE_OPTIMIZE, OnSurfaceOptimize) - ON_COMMAND(ID_SURFACE_EXPLODE, OnSurfaceExplode) - ON_UPDATE_COMMAND_UI(ID_SURFACE_OPTIMIZE, OnUpdateSurfaceOptimize) - ON_UPDATE_COMMAND_UI(ID_SURFACE_EXPLODE, OnUpdateSurfaceExplode) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ - -MagicDoc::MagicDoc() - : solid(0), selection(0) -{ - solid = new Solid; - selection = new Selection; - selector = new Selector(selection); - editor = new Editor(this); -} - -MagicDoc::~MagicDoc() -{ - if (editor) delete editor; - if (selector) delete selector; - if (selection) delete selection; - if (solid) delete solid; -} - -// +--------------------------------------------------------------------+ - -void -MagicDoc::InitCommandStack() -{ - nundo = 0; - commands.destroy(); -} - -void -MagicDoc::Exec(Command* command) -{ - int nredo = commands.size() - nundo; - - while (nredo) { - delete commands.removeIndex(commands.size()-1); - nredo--; - } - - if (nundo < 100) { - nundo++; - } - else { - delete commands.removeIndex(0); - } - - command->Do(); - commands.append(command); -} - -int -MagicDoc::NumUndo() const -{ - return nundo; -} - -int -MagicDoc::NumRedo() const -{ - return commands.size() - nundo; -} - -const char* -MagicDoc::GetUndoName() const -{ - if (nundo > 0 && nundo <= commands.size()) - return commands[nundo-1]->Name(); - else - return ""; -} - -const char* -MagicDoc::GetRedoName() const -{ - if (nundo >= 0 && nundo < commands.size()) - return commands[nundo]->Name(); - else - return ""; -} - -void -MagicDoc::Undo() -{ - if (nundo > 0 && nundo <= commands.size()) - commands[--nundo]->Undo(); -} - -void -MagicDoc::Redo() -{ - if (nundo >= 0 && nundo < commands.size()) - commands[nundo++]->Do(); -} - -// +--------------------------------------------------------------------+ - -BOOL MagicDoc::OnNewDocument() -{ - if (!CDocument::OnNewDocument()) - return FALSE; - - InitCommandStack(); - - if (solid) delete solid; - solid = new Solid; - - if (selection) - selection->Clear(); - - return TRUE; -} - -// +--------------------------------------------------------------------+ - -void MagicDoc::Serialize(CArchive& ar) -{ -} - -// +--------------------------------------------------------------------+ - -#ifdef _DEBUG -void MagicDoc::AssertValid() const -{ - CDocument::AssertValid(); -} - -void MagicDoc::Dump(CDumpContext& dc) const -{ - CDocument::Dump(dc); -} -#endif //_DEBUG - -// +--------------------------------------------------------------------+ - -BOOL MagicDoc::OnSaveDocument(LPCTSTR path_name) -{ - SetModifiedFlag(FALSE); - - ModelFileMAG mod_file(path_name); - mod_file.Save(solid->GetModel()); - - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - return TRUE; -} - -BOOL MagicDoc::OnOpenDocument(LPCTSTR path_name) -{ - FILE* fp = fopen(path_name, "rb"); - if (!fp) { - ::MessageBox(0, "Open Failed: could not open file", "ERROR", MB_OK); - return FALSE; - } - - int version = 1; - char file_id[5]; - fread(file_id, 4, 1, fp); - file_id[4] = '\0'; - fclose(fp); - - if (strncmp(file_id, "MAG", 3)) { - ::MessageBox(0, "Open Failed: Invalid file type", "ERROR", MB_OK); - return FALSE; - } - - switch (file_id[3]) { - case '6': version = 6; break; - case '5': version = 5; break; - default: version = 0; break; - } - - if (version < 5 || version > 6) { - ::MessageBox(0, "Open Failed: Unsupported version", "ERROR", MB_OK); - return FALSE; - } - - DeleteContents(); - - ModelFileMAG mod_file(path_name); - solid->Load(&mod_file); - solid->CreateShadows(); - - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - return TRUE; -} - -bool -MagicDoc::ImportFile(LPCTSTR path_name) -{ - if (strstr(path_name, ".obj") || strstr(path_name, ".OBJ")) { - ModelFileOBJ obj_file(path_name); - - if (solid->GetModel()) { - Solid* s = new Solid; - - if (s->Load(&obj_file)) { - // todo: insert command here - Model* orig = solid->GetModel(); - Model* imported = s->GetModel(); - - orig->GetMaterials().append(imported->GetMaterials()); - orig->GetSurfaces().append(imported->GetSurfaces()); - orig->OptimizeMaterials(); - - imported->GetMaterials().clear(); - imported->GetSurfaces().clear(); - - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - delete s; - return true; - } - - delete s; - } - else { - if (solid->Load(&obj_file)) { - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - return true; - } - } - - return false; - } - - if (strstr(path_name, ".3ds") || strstr(path_name, ".3DS")) { - ModelFile3DS model_file(path_name); - - if (solid->GetModel()) { - Solid* s = new Solid; - - if (s->Load(&model_file)) { - // todo: insert command here - Model* orig = solid->GetModel(); - Model* imported = s->GetModel(); - - orig->GetMaterials().append(imported->GetMaterials()); - orig->GetSurfaces().append(imported->GetSurfaces()); - orig->OptimizeMaterials(); - - imported->GetMaterials().clear(); - imported->GetSurfaces().clear(); - - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - delete s; - return true; - } - - delete s; - } - else { - if (solid->Load(&model_file)) { - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - return true; - } - } - - return false; - } - - FILE* fp = fopen(path_name, "rb"); - if (!fp) { - ::MessageBox(0, "Import Failed: could not open file", "ERROR", MB_OK); - return false; - } - - int version = 1; - char file_id[5]; - fread(file_id, 4, 1, fp); - file_id[4] = '\0'; - fclose(fp); - - if (strncmp(file_id, "MAG", 3)) { - ::MessageBox(0, "Open Failed: Invalid file type", "ERROR", MB_OK); - return false; - } - - switch (file_id[3]) { - case '6': version = 6; break; - case '5': version = 5; break; - default: version = 0; break; - } - - if (version < 5 || version > 6) { - ::MessageBox(0, "Open Failed: Unsupported version", "ERROR", MB_OK); - return false; - } - - ModelFileMAG mag_file(path_name); - - if (solid->GetModel()) { - Solid* s = new Solid; - if (s->Load(&mag_file)) { - // todo: insert command here - Model* orig = solid->GetModel(); - Model* imported = s->GetModel(); - - orig->GetMaterials().append(imported->GetMaterials()); - orig->GetSurfaces().append(imported->GetSurfaces()); - orig->OptimizeMaterials(); - - imported->GetMaterials().clear(); - imported->GetSurfaces().clear(); - - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - delete s; - return true; - } - - delete s; - } - else { - InitCommandStack(); - - if (solid->Load(&mag_file)) { - SetModifiedFlag(FALSE); - UpdateAllViews(NULL); - return true; - } - } - - return false; -} - -bool -MagicDoc::ExportFile(LPCTSTR path_name) -{ - if (!solid->GetModel()) - return false; - - if (strstr(path_name, ".obj") || strstr(path_name, ".OBJ")) { - ModelFileOBJ obj_file(path_name); - obj_file.Save(solid->GetModel()); - return true; - } - - if (strstr(path_name, ".3ds") || strstr(path_name, ".3DS")) { - return false; - } - - if (strstr(path_name, ".mag") || strstr(path_name, ".MAG")) { - ModelFileMAG mod_file(path_name); - mod_file.Save(solid->GetModel()); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate) -{ - buf = 0; - - FILE* f = ::fopen(filename, "rb"); - - if (f) { - ::fseek(f, 0, SEEK_END); - int len = ftell(f); - ::fseek(f, 0, SEEK_SET); - - if (null_terminate) { - buf = new BYTE[len+1]; - if (buf) - buf[len] = 0; - } - - else { - buf = new BYTE[len]; - } - - if (buf) - ::fread(buf, len, 1, f); - - ::fclose(f); - - return len; - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -void MagicDoc::DeleteContents() -{ - CDocument::DeleteContents(); - InitCommandStack(); - - if (solid) { - delete solid; - solid = new Solid; - } - - if (selection) - selection->Clear(); -} - -// +--------------------------------------------------------------------+ - -int LoadTexture(const char* fname, Bitmap*& bitmap, int type) -{ - int result = 0; - - if (!fname || !*fname) - return result; - - bitmap = Bitmap::CheckCache(fname); - - if (!bitmap) { - bool pcx_file = strstr(fname, ".pcx") || strstr(fname, ".PCX"); - - // handle PCX formats: - if (pcx_file) { - PcxImage pcx; - - if (pcx.Load((char*) fname) == PCX_OK) { - bitmap = new Bitmap; - - // 32-bit image - if (pcx.himap) { - bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap); - } - - // 8-bit image, check for 32-bit image as well - else if (pcx.bitmap) { - bitmap->CopyImage(pcx.width, pcx.height, pcx.bitmap); - - char tmp[256]; - int len = strlen(fname); - bool found = false; - - ZeroMemory(tmp, sizeof(tmp)); - - for (int i = 0; i < len && !found; i++) { - if (strstr(fname + i, ".pcx") == (fname+i)) { - found = true; - } - else { - tmp[i] = fname[i]; - } - } - - if (found) { - strcat_s(tmp, "+.pcx"); - if (pcx.Load(tmp) == PCX_OK && pcx.himap != 0) { - bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap); - } - } - } - } - } - - // for all other formats, use D3DX: - else { - D3DXImage d3dx; - if (d3dx.Load((char*) fname)) { - bitmap = new Bitmap; - bitmap->CopyHighColorImage(d3dx.width, d3dx.height, d3dx.image); - } - } - - if (bitmap) { - LoadAlpha(fname, *bitmap, type); - - bitmap->SetFilename(fname); - bitmap->SetType(type); - bitmap->MakeTexture(); - - Bitmap::AddToCache(bitmap); - } - } - - return result; -} - -int LoadAlpha(const char* name, Bitmap& bitmap, int type) -{ - PcxImage pcx; - D3DXImage d3dx; - bool pcx_file = strstr(name, ".pcx") || strstr(name, ".PCX"); - bool bmp_file = strstr(name, ".bmp") || strstr(name, ".BMP"); - bool jpg_file = strstr(name, ".jpg") || strstr(name, ".JPG"); - bool png_file = strstr(name, ".png") || strstr(name, ".PNG"); - bool tga_file = strstr(name, ".tga") || strstr(name, ".TGA"); - - // check for an associated alpha-only (grayscale) bitmap: - char filename[256]; - strcpy_s(filename, name); - - char* dot = strrchr(filename, '.'); - if (dot && pcx_file) - strcpy(dot, "@.pcx"); - else if (dot && bmp_file) - strcpy(dot, "@.bmp"); - else if (dot && jpg_file) - strcpy(dot, "@.jpg"); - else if (dot && png_file) - strcpy(dot, "@.png"); - else if (dot && tga_file) - strcpy(dot, "@.tga"); - else - return 0; - - // first try to load from current directory: - bool loaded = false; - - if (pcx_file) - loaded = pcx.Load(filename) == PCX_OK; - - else - loaded = d3dx.Load(filename); - - // now copy the alpha values into the bitmap: - if (loaded) { - if (pcx_file && pcx.bitmap) { - bitmap.CopyAlphaImage(pcx.width, pcx.height, pcx.bitmap); - } - else if (pcx_file && pcx.himap) { - bitmap.CopyAlphaRedChannel(pcx.width, pcx.height, pcx.himap); - } - else if (d3dx.image) { - bitmap.CopyAlphaRedChannel(d3dx.width, d3dx.height, d3dx.image); - } - } - - return 0; -} - - -void MagicDoc::OnSurfaceOptimize() -{ - if (solid && solid->GetModel()) { - solid->GetModel()->OptimizeMesh(); - solid->InvalidateSurfaceData(); - solid->InvalidateSegmentData(); - } -} - -void MagicDoc::OnUpdateSurfaceOptimize(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(solid && solid->GetModel()); -} - -void MagicDoc::OnSurfaceExplode() -{ - if (solid && solid->GetModel()) { - solid->GetModel()->ExplodeMesh(); - solid->InvalidateSurfaceData(); - solid->InvalidateSegmentData(); - } -} - -void MagicDoc::OnUpdateSurfaceExplode(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(solid && solid->GetModel()); -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MagicDoc.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the MagicDoc class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "ModelFileMAG.h" +#include "ModelFileOBJ.h" +#include "ModelFile3DS.h" +#include "Selection.h" +#include "Selector.h" +#include "Editor.h" +#include "Command.h" + +#include "Bitmap.h" +#include "Color.h" +#include "D3DXImage.h" +#include "Geometry.h" +#include "Pcx.h" +#include "Polygon.h" +#include "Solid.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ + +IMPLEMENT_DYNCREATE(MagicDoc, CDocument) + +BEGIN_MESSAGE_MAP(MagicDoc, CDocument) + //{{AFX_MSG_MAP(MagicDoc) + ON_COMMAND(ID_SURFACE_OPTIMIZE, OnSurfaceOptimize) + ON_COMMAND(ID_SURFACE_EXPLODE, OnSurfaceExplode) + ON_UPDATE_COMMAND_UI(ID_SURFACE_OPTIMIZE, OnUpdateSurfaceOptimize) + ON_UPDATE_COMMAND_UI(ID_SURFACE_EXPLODE, OnUpdateSurfaceExplode) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +MagicDoc::MagicDoc() + : solid(0), selection(0) +{ + solid = new Solid; + selection = new Selection; + selector = new Selector(selection); + editor = new Editor(this); +} + +MagicDoc::~MagicDoc() +{ + if (editor) delete editor; + if (selector) delete selector; + if (selection) delete selection; + if (solid) delete solid; +} + +// +--------------------------------------------------------------------+ + +void +MagicDoc::InitCommandStack() +{ + nundo = 0; + commands.destroy(); +} + +void +MagicDoc::Exec(Command* command) +{ + int nredo = commands.size() - nundo; + + while (nredo) { + delete commands.removeIndex(commands.size()-1); + nredo--; + } + + if (nundo < 100) { + nundo++; + } + else { + delete commands.removeIndex(0); + } + + command->Do(); + commands.append(command); +} + +int +MagicDoc::NumUndo() const +{ + return nundo; +} + +int +MagicDoc::NumRedo() const +{ + return commands.size() - nundo; +} + +const char* +MagicDoc::GetUndoName() const +{ + if (nundo > 0 && nundo <= commands.size()) + return commands[nundo-1]->Name(); + else + return ""; +} + +const char* +MagicDoc::GetRedoName() const +{ + if (nundo >= 0 && nundo < commands.size()) + return commands[nundo]->Name(); + else + return ""; +} + +void +MagicDoc::Undo() +{ + if (nundo > 0 && nundo <= commands.size()) + commands[--nundo]->Undo(); +} + +void +MagicDoc::Redo() +{ + if (nundo >= 0 && nundo < commands.size()) + commands[nundo++]->Do(); +} + +// +--------------------------------------------------------------------+ + +BOOL MagicDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + InitCommandStack(); + + if (solid) delete solid; + solid = new Solid; + + if (selection) + selection->Clear(); + + return TRUE; +} + +// +--------------------------------------------------------------------+ + +void MagicDoc::Serialize(CArchive& ar) +{ +} + +// +--------------------------------------------------------------------+ + +#ifdef _DEBUG +void MagicDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void MagicDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +// +--------------------------------------------------------------------+ + +BOOL MagicDoc::OnSaveDocument(LPCTSTR path_name) +{ + SetModifiedFlag(FALSE); + + ModelFileMAG mod_file(path_name); + mod_file.Save(solid->GetModel()); + + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + return TRUE; +} + +BOOL MagicDoc::OnOpenDocument(LPCTSTR path_name) +{ + FILE* fp = fopen(path_name, "rb"); + if (!fp) { + ::MessageBox(0, "Open Failed: could not open file", "ERROR", MB_OK); + return FALSE; + } + + int version = 1; + char file_id[5]; + fread(file_id, 4, 1, fp); + file_id[4] = '\0'; + fclose(fp); + + if (strncmp(file_id, "MAG", 3)) { + ::MessageBox(0, "Open Failed: Invalid file type", "ERROR", MB_OK); + return FALSE; + } + + switch (file_id[3]) { + case '6': version = 6; break; + case '5': version = 5; break; + default: version = 0; break; + } + + if (version < 5 || version > 6) { + ::MessageBox(0, "Open Failed: Unsupported version", "ERROR", MB_OK); + return FALSE; + } + + DeleteContents(); + + ModelFileMAG mod_file(path_name); + solid->Load(&mod_file); + solid->CreateShadows(); + + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + return TRUE; +} + +bool +MagicDoc::ImportFile(LPCTSTR path_name) +{ + if (strstr(path_name, ".obj") || strstr(path_name, ".OBJ")) { + ModelFileOBJ obj_file(path_name); + + if (solid->GetModel()) { + Solid* s = new Solid; + + if (s->Load(&obj_file)) { + // todo: insert command here + Model* orig = solid->GetModel(); + Model* imported = s->GetModel(); + + orig->GetMaterials().append(imported->GetMaterials()); + orig->GetSurfaces().append(imported->GetSurfaces()); + orig->OptimizeMaterials(); + + imported->GetMaterials().clear(); + imported->GetSurfaces().clear(); + + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + delete s; + return true; + } + + delete s; + } + else { + if (solid->Load(&obj_file)) { + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + return true; + } + } + + return false; + } + + if (strstr(path_name, ".3ds") || strstr(path_name, ".3DS")) { + ModelFile3DS model_file(path_name); + + if (solid->GetModel()) { + Solid* s = new Solid; + + if (s->Load(&model_file)) { + // todo: insert command here + Model* orig = solid->GetModel(); + Model* imported = s->GetModel(); + + orig->GetMaterials().append(imported->GetMaterials()); + orig->GetSurfaces().append(imported->GetSurfaces()); + orig->OptimizeMaterials(); + + imported->GetMaterials().clear(); + imported->GetSurfaces().clear(); + + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + delete s; + return true; + } + + delete s; + } + else { + if (solid->Load(&model_file)) { + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + return true; + } + } + + return false; + } + + FILE* fp = fopen(path_name, "rb"); + if (!fp) { + ::MessageBox(0, "Import Failed: could not open file", "ERROR", MB_OK); + return false; + } + + int version = 1; + char file_id[5]; + fread(file_id, 4, 1, fp); + file_id[4] = '\0'; + fclose(fp); + + if (strncmp(file_id, "MAG", 3)) { + ::MessageBox(0, "Open Failed: Invalid file type", "ERROR", MB_OK); + return false; + } + + switch (file_id[3]) { + case '6': version = 6; break; + case '5': version = 5; break; + default: version = 0; break; + } + + if (version < 5 || version > 6) { + ::MessageBox(0, "Open Failed: Unsupported version", "ERROR", MB_OK); + return false; + } + + ModelFileMAG mag_file(path_name); + + if (solid->GetModel()) { + Solid* s = new Solid; + if (s->Load(&mag_file)) { + // todo: insert command here + Model* orig = solid->GetModel(); + Model* imported = s->GetModel(); + + orig->GetMaterials().append(imported->GetMaterials()); + orig->GetSurfaces().append(imported->GetSurfaces()); + orig->OptimizeMaterials(); + + imported->GetMaterials().clear(); + imported->GetSurfaces().clear(); + + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + delete s; + return true; + } + + delete s; + } + else { + InitCommandStack(); + + if (solid->Load(&mag_file)) { + SetModifiedFlag(FALSE); + UpdateAllViews(NULL); + return true; + } + } + + return false; +} + +bool +MagicDoc::ExportFile(LPCTSTR path_name) +{ + if (!solid->GetModel()) + return false; + + if (strstr(path_name, ".obj") || strstr(path_name, ".OBJ")) { + ModelFileOBJ obj_file(path_name); + obj_file.Save(solid->GetModel()); + return true; + } + + if (strstr(path_name, ".3ds") || strstr(path_name, ".3DS")) { + return false; + } + + if (strstr(path_name, ".mag") || strstr(path_name, ".MAG")) { + ModelFileMAG mod_file(path_name); + mod_file.Save(solid->GetModel()); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate) +{ + buf = 0; + + FILE* f = ::fopen(filename, "rb"); + + if (f) { + ::fseek(f, 0, SEEK_END); + int len = ftell(f); + ::fseek(f, 0, SEEK_SET); + + if (null_terminate) { + buf = new BYTE[len+1]; + if (buf) + buf[len] = 0; + } + + else { + buf = new BYTE[len]; + } + + if (buf) + ::fread(buf, len, 1, f); + + ::fclose(f); + + return len; + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +void MagicDoc::DeleteContents() +{ + CDocument::DeleteContents(); + InitCommandStack(); + + if (solid) { + delete solid; + solid = new Solid; + } + + if (selection) + selection->Clear(); +} + +// +--------------------------------------------------------------------+ + +int LoadTexture(const char* fname, Bitmap*& bitmap, int type) +{ + int result = 0; + + if (!fname || !*fname) + return result; + + bitmap = Bitmap::CheckCache(fname); + + if (!bitmap) { + bool pcx_file = strstr(fname, ".pcx") || strstr(fname, ".PCX"); + + // handle PCX formats: + if (pcx_file) { + PcxImage pcx; + + if (pcx.Load((char*) fname) == PCX_OK) { + bitmap = new Bitmap; + + // 32-bit image + if (pcx.himap) { + bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap); + } + + // 8-bit image, check for 32-bit image as well + else if (pcx.bitmap) { + bitmap->CopyImage(pcx.width, pcx.height, pcx.bitmap); + + char tmp[256]; + int len = strlen(fname); + bool found = false; + + ZeroMemory(tmp, sizeof(tmp)); + + for (int i = 0; i < len && !found; i++) { + if (strstr(fname + i, ".pcx") == (fname+i)) { + found = true; + } + else { + tmp[i] = fname[i]; + } + } + + if (found) { + strcat_s(tmp, "+.pcx"); + if (pcx.Load(tmp) == PCX_OK && pcx.himap != 0) { + bitmap->CopyHighColorImage(pcx.width, pcx.height, pcx.himap); + } + } + } + } + } + + // for all other formats, use D3DX: + else { + D3DXImage d3dx; + if (d3dx.Load((char*) fname)) { + bitmap = new Bitmap; + bitmap->CopyHighColorImage(d3dx.width, d3dx.height, d3dx.image); + } + } + + if (bitmap) { + LoadAlpha(fname, *bitmap, type); + + bitmap->SetFilename(fname); + bitmap->SetType(type); + bitmap->MakeTexture(); + + Bitmap::AddToCache(bitmap); + } + } + + return result; +} + +int LoadAlpha(const char* name, Bitmap& bitmap, int type) +{ + PcxImage pcx; + D3DXImage d3dx; + bool pcx_file = strstr(name, ".pcx") || strstr(name, ".PCX"); + bool bmp_file = strstr(name, ".bmp") || strstr(name, ".BMP"); + bool jpg_file = strstr(name, ".jpg") || strstr(name, ".JPG"); + bool png_file = strstr(name, ".png") || strstr(name, ".PNG"); + bool tga_file = strstr(name, ".tga") || strstr(name, ".TGA"); + + // check for an associated alpha-only (grayscale) bitmap: + char filename[256]; + strcpy_s(filename, name); + + char* dot = strrchr(filename, '.'); + if (dot && pcx_file) + strcpy(dot, "@.pcx"); + else if (dot && bmp_file) + strcpy(dot, "@.bmp"); + else if (dot && jpg_file) + strcpy(dot, "@.jpg"); + else if (dot && png_file) + strcpy(dot, "@.png"); + else if (dot && tga_file) + strcpy(dot, "@.tga"); + else + return 0; + + // first try to load from current directory: + bool loaded = false; + + if (pcx_file) + loaded = pcx.Load(filename) == PCX_OK; + + else + loaded = d3dx.Load(filename); + + // now copy the alpha values into the bitmap: + if (loaded) { + if (pcx_file && pcx.bitmap) { + bitmap.CopyAlphaImage(pcx.width, pcx.height, pcx.bitmap); + } + else if (pcx_file && pcx.himap) { + bitmap.CopyAlphaRedChannel(pcx.width, pcx.height, pcx.himap); + } + else if (d3dx.image) { + bitmap.CopyAlphaRedChannel(d3dx.width, d3dx.height, d3dx.image); + } + } + + return 0; +} + + +void MagicDoc::OnSurfaceOptimize() +{ + if (solid && solid->GetModel()) { + solid->GetModel()->OptimizeMesh(); + solid->InvalidateSurfaceData(); + solid->InvalidateSegmentData(); + } +} + +void MagicDoc::OnUpdateSurfaceOptimize(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(solid && solid->GetModel()); +} + +void MagicDoc::OnSurfaceExplode() +{ + if (solid && solid->GetModel()) { + solid->GetModel()->ExplodeMesh(); + solid->InvalidateSurfaceData(); + solid->InvalidateSegmentData(); + } +} + +void MagicDoc::OnUpdateSurfaceExplode(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(solid && solid->GetModel()); +} diff --git a/Magic2/MagicDoc.h b/Magic2/MagicDoc.h index 489f5dc..a40c879 100644 --- a/Magic2/MagicDoc.h +++ b/Magic2/MagicDoc.h @@ -1,120 +1,144 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MagicDoc.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the MagicDoc class -*/ - - -#if !defined(AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_) -#define AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// +--------------------------------------------------------------------+ - -#include "List.h" - -// +--------------------------------------------------------------------+ - -class Bitmap; -class Command; -class Editor; -class Solid; -class Model; -class Surface; -class Segment; -class Selection; -class Selector; - -// +--------------------------------------------------------------------+ - -class MagicDoc : public CDocument -{ -protected: // create from serialization only - MagicDoc(); - DECLARE_DYNCREATE(MagicDoc) - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(MagicDoc) - public: - virtual BOOL OnNewDocument(); - virtual void Serialize(CArchive& ar); - virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); - virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); - virtual void DeleteContents(); - //}}AFX_VIRTUAL - - void InitCommandStack(); - void Exec(Command* command); - void Undo(); - void Redo(); - int NumUndo() const; - int NumRedo() const; - const char* GetUndoName() const; - const char* GetRedoName() const; - -// Implementation -public: - virtual ~MagicDoc(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - Solid* GetSolid() { return solid; } - Selection* GetSelection() { return selection; } - Selector* GetSelector() { return selector; } - Editor* GetEditor() { return editor; } - - bool ImportFile(LPCTSTR path_name); - bool ExportFile(LPCTSTR path_name); - -protected: - Solid* solid; - Selection* selection; - Selector* selector; - Editor* editor; - - List commands; - int nundo; - -// Generated message map functions -protected: - //{{AFX_MSG(MagicDoc) - afx_msg void OnSurfaceOptimize(); - afx_msg void OnSurfaceExplode(); - afx_msg void OnUpdateSurfaceOptimize(CCmdUI* pCmdUI); - afx_msg void OnUpdateSurfaceExplode(CCmdUI* pCmdUI); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -// +--------------------------------------------------------------------+ - -int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate=false); -int LoadTexture(const char* name, Bitmap*& bmp, int type=0); -int LoadAlpha(const char* name, Bitmap& bitmap, int type=0); - -// +--------------------------------------------------------------------+ - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_) +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MagicDoc.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the MagicDoc class +*/ + + +#if !defined(AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_) +#define AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// +--------------------------------------------------------------------+ + +#include "List.h" + +// +--------------------------------------------------------------------+ + +class Bitmap; +class Command; +class Editor; +class Solid; +class Model; +class Surface; +class Segment; +class Selection; +class Selector; + +// +--------------------------------------------------------------------+ + +class MagicDoc : public CDocument +{ +protected: // create from serialization only + MagicDoc(); + DECLARE_DYNCREATE(MagicDoc) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(MagicDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual void DeleteContents(); + //}}AFX_VIRTUAL + + void InitCommandStack(); + void Exec(Command* command); + void Undo(); + void Redo(); + int NumUndo() const; + int NumRedo() const; + const char* GetUndoName() const; + const char* GetRedoName() const; + +// Implementation +public: + virtual ~MagicDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + Solid* GetSolid() { return solid; } + Selection* GetSelection() { return selection; } + Selector* GetSelector() { return selector; } + Editor* GetEditor() { return editor; } + + bool ImportFile(LPCTSTR path_name); + bool ExportFile(LPCTSTR path_name); + +protected: + Solid* solid; + Selection* selection; + Selector* selector; + Editor* editor; + + List commands; + int nundo; + +// Generated message map functions +protected: + //{{AFX_MSG(MagicDoc) + afx_msg void OnSurfaceOptimize(); + afx_msg void OnSurfaceExplode(); + afx_msg void OnUpdateSurfaceOptimize(CCmdUI* pCmdUI); + afx_msg void OnUpdateSurfaceExplode(CCmdUI* pCmdUI); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +// +--------------------------------------------------------------------+ + +int LoadBuffer(const char* filename, BYTE*& buf, bool null_terminate=false); +int LoadTexture(const char* name, Bitmap*& bmp, int type=0); +int LoadAlpha(const char* name, Bitmap& bitmap, int type=0); + +// +--------------------------------------------------------------------+ + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAGICDOC_H__8B8D63A3_30F9_4023_BFA8_DB79891487C2__INCLUDED_) diff --git a/Magic2/MagicView.cpp b/Magic2/MagicView.cpp index 294c794..e29e5d3 100644 --- a/Magic2/MagicView.cpp +++ b/Magic2/MagicView.cpp @@ -1,1437 +1,1461 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MagicView.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the MagicView class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MagicDoc.h" -#include "MagicView.h" -#include "MainFrm.h" -#include "MaterialDialog.h" -#include "SurfacePropertiesDialog.h" -#include "TextureMapDialog.h" -#include "Editor.h" -#include "Grid.h" -#include "GridProps.h" -#include "Selection.h" -#include "Selector.h" -#include "UVMapView.h" - -#include "ActiveWindow.h" -#include "Color.h" -#include "Layout.h" -#include "Light.h" -#include "Scene.h" -#include "Screen.h" -#include "Shadow.h" -#include "Solid.h" -#include "Video.h" -#include "VideoDX9.h" -#include "VideoSettings.h" - -#include "ModelView.h" - -DWORD GetRealTime(); - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -extern PALETTEENTRY standard_palette[256]; -extern BYTE inverse_palette[32768]; - -// +--------------------------------------------------------------------+ - -IMPLEMENT_DYNCREATE(MagicView, CView) - -BEGIN_MESSAGE_MAP(MagicView, CView) - //{{AFX_MSG_MAP(MagicView) - ON_WM_SIZE() - ON_COMMAND(ID_VIEW_RENDER, OnRender) - ON_WM_PAINT() - ON_COMMAND(ID_VIEW_ALL, OnViewAll) - ON_UPDATE_COMMAND_UI(ID_VIEW_ALL, OnUpdateViewAll) - ON_COMMAND(ID_VIEW_FRONT, OnViewFront) - ON_UPDATE_COMMAND_UI(ID_VIEW_FRONT, OnUpdateViewFront) - ON_COMMAND(ID_VIEW_PERSPECTIVE, OnViewPerspective) - ON_UPDATE_COMMAND_UI(ID_VIEW_PERSPECTIVE, OnUpdateViewPerspective) - ON_COMMAND(ID_VIEW_SIDE, OnViewSide) - ON_UPDATE_COMMAND_UI(ID_VIEW_SIDE, OnUpdateViewSide) - ON_COMMAND(ID_VIEW_TOP, OnViewTop) - ON_UPDATE_COMMAND_UI(ID_VIEW_TOP, OnUpdateViewTop) - ON_COMMAND(ID_MODIFY_TEXTURE_MAP, OnTextureMap) - ON_COMMAND(ID_MODIFY_MATERIAL, OnModifyMaterial) - ON_WM_LBUTTONDOWN() - ON_WM_LBUTTONUP() - ON_WM_LBUTTONDBLCLK() - ON_WM_RBUTTONDOWN() - ON_WM_RBUTTONUP() - ON_WM_MOUSEMOVE() - ON_WM_MOUSEWHEEL() - ON_COMMAND(ID_VIEW_ZOOM_NORMAL, OnViewZoomNormal) - ON_COMMAND(ID_VIEW_ZOOM_IN, OnViewZoomIn) - ON_COMMAND(ID_VIEW_ZOOM_OUT, OnViewZoomOut) - ON_COMMAND(ID_VIEW_MODE_WIREFRAME, OnViewModeWireframe) - ON_COMMAND(ID_VIEW_MODE_SOLID, OnViewModeSolid) - ON_COMMAND(ID_VIEW_MODE_TEXTURED, OnViewModeTextured) - ON_WM_RBUTTONDBLCLK() - ON_COMMAND(ID_PROP_GRID, OnGridProperties) - ON_COMMAND(ID_GRID_SHOW, OnGridShow) - ON_COMMAND(ID_GRID_SNAP, OnGridSnap) - ON_UPDATE_COMMAND_UI(ID_GRID_SNAP, OnUpdateGridSnap) - ON_COMMAND(ID_VIEW_BACK_COLOR, OnViewBackColor) - ON_COMMAND(ID_FILE_IMPORT, OnFileImport) - ON_COMMAND(ID_FILE_EXPORT, OnFileExport) - ON_COMMAND(ID_EDIT_SELECT_ALL, OnSelectAll) - ON_COMMAND(ID_EDIT_SELECT_NONE, OnSelectNone) - ON_UPDATE_COMMAND_UI(ID_MODIFY_TEXTURE_MAP, OnUpdateTextureMap) - ON_UPDATE_COMMAND_UI(ID_MODIFY_MATERIAL, OnUpdateModifyMaterial) - ON_COMMAND(ID_EDIT_SELECT_INVERSE, OnSelectInverse) - ON_COMMAND(ID_MODIFY_UV_MAP, OnModifyUVMap) - ON_UPDATE_COMMAND_UI(ID_MODIFY_UV_MAP, OnUpdateModifyUVMap) - ON_COMMAND(ID_VIEW_SHADOWS, OnViewShadows) - ON_UPDATE_COMMAND_UI(ID_VIEW_SHADOWS, OnUpdateViewShadows) - ON_COMMAND(ID_VIEW_ANIMATELIGHT, OnViewAnimatelight) - ON_UPDATE_COMMAND_UI(ID_VIEW_ANIMATELIGHT, OnUpdateViewAnimatelight) - ON_COMMAND(ID_VIEW_BUMPMAPS, OnViewBumpmaps) - ON_UPDATE_COMMAND_UI(ID_VIEW_BUMPMAPS, OnUpdateViewBumpmaps) - ON_COMMAND(ID_VIEW_VERTEXSHADER, OnViewVertexshader) - ON_UPDATE_COMMAND_UI(ID_VIEW_VERTEXSHADER, OnUpdateViewVertexshader) - ON_COMMAND(ID_VIEW_PIXELSHADER, OnViewPixelshader) - ON_UPDATE_COMMAND_UI(ID_VIEW_PIXELSHADER, OnUpdateViewPixelshader) - ON_COMMAND(ID_VIEW_VISIBLESHADOWS, OnViewVisibleshadows) - ON_UPDATE_COMMAND_UI(ID_VIEW_VISIBLESHADOWS, OnUpdateViewVisibleshadows) - ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) - ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) - ON_COMMAND(ID_EDIT_REDO, OnEditRedo) - ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo) - ON_COMMAND(ID_PROP_SURFACE, OnSurfaceProperties) - ON_UPDATE_COMMAND_UI(ID_PROP_SURFACE, OnUpdateSurfaceProperties) - //}}AFX_MSG_MAP - // Standard printing commands - ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ - -static MagicView* magic_view = 0; - -MagicView::MagicView() - : video(0), video_settings(0), screen(0), scene(0), - drag_left(false), drag_right(false), grid(0), - main_light(0), back_light(0), view_shadows(true), view_bumpmaps(true), - animate_light(false) -{ - window_style = 0; - is_minimized = false; - is_maximized = false; - is_sizing = false; - view_mode = VIEW_ALL; - - main_win = 0; - view_win[0] = 0; - view_win[1] = 0; - view_win[2] = 0; - view_win[3] = 0; - model_view[0] = 0; - model_view[1] = 0; - model_view[2] = 0; - model_view[3] = 0; - uvmap_win = 0; - - grid = new Grid; - magic_view = this; - - Solid::EnableCollision(false); -} - -MagicView::~MagicView() -{ - if (grid) { - delete grid; - } - - if (scene) { - scene->Graphics().clear(); - delete scene; - } - - if (screen) delete screen; - if (video) delete video; - if (video_settings) delete video_settings; - - if (magic_view == this) - magic_view = 0; -} - -MagicView* MagicView::GetInstance() -{ - return magic_view; -} - -BOOL MagicView::PreCreateWindow(CREATESTRUCT& cs) -{ - return CView::PreCreateWindow(cs); -} - -// +--------------------------------------------------------------------+ -// -// MagicView diagnostics - -#ifdef _DEBUG -void MagicView::AssertValid() const -{ - CView::AssertValid(); -} - -void MagicView::Dump(CDumpContext& dc) const -{ - CView::Dump(dc); -} - -MagicDoc* MagicView::GetDocument() // non-debug version is inline -{ - ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(MagicDoc))); - return (MagicDoc*)m_pDocument; -} -#endif //_DEBUG - - -// +--------------------------------------------------------------------+ - -void MagicView::OnInitialUpdate() -{ - CView::OnInitialUpdate(); - Color::SetPalette(standard_palette, 256, inverse_palette); - - if (!video_settings) - video_settings = new VideoSettings; - - GetClientRect(&client_rect); - - // Use client area to set video window size - int w = client_rect.right - client_rect.left; - int h = client_rect.bottom - client_rect.top; - - video_settings->is_windowed = true; - video_settings->window_width = w; - video_settings->window_height = h; - - if (!video) { - video = new VideoDX9(GetSafeHwnd(), video_settings); - *video_settings = *video->GetVideoSettings(); - - if (video) { - Color::UseVideo(video); - video->UseXFont("System", 12, false, false); - - screen = new Screen(video); - if (!screen) { - ::Print("ERROR: Could not create Screen object.\n"); - return; - } - - ::Print(" Created screen object (%d x %d).\n", w, h); - - if (!screen->SetBackgroundColor(Color::Black)) - ::Print(" WARNING: could not set video background color to Black\n"); - - screen->ClearAllFrames(true); - - ::Print(" Established requested video parameters.\n"); - ::Print(" ---------------------------------------\n\n"); - - if (!scene) { - scene = new Scene; - - scene->SetAmbient(Color(60,60,60)); - - Point light_pos(3e6, 5e6, 4e6); - - main_light = new Light(1.0f); //1.25f); - main_light->MoveTo(light_pos); - main_light->SetType(Light::LIGHT_DIRECTIONAL); - main_light->SetColor(Color::White); - main_light->SetShadow(true); - - scene->AddLight(main_light); - - back_light = new Light(0.5f); - back_light->MoveTo(light_pos * -1); - back_light->SetType(Light::LIGHT_DIRECTIONAL); - back_light->SetColor(Color::White); - - scene->AddLight(back_light); - - Selection* seln = GetDocument()->GetSelection(); - Selector* selector = GetDocument()->GetSelector(); - - if (seln && selector) { - scene->Graphics().clear(); - scene->AddGraphic(seln); - scene->AddGraphic(selector); - - selector->UseModel(0); - } - } - - int mins[2] = { 0, 0 }; - float weights[2] = { 1, 1 }; - - main_win = new ActiveWindow(screen, 0, 0, w, h, 100, 0); - main_win->UseLayout(2, 2, mins, mins, weights, weights); - main_win->SetBackColor(Color::Gray); - - screen->AddWindow(main_win); - - DWORD view_types[] = { - ModelView::VIEW_PLAN, - ModelView::VIEW_PROJECT, - ModelView::VIEW_SIDE, - ModelView::VIEW_FRONT - }; - - for (int row = 0; row < 2; row++) { - for (int col = 0; col < 2; col++) { - int index = 2*row + col; - - ActiveWindow* win = new ActiveWindow(screen, - col*w/2, - row*h/2, - w/2, - h/2, - 101+index, - WIN_BLACK_FRAME, - main_win); - - win->SetCells(col, row, 1, 1); - win->SetCellInsets(Insets(1,1,1,1)); - win->SetBackColor(Color(160,160,160)); - - ModelView* mv = new ModelView(win, scene, view_types[index]); - - if (view_types[index] == ModelView::VIEW_PROJECT) - mv->SetFillMode(ModelView::FILL_TEXTURE); - - mv->UseGrid(grid); - win->AddView(mv); - - view_win[index] = win; - model_view[index] = mv; - } - } - - view_win[0]->SetStyle(WIN_WHITE_FRAME); - - uvmap_win = new ActiveWindow(screen, 0, 0, w, h, 110, WIN_BLACK_FRAME, main_win); - uvmap_view = new UVMapView(uvmap_win); - uvmap_win->AddView(uvmap_view); - - main_win->DoLayout(); - } - - else { - ::Print(" Could not establish requested video parameters.\n"); - ::Print(" -----------------------------------------------\n\n"); - } - } -} - -// +--------------------------------------------------------------------+ - -void -MagicView::SetupModelViews() -{ - switch (view_mode) { - case VIEW_ALL: { - for (int row = 0; row < 2; row++) { - for (int col = 0; col < 2; col++) { - int index = 2*row + col; - - ActiveWindow* win = view_win[index]; - - win->Show(); - win->SetCells(col, row, 1, 1); - win->SetCellInsets(Insets(1,1,1,1)); - } - } - - uvmap_win->Hide(); - uvmap_win->SetCells(0,0,0,0); - } - break; - - case VIEW_TOP: - case VIEW_SIDE: - case VIEW_FRONT: - case VIEW_PERSPECTIVE: { - view_focus = view_mode; - - for (int i = 0; i < 4; i++) { - ActiveWindow* win = view_win[i]; - - if (i == view_mode) { - win->Show(); - win->SetCells(0,0,2,2); - win->SetStyle(WIN_WHITE_FRAME); - } - - else { - win->Hide(); - win->SetCells(0,0,0,0); - win->SetStyle(WIN_BLACK_FRAME); - } - } - - uvmap_win->Hide(); - uvmap_win->SetCells(0,0,0,0); - } - break; - - case VIEW_UV_MAP: { - view_focus = view_mode; - - for (int i = 0; i < 4; i++) { - ActiveWindow* win = view_win[i]; - win->Hide(); - win->SetCells(0,0,0,0); - win->SetStyle(WIN_BLACK_FRAME); - } - - uvmap_win->Show(); - uvmap_win->SetCells(0,0,2,2); - } - break; - - default: - break; - } - - main_win->DoLayout(); -} - -void -MagicView::SetFocusModelView(int f) -{ - if (view_mode == VIEW_ALL) { - view_focus = f; - - for (int row = 0; row < 2; row++) { - for (int col = 0; col < 2; col++) { - int index = 2*row + col; - - ActiveWindow* win = view_win[index]; - - win->Show(); - win->SetCells(col, row, 1, 1); - win->SetCellInsets(Insets(1,1,1,1)); - - if (index == view_focus) { - win->SetStyle(WIN_WHITE_FRAME); - } - else { - win->SetStyle(WIN_BLACK_FRAME); - } - } - } - } - else if (IsUVEdit()) { - view_focus = view_mode; - } - else { - view_mode = f; - view_focus = f; - - for (int i = 0; i < 4; i++) { - ActiveWindow* win = view_win[i]; - - if (i == view_mode) { - win->Show(); - win->SetCells(0,0,2,2); - win->SetStyle(WIN_WHITE_FRAME); - } - - else { - win->Hide(); - win->SetCells(0,0,0,0); - win->SetStyle(WIN_BLACK_FRAME); - } - } - } - - main_win->DoLayout(); -} - -int -MagicView::GetWinIndexByPoint(int x, int y) -{ - if (view_mode == VIEW_ALL) { - for (int row = 0; row < 2; row++) { - for (int col = 0; col < 2; col++) { - int index = 2*row + col; - - ActiveWindow* win = view_win[index]; - if (win->GetRect().Contains(x, y)) - return index; - } - } - } - - return view_mode; -} - -ModelView* -MagicView::GetModelViewByIndex(int index) -{ - if (index >= 0 && index < 4) { - return model_view[index]; - } - - return model_view[0]; -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnPaint() -{ - ValidateRect(0); - OnRender(); -} - -void MagicView::OnDraw(CDC* dc) -{ -} - -// +--------------------------------------------------------------------+ - -void MagicView::ResizeVideo() -{ - if (!video || !video_settings) return; - - HRESULT hr = S_OK; - RECT client_old; - - client_old = client_rect; - - // Update window properties - GetClientRect(&client_rect); - - if (client_old.right - client_old.left != - client_rect.right - client_rect.left || - client_old.bottom - client_old.top != - client_rect.bottom - client_rect.top) { - - // A new window size will require a new backbuffer - // size, so the 3D structures must be changed accordingly. - - video_settings->is_windowed = true; - video_settings->window_width = client_rect.right - client_rect.left; - video_settings->window_height = client_rect.bottom - client_rect.top; - - ::Print("ResizeVideo() %d x %d\n", video_settings->window_width, video_settings->window_height); - - if (video) { - video->Reset(video_settings); - } - } - - // save a copy of the device-specific video settings: - if (video->GetVideoSettings()) { - *video_settings = *video->GetVideoSettings(); - } - - if (screen) - screen->Resize(video_settings->window_width, - video_settings->window_height); - - video->InvalidateCache(); - video->SetShadowEnabled(view_shadows); - video->SetBumpMapEnabled(view_bumpmaps); -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) -{ - CView::OnUpdate(pSender, lHint, pHint); - - Solid* solid = GetDocument()->GetSolid(); - Selection* seln = GetDocument()->GetSelection(); - Selector* selector = GetDocument()->GetSelector(); - - if (solid && scene) { - scene->Graphics().clear(); - scene->AddGraphic(solid); - scene->AddGraphic(seln); - scene->AddGraphic(selector); - } - - if (selector) - selector->UseModel(solid->GetModel()); -} - -CPoint -MagicView::LPtoWP(const CPoint& p) -{ - CPoint result; - ModelView* view = GetModelViewByIndex(view_focus); - CPoint origin = view->ProjectPoint(Vec3(0,0,0)); - double scale = view->GetFieldOfView() / 2; - - result.x = (LONG) (( p.x - origin.x) / scale); - result.y = (LONG) ((-p.y + origin.y) / scale); - - return result; -} - -// +--------------------------------------------------------------------+ -// -// MagicView message handlers - -void MagicView::OnEnterSizeMove() -{ - is_sizing = true; -} - -void MagicView::OnExitSizeMove() -{ - is_sizing = false; - ResizeVideo(); -} - -void MagicView::OnSize(UINT nType, int cx, int cy) -{ - CView::OnSize(nType, cx, cy); - - window_style = GetWindowLong(m_hWnd, GWL_STYLE); - - if (nType == SIZE_MINIMIZED) { - is_minimized = true; - is_maximized = false; - } - - else if (nType == SIZE_MAXIMIZED) { - is_minimized = false; - is_maximized = true; - ResizeVideo(); - } - - else if (nType == SIZE_RESTORED) { - if (is_maximized) { - is_maximized = false; - ResizeVideo(); - } - - else if (is_minimized) { - is_minimized = false; - ResizeVideo(); - } - else if (!is_sizing) { - // if this is not a resize due to dragging... - ResizeVideo(); - } - else { - // If we're neither maximized nor minimized, the window size - // is changing by the user dragging the window edges. In this - // case, we don't reset the device yet -- we wait until the - // user stops dragging, and a WM_EXITSIZEMOVE message comes. - } - } -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnRender() -{ - if (!screen || !video) - return; - - double s = sin(timeGetTime() * 0.001); - double c = cos(timeGetTime() * 0.001); - - // IF LIGHTS ANIMATED: - if (animate_light) { - Point light_pos(3e6*s, 5e6*c, 4e6*s); - - if (main_light) { - main_light->SetType(Light::LIGHT_POINT); - main_light->MoveTo(light_pos); - main_light->SetType(Light::LIGHT_DIRECTIONAL); - } - - if (back_light) { - back_light->SetType(Light::LIGHT_POINT); - back_light->MoveTo(light_pos * -1); - back_light->SetType(Light::LIGHT_DIRECTIONAL); - } - } - - if (screen->Refresh()) { - video->Present(); - } - else { - ::Print("ERROR: Screen refresh failed.\n"); - } -} - -void MagicView::CloseUVEditor() -{ - if (IsUVEdit()) { - MagicDoc* doc = GetDocument(); - Editor* editor = doc->GetEditor(); - Solid* solid = doc->GetSolid(); - - if (editor && solid) { - editor->UseModel(solid->GetModel()); - editor->Resegment(); - } - } -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnViewAll() -{ - CloseUVEditor(); - view_mode = VIEW_ALL; - SetupModelViews(); -} - -void MagicView::OnUpdateViewAll(CCmdUI* pCmdUI) -{ - if (pCmdUI) - pCmdUI->SetCheck(view_mode == VIEW_ALL); -} - -void MagicView::OnViewFront() -{ - CloseUVEditor(); - view_mode = VIEW_FRONT; - SetupModelViews(); -} - -void MagicView::OnUpdateViewFront(CCmdUI* pCmdUI) -{ - if (pCmdUI) - pCmdUI->SetCheck(view_mode == VIEW_FRONT); -} - -void MagicView::OnViewPerspective() -{ - CloseUVEditor(); - view_mode = VIEW_PERSPECTIVE; - SetupModelViews(); -} - -void MagicView::OnUpdateViewPerspective(CCmdUI* pCmdUI) -{ - if (pCmdUI) - pCmdUI->SetCheck(view_mode == VIEW_PERSPECTIVE); -} - -void MagicView::OnViewSide() -{ - CloseUVEditor(); - view_mode = VIEW_SIDE; - SetupModelViews(); -} - -void MagicView::OnUpdateViewSide(CCmdUI* pCmdUI) -{ - if (pCmdUI) - pCmdUI->SetCheck(view_mode == VIEW_SIDE); -} - -void MagicView::OnViewTop() -{ - CloseUVEditor(); - view_mode = VIEW_TOP; - SetupModelViews(); -} - -void MagicView::OnUpdateViewTop(CCmdUI* pCmdUI) -{ - if (pCmdUI) - pCmdUI->SetCheck(view_mode == VIEW_TOP); -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnFileImport() -{ - DWORD err = 0; - char filename[256]; - filename[0] = '\0'; - CFileDialog ofd(TRUE, "mag"); - - ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; - ofd.m_ofn.lpstrFile = filename; - ofd.m_ofn.nMaxFile = sizeof(filename); - - if (ofd.DoModal() != IDOK) - return; - - char mag_name[256]; - sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); - - MagicDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - - if (pDoc->ImportFile(mag_name)) { - Invalidate(); - pDoc->SetModifiedFlag(TRUE); - pDoc->UpdateAllViews(this); - } -} - -void MagicView::OnFileExport() -{ - DWORD err = 0; - char filename[256]; - filename[0] = '\0'; - CFileDialog ofd(FALSE, "mag"); - - ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; - ofd.m_ofn.lpstrFile = filename; - ofd.m_ofn.nMaxFile = sizeof(filename); - - if (ofd.DoModal() != IDOK) - return; - - char mag_name[256]; - sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); - - MagicDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - - if (pDoc->ExportFile(mag_name)) { - pDoc->SetModifiedFlag(FALSE); - pDoc->UpdateAllViews(this); - } -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnSurfaceProperties() -{ - SurfacePropertiesDialog dlg(this); - dlg.DoModal(); -} - -void MagicView::OnUpdateSurfaceProperties(CCmdUI* pCmdUI) -{ - Solid* solid = GetDocument()->GetSolid(); - pCmdUI->Enable(solid && solid->GetModel()); -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnTextureMap() -{ - TextureMapDialog dlg(this); - if (dlg.DoModal() == IDOK) { - MagicDoc* doc = GetDocument(); - Solid* solid = doc->GetSolid(); - Selection* seln = doc->GetSelection(); - Selector* selector = doc->GetSelector(); - Editor* editor = doc->GetEditor(); - Material* mtl = 0; - - if (dlg.mMaterialIndex >= 0) { - mtl = solid->GetModel()->GetMaterials()[dlg.mMaterialIndex]; - } - - editor->UseModel(solid->GetModel()); - editor->ApplyMaterial(mtl, seln->GetPolys(), - dlg.mMapType, 2-dlg.mAxis, (float) dlg.mScaleU, (float) dlg.mScaleV, - dlg.mFlip, dlg.mMirror, dlg.mRotate); - - selector->Reselect(); - - Invalidate(); - doc->SetModifiedFlag(TRUE); - doc->UpdateAllViews(this); - } -} - -void MagicView::OnUpdateTextureMap(CCmdUI* pCmdUI) -{ - Solid* solid = GetDocument()->GetSolid(); - Selection* seln = GetDocument()->GetSelection(); - - pCmdUI->Enable(solid && solid->GetModel() && seln && seln->GetPolys().size() > 0); -} - -void MagicView::OnModifyMaterial() -{ - MaterialDialog dlg(this); - dlg.DoModal(); - - Invalidate(); - GetDocument()->SetModifiedFlag(TRUE); - GetDocument()->UpdateAllViews(this); -} - -void MagicView::OnUpdateModifyMaterial(CCmdUI* pCmdUI) -{ - Solid* solid = GetDocument()->GetSolid(); - pCmdUI->Enable(solid && solid->GetModel()); -} - -void MagicView::OnModifyUVMap() -{ - Selection* seln = GetDocument()->GetSelection(); - - view_mode = VIEW_UV_MAP; - SetupModelViews(); - - if (seln && uvmap_view) { - Poly* p = seln->GetPolys().first(); - - if (p) { - uvmap_view->UseMaterial(p->material); - uvmap_view->UsePolys(seln->GetPolys()); - } - } -} - -void MagicView::OnUpdateModifyUVMap(CCmdUI* pCmdUI) -{ - OnUpdateTextureMap(pCmdUI); -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnGridProperties() -{ - GridProps dlg(grid, this); - dlg.DoModal(); -} - -void MagicView::OnGridShow() -{ - if (grid) - grid->SetShow(!grid->IsShow()); -} - -void MagicView::OnGridSnap() -{ - if (grid) - grid->SetSnap(!grid->IsSnap()); -} - -void MagicView::OnUpdateGridSnap(CCmdUI* pCmdUI) -{ - if (grid) - pCmdUI->SetCheck(grid->IsSnap()); -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnLButtonDown(UINT nFlags, CPoint point) -{ - CView::OnLButtonDown(nFlags, point); - SetCapture(); - - // set focus to the view that was clicked: - int index = GetWinIndexByPoint(point.x, point.y); - SetFocusModelView(index); - - drag_start = point; - drag_left = true; - drag_right = false; - - ModelView* mv = GetModelViewByIndex(index); - MagicDoc* pDoc = GetDocument(); - Model* model = pDoc->GetSolid()->GetModel(); - Selector* selector = pDoc->GetSelector(); - - if (IsUVEdit()) { - int select_mode = UVMapView::SELECT_APPEND; - - if (nFlags & MK_CONTROL) - select_mode = UVMapView::SELECT_REMOVE; - - if (!uvmap_view->WillSelect(point)) { - uvmap_view->Begin(select_mode); - uvmap_view->AddMark(point); - } - } - - else if (mv && selector) { - int select_mode = Selector::SELECT_APPEND; - - if (nFlags & MK_CONTROL) - select_mode = Selector::SELECT_REMOVE; - - selector->Begin(model, mv->GetViewMode(), select_mode); - selector->AddMark(point); - } -} - -void MagicView::OnLButtonUp(UINT nFlags, CPoint point) -{ - CView::OnLButtonUp(nFlags, point); - ReleaseCapture(); - - drag_left = false; - - MagicDoc* pDoc = GetDocument(); - Selector* selector = pDoc->GetSelector(); - - if (IsUVEdit()) - uvmap_view->End(); - - else if (selector && selector->IsActive()) - selector->End(); -} - -void MagicView::OnLButtonDblClk(UINT nFlags, CPoint point) -{ - CView::OnLButtonDblClk(nFlags, point); - - drag_left = false; - - MagicDoc* pDoc = GetDocument(); - Selector* selector = pDoc->GetSelector(); - - if (IsUVEdit()) - uvmap_view->Clear(); - - else if (selector) - selector->Clear(); -} - -void MagicView::OnRButtonDown(UINT nFlags, CPoint point) -{ - CView::OnRButtonDown(nFlags, point); - SetCapture(); - - // set focus to the view that was clicked: - int index = GetWinIndexByPoint(point.x, point.y); - SetFocusModelView(index); - - drag_start = point; - drag_left = false; - drag_right = true; -} - -void MagicView::OnRButtonUp(UINT nFlags, CPoint point) -{ - CView::OnRButtonUp(nFlags, point); - ReleaseCapture(); - - drag_right = false; -} - -void MagicView::OnRButtonDblClk(UINT nFlags, CPoint point) -{ - CView::OnRButtonDblClk(nFlags, point); - ReleaseCapture(); - - drag_right = false; - - if (view_mode == VIEW_ALL) { - view_mode = view_focus; - } - else if (IsUVEdit()) { - CloseUVEditor(); - view_mode = VIEW_ALL; - SetupModelViews(); - } - else { - view_mode = VIEW_ALL; - } - - SetFocusModelView(view_focus); -} - -void MagicView::OnMouseMove(UINT nFlags, CPoint point) -{ - if (drag_right) { - CPoint offset = point - drag_start; - - if (view_focus == VIEW_PERSPECTIVE) { - ModelView* view = GetModelViewByIndex(view_focus); - view->SpinBy(offset.x * 0.5 * DEGREES, - offset.y * 0.5 * DEGREES); - } - - else if (IsUVEdit()) { - uvmap_view->MoveBy(offset.x, offset.y); - } - - else { - ModelView* view = GetModelViewByIndex(view_focus); - view->MoveBy(offset.x, offset.y); - } - - drag_start = point; - Invalidate(); - } - - else if (drag_left) { - CPoint offset = point - drag_start; - MagicDoc* pDoc = GetDocument(); - Selector* selector = pDoc->GetSelector(); - - if (IsUVEdit()) { - if (uvmap_view->IsActive()) { - uvmap_view->AddMark(point); - } - else { - uvmap_view->DragBy(offset.x, offset.y); - drag_start = point; - } - } - - else if (selector && selector->IsActive()) { - selector->AddMark(point); - } - } - - // xy status message: - if (view_focus != VIEW_PERSPECTIVE) { - char xy[80]; - CPoint mouse = LPtoWP(point); - Selection* seln = GetDocument()->GetSelection(); - - int nv = seln ? seln->GetVerts().size() : 0; - int np = seln ? seln->GetPolys().size() : 0; - - if (np || nv) - sprintf_s(xy, "(%05d,%05d) Verts:%d Polys:%d", mouse.x, mouse.y, nv, np); - else - sprintf_s(xy, "(%05d,%05d)", mouse.x, mouse.y); - MainFrame::StatusXY(xy); - } - - CView::OnMouseMove(nFlags, point); -} - -BOOL MagicView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) -{ - if (view_focus == VIEW_PERSPECTIVE) { - ModelView* view = GetModelViewByIndex(view_focus); - - if (view) { - Camera* cam = view->GetCamera(); - Point pos = cam->Pos(); - double len = pos.length(); - - if (zDelta < 0) { - if (len < 10000) - pos *= 1.15; - } - else { - if (len > 0.10) - pos *= 0.85; - } - - cam->MoveTo(pos); - } - } - - else if (IsUVEdit()) { - if (zDelta < 0) { - uvmap_view->ZoomOut(); - } - else { - uvmap_view->ZoomIn(); - } - } - - else { - if (zDelta > 0) - OnViewZoomIn(); - else - OnViewZoomOut(); - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnViewZoomNormal() -{ - for (int i = 0; i < 4; i++) { - ModelView* view = GetModelViewByIndex(i); - - if (view) { - view->ZoomNormal(); - } - } -} - -void MagicView::OnViewZoomIn() -{ - for (int i = 0; i < 4; i++) { - ModelView* view = GetModelViewByIndex(i); - - if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { - double fov = view->GetFieldOfView() * 1.15; - view->SetFieldOfView(fov); - } - } -} - -void MagicView::OnViewZoomOut() -{ - for (int i = 0; i < 4; i++) { - ModelView* view = GetModelViewByIndex(i); - - if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { - double fov = view->GetFieldOfView() * 0.85; - view->SetFieldOfView(fov); - } - } -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnViewModeWireframe() -{ - ModelView* view = GetModelViewByIndex(view_focus); - - if (view) { - view->SetFillMode(ModelView::FILL_WIRE); - } -} - -void MagicView::OnViewModeSolid() -{ - ModelView* view = GetModelViewByIndex(view_focus); - - if (view) { - view->SetFillMode(ModelView::FILL_SOLID); - } -} - -void MagicView::OnViewModeTextured() -{ - ModelView* view = GetModelViewByIndex(view_focus); - - if (view) { - view->SetFillMode(ModelView::FILL_TEXTURE); - } -} - -void MagicView::OnViewBackColor() -{ - ModelView* view = GetModelViewByIndex(view_focus); - - if (view) { - ActiveWindow* win = (ActiveWindow*) view->GetWindow(); - Color c = win->GetBackColor(); - COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); - CColorDialog chooser(crgb); - - if (chooser.DoModal() == IDOK) { - crgb = chooser.GetColor(); - win->SetBackColor( Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)) ); - } - } -} - -// +--------------------------------------------------------------------+ - -void MagicView::OnSelectAll() -{ - Solid* solid = GetDocument()->GetSolid(); - Selector* selector = GetDocument()->GetSelector(); - - if (IsUVEdit()) { - uvmap_view->SelectAll(); - } - - else if (solid && selector) { - selector->UseModel(solid->GetModel()); - selector->SelectAll(Selector::SELECT_APPEND); - } -} - -void MagicView::OnSelectNone() -{ - Solid* solid = GetDocument()->GetSolid(); - Selector* selector = GetDocument()->GetSelector(); - - if (IsUVEdit()) { - uvmap_view->SelectNone(); - } - - else if (solid && selector) { - selector->UseModel(solid->GetModel()); - selector->SelectAll(Selector::SELECT_REMOVE); - } -} - -void MagicView::OnSelectInverse() -{ - Solid* solid = GetDocument()->GetSolid(); - Selector* selector = GetDocument()->GetSelector(); - - if (IsUVEdit()) { - uvmap_view->SelectInverse(); - } - - else if (solid && selector) { - selector->UseModel(solid->GetModel()); - selector->SelectInverse(); - } -} - -void MagicView::OnViewShadows() -{ - view_shadows = !view_shadows; - - if (video) - video->SetShadowEnabled(view_shadows); -} - -void MagicView::OnUpdateViewShadows(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(view_shadows); -} - -void MagicView::OnViewAnimatelight() -{ - animate_light = !animate_light; -} - -void MagicView::OnUpdateViewAnimatelight(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(animate_light); -} - -void MagicView::OnViewBumpmaps() -{ - view_bumpmaps = !view_bumpmaps; - - if (video) - video->SetBumpMapEnabled(view_bumpmaps); -} - -void MagicView::OnUpdateViewBumpmaps(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(view_bumpmaps); -} - -void MagicView::OnViewVertexshader() -{ - if (video) { - VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); - vs->enable_vs = !vs->enable_vs; - } -} - -void MagicView::OnUpdateViewVertexshader(CCmdUI* pCmdUI) -{ - if (video) - pCmdUI->SetCheck(video->GetVideoSettings()->enable_vs); -} - -void MagicView::OnViewPixelshader() -{ - if (video) { - VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); - vs->enable_ps = !vs->enable_ps; - } -} - -void MagicView::OnUpdateViewPixelshader(CCmdUI* pCmdUI) -{ - if (video) - pCmdUI->SetCheck(video->GetVideoSettings()->enable_ps); -} - -void MagicView::OnViewVisibleshadows() -{ - Shadow::SetVisibleShadowVolumes(!Shadow::GetVisibleShadowVolumes()); -} - -void MagicView::OnUpdateViewVisibleshadows(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(Shadow::GetVisibleShadowVolumes()); -} - -void MagicView::OnEditUndo() -{ - MagicDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - pDoc->Undo(); - - Solid* solid = GetDocument()->GetSolid(); - Selector* selector = GetDocument()->GetSelector(); - - if (selector) { - selector->UseModel(solid->GetModel()); - selector->Reselect(); - } - - Invalidate(); - pDoc->SetModifiedFlag(TRUE); - pDoc->UpdateAllViews(this); -} - -void MagicView::OnUpdateEditUndo(CCmdUI* pCmdUI) -{ - MagicDoc* pDoc = GetDocument(); - - if (pDoc->NumUndo() > 0) { - pCmdUI->Enable(TRUE); - pCmdUI->SetText(CString("Undo ") + pDoc->GetUndoName() + CString("\tCtrl+Z")); - } - else { - pCmdUI->Enable(FALSE); - pCmdUI->SetText("Can't Undo\tCtrl+Z"); - } -} - -void MagicView::OnEditRedo() -{ - MagicDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - pDoc->Redo(); - - Solid* solid = GetDocument()->GetSolid(); - Selector* selector = GetDocument()->GetSelector(); - - if (selector) { - selector->UseModel(solid->GetModel()); - selector->Reselect(); - } - - Invalidate(); - pDoc->SetModifiedFlag(TRUE); - pDoc->UpdateAllViews(this); -} - -void MagicView::OnUpdateEditRedo(CCmdUI* pCmdUI) -{ - MagicDoc* pDoc = GetDocument(); - - if (pDoc->NumRedo() > 0) { - pCmdUI->Enable(TRUE); - pCmdUI->SetText(CString("Redo ") + pDoc->GetRedoName() + CString("\tCtrl+Y")); - } - else { - pCmdUI->Enable(FALSE); - pCmdUI->SetText("Can't Redo"); - } -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MagicView.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the MagicView class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "MagicView.h" +#include "MainFrm.h" +#include "MaterialDialog.h" +#include "SurfacePropertiesDialog.h" +#include "TextureMapDialog.h" +#include "Editor.h" +#include "Grid.h" +#include "GridProps.h" +#include "Selection.h" +#include "Selector.h" +#include "UVMapView.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Layout.h" +#include "Light.h" +#include "Scene.h" +#include "Screen.h" +#include "Shadow.h" +#include "Solid.h" +#include "Video.h" +#include "VideoDX9.h" +#include "VideoSettings.h" + +#include "ModelView.h" + +DWORD GetRealTime(); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern PALETTEENTRY standard_palette[256]; +extern BYTE inverse_palette[32768]; + +// +--------------------------------------------------------------------+ + +IMPLEMENT_DYNCREATE(MagicView, CView) + +BEGIN_MESSAGE_MAP(MagicView, CView) + //{{AFX_MSG_MAP(MagicView) + ON_WM_SIZE() + ON_COMMAND(ID_VIEW_RENDER, OnRender) + ON_WM_PAINT() + ON_COMMAND(ID_VIEW_ALL, OnViewAll) + ON_UPDATE_COMMAND_UI(ID_VIEW_ALL, OnUpdateViewAll) + ON_COMMAND(ID_VIEW_FRONT, OnViewFront) + ON_UPDATE_COMMAND_UI(ID_VIEW_FRONT, OnUpdateViewFront) + ON_COMMAND(ID_VIEW_PERSPECTIVE, OnViewPerspective) + ON_UPDATE_COMMAND_UI(ID_VIEW_PERSPECTIVE, OnUpdateViewPerspective) + ON_COMMAND(ID_VIEW_SIDE, OnViewSide) + ON_UPDATE_COMMAND_UI(ID_VIEW_SIDE, OnUpdateViewSide) + ON_COMMAND(ID_VIEW_TOP, OnViewTop) + ON_UPDATE_COMMAND_UI(ID_VIEW_TOP, OnUpdateViewTop) + ON_COMMAND(ID_MODIFY_TEXTURE_MAP, OnTextureMap) + ON_COMMAND(ID_MODIFY_MATERIAL, OnModifyMaterial) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDOWN() + ON_WM_RBUTTONUP() + ON_WM_MOUSEMOVE() + ON_WM_MOUSEWHEEL() + ON_COMMAND(ID_VIEW_ZOOM_NORMAL, OnViewZoomNormal) + ON_COMMAND(ID_VIEW_ZOOM_IN, OnViewZoomIn) + ON_COMMAND(ID_VIEW_ZOOM_OUT, OnViewZoomOut) + ON_COMMAND(ID_VIEW_MODE_WIREFRAME, OnViewModeWireframe) + ON_COMMAND(ID_VIEW_MODE_SOLID, OnViewModeSolid) + ON_COMMAND(ID_VIEW_MODE_TEXTURED, OnViewModeTextured) + ON_WM_RBUTTONDBLCLK() + ON_COMMAND(ID_PROP_GRID, OnGridProperties) + ON_COMMAND(ID_GRID_SHOW, OnGridShow) + ON_COMMAND(ID_GRID_SNAP, OnGridSnap) + ON_UPDATE_COMMAND_UI(ID_GRID_SNAP, OnUpdateGridSnap) + ON_COMMAND(ID_VIEW_BACK_COLOR, OnViewBackColor) + ON_COMMAND(ID_FILE_IMPORT, OnFileImport) + ON_COMMAND(ID_FILE_EXPORT, OnFileExport) + ON_COMMAND(ID_EDIT_SELECT_ALL, OnSelectAll) + ON_COMMAND(ID_EDIT_SELECT_NONE, OnSelectNone) + ON_UPDATE_COMMAND_UI(ID_MODIFY_TEXTURE_MAP, OnUpdateTextureMap) + ON_UPDATE_COMMAND_UI(ID_MODIFY_MATERIAL, OnUpdateModifyMaterial) + ON_COMMAND(ID_EDIT_SELECT_INVERSE, OnSelectInverse) + ON_COMMAND(ID_MODIFY_UV_MAP, OnModifyUVMap) + ON_UPDATE_COMMAND_UI(ID_MODIFY_UV_MAP, OnUpdateModifyUVMap) + ON_COMMAND(ID_VIEW_SHADOWS, OnViewShadows) + ON_UPDATE_COMMAND_UI(ID_VIEW_SHADOWS, OnUpdateViewShadows) + ON_COMMAND(ID_VIEW_ANIMATELIGHT, OnViewAnimatelight) + ON_UPDATE_COMMAND_UI(ID_VIEW_ANIMATELIGHT, OnUpdateViewAnimatelight) + ON_COMMAND(ID_VIEW_BUMPMAPS, OnViewBumpmaps) + ON_UPDATE_COMMAND_UI(ID_VIEW_BUMPMAPS, OnUpdateViewBumpmaps) + ON_COMMAND(ID_VIEW_VERTEXSHADER, OnViewVertexshader) + ON_UPDATE_COMMAND_UI(ID_VIEW_VERTEXSHADER, OnUpdateViewVertexshader) + ON_COMMAND(ID_VIEW_PIXELSHADER, OnViewPixelshader) + ON_UPDATE_COMMAND_UI(ID_VIEW_PIXELSHADER, OnUpdateViewPixelshader) + ON_COMMAND(ID_VIEW_VISIBLESHADOWS, OnViewVisibleshadows) + ON_UPDATE_COMMAND_UI(ID_VIEW_VISIBLESHADOWS, OnUpdateViewVisibleshadows) + ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) + ON_COMMAND(ID_EDIT_REDO, OnEditRedo) + ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo) + ON_COMMAND(ID_PROP_SURFACE, OnSurfaceProperties) + ON_UPDATE_COMMAND_UI(ID_PROP_SURFACE, OnUpdateSurfaceProperties) + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +static MagicView* magic_view = 0; + +MagicView::MagicView() + : video(0), video_settings(0), screen(0), scene(0), + drag_left(false), drag_right(false), grid(0), + main_light(0), back_light(0), view_shadows(true), view_bumpmaps(true), + animate_light(false) +{ + window_style = 0; + is_minimized = false; + is_maximized = false; + is_sizing = false; + view_mode = VIEW_ALL; + + main_win = 0; + view_win[0] = 0; + view_win[1] = 0; + view_win[2] = 0; + view_win[3] = 0; + model_view[0] = 0; + model_view[1] = 0; + model_view[2] = 0; + model_view[3] = 0; + uvmap_win = 0; + + grid = new Grid; + magic_view = this; + + Solid::EnableCollision(false); +} + +MagicView::~MagicView() +{ + if (grid) { + delete grid; + } + + if (scene) { + scene->Graphics().clear(); + delete scene; + } + + if (screen) delete screen; + if (video) delete video; + if (video_settings) delete video_settings; + + if (magic_view == this) + magic_view = 0; +} + +MagicView* MagicView::GetInstance() +{ + return magic_view; +} + +BOOL MagicView::PreCreateWindow(CREATESTRUCT& cs) +{ + return CView::PreCreateWindow(cs); +} + +// +--------------------------------------------------------------------+ +// +// MagicView diagnostics + +#ifdef _DEBUG +void MagicView::AssertValid() const +{ + CView::AssertValid(); +} + +void MagicView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +MagicDoc* MagicView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(MagicDoc))); + return (MagicDoc*)m_pDocument; +} +#endif //_DEBUG + + +// +--------------------------------------------------------------------+ + +void MagicView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + Color::SetPalette(standard_palette, 256, inverse_palette); + + if (!video_settings) + video_settings = new VideoSettings; + + GetClientRect(&client_rect); + + // Use client area to set video window size + int w = client_rect.right - client_rect.left; + int h = client_rect.bottom - client_rect.top; + + video_settings->is_windowed = true; + video_settings->window_width = w; + video_settings->window_height = h; + + if (!video) { + video = new VideoDX9(GetSafeHwnd(), video_settings); + *video_settings = *video->GetVideoSettings(); + + if (video) { + Color::UseVideo(video); + video->UseXFont("System", 12, false, false); + + screen = new Screen(video); + if (!screen) { + ::Print("ERROR: Could not create Screen object.\n"); + return; + } + + ::Print(" Created screen object (%d x %d).\n", w, h); + + if (!screen->SetBackgroundColor(Color::Black)) + ::Print(" WARNING: could not set video background color to Black\n"); + + screen->ClearAllFrames(true); + + ::Print(" Established requested video parameters.\n"); + ::Print(" ---------------------------------------\n\n"); + + if (!scene) { + scene = new Scene; + + scene->SetAmbient(Color(60,60,60)); + + Point light_pos(3e6, 5e6, 4e6); + + main_light = new Light(1.0f); //1.25f); + main_light->MoveTo(light_pos); + main_light->SetType(Light::LIGHT_DIRECTIONAL); + main_light->SetColor(Color::White); + main_light->SetShadow(true); + + scene->AddLight(main_light); + + back_light = new Light(0.5f); + back_light->MoveTo(light_pos * -1); + back_light->SetType(Light::LIGHT_DIRECTIONAL); + back_light->SetColor(Color::White); + + scene->AddLight(back_light); + + Selection* seln = GetDocument()->GetSelection(); + Selector* selector = GetDocument()->GetSelector(); + + if (seln && selector) { + scene->Graphics().clear(); + scene->AddGraphic(seln); + scene->AddGraphic(selector); + + selector->UseModel(0); + } + } + + int mins[2] = { 0, 0 }; + float weights[2] = { 1, 1 }; + + main_win = new ActiveWindow(screen, 0, 0, w, h, 100, 0); + main_win->UseLayout(2, 2, mins, mins, weights, weights); + main_win->SetBackColor(Color::Gray); + + screen->AddWindow(main_win); + + DWORD view_types[] = { + ModelView::VIEW_PLAN, + ModelView::VIEW_PROJECT, + ModelView::VIEW_SIDE, + ModelView::VIEW_FRONT + }; + + for (int row = 0; row < 2; row++) { + for (int col = 0; col < 2; col++) { + int index = 2*row + col; + + ActiveWindow* win = new ActiveWindow(screen, + col*w/2, + row*h/2, + w/2, + h/2, + 101+index, + WIN_BLACK_FRAME, + main_win); + + win->SetCells(col, row, 1, 1); + win->SetCellInsets(Insets(1,1,1,1)); + win->SetBackColor(Color(160,160,160)); + + ModelView* mv = new ModelView(win, scene, view_types[index]); + + if (view_types[index] == ModelView::VIEW_PROJECT) + mv->SetFillMode(ModelView::FILL_TEXTURE); + + mv->UseGrid(grid); + win->AddView(mv); + + view_win[index] = win; + model_view[index] = mv; + } + } + + view_win[0]->SetStyle(WIN_WHITE_FRAME); + + uvmap_win = new ActiveWindow(screen, 0, 0, w, h, 110, WIN_BLACK_FRAME, main_win); + uvmap_view = new UVMapView(uvmap_win); + uvmap_win->AddView(uvmap_view); + + main_win->DoLayout(); + } + + else { + ::Print(" Could not establish requested video parameters.\n"); + ::Print(" -----------------------------------------------\n\n"); + } + } +} + +// +--------------------------------------------------------------------+ + +void +MagicView::SetupModelViews() +{ + switch (view_mode) { + case VIEW_ALL: { + for (int row = 0; row < 2; row++) { + for (int col = 0; col < 2; col++) { + int index = 2*row + col; + + ActiveWindow* win = view_win[index]; + + win->Show(); + win->SetCells(col, row, 1, 1); + win->SetCellInsets(Insets(1,1,1,1)); + } + } + + uvmap_win->Hide(); + uvmap_win->SetCells(0,0,0,0); + } + break; + + case VIEW_TOP: + case VIEW_SIDE: + case VIEW_FRONT: + case VIEW_PERSPECTIVE: { + view_focus = view_mode; + + for (int i = 0; i < 4; i++) { + ActiveWindow* win = view_win[i]; + + if (i == view_mode) { + win->Show(); + win->SetCells(0,0,2,2); + win->SetStyle(WIN_WHITE_FRAME); + } + + else { + win->Hide(); + win->SetCells(0,0,0,0); + win->SetStyle(WIN_BLACK_FRAME); + } + } + + uvmap_win->Hide(); + uvmap_win->SetCells(0,0,0,0); + } + break; + + case VIEW_UV_MAP: { + view_focus = view_mode; + + for (int i = 0; i < 4; i++) { + ActiveWindow* win = view_win[i]; + win->Hide(); + win->SetCells(0,0,0,0); + win->SetStyle(WIN_BLACK_FRAME); + } + + uvmap_win->Show(); + uvmap_win->SetCells(0,0,2,2); + } + break; + + default: + break; + } + + main_win->DoLayout(); +} + +void +MagicView::SetFocusModelView(int f) +{ + if (view_mode == VIEW_ALL) { + view_focus = f; + + for (int row = 0; row < 2; row++) { + for (int col = 0; col < 2; col++) { + int index = 2*row + col; + + ActiveWindow* win = view_win[index]; + + win->Show(); + win->SetCells(col, row, 1, 1); + win->SetCellInsets(Insets(1,1,1,1)); + + if (index == view_focus) { + win->SetStyle(WIN_WHITE_FRAME); + } + else { + win->SetStyle(WIN_BLACK_FRAME); + } + } + } + } + else if (IsUVEdit()) { + view_focus = view_mode; + } + else { + view_mode = f; + view_focus = f; + + for (int i = 0; i < 4; i++) { + ActiveWindow* win = view_win[i]; + + if (i == view_mode) { + win->Show(); + win->SetCells(0,0,2,2); + win->SetStyle(WIN_WHITE_FRAME); + } + + else { + win->Hide(); + win->SetCells(0,0,0,0); + win->SetStyle(WIN_BLACK_FRAME); + } + } + } + + main_win->DoLayout(); +} + +int +MagicView::GetWinIndexByPoint(int x, int y) +{ + if (view_mode == VIEW_ALL) { + for (int row = 0; row < 2; row++) { + for (int col = 0; col < 2; col++) { + int index = 2*row + col; + + ActiveWindow* win = view_win[index]; + if (win->GetRect().Contains(x, y)) + return index; + } + } + } + + return view_mode; +} + +ModelView* +MagicView::GetModelViewByIndex(int index) +{ + if (index >= 0 && index < 4) { + return model_view[index]; + } + + return model_view[0]; +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnPaint() +{ + ValidateRect(0); + OnRender(); +} + +void MagicView::OnDraw(CDC* dc) +{ +} + +// +--------------------------------------------------------------------+ + +void MagicView::ResizeVideo() +{ + if (!video || !video_settings) return; + + HRESULT hr = S_OK; + RECT client_old; + + client_old = client_rect; + + // Update window properties + GetClientRect(&client_rect); + + if (client_old.right - client_old.left != + client_rect.right - client_rect.left || + client_old.bottom - client_old.top != + client_rect.bottom - client_rect.top) { + + // A new window size will require a new backbuffer + // size, so the 3D structures must be changed accordingly. + + video_settings->is_windowed = true; + video_settings->window_width = client_rect.right - client_rect.left; + video_settings->window_height = client_rect.bottom - client_rect.top; + + ::Print("ResizeVideo() %d x %d\n", video_settings->window_width, video_settings->window_height); + + if (video) { + video->Reset(video_settings); + } + } + + // save a copy of the device-specific video settings: + if (video->GetVideoSettings()) { + *video_settings = *video->GetVideoSettings(); + } + + if (screen) + screen->Resize(video_settings->window_width, + video_settings->window_height); + + video->InvalidateCache(); + video->SetShadowEnabled(view_shadows); + video->SetBumpMapEnabled(view_bumpmaps); +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) +{ + CView::OnUpdate(pSender, lHint, pHint); + + Solid* solid = GetDocument()->GetSolid(); + Selection* seln = GetDocument()->GetSelection(); + Selector* selector = GetDocument()->GetSelector(); + + if (solid && scene) { + scene->Graphics().clear(); + scene->AddGraphic(solid); + scene->AddGraphic(seln); + scene->AddGraphic(selector); + } + + if (selector) + selector->UseModel(solid->GetModel()); +} + +CPoint +MagicView::LPtoWP(const CPoint& p) +{ + CPoint result; + ModelView* view = GetModelViewByIndex(view_focus); + CPoint origin = view->ProjectPoint(Vec3(0,0,0)); + double scale = view->GetFieldOfView() / 2; + + result.x = (LONG) (( p.x - origin.x) / scale); + result.y = (LONG) ((-p.y + origin.y) / scale); + + return result; +} + +// +--------------------------------------------------------------------+ +// +// MagicView message handlers + +void MagicView::OnEnterSizeMove() +{ + is_sizing = true; +} + +void MagicView::OnExitSizeMove() +{ + is_sizing = false; + ResizeVideo(); +} + +void MagicView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + window_style = GetWindowLong(m_hWnd, GWL_STYLE); + + if (nType == SIZE_MINIMIZED) { + is_minimized = true; + is_maximized = false; + } + + else if (nType == SIZE_MAXIMIZED) { + is_minimized = false; + is_maximized = true; + ResizeVideo(); + } + + else if (nType == SIZE_RESTORED) { + if (is_maximized) { + is_maximized = false; + ResizeVideo(); + } + + else if (is_minimized) { + is_minimized = false; + ResizeVideo(); + } + else if (!is_sizing) { + // if this is not a resize due to dragging... + ResizeVideo(); + } + else { + // If we're neither maximized nor minimized, the window size + // is changing by the user dragging the window edges. In this + // case, we don't reset the device yet -- we wait until the + // user stops dragging, and a WM_EXITSIZEMOVE message comes. + } + } +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnRender() +{ + if (!screen || !video) + return; + + double s = sin(timeGetTime() * 0.001); + double c = cos(timeGetTime() * 0.001); + + // IF LIGHTS ANIMATED: + if (animate_light) { + Point light_pos(3e6*s, 5e6*c, 4e6*s); + + if (main_light) { + main_light->SetType(Light::LIGHT_POINT); + main_light->MoveTo(light_pos); + main_light->SetType(Light::LIGHT_DIRECTIONAL); + } + + if (back_light) { + back_light->SetType(Light::LIGHT_POINT); + back_light->MoveTo(light_pos * -1); + back_light->SetType(Light::LIGHT_DIRECTIONAL); + } + } + + if (screen->Refresh()) { + video->Present(); + } + else { + ::Print("ERROR: Screen refresh failed.\n"); + } +} + +void MagicView::CloseUVEditor() +{ + if (IsUVEdit()) { + MagicDoc* doc = GetDocument(); + Editor* editor = doc->GetEditor(); + Solid* solid = doc->GetSolid(); + + if (editor && solid) { + editor->UseModel(solid->GetModel()); + editor->Resegment(); + } + } +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnViewAll() +{ + CloseUVEditor(); + view_mode = VIEW_ALL; + SetupModelViews(); +} + +void MagicView::OnUpdateViewAll(CCmdUI* pCmdUI) +{ + if (pCmdUI) + pCmdUI->SetCheck(view_mode == VIEW_ALL); +} + +void MagicView::OnViewFront() +{ + CloseUVEditor(); + view_mode = VIEW_FRONT; + SetupModelViews(); +} + +void MagicView::OnUpdateViewFront(CCmdUI* pCmdUI) +{ + if (pCmdUI) + pCmdUI->SetCheck(view_mode == VIEW_FRONT); +} + +void MagicView::OnViewPerspective() +{ + CloseUVEditor(); + view_mode = VIEW_PERSPECTIVE; + SetupModelViews(); +} + +void MagicView::OnUpdateViewPerspective(CCmdUI* pCmdUI) +{ + if (pCmdUI) + pCmdUI->SetCheck(view_mode == VIEW_PERSPECTIVE); +} + +void MagicView::OnViewSide() +{ + CloseUVEditor(); + view_mode = VIEW_SIDE; + SetupModelViews(); +} + +void MagicView::OnUpdateViewSide(CCmdUI* pCmdUI) +{ + if (pCmdUI) + pCmdUI->SetCheck(view_mode == VIEW_SIDE); +} + +void MagicView::OnViewTop() +{ + CloseUVEditor(); + view_mode = VIEW_TOP; + SetupModelViews(); +} + +void MagicView::OnUpdateViewTop(CCmdUI* pCmdUI) +{ + if (pCmdUI) + pCmdUI->SetCheck(view_mode == VIEW_TOP); +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnFileImport() +{ + DWORD err = 0; + char filename[256]; + filename[0] = '\0'; + CFileDialog ofd(TRUE, "mag"); + + ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; + ofd.m_ofn.lpstrFile = filename; + ofd.m_ofn.nMaxFile = sizeof(filename); + + if (ofd.DoModal() != IDOK) + return; + + char mag_name[256]; + sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); + + MagicDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if (pDoc->ImportFile(mag_name)) { + Invalidate(); + pDoc->SetModifiedFlag(TRUE); + pDoc->UpdateAllViews(this); + } +} + +void MagicView::OnFileExport() +{ + DWORD err = 0; + char filename[256]; + filename[0] = '\0'; + CFileDialog ofd(FALSE, "mag"); + + ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; + ofd.m_ofn.lpstrFile = filename; + ofd.m_ofn.nMaxFile = sizeof(filename); + + if (ofd.DoModal() != IDOK) + return; + + char mag_name[256]; + sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); + + MagicDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if (pDoc->ExportFile(mag_name)) { + pDoc->SetModifiedFlag(FALSE); + pDoc->UpdateAllViews(this); + } +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnSurfaceProperties() +{ + SurfacePropertiesDialog dlg(this); + dlg.DoModal(); +} + +void MagicView::OnUpdateSurfaceProperties(CCmdUI* pCmdUI) +{ + Solid* solid = GetDocument()->GetSolid(); + pCmdUI->Enable(solid && solid->GetModel()); +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnTextureMap() +{ + TextureMapDialog dlg(this); + if (dlg.DoModal() == IDOK) { + MagicDoc* doc = GetDocument(); + Solid* solid = doc->GetSolid(); + Selection* seln = doc->GetSelection(); + Selector* selector = doc->GetSelector(); + Editor* editor = doc->GetEditor(); + Material* mtl = 0; + + if (dlg.mMaterialIndex >= 0) { + mtl = solid->GetModel()->GetMaterials()[dlg.mMaterialIndex]; + } + + editor->UseModel(solid->GetModel()); + editor->ApplyMaterial(mtl, seln->GetPolys(), + dlg.mMapType, 2-dlg.mAxis, (float) dlg.mScaleU, (float) dlg.mScaleV, + dlg.mFlip, dlg.mMirror, dlg.mRotate); + + selector->Reselect(); + + Invalidate(); + doc->SetModifiedFlag(TRUE); + doc->UpdateAllViews(this); + } +} + +void MagicView::OnUpdateTextureMap(CCmdUI* pCmdUI) +{ + Solid* solid = GetDocument()->GetSolid(); + Selection* seln = GetDocument()->GetSelection(); + + pCmdUI->Enable(solid && solid->GetModel() && seln && seln->GetPolys().size() > 0); +} + +void MagicView::OnModifyMaterial() +{ + MaterialDialog dlg(this); + dlg.DoModal(); + + Invalidate(); + GetDocument()->SetModifiedFlag(TRUE); + GetDocument()->UpdateAllViews(this); +} + +void MagicView::OnUpdateModifyMaterial(CCmdUI* pCmdUI) +{ + Solid* solid = GetDocument()->GetSolid(); + pCmdUI->Enable(solid && solid->GetModel()); +} + +void MagicView::OnModifyUVMap() +{ + Selection* seln = GetDocument()->GetSelection(); + + view_mode = VIEW_UV_MAP; + SetupModelViews(); + + if (seln && uvmap_view) { + Poly* p = seln->GetPolys().first(); + + if (p) { + uvmap_view->UseMaterial(p->material); + uvmap_view->UsePolys(seln->GetPolys()); + } + } +} + +void MagicView::OnUpdateModifyUVMap(CCmdUI* pCmdUI) +{ + OnUpdateTextureMap(pCmdUI); +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnGridProperties() +{ + GridProps dlg(grid, this); + dlg.DoModal(); +} + +void MagicView::OnGridShow() +{ + if (grid) + grid->SetShow(!grid->IsShow()); +} + +void MagicView::OnGridSnap() +{ + if (grid) + grid->SetSnap(!grid->IsSnap()); +} + +void MagicView::OnUpdateGridSnap(CCmdUI* pCmdUI) +{ + if (grid) + pCmdUI->SetCheck(grid->IsSnap()); +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnLButtonDown(UINT nFlags, CPoint point) +{ + CView::OnLButtonDown(nFlags, point); + SetCapture(); + + // set focus to the view that was clicked: + int index = GetWinIndexByPoint(point.x, point.y); + SetFocusModelView(index); + + drag_start = point; + drag_left = true; + drag_right = false; + + ModelView* mv = GetModelViewByIndex(index); + MagicDoc* pDoc = GetDocument(); + Model* model = pDoc->GetSolid()->GetModel(); + Selector* selector = pDoc->GetSelector(); + + if (IsUVEdit()) { + int select_mode = UVMapView::SELECT_APPEND; + + if (nFlags & MK_CONTROL) + select_mode = UVMapView::SELECT_REMOVE; + + if (!uvmap_view->WillSelect(point)) { + uvmap_view->Begin(select_mode); + uvmap_view->AddMark(point); + } + } + + else if (mv && selector) { + int select_mode = Selector::SELECT_APPEND; + + if (nFlags & MK_CONTROL) + select_mode = Selector::SELECT_REMOVE; + + selector->Begin(model, mv->GetViewMode(), select_mode); + selector->AddMark(point); + } +} + +void MagicView::OnLButtonUp(UINT nFlags, CPoint point) +{ + CView::OnLButtonUp(nFlags, point); + ReleaseCapture(); + + drag_left = false; + + MagicDoc* pDoc = GetDocument(); + Selector* selector = pDoc->GetSelector(); + + if (IsUVEdit()) + uvmap_view->End(); + + else if (selector && selector->IsActive()) + selector->End(); +} + +void MagicView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + CView::OnLButtonDblClk(nFlags, point); + + drag_left = false; + + MagicDoc* pDoc = GetDocument(); + Selector* selector = pDoc->GetSelector(); + + if (IsUVEdit()) + uvmap_view->Clear(); + + else if (selector) + selector->Clear(); +} + +void MagicView::OnRButtonDown(UINT nFlags, CPoint point) +{ + CView::OnRButtonDown(nFlags, point); + SetCapture(); + + // set focus to the view that was clicked: + int index = GetWinIndexByPoint(point.x, point.y); + SetFocusModelView(index); + + drag_start = point; + drag_left = false; + drag_right = true; +} + +void MagicView::OnRButtonUp(UINT nFlags, CPoint point) +{ + CView::OnRButtonUp(nFlags, point); + ReleaseCapture(); + + drag_right = false; +} + +void MagicView::OnRButtonDblClk(UINT nFlags, CPoint point) +{ + CView::OnRButtonDblClk(nFlags, point); + ReleaseCapture(); + + drag_right = false; + + if (view_mode == VIEW_ALL) { + view_mode = view_focus; + } + else if (IsUVEdit()) { + CloseUVEditor(); + view_mode = VIEW_ALL; + SetupModelViews(); + } + else { + view_mode = VIEW_ALL; + } + + SetFocusModelView(view_focus); +} + +void MagicView::OnMouseMove(UINT nFlags, CPoint point) +{ + if (drag_right) { + CPoint offset = point - drag_start; + + if (view_focus == VIEW_PERSPECTIVE) { + ModelView* view = GetModelViewByIndex(view_focus); + view->SpinBy(offset.x * 0.5 * DEGREES, + offset.y * 0.5 * DEGREES); + } + + else if (IsUVEdit()) { + uvmap_view->MoveBy(offset.x, offset.y); + } + + else { + ModelView* view = GetModelViewByIndex(view_focus); + view->MoveBy(offset.x, offset.y); + } + + drag_start = point; + Invalidate(); + } + + else if (drag_left) { + CPoint offset = point - drag_start; + MagicDoc* pDoc = GetDocument(); + Selector* selector = pDoc->GetSelector(); + + if (IsUVEdit()) { + if (uvmap_view->IsActive()) { + uvmap_view->AddMark(point); + } + else { + uvmap_view->DragBy(offset.x, offset.y); + drag_start = point; + } + } + + else if (selector && selector->IsActive()) { + selector->AddMark(point); + } + } + + // xy status message: + if (view_focus != VIEW_PERSPECTIVE) { + char xy[80]; + CPoint mouse = LPtoWP(point); + Selection* seln = GetDocument()->GetSelection(); + + int nv = seln ? seln->GetVerts().size() : 0; + int np = seln ? seln->GetPolys().size() : 0; + + if (np || nv) + sprintf_s(xy, "(%05d,%05d) Verts:%d Polys:%d", mouse.x, mouse.y, nv, np); + else + sprintf_s(xy, "(%05d,%05d)", mouse.x, mouse.y); + MainFrame::StatusXY(xy); + } + + CView::OnMouseMove(nFlags, point); +} + +BOOL MagicView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) +{ + if (view_focus == VIEW_PERSPECTIVE) { + ModelView* view = GetModelViewByIndex(view_focus); + + if (view) { + Camera* cam = view->GetCamera(); + Point pos = cam->Pos(); + double len = pos.length(); + + if (zDelta < 0) { + if (len < 10000) + pos *= 1.15; + } + else { + if (len > 0.10) + pos *= 0.85; + } + + cam->MoveTo(pos); + } + } + + else if (IsUVEdit()) { + if (zDelta < 0) { + uvmap_view->ZoomOut(); + } + else { + uvmap_view->ZoomIn(); + } + } + + else { + if (zDelta > 0) + OnViewZoomIn(); + else + OnViewZoomOut(); + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnViewZoomNormal() +{ + for (int i = 0; i < 4; i++) { + ModelView* view = GetModelViewByIndex(i); + + if (view) { + view->ZoomNormal(); + } + } +} + +void MagicView::OnViewZoomIn() +{ + for (int i = 0; i < 4; i++) { + ModelView* view = GetModelViewByIndex(i); + + if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { + double fov = view->GetFieldOfView() * 1.15; + view->SetFieldOfView(fov); + } + } +} + +void MagicView::OnViewZoomOut() +{ + for (int i = 0; i < 4; i++) { + ModelView* view = GetModelViewByIndex(i); + + if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { + double fov = view->GetFieldOfView() * 0.85; + view->SetFieldOfView(fov); + } + } +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnViewModeWireframe() +{ + ModelView* view = GetModelViewByIndex(view_focus); + + if (view) { + view->SetFillMode(ModelView::FILL_WIRE); + } +} + +void MagicView::OnViewModeSolid() +{ + ModelView* view = GetModelViewByIndex(view_focus); + + if (view) { + view->SetFillMode(ModelView::FILL_SOLID); + } +} + +void MagicView::OnViewModeTextured() +{ + ModelView* view = GetModelViewByIndex(view_focus); + + if (view) { + view->SetFillMode(ModelView::FILL_TEXTURE); + } +} + +void MagicView::OnViewBackColor() +{ + ModelView* view = GetModelViewByIndex(view_focus); + + if (view) { + ActiveWindow* win = (ActiveWindow*) view->GetWindow(); + Color c = win->GetBackColor(); + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + win->SetBackColor( Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)) ); + } + } +} + +// +--------------------------------------------------------------------+ + +void MagicView::OnSelectAll() +{ + Solid* solid = GetDocument()->GetSolid(); + Selector* selector = GetDocument()->GetSelector(); + + if (IsUVEdit()) { + uvmap_view->SelectAll(); + } + + else if (solid && selector) { + selector->UseModel(solid->GetModel()); + selector->SelectAll(Selector::SELECT_APPEND); + } +} + +void MagicView::OnSelectNone() +{ + Solid* solid = GetDocument()->GetSolid(); + Selector* selector = GetDocument()->GetSelector(); + + if (IsUVEdit()) { + uvmap_view->SelectNone(); + } + + else if (solid && selector) { + selector->UseModel(solid->GetModel()); + selector->SelectAll(Selector::SELECT_REMOVE); + } +} + +void MagicView::OnSelectInverse() +{ + Solid* solid = GetDocument()->GetSolid(); + Selector* selector = GetDocument()->GetSelector(); + + if (IsUVEdit()) { + uvmap_view->SelectInverse(); + } + + else if (solid && selector) { + selector->UseModel(solid->GetModel()); + selector->SelectInverse(); + } +} + +void MagicView::OnViewShadows() +{ + view_shadows = !view_shadows; + + if (video) + video->SetShadowEnabled(view_shadows); +} + +void MagicView::OnUpdateViewShadows(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(view_shadows); +} + +void MagicView::OnViewAnimatelight() +{ + animate_light = !animate_light; +} + +void MagicView::OnUpdateViewAnimatelight(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(animate_light); +} + +void MagicView::OnViewBumpmaps() +{ + view_bumpmaps = !view_bumpmaps; + + if (video) + video->SetBumpMapEnabled(view_bumpmaps); +} + +void MagicView::OnUpdateViewBumpmaps(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(view_bumpmaps); +} + +void MagicView::OnViewVertexshader() +{ + if (video) { + VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); + vs->enable_vs = !vs->enable_vs; + } +} + +void MagicView::OnUpdateViewVertexshader(CCmdUI* pCmdUI) +{ + if (video) + pCmdUI->SetCheck(video->GetVideoSettings()->enable_vs); +} + +void MagicView::OnViewPixelshader() +{ + if (video) { + VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); + vs->enable_ps = !vs->enable_ps; + } +} + +void MagicView::OnUpdateViewPixelshader(CCmdUI* pCmdUI) +{ + if (video) + pCmdUI->SetCheck(video->GetVideoSettings()->enable_ps); +} + +void MagicView::OnViewVisibleshadows() +{ + Shadow::SetVisibleShadowVolumes(!Shadow::GetVisibleShadowVolumes()); +} + +void MagicView::OnUpdateViewVisibleshadows(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(Shadow::GetVisibleShadowVolumes()); +} + +void MagicView::OnEditUndo() +{ + MagicDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + pDoc->Undo(); + + Solid* solid = GetDocument()->GetSolid(); + Selector* selector = GetDocument()->GetSelector(); + + if (selector) { + selector->UseModel(solid->GetModel()); + selector->Reselect(); + } + + Invalidate(); + pDoc->SetModifiedFlag(TRUE); + pDoc->UpdateAllViews(this); +} + +void MagicView::OnUpdateEditUndo(CCmdUI* pCmdUI) +{ + MagicDoc* pDoc = GetDocument(); + + if (pDoc->NumUndo() > 0) { + pCmdUI->Enable(TRUE); + pCmdUI->SetText(CString("Undo ") + pDoc->GetUndoName() + CString("\tCtrl+Z")); + } + else { + pCmdUI->Enable(FALSE); + pCmdUI->SetText("Can't Undo\tCtrl+Z"); + } +} + +void MagicView::OnEditRedo() +{ + MagicDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + pDoc->Redo(); + + Solid* solid = GetDocument()->GetSolid(); + Selector* selector = GetDocument()->GetSelector(); + + if (selector) { + selector->UseModel(solid->GetModel()); + selector->Reselect(); + } + + Invalidate(); + pDoc->SetModifiedFlag(TRUE); + pDoc->UpdateAllViews(this); +} + +void MagicView::OnUpdateEditRedo(CCmdUI* pCmdUI) +{ + MagicDoc* pDoc = GetDocument(); + + if (pDoc->NumRedo() > 0) { + pCmdUI->Enable(TRUE); + pCmdUI->SetText(CString("Redo ") + pDoc->GetRedoName() + CString("\tCtrl+Y")); + } + else { + pCmdUI->Enable(FALSE); + pCmdUI->SetText("Can't Redo"); + } +} diff --git a/Magic2/MagicView.h b/Magic2/MagicView.h index 8bd5e28..287982c 100644 --- a/Magic2/MagicView.h +++ b/Magic2/MagicView.h @@ -1,201 +1,225 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MagicView.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the MagicView class -*/ - - -#if !defined(AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_) -#define AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// +--------------------------------------------------------------------+ - -class MagicDoc; -class ActiveWindow; -class Grid; -class Light; -class Scene; -class Screen; -class Video; -class VideoSettings; -class ModelView; -class UVMapView; - -// +--------------------------------------------------------------------+ - -class MagicView : public CView -{ -protected: // create from serialization only - MagicView(); - DECLARE_DYNCREATE(MagicView) - -// Attributes -public: - MagicDoc* GetDocument(); - - static MagicView* GetInstance(); - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(MagicView) - public: - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - virtual void OnInitialUpdate(); - protected: - virtual void OnDraw(CDC* pDC); - virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~MagicView(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - virtual void OnEnterSizeMove(); - virtual void OnExitSizeMove(); - virtual void ResizeVideo(); - virtual CPoint LPtoWP(const CPoint& p); - -protected: - Video* video; - VideoSettings* video_settings; - Screen* screen; - RECT client_rect; - DWORD window_style; - bool is_minimized; - bool is_maximized; - bool is_sizing; - - Grid* grid; - Scene* scene; - Light* main_light; - Light* back_light; - ActiveWindow* main_win; - ActiveWindow* view_win[4]; - ModelView* model_view[4]; - ActiveWindow* uvmap_win; - UVMapView* uvmap_view; - int view_mode; - int view_focus; - bool drag_left; - bool drag_right; - CPoint drag_start; - - bool view_bumpmaps; - bool view_shadows; - bool animate_light; - - enum VIEW_MODE { - VIEW_TOP = 0, - VIEW_PERSPECTIVE = 1, - VIEW_SIDE = 2, - VIEW_FRONT = 3, - VIEW_ALL = 4, - VIEW_UV_MAP = 5 - }; - - virtual void SetupModelViews(); - virtual void SetFocusModelView(int f); - virtual int GetWinIndexByPoint(int x, int y); - ModelView* GetModelViewByIndex(int index); - - bool IsUVEdit() const { return (view_mode == VIEW_UV_MAP) && (uvmap_view != 0); } - void CloseUVEditor(); - -// Generated message map functions -protected: - //{{AFX_MSG(MagicView) - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg void OnRender(); - afx_msg void OnPaint(); - afx_msg void OnViewAll(); - afx_msg void OnUpdateViewAll(CCmdUI* pCmdUI); - afx_msg void OnViewFront(); - afx_msg void OnUpdateViewFront(CCmdUI* pCmdUI); - afx_msg void OnViewPerspective(); - afx_msg void OnUpdateViewPerspective(CCmdUI* pCmdUI); - afx_msg void OnViewSide(); - afx_msg void OnUpdateViewSide(CCmdUI* pCmdUI); - afx_msg void OnViewTop(); - afx_msg void OnUpdateViewTop(CCmdUI* pCmdUI); - afx_msg void OnTextureMap(); - afx_msg void OnModifyMaterial(); - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - afx_msg void OnLButtonUp(UINT nFlags, CPoint point); - afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); - afx_msg void OnRButtonDown(UINT nFlags, CPoint point); - afx_msg void OnRButtonUp(UINT nFlags, CPoint point); - afx_msg void OnMouseMove(UINT nFlags, CPoint point); - afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); - afx_msg void OnViewZoomNormal(); - afx_msg void OnViewZoomIn(); - afx_msg void OnViewZoomOut(); - afx_msg void OnViewModeWireframe(); - afx_msg void OnViewModeSolid(); - afx_msg void OnViewModeTextured(); - afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); - afx_msg void OnGridProperties(); - afx_msg void OnGridShow(); - afx_msg void OnGridSnap(); - afx_msg void OnUpdateGridSnap(CCmdUI* pCmdUI); - afx_msg void OnViewBackColor(); - afx_msg void OnFileImport(); - afx_msg void OnFileExport(); - afx_msg void OnSelectAll(); - afx_msg void OnSelectNone(); - afx_msg void OnUpdateTextureMap(CCmdUI* pCmdUI); - afx_msg void OnUpdateModifyMaterial(CCmdUI* pCmdUI); - afx_msg void OnSelectInverse(); - afx_msg void OnModifyUVMap(); - afx_msg void OnUpdateModifyUVMap(CCmdUI* pCmdUI); - afx_msg void OnViewShadows(); - afx_msg void OnUpdateViewShadows(CCmdUI* pCmdUI); - afx_msg void OnViewAnimatelight(); - afx_msg void OnUpdateViewAnimatelight(CCmdUI* pCmdUI); - afx_msg void OnViewBumpmaps(); - afx_msg void OnUpdateViewBumpmaps(CCmdUI* pCmdUI); - afx_msg void OnViewVertexshader(); - afx_msg void OnUpdateViewVertexshader(CCmdUI* pCmdUI); - afx_msg void OnViewPixelshader(); - afx_msg void OnUpdateViewPixelshader(CCmdUI* pCmdUI); - afx_msg void OnViewVisibleshadows(); - afx_msg void OnUpdateViewVisibleshadows(CCmdUI* pCmdUI); - afx_msg void OnEditUndo(); - afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI); - afx_msg void OnEditRedo(); - afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI); - afx_msg void OnSurfaceProperties(); - afx_msg void OnUpdateSurfaceProperties(CCmdUI* pCmdUI); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -#ifndef _DEBUG // debug version in MagicView.cpp -inline MagicDoc* MagicView::GetDocument() - { return (MagicDoc*)m_pDocument; } -#endif - -// +--------------------------------------------------------------------+ - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_) +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MagicView.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the MagicView class +*/ + + +#if !defined(AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_) +#define AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// +--------------------------------------------------------------------+ + +class MagicDoc; +class ActiveWindow; +class Grid; +class Light; +class Scene; +class Screen; +class Video; +class VideoSettings; +class ModelView; +class UVMapView; + +// +--------------------------------------------------------------------+ + +class MagicView : public CView +{ +protected: // create from serialization only + MagicView(); + DECLARE_DYNCREATE(MagicView) + +// Attributes +public: + MagicDoc* GetDocument(); + + static MagicView* GetInstance(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(MagicView) + public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnInitialUpdate(); + protected: + virtual void OnDraw(CDC* pDC); + virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~MagicView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + virtual void OnEnterSizeMove(); + virtual void OnExitSizeMove(); + virtual void ResizeVideo(); + virtual CPoint LPtoWP(const CPoint& p); + +protected: + Video* video; + VideoSettings* video_settings; + Screen* screen; + RECT client_rect; + DWORD window_style; + bool is_minimized; + bool is_maximized; + bool is_sizing; + + Grid* grid; + Scene* scene; + Light* main_light; + Light* back_light; + ActiveWindow* main_win; + ActiveWindow* view_win[4]; + ModelView* model_view[4]; + ActiveWindow* uvmap_win; + UVMapView* uvmap_view; + int view_mode; + int view_focus; + bool drag_left; + bool drag_right; + CPoint drag_start; + + bool view_bumpmaps; + bool view_shadows; + bool animate_light; + + enum VIEW_MODE { + VIEW_TOP = 0, + VIEW_PERSPECTIVE = 1, + VIEW_SIDE = 2, + VIEW_FRONT = 3, + VIEW_ALL = 4, + VIEW_UV_MAP = 5 + }; + + virtual void SetupModelViews(); + virtual void SetFocusModelView(int f); + virtual int GetWinIndexByPoint(int x, int y); + ModelView* GetModelViewByIndex(int index); + + bool IsUVEdit() const { return (view_mode == VIEW_UV_MAP) && (uvmap_view != 0); } + void CloseUVEditor(); + +// Generated message map functions +protected: + //{{AFX_MSG(MagicView) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnRender(); + afx_msg void OnPaint(); + afx_msg void OnViewAll(); + afx_msg void OnUpdateViewAll(CCmdUI* pCmdUI); + afx_msg void OnViewFront(); + afx_msg void OnUpdateViewFront(CCmdUI* pCmdUI); + afx_msg void OnViewPerspective(); + afx_msg void OnUpdateViewPerspective(CCmdUI* pCmdUI); + afx_msg void OnViewSide(); + afx_msg void OnUpdateViewSide(CCmdUI* pCmdUI); + afx_msg void OnViewTop(); + afx_msg void OnUpdateViewTop(CCmdUI* pCmdUI); + afx_msg void OnTextureMap(); + afx_msg void OnModifyMaterial(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnViewZoomNormal(); + afx_msg void OnViewZoomIn(); + afx_msg void OnViewZoomOut(); + afx_msg void OnViewModeWireframe(); + afx_msg void OnViewModeSolid(); + afx_msg void OnViewModeTextured(); + afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnGridProperties(); + afx_msg void OnGridShow(); + afx_msg void OnGridSnap(); + afx_msg void OnUpdateGridSnap(CCmdUI* pCmdUI); + afx_msg void OnViewBackColor(); + afx_msg void OnFileImport(); + afx_msg void OnFileExport(); + afx_msg void OnSelectAll(); + afx_msg void OnSelectNone(); + afx_msg void OnUpdateTextureMap(CCmdUI* pCmdUI); + afx_msg void OnUpdateModifyMaterial(CCmdUI* pCmdUI); + afx_msg void OnSelectInverse(); + afx_msg void OnModifyUVMap(); + afx_msg void OnUpdateModifyUVMap(CCmdUI* pCmdUI); + afx_msg void OnViewShadows(); + afx_msg void OnUpdateViewShadows(CCmdUI* pCmdUI); + afx_msg void OnViewAnimatelight(); + afx_msg void OnUpdateViewAnimatelight(CCmdUI* pCmdUI); + afx_msg void OnViewBumpmaps(); + afx_msg void OnUpdateViewBumpmaps(CCmdUI* pCmdUI); + afx_msg void OnViewVertexshader(); + afx_msg void OnUpdateViewVertexshader(CCmdUI* pCmdUI); + afx_msg void OnViewPixelshader(); + afx_msg void OnUpdateViewPixelshader(CCmdUI* pCmdUI); + afx_msg void OnViewVisibleshadows(); + afx_msg void OnUpdateViewVisibleshadows(CCmdUI* pCmdUI); + afx_msg void OnEditUndo(); + afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI); + afx_msg void OnEditRedo(); + afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI); + afx_msg void OnSurfaceProperties(); + afx_msg void OnUpdateSurfaceProperties(CCmdUI* pCmdUI); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in MagicView.cpp +inline MagicDoc* MagicView::GetDocument() + { return (MagicDoc*)m_pDocument; } +#endif + +// +--------------------------------------------------------------------+ + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAGICVIEW_H__387B567A_8235_41B8_A993_E41567E680D7__INCLUDED_) diff --git a/Magic2/MainFrm.cpp b/Magic2/MainFrm.cpp index 97ee18b..3d2d256 100644 --- a/Magic2/MainFrm.cpp +++ b/Magic2/MainFrm.cpp @@ -1,152 +1,178 @@ -// MainFrm.cpp : implementation of the MainFrame class -// - -#include "stdafx.h" -#include "Magic.h" - -#include "MainFrm.h" -#include "MagicView.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// MainFrame - -#include "Bitmap.h" - -IMPLEMENT_DYNCREATE(MainFrame, CFrameWnd) - -BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd) - //{{AFX_MSG_MAP(MainFrame) - ON_WM_CREATE() - ON_WM_ACTIVATEAPP() - ON_COMMAND(ID_VIEW_RENDER, OnRender) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -static UINT indicators[] = -{ - ID_SEPARATOR, // status line indicator - ID_SEPARATOR, // xy indicator - ID_INDICATOR_CAPS, - ID_INDICATOR_NUM, - ID_INDICATOR_SCRL, -}; - -///////////////////////////////////////////////////////////////////////////// -// MainFrame construction/destruction - -MainFrame* MainFrame::statframe; - - -MainFrame::MainFrame() -{ - statframe = this; - -} - -MainFrame::~MainFrame() -{ - Bitmap::ClearCache(); -} - -BOOL MainFrame::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) -{ - if (message == WM_ENTERSIZEMOVE) { - MagicView* magic_view = MagicView::GetInstance(); - if (magic_view) - magic_view->OnEnterSizeMove(); - } - - else if (message == WM_EXITSIZEMOVE) { - MagicView* magic_view = MagicView::GetInstance(); - if (magic_view) - magic_view->OnExitSizeMove(); - } - - return CFrameWnd::OnWndMsg(message, wParam, lParam, pResult); -} - -int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CFrameWnd::OnCreate(lpCreateStruct) == -1) - return -1; - - if (!m_wndToolBar.Create(this) || - !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) - { - TRACE0("Failed to create toolbar\n"); - return -1; // fail to create - } - - if (!m_wndStatusBar.Create(this) || - !m_wndStatusBar.SetIndicators(indicators, - sizeof(indicators)/sizeof(UINT))) - { - TRACE0("Failed to create status bar\n"); - return -1; // fail to create - } - - // TODO: Remove this if you don't want tool tips or a resizeable toolbar - m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | - CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); - - // TODO: Delete these three lines if you don't want the toolbar to - // be dockable - m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); - EnableDocking(CBRS_ALIGN_ANY); - DockControlBar(&m_wndToolBar); - - return 0; -} - -BOOL MainFrame::PreCreateWindow(CREATESTRUCT& cs) -{ - if( !CFrameWnd::PreCreateWindow(cs) ) - return FALSE; - // TODO: Modify the Window class or styles here by modifying - // the CREATESTRUCT cs - - return TRUE; -} - -void MainFrame::StatusXY(const char* xy) -{ - statframe->m_wndStatusBar.SetPaneText(1, xy, TRUE); -} - -///////////////////////////////////////////////////////////////////////////// -// MainFrame diagnostics - -#ifdef _DEBUG -void MainFrame::AssertValid() const -{ - CFrameWnd::AssertValid(); -} - -void MainFrame::Dump(CDumpContext& dc) const -{ - CFrameWnd::Dump(dc); -} - -#endif //_DEBUG - -///////////////////////////////////////////////////////////////////////////// -// MainFrame message handlers - - -void MainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID) -{ - ((Magic*)AfxGetApp())->SetAppActivated(bActive ? true : false); -} - -void MainFrame::OnRender() -{ - MagicView* magic_view = MagicView::GetInstance(); - if (magic_view) - magic_view->SendMessage(WM_COMMAND, ID_VIEW_RENDER); -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdafx.h" +#include "Magic.h" + +#include "MainFrm.h" +#include "MagicView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// MainFrame + +#include "Bitmap.h" + +IMPLEMENT_DYNCREATE(MainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd) + //{{AFX_MSG_MAP(MainFrame) + ON_WM_CREATE() + ON_WM_ACTIVATEAPP() + ON_COMMAND(ID_VIEW_RENDER, OnRender) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_SEPARATOR, // xy indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// MainFrame construction/destruction + +MainFrame* MainFrame::statframe; + + +MainFrame::MainFrame() +{ + statframe = this; + +} + +MainFrame::~MainFrame() +{ + Bitmap::ClearCache(); +} + +BOOL MainFrame::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + if (message == WM_ENTERSIZEMOVE) { + MagicView* magic_view = MagicView::GetInstance(); + if (magic_view) + magic_view->OnEnterSizeMove(); + } + + else if (message == WM_EXITSIZEMOVE) { + MagicView* magic_view = MagicView::GetInstance(); + if (magic_view) + magic_view->OnExitSizeMove(); + } + + return CFrameWnd::OnWndMsg(message, wParam, lParam, pResult); +} + +int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.Create(this) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + // TODO: Remove this if you don't want tool tips or a resizeable toolbar + m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | + CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); + + // TODO: Delete these three lines if you don't want the toolbar to + // be dockable + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + + return 0; +} + +BOOL MainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return TRUE; +} + +void MainFrame::StatusXY(const char* xy) +{ + statframe->m_wndStatusBar.SetPaneText(1, xy, TRUE); +} + +///////////////////////////////////////////////////////////////////////////// +// MainFrame diagnostics + +#ifdef _DEBUG +void MainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void MainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// MainFrame message handlers + + +void MainFrame::OnActivateApp(BOOL bActive, DWORD dwThreadID) +{ + ((Magic*)AfxGetApp())->SetAppActivated(bActive ? true : false); +} + +void MainFrame::OnRender() +{ + MagicView* magic_view = MagicView::GetInstance(); + if (magic_view) + magic_view->SendMessage(WM_COMMAND, ID_VIEW_RENDER); +} diff --git a/Magic2/MainFrm.h b/Magic2/MainFrm.h index 8d51197..39e43bd 100644 --- a/Magic2/MainFrm.h +++ b/Magic2/MainFrm.h @@ -1,62 +1,87 @@ -// MainFrm.h : interface of the MainFrame class -// -///////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_) -#define AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -class MainFrame : public CFrameWnd -{ - -protected: // create from serialization only - MainFrame(); - DECLARE_DYNCREATE(MainFrame) - -// Attributes -public: - static MainFrame* statframe; - -// Operations -public: - static void StatusXY(const char* xy); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(MainFrame) - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~MainFrame(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: // control bar embedded members - CStatusBar m_wndStatusBar; - CToolBar m_wndToolBar; - - virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult); - -// Generated message map functions -protected: - //{{AFX_MSG(MainFrame) - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnActivateApp(BOOL bActive, DWORD dwThreadID); - afx_msg void OnRender(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_) +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_) +#define AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class MainFrame : public CFrameWnd +{ + +protected: // create from serialization only + MainFrame(); + DECLARE_DYNCREATE(MainFrame) + +// Attributes +public: + static MainFrame* statframe; + +// Operations +public: + static void StatusXY(const char* xy); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(MainFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~MainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + + virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult); + +// Generated message map functions +protected: + //{{AFX_MSG(MainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnActivateApp(BOOL bActive, DWORD dwThreadID); + afx_msg void OnRender(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__F5D788D5_8FA2_4A6B_94F0_7938C797BE5D__INCLUDED_) diff --git a/Magic2/MaterialDialog.cpp b/Magic2/MaterialDialog.cpp index 1acef19..15d13a8 100644 --- a/Magic2/MaterialDialog.cpp +++ b/Magic2/MaterialDialog.cpp @@ -1,693 +1,717 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MaterialDialog.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Material Editor Dialog interface file -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "MagicView.h" -#include "MaterialDialog.h" -#include "Selection.h" -#include "Selector.h" -#include "Thumbnail.h" - -#include "Bitmap.h" -#include "Polygon.h" -#include "Solid.h" -#include "Video.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -inline int BlendModeToSelection(int mode) -{ - switch (mode) { - case Material::MTL_SOLID: return 0; - case Material::MTL_TRANSLUCENT: return 1; - case Material::MTL_ADDITIVE: return 2; - } - - return 0; -} - -inline int SelectionToBlendMode(int sel) -{ - switch (sel) { - case 0: return Material::MTL_SOLID; - case 1: return Material::MTL_TRANSLUCENT; - case 2: return Material::MTL_ADDITIVE; - } - - return Material::MTL_SOLID; -} - -// +--------------------------------------------------------------------+ -// MaterialDialog dialog -// +--------------------------------------------------------------------+ - -static Material emergency_material; - -MaterialDialog::MaterialDialog(MagicView* pParent /*=NULL*/) - : CDialog(MaterialDialog::IDD, pParent), solid(0), material(0), doc(0) -{ - //{{AFX_DATA_INIT(MaterialDialog) - mAmbientValue = 0.0; - mBrillianceValue = 0.0; - mBumpValue = 0.0; - mDiffuseValue = 0.0; - mEmissiveValue = 0.0; - mMaterialName = _T(""); - mPowerValue = 0.0; - mSpecularValue = 0.0; - mSpecularTexture = _T(""); - mDiffuseTexture = _T(""); - mBumpTexture = _T(""); - mEmissiveTexture = _T(""); - mMaterialShader = _T(""); - //}}AFX_DATA_INIT - - doc = pParent->GetDocument(); - - if (doc && doc->GetSolid()) { - solid = doc->GetSolid(); - - Selection* seln = doc->GetSelection(); - - if (seln->GetPolys().size() > 0) { - material = seln->GetPolys().first()->material; - } - } -} - -MaterialDialog::~MaterialDialog() -{ -} - - -void MaterialDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(MaterialDialog) - DDX_Control(pDX, IDC_SHADOW, mShadowList); - DDX_Control(pDX, IDC_BLEND_MODE, mBlendModeList); - DDX_Control(pDX, IDC_MATERIAL_LIST, mMaterialList); - DDX_Control(pDX, IDC_MATERIAL_PREVIEW, mMaterialThumb); - DDX_Control(pDX, IDC_SPECULAR_COLOR, mSpecularColor); - DDX_Control(pDX, IDC_EMISSIVE_COLOR, mEmissiveColor); - DDX_Control(pDX, IDC_DIFFUSE_COLOR, mDiffuseColor); - DDX_Control(pDX, IDC_AMBIENT_COLOR, mAmbientColor); - DDX_Text(pDX, IDC_AMBIENT_VALUE, mAmbientValue); - DDX_Text(pDX, IDC_BRILLIANCE_VALUE, mBrillianceValue); - DDX_Text(pDX, IDC_BUMP_VALUE, mBumpValue); - DDX_Text(pDX, IDC_DIFFUSE_VALUE, mDiffuseValue); - DDX_Text(pDX, IDC_EMISSIVE_VALUE, mEmissiveValue); - DDX_Text(pDX, IDC_MATERIAL_NAME, mMaterialName); - DDX_Text(pDX, IDC_POWER_VALUE, mPowerValue); - DDX_Text(pDX, IDC_SPECULAR_VALUE, mSpecularValue); - DDX_Text(pDX, IDC_SPECULAR_TEXTURE, mSpecularTexture); - DDX_Text(pDX, IDC_DIFFUSE_TEXTURE, mDiffuseTexture); - DDX_Text(pDX, IDC_BUMP_TEXTURE, mBumpTexture); - DDX_Text(pDX, IDC_EMISSIVE_TEXTURE, mEmissiveTexture); - DDX_Text(pDX, IDC_MATERIAL_SHADER, mMaterialShader); - //}}AFX_DATA_MAP - - if (!pDX->m_bSaveAndValidate) { - if (solid && solid->GetModel()) { - mMaterialList.ResetContent(); - - Model* model = solid->GetModel(); - for (int i = 0; i < model->NumMaterials(); i++) { - Material* m = model->GetMaterials()[i]; - mMaterialList.AddString(m->name); - - if (m == material) - mMaterialList.SetCurSel(i); - } - } - - if (mBlendModeList.GetSafeHwnd()) - mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); - - if (mShadowList.GetSafeHwnd()) - mShadowList.SetCurSel(material->shadow); - } -} - - -BEGIN_MESSAGE_MAP(MaterialDialog, CDialog) - //{{AFX_MSG_MAP(MaterialDialog) - ON_WM_PAINT() - ON_BN_CLICKED(IDC_AMBIENT_COLOR, OnAmbientColor) - ON_BN_CLICKED(IDC_DIFFUSE_COLOR, OnDiffuseColor) - ON_BN_CLICKED(IDC_EMISSIVE_COLOR, OnEmissiveColor) - ON_BN_CLICKED(IDC_SPECULAR_COLOR, OnSpecularColor) - ON_WM_DRAWITEM() - ON_EN_CHANGE(IDC_AMBIENT_VALUE, OnChangeMaterialValue) - ON_BN_CLICKED(IDC_FILE_DIFFUSE, OnFileDiffuse) - ON_BN_CLICKED(IDC_FILE_SPECULAR, OnFileSpecular) - ON_BN_CLICKED(IDC_FILE_EMISSIVE, OnFileEmissive) - ON_BN_CLICKED(IDC_FILE_BUMP, OnFileBump) - ON_EN_CHANGE(IDC_DIFFUSE_TEXTURE, OnChangeDiffuseTexture) - ON_EN_CHANGE(IDC_SPECULAR_TEXTURE, OnChangeSpecularTexture) - ON_EN_CHANGE(IDC_EMISSIVE_TEXTURE, OnChangeEmissiveTexture) - ON_EN_CHANGE(IDC_BUMP_TEXTURE, OnChangeBumpTexture) - ON_EN_CHANGE(IDC_MATERIAL_NAME, OnChangeMaterialName) - ON_LBN_SELCHANGE(IDC_MATERIAL_LIST, OnSelectMaterial) - ON_BN_CLICKED(IDC_SELECT_POLYS, OnSelectPolys) - ON_BN_CLICKED(IDC_NEW_MATERIAL, OnNewMaterial) - ON_BN_CLICKED(IDC_DEL_MATERIAL, OnDelMaterial) - ON_CBN_SELCHANGE(IDC_BLEND_MODE, OnSelectBlendMode) - ON_CBN_SELCHANGE(IDC_SHADOW, OnSelectShadow) - ON_EN_CHANGE(IDC_BRILLIANCE_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_BUMP_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_DIFFUSE_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_EMISSIVE_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_POWER_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_SPECULAR_VALUE, OnChangeMaterialValue) - ON_EN_CHANGE(IDC_MATERIAL_SHADER, OnChangeMaterialShader) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ - -void MaterialDialog::UpdateMaterial() -{ - if (material) { - UpdateData(); - - strcpy_s(material->name, mMaterialName); - strcpy_s(material->shader, mMaterialShader); - - material->ambient_value = mAmbientValue; - material->diffuse_value = mDiffuseValue; - material->specular_value = mSpecularValue; - material->emissive_value = mEmissiveValue; - material->power = mPowerValue; - material->brilliance = mBrillianceValue; - material->bump = mBumpValue; - material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); - material->shadow = mShadowList.GetCurSel() ? true : false; - - material->Ka = ColorValue(material->ambient_color) * material->ambient_value; - material->Kd = ColorValue(material->diffuse_color) * material->diffuse_value; - material->Ks = ColorValue(material->specular_color) * material->specular_value; - material->Ke = ColorValue(material->emissive_color) * material->emissive_value; - - material->CreateThumbnail(); - - InvalidateRect(NULL, FALSE); - } -} - -// +--------------------------------------------------------------------+ -// MaterialDialog message handlers -// +--------------------------------------------------------------------+ - -BOOL MaterialDialog::OnInitDialog() -{ - if (solid && solid->GetModel() && !material) { - Model* model = solid->GetModel(); - - if (model->NumMaterials() > 0) - material = model->GetMaterials().first(); - } - - if (!material) - material = &emergency_material; - - mMaterialName = material->name; - mMaterialShader = material->shader; - mAmbientValue = material->ambient_value; - mDiffuseValue = material->diffuse_value; - mSpecularValue = material->specular_value; - mEmissiveValue = material->emissive_value; - mPowerValue = material->power; - mBrillianceValue = material->brilliance; - mBumpValue = material->bump; - - mDiffuseTexture = material->tex_diffuse ? - material->tex_diffuse->GetFilename() : ""; - - mSpecularTexture = material->tex_specular ? - material->tex_specular->GetFilename() : ""; - - mEmissiveTexture = material->tex_emissive ? - material->tex_emissive->GetFilename() : ""; - - mBumpTexture = material->tex_bumpmap ? - material->tex_bumpmap->GetFilename() : ""; - - CDialog::OnInitDialog(); - - UpdateMaterial(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void MaterialDialog::OnPaint() -{ - CPaintDC dc(this); // device context for painting - - if (material && material->thumbnail) { - ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); - } -} - -void MaterialDialog::OnAmbientColor() -{ - if (material) { - Color c = material->ambient_color; - COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); - CColorDialog chooser(crgb); - - if (chooser.DoModal() == IDOK) { - crgb = chooser.GetColor(); - material->ambient_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); - UpdateMaterial(); - } - } -} - -void MaterialDialog::OnDiffuseColor() -{ - if (material) { - Color c = material->diffuse_color; - COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); - CColorDialog chooser(crgb); - - if (chooser.DoModal() == IDOK) { - crgb = chooser.GetColor(); - material->diffuse_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); - UpdateMaterial(); - } - } -} - -void MaterialDialog::OnSpecularColor() -{ - if (material) { - Color c = material->specular_color; - COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); - CColorDialog chooser(crgb); - - if (chooser.DoModal() == IDOK) { - crgb = chooser.GetColor(); - material->specular_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); - UpdateMaterial(); - } - } -} - -void MaterialDialog::OnEmissiveColor() -{ - if (material) { - Color c = material->emissive_color; - COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); - CColorDialog chooser(crgb); - - if (chooser.DoModal() == IDOK) { - crgb = chooser.GetColor(); - material->emissive_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); - UpdateMaterial(); - } - } -} - -void MaterialDialog::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) -{ - CWnd* wnd = GetDlgItem(nIDCtl); - Color c = Color::LightGray; - - if (material) { - if (wnd->GetSafeHwnd() == mAmbientColor.GetSafeHwnd()) - c = material->ambient_color; - - else if (wnd->GetSafeHwnd() == mDiffuseColor.GetSafeHwnd()) - c = material->diffuse_color; - - else if (wnd->GetSafeHwnd() == mSpecularColor.GetSafeHwnd()) - c = material->specular_color; - - else if (wnd->GetSafeHwnd() == mEmissiveColor.GetSafeHwnd()) - c = material->emissive_color; - } - - CBrush brush(RGB(c.Red(), c.Green(), c.Blue())); - - ::FillRect(lpDrawItemStruct->hDC, - &lpDrawItemStruct->rcItem, - brush); - - CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); -} - -// +--------------------------------------------------------------------+ - -void MaterialDialog::OnChangeMaterialValue() -{ - UpdateMaterial(); -} - -// +--------------------------------------------------------------------+ - -void MaterialDialog::OnFileTexture(int type) -{ - if (!material) - return; - - char filename[512]; - filename[0] = '\0'; - CFileDialog ofd(TRUE, "pcx"); - - ofd.m_ofn.lpstrFilter = "All Image Files\0*.bmp; *.dds; *.jpg; *.pcx; *.png; *.tga\0Bitmap Files (*.bmp)\0*.bmp\0JPEG Files (*.jpg)\0*.pcx\0PCX Files (*.pcx)\0*.pcx\0PNG Files (*.png)\0*.png\0Truevision Targa Files (*.tga)\0*.png\0All Files\0*.*\0\0"; - ofd.m_ofn.lpstrFile = filename; - ofd.m_ofn.nMaxFile = sizeof(filename); - - if (ofd.DoModal() != IDOK) - return; - - char tex_name[512]; - sprintf_s(tex_name, "%s", ofd.GetFileName().GetBuffer(0)); - - ChangeFileTexture(tex_name, type); -} - -void MaterialDialog::ChangeFileTexture(char* fname, int type) -{ - Bitmap* bmp = 0; - - LoadTexture(fname, bmp); - - if (bmp) { - switch (type) { - case 0: - material->tex_diffuse = bmp; - mDiffuseTexture = fname; - break; - - case 1: - material->tex_specular = bmp; - mSpecularTexture = fname; - break; - - case 2: - material->tex_emissive = bmp; - mEmissiveTexture = fname; - break; - - case 3: - material->tex_bumpmap = bmp; - mBumpTexture = fname; - break; - } - - UpdateData(FALSE); - UpdateMaterial(); - } -} - -void MaterialDialog::OnFileDiffuse() -{ - OnFileTexture(0); -} - -void MaterialDialog::OnFileSpecular() -{ - OnFileTexture(1); -} - -void MaterialDialog::OnFileEmissive() -{ - OnFileTexture(2); -} - -void MaterialDialog::OnFileBump() -{ - OnFileTexture(3); -} - -void MaterialDialog::OnChangeDiffuseTexture() -{ - if (material) { - UpdateData(); - - if (mDiffuseTexture.GetLength() < 1) { - material->tex_diffuse = 0; - UpdateMaterial(); - return; - } - - char* filename = mDiffuseTexture.LockBuffer(); - ChangeFileTexture(filename, 0); - mDiffuseTexture.UnlockBuffer(); - } -} - -void MaterialDialog::OnChangeSpecularTexture() -{ - if (material) { - UpdateData(); - - if (mSpecularTexture.GetLength() < 1) { - material->tex_specular = 0; - UpdateMaterial(); - return; - } - - char* filename = mSpecularTexture.LockBuffer(); - ChangeFileTexture(filename, 1); - mSpecularTexture.UnlockBuffer(); - } -} - -void MaterialDialog::OnChangeEmissiveTexture() -{ - if (material) { - UpdateData(); - - if (mEmissiveTexture.GetLength() < 1) { - material->tex_emissive = 0; - UpdateMaterial(); - return; - } - - char* filename = mEmissiveTexture.LockBuffer(); - ChangeFileTexture(filename, 2); - mEmissiveTexture.UnlockBuffer(); - } -} - -void MaterialDialog::OnChangeBumpTexture() -{ - if (material) { - UpdateData(); - - if (mBumpTexture.GetLength() < 1) { - material->tex_bumpmap = 0; - UpdateMaterial(); - return; - } - - char* filename = mBumpTexture.LockBuffer(); - ChangeFileTexture(filename, 3); - mBumpTexture.UnlockBuffer(); - } -} - -// +--------------------------------------------------------------------+ - -void MaterialDialog::OnChangeMaterialName() -{ - if (material) { - UpdateData(); - strcpy_s(material->name, mMaterialName); - } -} - -void MaterialDialog::OnChangeMaterialShader() -{ - if (material) { - UpdateData(); - strcpy_s(material->shader, mMaterialShader); - } -} - -void MaterialDialog::OnSelectMaterial() -{ - int selected = mMaterialList.GetCurSel(); - Material* mtl = 0; - - if (solid && solid->GetModel()) { - Model* model = solid->GetModel(); - - if (model->NumMaterials() > 0 && selected < model->NumMaterials()) - mtl = model->GetMaterials()[selected]; - } - - if (!mtl) - mtl = &emergency_material; - - if (material != mtl) { - material = mtl; - - mMaterialName = material->name; - mMaterialShader = material->shader; - mAmbientValue = material->ambient_value; - mDiffuseValue = material->diffuse_value; - mSpecularValue = material->specular_value; - mEmissiveValue = material->emissive_value; - mPowerValue = material->power; - mBrillianceValue = material->brilliance; - mBumpValue = material->bump; - - mDiffuseTexture = material->tex_diffuse ? - material->tex_diffuse->GetFilename() : ""; - - mSpecularTexture = material->tex_specular ? - material->tex_specular->GetFilename() : ""; - - mEmissiveTexture = material->tex_emissive ? - material->tex_emissive->GetFilename() : ""; - - mBumpTexture = material->tex_bumpmap ? - material->tex_bumpmap->GetFilename() : ""; - - if (mBlendModeList.GetSafeHwnd()) - mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); - - if (mShadowList.GetSafeHwnd()) - mShadowList.SetCurSel(material->shadow); - - UpdateData(FALSE); - UpdateMaterial(); - } -} - -// +--------------------------------------------------------------------+ - -void MaterialDialog::OnNewMaterial() -{ - if (solid && material && material != &emergency_material) { - Model* model = solid->GetModel(); - Material* mtl = new Material; - - if (model && mtl) { - mtl->Ka = Color::DarkGray; - mtl->Kd = Color::LightGray; - mtl->Ks = ColorValue(0.1f,0.1f,0.1f); - mtl->power = 10.0f; - - mtl->ambient_value = 0.2f; - mtl->ambient_color = Color::DarkGray; - mtl->diffuse_value = 0.8f; - mtl->diffuse_color = Color::LightGray; - mtl->specular_value = 0.5f; - mtl->specular_color = Color::White; - strcpy_s(mtl->name, "(new)"); - - model->GetMaterials().append(mtl); - - material = 0; - mMaterialList.AddString(mtl->name); - mMaterialList.SetCurSel(model->NumMaterials()-1); - - mBlendModeList.SetCurSel(0); - mShadowList.SetCurSel(1); - - OnSelectMaterial(); - } - } -} - -void MaterialDialog::OnDelMaterial() -{ - if (solid && material && material != &emergency_material) { - Model* model = solid->GetModel(); - - // do not delete the last material: - if (model->NumMaterials() > 1 && model->GetMaterials().contains(material)) { - Material* mtl = model->GetMaterials().first(); - - if (mtl == material) - mtl = model->GetMaterials()[1]; - - // reassign the material for any polys and segments - // that are using the one we are about to delete: - ListIter iter = model->GetSurfaces(); - - while (++iter) { - Surface* s = iter.value(); - - for (int i = 0; i < s->NumPolys(); i++) { - Poly* p = s->GetPolys() + i; - - if (p->material == material) { - p->material = mtl; - } - } - - ListIter seg_iter = s->GetSegments(); - while (++seg_iter) { - Segment* segment = seg_iter.value(); - if (segment->material == material) - segment->material = mtl; - } - } - - // now delete the material: - model->GetMaterials().remove(material); - delete material; - - material = 0; - mMaterialList.SetCurSel(0); - OnSelectMaterial(); - } - } -} - -void MaterialDialog::OnSelectPolys() -{ - if (solid && doc && doc->GetSelector()) { - Selector* selector = doc->GetSelector(); - - if (!material || material == &emergency_material) - selector->SelectMaterial(0); - else - selector->SelectMaterial(material); - } -} - -void MaterialDialog::OnSelectBlendMode() -{ - if (material) - material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); -} - -void MaterialDialog::OnSelectShadow() -{ - if (material) - material->shadow = mShadowList.GetCurSel() ? true : false; -} - -void MaterialDialog::OnOK() -{ - Video* video = Video::GetInstance(); - if (video) - video->InvalidateCache(); - - CDialog::OnOK(); -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MaterialDialog.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Material Editor Dialog interface file +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "MagicView.h" +#include "MaterialDialog.h" +#include "Selection.h" +#include "Selector.h" +#include "Thumbnail.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "Solid.h" +#include "Video.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +inline int BlendModeToSelection(int mode) +{ + switch (mode) { + case Material::MTL_SOLID: return 0; + case Material::MTL_TRANSLUCENT: return 1; + case Material::MTL_ADDITIVE: return 2; + } + + return 0; +} + +inline int SelectionToBlendMode(int sel) +{ + switch (sel) { + case 0: return Material::MTL_SOLID; + case 1: return Material::MTL_TRANSLUCENT; + case 2: return Material::MTL_ADDITIVE; + } + + return Material::MTL_SOLID; +} + +// +--------------------------------------------------------------------+ +// MaterialDialog dialog +// +--------------------------------------------------------------------+ + +static Material emergency_material; + +MaterialDialog::MaterialDialog(MagicView* pParent /*=NULL*/) + : CDialog(MaterialDialog::IDD, pParent), solid(0), material(0), doc(0) +{ + //{{AFX_DATA_INIT(MaterialDialog) + mAmbientValue = 0.0; + mBrillianceValue = 0.0; + mBumpValue = 0.0; + mDiffuseValue = 0.0; + mEmissiveValue = 0.0; + mMaterialName = _T(""); + mPowerValue = 0.0; + mSpecularValue = 0.0; + mSpecularTexture = _T(""); + mDiffuseTexture = _T(""); + mBumpTexture = _T(""); + mEmissiveTexture = _T(""); + mMaterialShader = _T(""); + //}}AFX_DATA_INIT + + doc = pParent->GetDocument(); + + if (doc && doc->GetSolid()) { + solid = doc->GetSolid(); + + Selection* seln = doc->GetSelection(); + + if (seln->GetPolys().size() > 0) { + material = seln->GetPolys().first()->material; + } + } +} + +MaterialDialog::~MaterialDialog() +{ +} + + +void MaterialDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(MaterialDialog) + DDX_Control(pDX, IDC_SHADOW, mShadowList); + DDX_Control(pDX, IDC_BLEND_MODE, mBlendModeList); + DDX_Control(pDX, IDC_MATERIAL_LIST, mMaterialList); + DDX_Control(pDX, IDC_MATERIAL_PREVIEW, mMaterialThumb); + DDX_Control(pDX, IDC_SPECULAR_COLOR, mSpecularColor); + DDX_Control(pDX, IDC_EMISSIVE_COLOR, mEmissiveColor); + DDX_Control(pDX, IDC_DIFFUSE_COLOR, mDiffuseColor); + DDX_Control(pDX, IDC_AMBIENT_COLOR, mAmbientColor); + DDX_Text(pDX, IDC_AMBIENT_VALUE, mAmbientValue); + DDX_Text(pDX, IDC_BRILLIANCE_VALUE, mBrillianceValue); + DDX_Text(pDX, IDC_BUMP_VALUE, mBumpValue); + DDX_Text(pDX, IDC_DIFFUSE_VALUE, mDiffuseValue); + DDX_Text(pDX, IDC_EMISSIVE_VALUE, mEmissiveValue); + DDX_Text(pDX, IDC_MATERIAL_NAME, mMaterialName); + DDX_Text(pDX, IDC_POWER_VALUE, mPowerValue); + DDX_Text(pDX, IDC_SPECULAR_VALUE, mSpecularValue); + DDX_Text(pDX, IDC_SPECULAR_TEXTURE, mSpecularTexture); + DDX_Text(pDX, IDC_DIFFUSE_TEXTURE, mDiffuseTexture); + DDX_Text(pDX, IDC_BUMP_TEXTURE, mBumpTexture); + DDX_Text(pDX, IDC_EMISSIVE_TEXTURE, mEmissiveTexture); + DDX_Text(pDX, IDC_MATERIAL_SHADER, mMaterialShader); + //}}AFX_DATA_MAP + + if (!pDX->m_bSaveAndValidate) { + if (solid && solid->GetModel()) { + mMaterialList.ResetContent(); + + Model* model = solid->GetModel(); + for (int i = 0; i < model->NumMaterials(); i++) { + Material* m = model->GetMaterials()[i]; + mMaterialList.AddString(m->name); + + if (m == material) + mMaterialList.SetCurSel(i); + } + } + + if (mBlendModeList.GetSafeHwnd()) + mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); + + if (mShadowList.GetSafeHwnd()) + mShadowList.SetCurSel(material->shadow); + } +} + + +BEGIN_MESSAGE_MAP(MaterialDialog, CDialog) + //{{AFX_MSG_MAP(MaterialDialog) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_AMBIENT_COLOR, OnAmbientColor) + ON_BN_CLICKED(IDC_DIFFUSE_COLOR, OnDiffuseColor) + ON_BN_CLICKED(IDC_EMISSIVE_COLOR, OnEmissiveColor) + ON_BN_CLICKED(IDC_SPECULAR_COLOR, OnSpecularColor) + ON_WM_DRAWITEM() + ON_EN_CHANGE(IDC_AMBIENT_VALUE, OnChangeMaterialValue) + ON_BN_CLICKED(IDC_FILE_DIFFUSE, OnFileDiffuse) + ON_BN_CLICKED(IDC_FILE_SPECULAR, OnFileSpecular) + ON_BN_CLICKED(IDC_FILE_EMISSIVE, OnFileEmissive) + ON_BN_CLICKED(IDC_FILE_BUMP, OnFileBump) + ON_EN_CHANGE(IDC_DIFFUSE_TEXTURE, OnChangeDiffuseTexture) + ON_EN_CHANGE(IDC_SPECULAR_TEXTURE, OnChangeSpecularTexture) + ON_EN_CHANGE(IDC_EMISSIVE_TEXTURE, OnChangeEmissiveTexture) + ON_EN_CHANGE(IDC_BUMP_TEXTURE, OnChangeBumpTexture) + ON_EN_CHANGE(IDC_MATERIAL_NAME, OnChangeMaterialName) + ON_LBN_SELCHANGE(IDC_MATERIAL_LIST, OnSelectMaterial) + ON_BN_CLICKED(IDC_SELECT_POLYS, OnSelectPolys) + ON_BN_CLICKED(IDC_NEW_MATERIAL, OnNewMaterial) + ON_BN_CLICKED(IDC_DEL_MATERIAL, OnDelMaterial) + ON_CBN_SELCHANGE(IDC_BLEND_MODE, OnSelectBlendMode) + ON_CBN_SELCHANGE(IDC_SHADOW, OnSelectShadow) + ON_EN_CHANGE(IDC_BRILLIANCE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_BUMP_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_DIFFUSE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_EMISSIVE_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_POWER_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_SPECULAR_VALUE, OnChangeMaterialValue) + ON_EN_CHANGE(IDC_MATERIAL_SHADER, OnChangeMaterialShader) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ + +void MaterialDialog::UpdateMaterial() +{ + if (material) { + UpdateData(); + + strcpy_s(material->name, mMaterialName); + strcpy_s(material->shader, mMaterialShader); + + material->ambient_value = mAmbientValue; + material->diffuse_value = mDiffuseValue; + material->specular_value = mSpecularValue; + material->emissive_value = mEmissiveValue; + material->power = mPowerValue; + material->brilliance = mBrillianceValue; + material->bump = mBumpValue; + material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); + material->shadow = mShadowList.GetCurSel() ? true : false; + + material->Ka = ColorValue(material->ambient_color) * material->ambient_value; + material->Kd = ColorValue(material->diffuse_color) * material->diffuse_value; + material->Ks = ColorValue(material->specular_color) * material->specular_value; + material->Ke = ColorValue(material->emissive_color) * material->emissive_value; + + material->CreateThumbnail(); + + InvalidateRect(NULL, FALSE); + } +} + +// +--------------------------------------------------------------------+ +// MaterialDialog message handlers +// +--------------------------------------------------------------------+ + +BOOL MaterialDialog::OnInitDialog() +{ + if (solid && solid->GetModel() && !material) { + Model* model = solid->GetModel(); + + if (model->NumMaterials() > 0) + material = model->GetMaterials().first(); + } + + if (!material) + material = &emergency_material; + + mMaterialName = material->name; + mMaterialShader = material->shader; + mAmbientValue = material->ambient_value; + mDiffuseValue = material->diffuse_value; + mSpecularValue = material->specular_value; + mEmissiveValue = material->emissive_value; + mPowerValue = material->power; + mBrillianceValue = material->brilliance; + mBumpValue = material->bump; + + mDiffuseTexture = material->tex_diffuse ? + material->tex_diffuse->GetFilename() : ""; + + mSpecularTexture = material->tex_specular ? + material->tex_specular->GetFilename() : ""; + + mEmissiveTexture = material->tex_emissive ? + material->tex_emissive->GetFilename() : ""; + + mBumpTexture = material->tex_bumpmap ? + material->tex_bumpmap->GetFilename() : ""; + + CDialog::OnInitDialog(); + + UpdateMaterial(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void MaterialDialog::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + if (material && material->thumbnail) { + ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); + } +} + +void MaterialDialog::OnAmbientColor() +{ + if (material) { + Color c = material->ambient_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->ambient_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnDiffuseColor() +{ + if (material) { + Color c = material->diffuse_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->diffuse_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnSpecularColor() +{ + if (material) { + Color c = material->specular_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->specular_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnEmissiveColor() +{ + if (material) { + Color c = material->emissive_color; + COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); + CColorDialog chooser(crgb); + + if (chooser.DoModal() == IDOK) { + crgb = chooser.GetColor(); + material->emissive_color = Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)); + UpdateMaterial(); + } + } +} + +void MaterialDialog::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CWnd* wnd = GetDlgItem(nIDCtl); + Color c = Color::LightGray; + + if (material) { + if (wnd->GetSafeHwnd() == mAmbientColor.GetSafeHwnd()) + c = material->ambient_color; + + else if (wnd->GetSafeHwnd() == mDiffuseColor.GetSafeHwnd()) + c = material->diffuse_color; + + else if (wnd->GetSafeHwnd() == mSpecularColor.GetSafeHwnd()) + c = material->specular_color; + + else if (wnd->GetSafeHwnd() == mEmissiveColor.GetSafeHwnd()) + c = material->emissive_color; + } + + CBrush brush(RGB(c.Red(), c.Green(), c.Blue())); + + ::FillRect(lpDrawItemStruct->hDC, + &lpDrawItemStruct->rcItem, + brush); + + CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnChangeMaterialValue() +{ + UpdateMaterial(); +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnFileTexture(int type) +{ + if (!material) + return; + + char filename[512]; + filename[0] = '\0'; + CFileDialog ofd(TRUE, "pcx"); + + ofd.m_ofn.lpstrFilter = "All Image Files\0*.bmp; *.dds; *.jpg; *.pcx; *.png; *.tga\0Bitmap Files (*.bmp)\0*.bmp\0JPEG Files (*.jpg)\0*.pcx\0PCX Files (*.pcx)\0*.pcx\0PNG Files (*.png)\0*.png\0Truevision Targa Files (*.tga)\0*.png\0All Files\0*.*\0\0"; + ofd.m_ofn.lpstrFile = filename; + ofd.m_ofn.nMaxFile = sizeof(filename); + + if (ofd.DoModal() != IDOK) + return; + + char tex_name[512]; + sprintf_s(tex_name, "%s", ofd.GetFileName().GetBuffer(0)); + + ChangeFileTexture(tex_name, type); +} + +void MaterialDialog::ChangeFileTexture(char* fname, int type) +{ + Bitmap* bmp = 0; + + LoadTexture(fname, bmp); + + if (bmp) { + switch (type) { + case 0: + material->tex_diffuse = bmp; + mDiffuseTexture = fname; + break; + + case 1: + material->tex_specular = bmp; + mSpecularTexture = fname; + break; + + case 2: + material->tex_emissive = bmp; + mEmissiveTexture = fname; + break; + + case 3: + material->tex_bumpmap = bmp; + mBumpTexture = fname; + break; + } + + UpdateData(FALSE); + UpdateMaterial(); + } +} + +void MaterialDialog::OnFileDiffuse() +{ + OnFileTexture(0); +} + +void MaterialDialog::OnFileSpecular() +{ + OnFileTexture(1); +} + +void MaterialDialog::OnFileEmissive() +{ + OnFileTexture(2); +} + +void MaterialDialog::OnFileBump() +{ + OnFileTexture(3); +} + +void MaterialDialog::OnChangeDiffuseTexture() +{ + if (material) { + UpdateData(); + + if (mDiffuseTexture.GetLength() < 1) { + material->tex_diffuse = 0; + UpdateMaterial(); + return; + } + + char* filename = mDiffuseTexture.LockBuffer(); + ChangeFileTexture(filename, 0); + mDiffuseTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeSpecularTexture() +{ + if (material) { + UpdateData(); + + if (mSpecularTexture.GetLength() < 1) { + material->tex_specular = 0; + UpdateMaterial(); + return; + } + + char* filename = mSpecularTexture.LockBuffer(); + ChangeFileTexture(filename, 1); + mSpecularTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeEmissiveTexture() +{ + if (material) { + UpdateData(); + + if (mEmissiveTexture.GetLength() < 1) { + material->tex_emissive = 0; + UpdateMaterial(); + return; + } + + char* filename = mEmissiveTexture.LockBuffer(); + ChangeFileTexture(filename, 2); + mEmissiveTexture.UnlockBuffer(); + } +} + +void MaterialDialog::OnChangeBumpTexture() +{ + if (material) { + UpdateData(); + + if (mBumpTexture.GetLength() < 1) { + material->tex_bumpmap = 0; + UpdateMaterial(); + return; + } + + char* filename = mBumpTexture.LockBuffer(); + ChangeFileTexture(filename, 3); + mBumpTexture.UnlockBuffer(); + } +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnChangeMaterialName() +{ + if (material) { + UpdateData(); + strcpy_s(material->name, mMaterialName); + } +} + +void MaterialDialog::OnChangeMaterialShader() +{ + if (material) { + UpdateData(); + strcpy_s(material->shader, mMaterialShader); + } +} + +void MaterialDialog::OnSelectMaterial() +{ + int selected = mMaterialList.GetCurSel(); + Material* mtl = 0; + + if (solid && solid->GetModel()) { + Model* model = solid->GetModel(); + + if (model->NumMaterials() > 0 && selected < model->NumMaterials()) + mtl = model->GetMaterials()[selected]; + } + + if (!mtl) + mtl = &emergency_material; + + if (material != mtl) { + material = mtl; + + mMaterialName = material->name; + mMaterialShader = material->shader; + mAmbientValue = material->ambient_value; + mDiffuseValue = material->diffuse_value; + mSpecularValue = material->specular_value; + mEmissiveValue = material->emissive_value; + mPowerValue = material->power; + mBrillianceValue = material->brilliance; + mBumpValue = material->bump; + + mDiffuseTexture = material->tex_diffuse ? + material->tex_diffuse->GetFilename() : ""; + + mSpecularTexture = material->tex_specular ? + material->tex_specular->GetFilename() : ""; + + mEmissiveTexture = material->tex_emissive ? + material->tex_emissive->GetFilename() : ""; + + mBumpTexture = material->tex_bumpmap ? + material->tex_bumpmap->GetFilename() : ""; + + if (mBlendModeList.GetSafeHwnd()) + mBlendModeList.SetCurSel(BlendModeToSelection(material->blend)); + + if (mShadowList.GetSafeHwnd()) + mShadowList.SetCurSel(material->shadow); + + UpdateData(FALSE); + UpdateMaterial(); + } +} + +// +--------------------------------------------------------------------+ + +void MaterialDialog::OnNewMaterial() +{ + if (solid && material && material != &emergency_material) { + Model* model = solid->GetModel(); + Material* mtl = new Material; + + if (model && mtl) { + mtl->Ka = Color::DarkGray; + mtl->Kd = Color::LightGray; + mtl->Ks = ColorValue(0.1f,0.1f,0.1f); + mtl->power = 10.0f; + + mtl->ambient_value = 0.2f; + mtl->ambient_color = Color::DarkGray; + mtl->diffuse_value = 0.8f; + mtl->diffuse_color = Color::LightGray; + mtl->specular_value = 0.5f; + mtl->specular_color = Color::White; + strcpy_s(mtl->name, "(new)"); + + model->GetMaterials().append(mtl); + + material = 0; + mMaterialList.AddString(mtl->name); + mMaterialList.SetCurSel(model->NumMaterials()-1); + + mBlendModeList.SetCurSel(0); + mShadowList.SetCurSel(1); + + OnSelectMaterial(); + } + } +} + +void MaterialDialog::OnDelMaterial() +{ + if (solid && material && material != &emergency_material) { + Model* model = solid->GetModel(); + + // do not delete the last material: + if (model->NumMaterials() > 1 && model->GetMaterials().contains(material)) { + Material* mtl = model->GetMaterials().first(); + + if (mtl == material) + mtl = model->GetMaterials()[1]; + + // reassign the material for any polys and segments + // that are using the one we are about to delete: + ListIter iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + + for (int i = 0; i < s->NumPolys(); i++) { + Poly* p = s->GetPolys() + i; + + if (p->material == material) { + p->material = mtl; + } + } + + ListIter seg_iter = s->GetSegments(); + while (++seg_iter) { + Segment* segment = seg_iter.value(); + if (segment->material == material) + segment->material = mtl; + } + } + + // now delete the material: + model->GetMaterials().remove(material); + delete material; + + material = 0; + mMaterialList.SetCurSel(0); + OnSelectMaterial(); + } + } +} + +void MaterialDialog::OnSelectPolys() +{ + if (solid && doc && doc->GetSelector()) { + Selector* selector = doc->GetSelector(); + + if (!material || material == &emergency_material) + selector->SelectMaterial(0); + else + selector->SelectMaterial(material); + } +} + +void MaterialDialog::OnSelectBlendMode() +{ + if (material) + material->blend = SelectionToBlendMode(mBlendModeList.GetCurSel()); +} + +void MaterialDialog::OnSelectShadow() +{ + if (material) + material->shadow = mShadowList.GetCurSel() ? true : false; +} + +void MaterialDialog::OnOK() +{ + Video* video = Video::GetInstance(); + if (video) + video->InvalidateCache(); + + CDialog::OnOK(); +} diff --git a/Magic2/MaterialDialog.h b/Magic2/MaterialDialog.h index b6fabcf..24f33b4 100644 --- a/Magic2/MaterialDialog.h +++ b/Magic2/MaterialDialog.h @@ -1,117 +1,141 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: MaterialDialog.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Material Editor Dialog interface file -*/ - -#if !defined(AFX_MATERIALDIALOG_H__DD978D83_EB03_479B_92A4_D1FCC333BECA__INCLUDED_) -#define AFX_MATERIALDIALOG_H__DD978D83_EB03_479B_92A4_D1FCC333BECA__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -// +--------------------------------------------------------------------+ - -class MagicDoc; -class MagicView; -struct Material; - -// +--------------------------------------------------------------------+ -// MaterialDialog dialog -// +--------------------------------------------------------------------+ - -class MaterialDialog : public CDialog -{ -// Construction -public: - MaterialDialog(MagicView* pParent = NULL); - virtual ~MaterialDialog(); - -// Dialog Data - //{{AFX_DATA(MaterialDialog) - enum { IDD = IDD_MODIFY_MATERIAL }; - CComboBox mShadowList; - CComboBox mBlendModeList; - CListBox mMaterialList; - CStatic mMaterialThumb; - CStatic mSpecularColor; - CStatic mEmissiveColor; - CStatic mDiffuseColor; - CStatic mAmbientColor; - float mAmbientValue; - float mBrillianceValue; - float mBumpValue; - float mDiffuseValue; - float mEmissiveValue; - CString mMaterialName; - float mPowerValue; - float mSpecularValue; - CString mSpecularTexture; - CString mDiffuseTexture; - CString mBumpTexture; - CString mEmissiveTexture; - CString mMaterialShader; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(MaterialDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - void UpdateMaterial(); - void OnFileTexture(int type); - void ChangeFileTexture(char* fname, int type); - - MagicDoc* doc; - Solid* solid; - Material* material; - - // Generated message map functions - //{{AFX_MSG(MaterialDialog) - virtual BOOL OnInitDialog(); - afx_msg void OnPaint(); - afx_msg void OnAmbientColor(); - afx_msg void OnDiffuseColor(); - afx_msg void OnEmissiveColor(); - afx_msg void OnSpecularColor(); - afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); - afx_msg void OnChangeMaterialValue(); - afx_msg void OnFileDiffuse(); - afx_msg void OnFileSpecular(); - afx_msg void OnFileEmissive(); - afx_msg void OnFileBump(); - afx_msg void OnChangeDiffuseTexture(); - afx_msg void OnChangeSpecularTexture(); - afx_msg void OnChangeEmissiveTexture(); - afx_msg void OnChangeBumpTexture(); - afx_msg void OnChangeMaterialName(); - afx_msg void OnSelectMaterial(); - afx_msg void OnSelectPolys(); - afx_msg void OnNewMaterial(); - afx_msg void OnDelMaterial(); - afx_msg void OnSelectBlendMode(); - afx_msg void OnSelectShadow(); - virtual void OnOK(); - afx_msg void OnChangeMaterialShader(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: MaterialDialog.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Material Editor Dialog interface file +*/ + +#if !defined(AFX_MATERIALDIALOG_H__DD978D83_EB03_479B_92A4_D1FCC333BECA__INCLUDED_) +#define AFX_MATERIALDIALOG_H__DD978D83_EB03_479B_92A4_D1FCC333BECA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// +--------------------------------------------------------------------+ + +class MagicDoc; +class MagicView; +struct Material; + +// +--------------------------------------------------------------------+ +// MaterialDialog dialog +// +--------------------------------------------------------------------+ + +class MaterialDialog : public CDialog +{ +// Construction +public: + MaterialDialog(MagicView* pParent = NULL); + virtual ~MaterialDialog(); + +// Dialog Data + //{{AFX_DATA(MaterialDialog) + enum { IDD = IDD_MODIFY_MATERIAL }; + CComboBox mShadowList; + CComboBox mBlendModeList; + CListBox mMaterialList; + CStatic mMaterialThumb; + CStatic mSpecularColor; + CStatic mEmissiveColor; + CStatic mDiffuseColor; + CStatic mAmbientColor; + float mAmbientValue; + float mBrillianceValue; + float mBumpValue; + float mDiffuseValue; + float mEmissiveValue; + CString mMaterialName; + float mPowerValue; + float mSpecularValue; + CString mSpecularTexture; + CString mDiffuseTexture; + CString mBumpTexture; + CString mEmissiveTexture; + CString mMaterialShader; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(MaterialDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + void UpdateMaterial(); + void OnFileTexture(int type); + void ChangeFileTexture(char* fname, int type); + + MagicDoc* doc; + Solid* solid; + Material* material; + + // Generated message map functions + //{{AFX_MSG(MaterialDialog) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg void OnAmbientColor(); + afx_msg void OnDiffuseColor(); + afx_msg void OnEmissiveColor(); + afx_msg void OnSpecularColor(); + afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); + afx_msg void OnChangeMaterialValue(); + afx_msg void OnFileDiffuse(); + afx_msg void OnFileSpecular(); + afx_msg void OnFileEmissive(); + afx_msg void OnFileBump(); + afx_msg void OnChangeDiffuseTexture(); + afx_msg void OnChangeSpecularTexture(); + afx_msg void OnChangeEmissiveTexture(); + afx_msg void OnChangeBumpTexture(); + afx_msg void OnChangeMaterialName(); + afx_msg void OnSelectMaterial(); + afx_msg void OnSelectPolys(); + afx_msg void OnNewMaterial(); + afx_msg void OnDelMaterial(); + afx_msg void OnSelectBlendMode(); + afx_msg void OnSelectShadow(); + virtual void OnOK(); + afx_msg void OnChangeMaterialShader(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif diff --git a/Magic2/ModelFile3DS.cpp b/Magic2/ModelFile3DS.cpp index db309ba..7094f00 100644 --- a/Magic2/ModelFile3DS.cpp +++ b/Magic2/ModelFile3DS.cpp @@ -1,283 +1,307 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFile3DS.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for 3DStudio MAX 3DS format models -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "ModelFile3DS.h" - -#include "Bitmap.h" -#include "Polygon.h" -#include "Text.h" -#include "List.h" -#include "l3ds.h" - -// +--------------------------------------------------------------------+ - -ModelFile3DS::ModelFile3DS(const char* fname) - : ModelFile(fname) -{ -} - -ModelFile3DS::~ModelFile3DS() -{ -} - -// +--------------------------------------------------------------------+ - -static int mcomp(const void* a, const void* b) -{ - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; - - if (pa->sortval == pb->sortval) - return 0; - - if (pa->sortval < pb->sortval) - return 1; - - return -1; -} - -bool -ModelFile3DS::Load(Model* model, double scale) -{ - if (model && scale > 0 && strlen(filename) > 0) { - ModelFile::Load(model, scale); - - L3DS loader; - - if (!loader.LoadFile(filename)) { - ::MessageBox(0, "3DS Import Failed: Magic could not open the file for reading", "ERROR", MB_OK); - return false; - } - - int ntex = 0; - int nsurfs = 0; - int nverts = 0; - int npolys = 0; - int nmatls = 0; - int nmeshs = loader.GetMeshCount(); - - int* mesh_verts = new int[nmeshs]; - - for (int m = 0; m < nmeshs; m++) { - LMesh& mesh = loader.GetMesh(m); - - mesh_verts[m] = nverts; - - // count verts and polys: - nverts += mesh.GetVertexCount(); - npolys += mesh.GetTriangleCount(); - } - - if (nverts > Model::MAX_VERTS || npolys > Model::MAX_POLYS) { - ::MessageBox(0, "3DS Import Failed: model was too large (max 16000 polys)", "ERROR", MB_OK); - delete [] mesh_verts; - return FALSE; - } - - // get materials: - nmatls = loader.GetMaterialCount(); - - for (int i = 0; i < nmatls; i++) { - LMaterial& matl = loader.GetMaterial(i); - LMap& tex_diff = matl.GetTextureMap1(); - LMap& tex_spec = matl.GetSpecularMap(); - LMap& tex_bump = matl.GetBumpMap(); - LMap& tex_glow = matl.GetTextureMap2(); - - Material* material = new Material; - - strncpy(material->name, matl.GetName().c_str(), Material::NAMELEN); - - material->Ka.Set( matl.GetAmbientColor().r, - matl.GetAmbientColor().g, - matl.GetAmbientColor().b ); - - material->ambient_value = 1.0f; - material->ambient_color = material->Ka.ToColor(); - - material->Kd.Set( matl.GetDiffuseColor().r, - matl.GetDiffuseColor().g, - matl.GetDiffuseColor().b ); - - material->diffuse_value = 1.0f; - material->diffuse_color = material->Kd.ToColor(); - - material->Ks.Set( matl.GetSpecularColor().r, - matl.GetSpecularColor().g, - matl.GetSpecularColor().b ); - - material->specular_value = 1.0f; - material->specular_color = material->Ks.ToColor(); - - material->power = matl.GetShininess() * 100; - - if (tex_diff.mapName[0]) - LoadTexture(tex_diff.mapName, material->tex_diffuse); - - if (tex_spec.mapName[0]) - LoadTexture(tex_spec.mapName, material->tex_specular); - - if (tex_bump.mapName[0]) - LoadTexture(tex_bump.mapName, material->tex_bumpmap); - - if (tex_glow.mapName[0]) - LoadTexture(tex_glow.mapName, material->tex_emissive); - - model->GetMaterials().append(material); - } - - Surface* surface = new Surface; - model->GetSurfaces().append(surface); - - surface->CreateVerts(nverts); - surface->CreatePolys(npolys); - - VertexSet* vset = surface->GetVertexSet(); - Poly* polys = surface->GetPolys(); - float radius = 0; - int v = 0; - - for (int m = 0; m < nmeshs && v < nverts; m++) { - LMesh& mesh = loader.GetMesh(m); - - // read vertex set: - for (int i = 0; i < mesh.GetVertexCount() && v < nverts; i++) { - vset->loc[v].x = mesh.GetVertex(i).x; - vset->loc[v].y = mesh.GetVertex(i).z; - vset->loc[v].z = mesh.GetVertex(i).y; - - vset->nrm[v].x = mesh.GetNormal(i).x; - vset->nrm[v].y = mesh.GetNormal(i).z; - vset->nrm[v].z = mesh.GetNormal(i).y; - - vset->tu[v] = mesh.GetUV(i).x; - vset->tv[v] = mesh.GetUV(i).y; - - float d = vset->loc[v].length(); - if (d > radius) - radius = d; - - v++; - } - } - - if (radius < 16) { - model->ScaleBy(256.0f / radius); - radius = 256.0f; - } - - int n = 0; - - for (int m = 0; m < nmeshs && n < npolys; m++) { - LMesh& mesh = loader.GetMesh(m); - - // read polys: - int mesh_tris = mesh.GetTriangleCount(); - for (int i = 0; i < mesh_tris && n < npolys; i++) { - Poly* p = surface->GetPolys() + n++; - const LTriangle& tri = mesh.GetTriangle(i); - LTriangle2 tri2 = mesh.GetTriangle2(i); - - p->nverts = 3; - - p->verts[0] = tri.a + mesh_verts[m]; - p->verts[1] = tri.b + mesh_verts[m]; - p->verts[2] = tri.c + mesh_verts[m]; - - if (p->verts[0] > nverts || p->verts[1] > nverts || p->verts[2] > nverts) { - p->verts[0] = 0; - p->verts[1] = 1; - p->verts[2] = 2; - } - - if (tri2.vertexNormals[0] == tri2.vertexNormals[1] && - tri2.vertexNormals[0] == tri2.vertexNormals[2]) - p->flatness = 1.0f; - else - p->flatness = 0.0f; - - p->vertex_set = vset; - p->material = model->GetMaterials()[ tri2.materialId ]; - p->sortval = tri2.materialId; - - p->plane = Plane(vset->loc[ p->verts[0] ], - vset->loc[ p->verts[2] ], - vset->loc[ p->verts[1] ]); - - surface->AddIndices(p->nverts); - } - } - - // sort the polys by material index: - qsort((void*) polys, npolys, sizeof(Poly), mcomp); - - // then assign them to cohesive segments: - Segment* segment = 0; - - for (int n = 0; n < npolys; n++) { - if (segment && segment->material == polys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new Segment; - - segment->npolys = 1; - segment->polys = &polys[n]; - segment->material = segment->polys->material; - - surface->GetSegments().append(segment); - } - } - - *pnverts = nverts; - *pnpolys = npolys; - *pradius = radius; - - model->Normalize(); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -ModelFile3DS::Save(Model* m) -{ - if (m) { - ModelFile::Save(m); - - FILE* f = fopen(filename, "w"); - if (!f) { - ::MessageBox(0, "3DS Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); - return false; - } - - fclose(f); - - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFile3DS.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for 3DStudio MAX 3DS format models +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "ModelFile3DS.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "Text.h" +#include "List.h" +#include "l3ds.h" + +// +--------------------------------------------------------------------+ + +ModelFile3DS::ModelFile3DS(const char* fname) + : ModelFile(fname) +{ +} + +ModelFile3DS::~ModelFile3DS() +{ +} + +// +--------------------------------------------------------------------+ + +static int mcomp(const void* a, const void* b) +{ + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; + + if (pa->sortval == pb->sortval) + return 0; + + if (pa->sortval < pb->sortval) + return 1; + + return -1; +} + +bool +ModelFile3DS::Load(Model* model, double scale) +{ + if (model && scale > 0 && strlen(filename) > 0) { + ModelFile::Load(model, scale); + + L3DS loader; + + if (!loader.LoadFile(filename)) { + ::MessageBox(0, "3DS Import Failed: Magic could not open the file for reading", "ERROR", MB_OK); + return false; + } + + int ntex = 0; + int nsurfs = 0; + int nverts = 0; + int npolys = 0; + int nmatls = 0; + int nmeshs = loader.GetMeshCount(); + + int* mesh_verts = new int[nmeshs]; + + for (int m = 0; m < nmeshs; m++) { + LMesh& mesh = loader.GetMesh(m); + + mesh_verts[m] = nverts; + + // count verts and polys: + nverts += mesh.GetVertexCount(); + npolys += mesh.GetTriangleCount(); + } + + if (nverts > Model::MAX_VERTS || npolys > Model::MAX_POLYS) { + ::MessageBox(0, "3DS Import Failed: model was too large (max 16000 polys)", "ERROR", MB_OK); + delete [] mesh_verts; + return FALSE; + } + + // get materials: + nmatls = loader.GetMaterialCount(); + + for (int i = 0; i < nmatls; i++) { + LMaterial& matl = loader.GetMaterial(i); + LMap& tex_diff = matl.GetTextureMap1(); + LMap& tex_spec = matl.GetSpecularMap(); + LMap& tex_bump = matl.GetBumpMap(); + LMap& tex_glow = matl.GetTextureMap2(); + + Material* material = new Material; + + strncpy(material->name, matl.GetName().c_str(), Material::NAMELEN); + + material->Ka.Set( matl.GetAmbientColor().r, + matl.GetAmbientColor().g, + matl.GetAmbientColor().b ); + + material->ambient_value = 1.0f; + material->ambient_color = material->Ka.ToColor(); + + material->Kd.Set( matl.GetDiffuseColor().r, + matl.GetDiffuseColor().g, + matl.GetDiffuseColor().b ); + + material->diffuse_value = 1.0f; + material->diffuse_color = material->Kd.ToColor(); + + material->Ks.Set( matl.GetSpecularColor().r, + matl.GetSpecularColor().g, + matl.GetSpecularColor().b ); + + material->specular_value = 1.0f; + material->specular_color = material->Ks.ToColor(); + + material->power = matl.GetShininess() * 100; + + if (tex_diff.mapName[0]) + LoadTexture(tex_diff.mapName, material->tex_diffuse); + + if (tex_spec.mapName[0]) + LoadTexture(tex_spec.mapName, material->tex_specular); + + if (tex_bump.mapName[0]) + LoadTexture(tex_bump.mapName, material->tex_bumpmap); + + if (tex_glow.mapName[0]) + LoadTexture(tex_glow.mapName, material->tex_emissive); + + model->GetMaterials().append(material); + } + + Surface* surface = new Surface; + model->GetSurfaces().append(surface); + + surface->CreateVerts(nverts); + surface->CreatePolys(npolys); + + VertexSet* vset = surface->GetVertexSet(); + Poly* polys = surface->GetPolys(); + float radius = 0; + int v = 0; + + for (int m = 0; m < nmeshs && v < nverts; m++) { + LMesh& mesh = loader.GetMesh(m); + + // read vertex set: + for (int i = 0; i < mesh.GetVertexCount() && v < nverts; i++) { + vset->loc[v].x = mesh.GetVertex(i).x; + vset->loc[v].y = mesh.GetVertex(i).z; + vset->loc[v].z = mesh.GetVertex(i).y; + + vset->nrm[v].x = mesh.GetNormal(i).x; + vset->nrm[v].y = mesh.GetNormal(i).z; + vset->nrm[v].z = mesh.GetNormal(i).y; + + vset->tu[v] = mesh.GetUV(i).x; + vset->tv[v] = mesh.GetUV(i).y; + + float d = vset->loc[v].length(); + if (d > radius) + radius = d; + + v++; + } + } + + if (radius < 16) { + model->ScaleBy(256.0f / radius); + radius = 256.0f; + } + + int n = 0; + + for (int m = 0; m < nmeshs && n < npolys; m++) { + LMesh& mesh = loader.GetMesh(m); + + // read polys: + int mesh_tris = mesh.GetTriangleCount(); + for (int i = 0; i < mesh_tris && n < npolys; i++) { + Poly* p = surface->GetPolys() + n++; + const LTriangle& tri = mesh.GetTriangle(i); + LTriangle2 tri2 = mesh.GetTriangle2(i); + + p->nverts = 3; + + p->verts[0] = tri.a + mesh_verts[m]; + p->verts[1] = tri.b + mesh_verts[m]; + p->verts[2] = tri.c + mesh_verts[m]; + + if (p->verts[0] > nverts || p->verts[1] > nverts || p->verts[2] > nverts) { + p->verts[0] = 0; + p->verts[1] = 1; + p->verts[2] = 2; + } + + if (tri2.vertexNormals[0] == tri2.vertexNormals[1] && + tri2.vertexNormals[0] == tri2.vertexNormals[2]) + p->flatness = 1.0f; + else + p->flatness = 0.0f; + + p->vertex_set = vset; + p->material = model->GetMaterials()[ tri2.materialId ]; + p->sortval = tri2.materialId; + + p->plane = Plane(vset->loc[ p->verts[0] ], + vset->loc[ p->verts[2] ], + vset->loc[ p->verts[1] ]); + + surface->AddIndices(p->nverts); + } + } + + // sort the polys by material index: + qsort((void*) polys, npolys, sizeof(Poly), mcomp); + + // then assign them to cohesive segments: + Segment* segment = 0; + + for (int n = 0; n < npolys; n++) { + if (segment && segment->material == polys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new Segment; + + segment->npolys = 1; + segment->polys = &polys[n]; + segment->material = segment->polys->material; + + surface->GetSegments().append(segment); + } + } + + *pnverts = nverts; + *pnpolys = npolys; + *pradius = radius; + + model->Normalize(); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +ModelFile3DS::Save(Model* m) +{ + if (m) { + ModelFile::Save(m); + + FILE* f = fopen(filename, "w"); + if (!f) { + ::MessageBox(0, "3DS Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); + return false; + } + + fclose(f); + + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ diff --git a/Magic2/ModelFile3DS.h b/Magic2/ModelFile3DS.h index bf49d09..19a255a 100644 --- a/Magic2/ModelFile3DS.h +++ b/Magic2/ModelFile3DS.h @@ -1,37 +1,61 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFile3DS.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for 3DStudio MAX 3DS format models -*/ - -#ifndef ModelFile3DS_h -#define ModelFile3DS_h - -#include "Solid.h" - -// +--------------------------------------------------------------------+ - -class ModelFile3DS : public ModelFile -{ -public: - ModelFile3DS(const char* fname); - virtual ~ModelFile3DS(); - - virtual bool Load(Model* m, double scale=1.0); - virtual bool Save(Model* m); - -protected: -}; - -// +--------------------------------------------------------------------+ - -#endif ModelFile3DS_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFile3DS.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for 3DStudio MAX 3DS format models +*/ + +#ifndef ModelFile3DS_h +#define ModelFile3DS_h + +#include "Solid.h" + +// +--------------------------------------------------------------------+ + +class ModelFile3DS : public ModelFile +{ +public: + ModelFile3DS(const char* fname); + virtual ~ModelFile3DS(); + + virtual bool Load(Model* m, double scale=1.0); + virtual bool Save(Model* m); + +protected: +}; + +// +--------------------------------------------------------------------+ + +#endif ModelFile3DS_h + diff --git a/Magic2/ModelFileMAG.cpp b/Magic2/ModelFileMAG.cpp index 953f22d..51c6a46 100644 --- a/Magic2/ModelFileMAG.cpp +++ b/Magic2/ModelFileMAG.cpp @@ -1,825 +1,849 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFileMAG.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for MAG format models -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "ModelFileMAG.h" - -#include "Bitmap.h" -#include "Polygon.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -struct MaterialMag6 { - char name[Material::NAMELEN]; - char shader[Material::NAMELEN]; - float power; // highlight sharpness (big=shiny) - float brilliance; // diffuse power function - float bump; // bump level (0=none) - DWORD blend; // alpha blend type - bool shadow; // material casts shadow - bool luminous; // verts have their own lighting - - Color ambient_color; - Color diffuse_color; - Color specular_color; - Color emissive_color; - - float ambient_value; - float diffuse_value; - float specular_value; - float emissive_value; - - BYTE tex_diffuse; - BYTE tex_specular; - BYTE tex_bumpmap; - BYTE tex_emissive; -}; - -// +--------------------------------------------------------------------+ - -ModelFileMAG::ModelFileMAG(const char* fname) - : ModelFile(fname) -{ -} - -ModelFileMAG::~ModelFileMAG() -{ -} - -// +--------------------------------------------------------------------+ - -bool -ModelFileMAG::Load(Model* m, double scale) -{ - if (m && scale > 0 && strlen(filename) > 0) { - ModelFile::Load(m, scale); - - bool result = false; - FILE* fp = fopen(filename, "rb"); - - // check MAG file: - if (!fp) { - ::MessageBox(0, "File Open Failed:\nMagic could not open the requested file.", "ERROR", MB_OK); - return result; - } - - ZeroMemory(pname, 64); - strncpy(pname, filename, 63); - - char file_id[5]; - fread(file_id, 4, 1, fp); - file_id[4] = '\0'; - int version = 1; - - if (!strcmp(file_id, "MAG6")) { - version = 6; - } - else if (!strcmp(file_id, "MAG5")) { - version = 5; - } - else if (!strcmp(file_id, "MAG4")) { - version = 4; - } - else { - ::MessageBox(0, "File Open Failed:\nThe requested file uses an invalid format.", "ERROR", MB_OK); - fclose(fp); - return result; - } - - // get ready to load, delete existing model: - m->GetSurfaces().destroy(); - m->GetMaterials().destroy(); - *pnverts = 0; - *pnpolys = 0; - - // now load the model: - switch (version) { - case 4: - case 5: - result = LoadMag5(fp, m, scale); - break; - - case 6: - result = LoadMag6(fp, m, scale); - break; - - default: - break; - } - - fclose(fp); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -ModelFileMAG::Save(Model* m) -{ - if (m) { - ModelFile::Save(m); - - FILE* fp = fopen(filename, "wb"); - if (!fp) { - ::MessageBox(0, "Save Failed:\nMagic could not open the file for writing.", "ERROR", MB_OK); - return FALSE; - } - - fwrite("MAG6", 4, 1, fp); - - int i = 0; - int ntex = 0; - int nmtls = 0; - int nsurfs = m->NumSurfaces(); - List textures; - - ListIter m_iter = m->GetMaterials(); - while (++m_iter) { - Material* mtl = m_iter.value(); - Bitmap* bmp = mtl->tex_diffuse; - - if (bmp && !textures.contains(bmp)) { - textures.append(bmp); - } - - bmp = mtl->tex_specular; - - if (bmp && !textures.contains(bmp)) { - textures.append(bmp); - } - - bmp = mtl->tex_emissive; - - if (bmp && !textures.contains(bmp)) { - textures.append(bmp); - } - - bmp = mtl->tex_bumpmap; - - if (bmp && !textures.contains(bmp)) { - textures.append(bmp); - } - - nmtls++; - } - - ListIter t_iter = textures; - while (++t_iter) { - Bitmap* bmp = t_iter.value(); - ntex += strlen(bmp->GetFilename()) + 1; - } - - nsurfs = m->GetSurfaces().size(); - - fwrite(&ntex, 4, 1, fp); - fwrite(&nmtls, 4, 1, fp); - fwrite(&nsurfs, 4, 1, fp); - - if (ntex) { - t_iter.reset(); - while (++t_iter) { - Bitmap* bmp = t_iter.value(); - - fwrite(bmp->GetFilename(), - strlen(bmp->GetFilename()) + 1, - 1, - fp); - } - } - - if (nmtls) { - m_iter.reset(); - while (++m_iter) { - Material* mtl = m_iter.value(); - MaterialMag6 m6; - - ZeroMemory(&m6, sizeof(m6)); - - CopyMemory(m6.name, mtl->name, Material::NAMELEN); - CopyMemory(m6.shader, mtl->shader, Material::NAMELEN); - - m6.ambient_value = mtl->ambient_value; - m6.ambient_color = mtl->ambient_color; - m6.diffuse_value = mtl->diffuse_value; - m6.diffuse_color = mtl->diffuse_color; - m6.specular_value = mtl->specular_value; - m6.specular_color = mtl->specular_color; - m6.emissive_value = mtl->emissive_value; - m6.emissive_color = mtl->emissive_color; - - m6.power = mtl->power; - m6.brilliance = mtl->brilliance; - m6.bump = mtl->bump; - m6.blend = mtl->blend; - m6.shadow = mtl->shadow; - m6.luminous = mtl->luminous; - - if (mtl->tex_diffuse) - m6.tex_diffuse = textures.index(mtl->tex_diffuse) + 1; - - if (mtl->tex_specular) - m6.tex_specular = textures.index(mtl->tex_specular) + 1; - - if (mtl->tex_emissive) - m6.tex_emissive = textures.index(mtl->tex_emissive) + 1; - - if (mtl->tex_bumpmap) - m6.tex_bumpmap = textures.index(mtl->tex_bumpmap) + 1; - - fwrite(&m6, sizeof(m6), 1, fp); - } - } - - ListIter s_iter = m->GetSurfaces(); - while (++s_iter) { - Surface* s = s_iter.value(); - - int nverts = s->NumVerts(); - int npolys = s->NumPolys(); - BYTE namelen = strlen(s->Name()) + 1; - - fwrite(&nverts, 4, 1, fp); - fwrite(&npolys, 4, 1, fp); - fwrite(&namelen, 1, 1, fp); - fwrite(s->Name(), 1, namelen, fp); - - VertexSet* vset = s->GetVertexSet(); - Poly* polys = s->GetPolys(); - - // write vertex set: - for (int v = 0; v < nverts; v++) { - fwrite(&vset->loc[v], sizeof(float), 3, fp); - fwrite(&vset->nrm[v], sizeof(float), 3, fp); - fwrite(&vset->tu[v], sizeof(float), 1, fp); - fwrite(&vset->tv[v], sizeof(float), 1, fp); - } - - // write polys: - for (int n = 0; n < npolys; n++) { - Poly& poly = polys[n]; - BYTE poly_nverts = (BYTE) poly.nverts; - BYTE material_index = 0; - WORD poly_verts[8]; - - m_iter.reset(); - while (++m_iter && !material_index) { - if (poly.material == m_iter.value()) - material_index = m_iter.index() + 1; - } - - for (int i = 0; i < poly_nverts; i++) { - poly_verts[i] = poly.verts[i]; - } - - fwrite(&poly_nverts, sizeof(BYTE), 1, fp); - fwrite(&material_index, sizeof(BYTE), 1, fp); - fwrite(&poly_verts[0], sizeof(WORD), poly_nverts, fp); - } - } - - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -struct HomogenousPlane -{ - double distance; - double normal_x; - double normal_y; - double normal_z; - double normal_w; -}; - -static void LoadPlane(Plane& p, FILE* fp) -{ - HomogenousPlane tmp; - fread(&tmp, sizeof(HomogenousPlane), 1, fp); -} - -static void LoadFlags(LPDWORD flags, FILE* fp) -{ - DWORD magic_flags; - fread(&magic_flags, sizeof(DWORD), 1, fp); - - /** MAGIC FLAGS - enum { FLAT_SHADED = 1, - LUMINOUS = 2, - TRANSLUCENT = 4, \\ must swap - CHROMAKEY = 8, // these two - FOREGROUND = 16, -- not used - WIREFRAME = 32, -- not used - SPECULAR1 = 64, - SPECULAR2 = 128 }; - ***/ - - const DWORD magic_mask = 0x0fc3; - - *flags = magic_flags & magic_mask; -} - -// +--------------------------------------------------------------------+ - -static int mcomp(const void* a, const void* b) -{ - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; - - if (pa->sortval == pb->sortval) - return 0; - - if (pa->sortval < pb->sortval) - return -1; - - return 1; -} - -bool -ModelFileMAG::LoadMag5(FILE* fp, Model* m, double scale) -{ - bool result = false; - int ntex = 0; - int nsurfs = 0; - double radius = 0; - - fread(&ntex, sizeof(ntex), 1, fp); - fread(&nsurfs, sizeof(nsurfs), 1, fp); - - // create a default gray material: - Material* mtl = new Material; - - if (mtl) { - mtl->Ka = Color::DarkGray; - mtl->Kd = Color::LightGray; - mtl->Ks = ColorValue(0.1f,0.1f,0.1f); - mtl->power = 10.0f; - - mtl->ambient_value = 0.2f; - mtl->ambient_color = Color::DarkGray; - mtl->diffuse_value = 0.8f; - mtl->diffuse_color = Color::LightGray; - mtl->specular_value = 0.5f; - mtl->specular_color = Color::White; - strcpy_s(mtl->name, "(default)"); - - m->GetMaterials().append(mtl); - } - - // read texture list: - for (int i = 0; i < ntex; i++) { - Material* mtl = new Material; - char tname[32]; - - if (mtl) { - mtl->Ka = ColorValue(0.5f,0.5f,0.5f); - mtl->Kd = ColorValue(1.0f,1.0f,1.0f); - mtl->Ks = ColorValue(0.2f,0.2f,0.2f); - mtl->power = 20.0f; - - mtl->ambient_value = 1.0f; - mtl->ambient_color = Color::Gray; - mtl->diffuse_value = 1.0f; - mtl->diffuse_color = Color::White; - mtl->specular_value = 0.2f; - mtl->specular_color = Color::White; - - fread(tname, 32, 1, fp); - LoadTexture(tname, mtl->tex_diffuse, Bitmap::BMP_SOLID); - strcpy_s(mtl->name, tname); - - char* dot = strrchr(mtl->name, '.'); - if (dot) - *dot = 0; - - char* plus = strrchr(mtl->name, '+'); - if (plus) - *plus = 0; - - m->GetMaterials().append(mtl); - } - } - - int nverts = 0; - int npolys = 0; - - fread(&nverts, 4, 1, fp); - fread(&npolys, 4, 1, fp); - - // plan on creating four verts per poly: - int mag_nverts = nverts; - int next_vert = nverts; - - nverts = npolys * 4; - Surface* s = new Surface; - VertexSet* vset = 0; - Poly* polys = 0; - - if (s) { - s->SetName("default"); - s->CreateVerts(nverts); - s->CreatePolys(npolys); - - vset = s->GetVertexSet(); - polys = s->GetPolys(); - - ZeroMemory(vset->loc, nverts * sizeof(Vec3)); - ZeroMemory(vset->diffuse, nverts * sizeof(DWORD)); - ZeroMemory(vset->specular, nverts * sizeof(DWORD)); - ZeroMemory(vset->tu, nverts * sizeof(float)); - ZeroMemory(vset->tv, nverts * sizeof(float)); - ZeroMemory(vset->rw, nverts * sizeof(float)); - - // read vertex set: - int v; - for (v = 0; v < mag_nverts; v++) { - Vec3 vert, norm; - DWORD vstate; - - fread(&vert, sizeof(Vec3), 1, fp); - fread(&norm, sizeof(Vec3), 1, fp); - fread(&vstate, sizeof(DWORD), 1, fp); - - vert.SwapYZ(); - vert *= (float) scale; - - norm.SwapYZ(); - - vset->loc[v] = vert; - vset->nrm[v] = norm; - - double d = vert.length(); - if (d > radius) - radius = (float) d; - } - - while (v < nverts) - vset->nrm[v++] = Vec3(1,0,0); - - // read polys: - Vec3 dummy_center; - DWORD dummy_flags; - DWORD dummy_color; - int texture_num; - int poly_nverts; - int vert_index_buffer[32]; - float texture_index_buffer[32]; - - for (int n = 0; n < npolys; n++) { - Poly& poly = polys[n]; - poly.vertex_set = vset; - - fread(&dummy_flags, sizeof(DWORD), 1, fp); - fread(&dummy_center, sizeof(Vec3), 1, fp); - LoadPlane(poly.plane, fp); - fread(&dummy_color, sizeof(DWORD), 1, fp); - fread(&texture_num, sizeof(int), 1, fp); - - if (texture_num >= 0 && texture_num < ntex) { - texture_num++; - - poly.material = m->GetMaterials()[texture_num]; - poly.sortval = texture_num; - - if (dummy_flags & 2) { // luminous - Material* mtl = m->GetMaterials()[texture_num]; - - mtl->ambient_value = 0.0f; - mtl->ambient_color = Color::Black; - mtl->diffuse_value = 0.0f; - mtl->diffuse_color = Color::Black; - mtl->specular_value = 0.0f; - mtl->specular_color = Color::Black; - mtl->emissive_value = 1.0f; - mtl->emissive_color = Color::White; - - mtl->Ka = ColorValue(0,0,0,0); - mtl->Kd = ColorValue(0,0,0,0); - mtl->Ks = ColorValue(0,0,0,0); - mtl->Ke = ColorValue(1,1,1,1); - - mtl->tex_emissive = mtl->tex_diffuse; - } - } - else { - poly.material = m->GetMaterials().first(); // default material - poly.sortval = 1000; - } - - // hack: store flat shaded flag in unused visible byte - poly.visible = (BYTE) (dummy_flags & 1); - - fread(&poly_nverts, sizeof(int), 1, fp); - fread(vert_index_buffer, sizeof(int), poly_nverts, fp); - - if (poly_nverts == 3) - s->AddIndices(3); - - else if (poly_nverts == 4) - s->AddIndices(6); - - poly.nverts = poly_nverts; - for (int vi = 0; vi < poly_nverts; vi++) { - int v = vert_index_buffer[vi]; - - if (vset->rw[v] > 0) { - vset->CopyVertex(next_vert, v); - v = next_vert++; - } - - vset->rw[v] = 1; - poly.verts[vi] = v; - } - - fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tu's - for (int vi = 0; vi < poly_nverts; vi++) { - int v = poly.verts[vi]; - vset->tu[v] = texture_index_buffer[vi]; - } - - fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tv's - for (int vi = 0; vi < poly_nverts; vi++) { - int v = poly.verts[vi]; - vset->tv[v] = texture_index_buffer[vi]; - } - - DWORD unused[32]; - fread(unused, 16, 1, fp); - } - - // pass 2 (adjust vertex normals for flat polys): - for (int n = 0; n < npolys; n++) { - Poly& poly = polys[n]; - - poly.plane = Plane(vset->loc[poly.verts[0]], - vset->loc[poly.verts[2]], - vset->loc[poly.verts[1]]); - - // hack: retrieve flat shaded flag from unused visible byte - if (poly.visible) { - int poly_nverts = poly.nverts; - - for (int vi = 0; vi < poly_nverts; vi++) { - int v = poly.verts[vi]; - vset->nrm[v] = poly.plane.normal; - } - } - } - - // sort the polys by material index: - qsort((void*) polys, npolys, sizeof(Poly), mcomp); - - // then assign them to cohesive segments: - Segment* segment = 0; - - for (int n = 0; n < npolys; n++) { - if (segment && segment->material == polys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new Segment; - - segment->npolys = 1; - segment->polys = &polys[n]; - segment->material = segment->polys->material; - - s->GetSegments().append(segment); - } - } - - s->BuildHull(); - m->GetSurfaces().append(s); - - *pnverts = nverts; - *pnpolys = npolys; - *pradius = (float) radius; - - result = nverts && npolys; - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -ModelFileMAG::LoadMag6(FILE* fp, Model* m, double scale) -{ - bool result = false; - int i = 0; - int ntex = 0; - int nmtls = 0; - int nsurfs = 0; - double radius = 0; - List textures; - - fread(&ntex, sizeof(ntex), 1, fp); // size of texture block - fread(&nmtls, sizeof(nmtls), 1, fp); // number of materials - fread(&nsurfs, sizeof(nsurfs), 1, fp); // number of surfaces - - // read texture list: - if (ntex) { - char* buffer = new char[ntex]; - char* p = buffer; - Bitmap* bmp = 0; - - fread(buffer, ntex, 1, fp); - - while (p < buffer + ntex) { - LoadTexture(p, bmp, Bitmap::BMP_SOLID); - textures.append(bmp); - - p += strlen(p) + 1; - } - - delete [] buffer; - } - - for (i = 0; i < nmtls; i++) { - MaterialMag6 m6; - Material* mtl = new Material; - - fread(&m6, sizeof(m6), 1, fp); - - if (mtl) { - CopyMemory(mtl->name, m6.name, Material::NAMELEN); - CopyMemory(mtl->shader, m6.shader, Material::NAMELEN); - - mtl->ambient_value = m6.ambient_value; - mtl->ambient_color = m6.ambient_color; - mtl->diffuse_value = m6.diffuse_value; - mtl->diffuse_color = m6.diffuse_color; - mtl->specular_value = m6.specular_value; - mtl->specular_color = m6.specular_color; - mtl->emissive_value = m6.emissive_value; - mtl->emissive_color = m6.emissive_color; - - mtl->Ka = ColorValue(mtl->ambient_color) * mtl->ambient_value; - mtl->Kd = ColorValue(mtl->diffuse_color) * mtl->diffuse_value; - mtl->Ks = ColorValue(mtl->specular_color) * mtl->specular_value; - mtl->Ke = ColorValue(mtl->emissive_color) * mtl->emissive_value; - - mtl->power = m6.power; - mtl->brilliance = m6.brilliance; - mtl->bump = m6.bump; - mtl->blend = m6.blend; - mtl->shadow = m6.shadow; - mtl->luminous = m6.luminous; - - if (m6.tex_diffuse && m6.tex_diffuse <= textures.size()) - mtl->tex_diffuse = textures[m6.tex_diffuse - 1]; - - if (m6.tex_specular && m6.tex_specular <= textures.size()) - mtl->tex_specular = textures[m6.tex_specular - 1]; - - if (m6.tex_emissive && m6.tex_emissive <= textures.size()) - mtl->tex_emissive = textures[m6.tex_emissive - 1]; - - if (m6.tex_bumpmap && m6.tex_bumpmap <= textures.size()) - mtl->tex_bumpmap = textures[m6.tex_bumpmap - 1]; - - m->GetMaterials().append(mtl); - } - } - - for (i = 0; i < nsurfs; i++) { - int nverts = 0; - int npolys = 0; - BYTE namelen = 0; - char name[128]; - - fread(&nverts, 4, 1, fp); - fread(&npolys, 4, 1, fp); - fread(&namelen, 1, 1, fp); - fread(name, 1, namelen, fp); - - Surface* surface = new Surface; - surface->SetName(name); - surface->CreateVerts(nverts); - surface->CreatePolys(npolys); - - VertexSet* vset = surface->GetVertexSet(); - Poly* polys = surface->GetPolys(); - - ZeroMemory(polys, sizeof(Poly) * npolys); - - // read vertex set: - for (int v = 0; v < nverts; v++) { - fread(&vset->loc[v], sizeof(float), 3, fp); - fread(&vset->nrm[v], sizeof(float), 3, fp); - fread(&vset->tu[v], sizeof(float), 1, fp); - fread(&vset->tv[v], sizeof(float), 1, fp); - - double d = vset->loc[v].length(); - if (d > radius) - radius = d; - } - - // read polys: - for (int n = 0; n < npolys; n++) { - Poly& poly = polys[n]; - BYTE poly_nverts = 0; - BYTE material_index = 0; - WORD poly_verts[8]; - - fread(&poly_nverts, sizeof(BYTE), 1, fp); - fread(&material_index, sizeof(BYTE), 1, fp); - fread(&poly_verts[0], sizeof(WORD), poly_nverts, fp); - - if (poly_nverts >= 3) { - poly.nverts = poly_nverts; - - for (int i = 0; i < poly_nverts; i++) { - poly.verts[i] = poly_verts[i]; - } - } - else { - poly.sortval = 666; - } - - if (material_index > 0) { - poly.material = m->GetMaterials()[material_index-1]; - poly.sortval = material_index; - } - else if (m->NumMaterials()) { - poly.material = m->GetMaterials().first(); - poly.sortval = 1; - } - else { - poly.sortval = 1000; - } - - if (poly.nverts == 3) - surface->AddIndices(3); - - else if (poly.nverts == 4) - surface->AddIndices(6); - - poly.vertex_set = vset; - poly.plane = Plane(vset->loc[poly.verts[0]], - vset->loc[poly.verts[2]], - vset->loc[poly.verts[1]]); - } - - // sort the polys by material index: - qsort((void*) polys, npolys, sizeof(Poly), mcomp); - - // then assign them to cohesive segments: - Segment* segment = 0; - - for (int n = 0; n < npolys; n++) { - if (segment && segment->material == polys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new Segment; - - segment->npolys = 1; - segment->polys = &polys[n]; - segment->material = segment->polys->material; - - surface->GetSegments().append(segment); - } - } - - surface->ComputeTangents(); - surface->BuildHull(); - m->GetSurfaces().append(surface); - - *pnverts = nverts; - *pnpolys = npolys; - *pradius = (float) radius; - - result = nverts && npolys; - } - - return result; -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFileMAG.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for MAG format models +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "ModelFileMAG.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +struct MaterialMag6 { + char name[Material::NAMELEN]; + char shader[Material::NAMELEN]; + float power; // highlight sharpness (big=shiny) + float brilliance; // diffuse power function + float bump; // bump level (0=none) + DWORD blend; // alpha blend type + bool shadow; // material casts shadow + bool luminous; // verts have their own lighting + + Color ambient_color; + Color diffuse_color; + Color specular_color; + Color emissive_color; + + float ambient_value; + float diffuse_value; + float specular_value; + float emissive_value; + + BYTE tex_diffuse; + BYTE tex_specular; + BYTE tex_bumpmap; + BYTE tex_emissive; +}; + +// +--------------------------------------------------------------------+ + +ModelFileMAG::ModelFileMAG(const char* fname) + : ModelFile(fname) +{ +} + +ModelFileMAG::~ModelFileMAG() +{ +} + +// +--------------------------------------------------------------------+ + +bool +ModelFileMAG::Load(Model* m, double scale) +{ + if (m && scale > 0 && strlen(filename) > 0) { + ModelFile::Load(m, scale); + + bool result = false; + FILE* fp = fopen(filename, "rb"); + + // check MAG file: + if (!fp) { + ::MessageBox(0, "File Open Failed:\nMagic could not open the requested file.", "ERROR", MB_OK); + return result; + } + + ZeroMemory(pname, 64); + strncpy(pname, filename, 63); + + char file_id[5]; + fread(file_id, 4, 1, fp); + file_id[4] = '\0'; + int version = 1; + + if (!strcmp(file_id, "MAG6")) { + version = 6; + } + else if (!strcmp(file_id, "MAG5")) { + version = 5; + } + else if (!strcmp(file_id, "MAG4")) { + version = 4; + } + else { + ::MessageBox(0, "File Open Failed:\nThe requested file uses an invalid format.", "ERROR", MB_OK); + fclose(fp); + return result; + } + + // get ready to load, delete existing model: + m->GetSurfaces().destroy(); + m->GetMaterials().destroy(); + *pnverts = 0; + *pnpolys = 0; + + // now load the model: + switch (version) { + case 4: + case 5: + result = LoadMag5(fp, m, scale); + break; + + case 6: + result = LoadMag6(fp, m, scale); + break; + + default: + break; + } + + fclose(fp); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +ModelFileMAG::Save(Model* m) +{ + if (m) { + ModelFile::Save(m); + + FILE* fp = fopen(filename, "wb"); + if (!fp) { + ::MessageBox(0, "Save Failed:\nMagic could not open the file for writing.", "ERROR", MB_OK); + return FALSE; + } + + fwrite("MAG6", 4, 1, fp); + + int i = 0; + int ntex = 0; + int nmtls = 0; + int nsurfs = m->NumSurfaces(); + List textures; + + ListIter m_iter = m->GetMaterials(); + while (++m_iter) { + Material* mtl = m_iter.value(); + Bitmap* bmp = mtl->tex_diffuse; + + if (bmp && !textures.contains(bmp)) { + textures.append(bmp); + } + + bmp = mtl->tex_specular; + + if (bmp && !textures.contains(bmp)) { + textures.append(bmp); + } + + bmp = mtl->tex_emissive; + + if (bmp && !textures.contains(bmp)) { + textures.append(bmp); + } + + bmp = mtl->tex_bumpmap; + + if (bmp && !textures.contains(bmp)) { + textures.append(bmp); + } + + nmtls++; + } + + ListIter t_iter = textures; + while (++t_iter) { + Bitmap* bmp = t_iter.value(); + ntex += strlen(bmp->GetFilename()) + 1; + } + + nsurfs = m->GetSurfaces().size(); + + fwrite(&ntex, 4, 1, fp); + fwrite(&nmtls, 4, 1, fp); + fwrite(&nsurfs, 4, 1, fp); + + if (ntex) { + t_iter.reset(); + while (++t_iter) { + Bitmap* bmp = t_iter.value(); + + fwrite(bmp->GetFilename(), + strlen(bmp->GetFilename()) + 1, + 1, + fp); + } + } + + if (nmtls) { + m_iter.reset(); + while (++m_iter) { + Material* mtl = m_iter.value(); + MaterialMag6 m6; + + ZeroMemory(&m6, sizeof(m6)); + + CopyMemory(m6.name, mtl->name, Material::NAMELEN); + CopyMemory(m6.shader, mtl->shader, Material::NAMELEN); + + m6.ambient_value = mtl->ambient_value; + m6.ambient_color = mtl->ambient_color; + m6.diffuse_value = mtl->diffuse_value; + m6.diffuse_color = mtl->diffuse_color; + m6.specular_value = mtl->specular_value; + m6.specular_color = mtl->specular_color; + m6.emissive_value = mtl->emissive_value; + m6.emissive_color = mtl->emissive_color; + + m6.power = mtl->power; + m6.brilliance = mtl->brilliance; + m6.bump = mtl->bump; + m6.blend = mtl->blend; + m6.shadow = mtl->shadow; + m6.luminous = mtl->luminous; + + if (mtl->tex_diffuse) + m6.tex_diffuse = textures.index(mtl->tex_diffuse) + 1; + + if (mtl->tex_specular) + m6.tex_specular = textures.index(mtl->tex_specular) + 1; + + if (mtl->tex_emissive) + m6.tex_emissive = textures.index(mtl->tex_emissive) + 1; + + if (mtl->tex_bumpmap) + m6.tex_bumpmap = textures.index(mtl->tex_bumpmap) + 1; + + fwrite(&m6, sizeof(m6), 1, fp); + } + } + + ListIter s_iter = m->GetSurfaces(); + while (++s_iter) { + Surface* s = s_iter.value(); + + int nverts = s->NumVerts(); + int npolys = s->NumPolys(); + BYTE namelen = strlen(s->Name()) + 1; + + fwrite(&nverts, 4, 1, fp); + fwrite(&npolys, 4, 1, fp); + fwrite(&namelen, 1, 1, fp); + fwrite(s->Name(), 1, namelen, fp); + + VertexSet* vset = s->GetVertexSet(); + Poly* polys = s->GetPolys(); + + // write vertex set: + for (int v = 0; v < nverts; v++) { + fwrite(&vset->loc[v], sizeof(float), 3, fp); + fwrite(&vset->nrm[v], sizeof(float), 3, fp); + fwrite(&vset->tu[v], sizeof(float), 1, fp); + fwrite(&vset->tv[v], sizeof(float), 1, fp); + } + + // write polys: + for (int n = 0; n < npolys; n++) { + Poly& poly = polys[n]; + BYTE poly_nverts = (BYTE) poly.nverts; + BYTE material_index = 0; + WORD poly_verts[8]; + + m_iter.reset(); + while (++m_iter && !material_index) { + if (poly.material == m_iter.value()) + material_index = m_iter.index() + 1; + } + + for (int i = 0; i < poly_nverts; i++) { + poly_verts[i] = poly.verts[i]; + } + + fwrite(&poly_nverts, sizeof(BYTE), 1, fp); + fwrite(&material_index, sizeof(BYTE), 1, fp); + fwrite(&poly_verts[0], sizeof(WORD), poly_nverts, fp); + } + } + + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +struct HomogenousPlane +{ + double distance; + double normal_x; + double normal_y; + double normal_z; + double normal_w; +}; + +static void LoadPlane(Plane& p, FILE* fp) +{ + HomogenousPlane tmp; + fread(&tmp, sizeof(HomogenousPlane), 1, fp); +} + +static void LoadFlags(LPDWORD flags, FILE* fp) +{ + DWORD magic_flags; + fread(&magic_flags, sizeof(DWORD), 1, fp); + + /** MAGIC FLAGS + enum { FLAT_SHADED = 1, + LUMINOUS = 2, + TRANSLUCENT = 4, \\ must swap + CHROMAKEY = 8, // these two + FOREGROUND = 16, -- not used + WIREFRAME = 32, -- not used + SPECULAR1 = 64, + SPECULAR2 = 128 }; + ***/ + + const DWORD magic_mask = 0x0fc3; + + *flags = magic_flags & magic_mask; +} + +// +--------------------------------------------------------------------+ + +static int mcomp(const void* a, const void* b) +{ + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; + + if (pa->sortval == pb->sortval) + return 0; + + if (pa->sortval < pb->sortval) + return -1; + + return 1; +} + +bool +ModelFileMAG::LoadMag5(FILE* fp, Model* m, double scale) +{ + bool result = false; + int ntex = 0; + int nsurfs = 0; + double radius = 0; + + fread(&ntex, sizeof(ntex), 1, fp); + fread(&nsurfs, sizeof(nsurfs), 1, fp); + + // create a default gray material: + Material* mtl = new Material; + + if (mtl) { + mtl->Ka = Color::DarkGray; + mtl->Kd = Color::LightGray; + mtl->Ks = ColorValue(0.1f,0.1f,0.1f); + mtl->power = 10.0f; + + mtl->ambient_value = 0.2f; + mtl->ambient_color = Color::DarkGray; + mtl->diffuse_value = 0.8f; + mtl->diffuse_color = Color::LightGray; + mtl->specular_value = 0.5f; + mtl->specular_color = Color::White; + strcpy_s(mtl->name, "(default)"); + + m->GetMaterials().append(mtl); + } + + // read texture list: + for (int i = 0; i < ntex; i++) { + Material* mtl = new Material; + char tname[32]; + + if (mtl) { + mtl->Ka = ColorValue(0.5f,0.5f,0.5f); + mtl->Kd = ColorValue(1.0f,1.0f,1.0f); + mtl->Ks = ColorValue(0.2f,0.2f,0.2f); + mtl->power = 20.0f; + + mtl->ambient_value = 1.0f; + mtl->ambient_color = Color::Gray; + mtl->diffuse_value = 1.0f; + mtl->diffuse_color = Color::White; + mtl->specular_value = 0.2f; + mtl->specular_color = Color::White; + + fread(tname, 32, 1, fp); + LoadTexture(tname, mtl->tex_diffuse, Bitmap::BMP_SOLID); + strcpy_s(mtl->name, tname); + + char* dot = strrchr(mtl->name, '.'); + if (dot) + *dot = 0; + + char* plus = strrchr(mtl->name, '+'); + if (plus) + *plus = 0; + + m->GetMaterials().append(mtl); + } + } + + int nverts = 0; + int npolys = 0; + + fread(&nverts, 4, 1, fp); + fread(&npolys, 4, 1, fp); + + // plan on creating four verts per poly: + int mag_nverts = nverts; + int next_vert = nverts; + + nverts = npolys * 4; + Surface* s = new Surface; + VertexSet* vset = 0; + Poly* polys = 0; + + if (s) { + s->SetName("default"); + s->CreateVerts(nverts); + s->CreatePolys(npolys); + + vset = s->GetVertexSet(); + polys = s->GetPolys(); + + ZeroMemory(vset->loc, nverts * sizeof(Vec3)); + ZeroMemory(vset->diffuse, nverts * sizeof(DWORD)); + ZeroMemory(vset->specular, nverts * sizeof(DWORD)); + ZeroMemory(vset->tu, nverts * sizeof(float)); + ZeroMemory(vset->tv, nverts * sizeof(float)); + ZeroMemory(vset->rw, nverts * sizeof(float)); + + // read vertex set: + int v; + for (v = 0; v < mag_nverts; v++) { + Vec3 vert, norm; + DWORD vstate; + + fread(&vert, sizeof(Vec3), 1, fp); + fread(&norm, sizeof(Vec3), 1, fp); + fread(&vstate, sizeof(DWORD), 1, fp); + + vert.SwapYZ(); + vert *= (float) scale; + + norm.SwapYZ(); + + vset->loc[v] = vert; + vset->nrm[v] = norm; + + double d = vert.length(); + if (d > radius) + radius = (float) d; + } + + while (v < nverts) + vset->nrm[v++] = Vec3(1,0,0); + + // read polys: + Vec3 dummy_center; + DWORD dummy_flags; + DWORD dummy_color; + int texture_num; + int poly_nverts; + int vert_index_buffer[32]; + float texture_index_buffer[32]; + + for (int n = 0; n < npolys; n++) { + Poly& poly = polys[n]; + poly.vertex_set = vset; + + fread(&dummy_flags, sizeof(DWORD), 1, fp); + fread(&dummy_center, sizeof(Vec3), 1, fp); + LoadPlane(poly.plane, fp); + fread(&dummy_color, sizeof(DWORD), 1, fp); + fread(&texture_num, sizeof(int), 1, fp); + + if (texture_num >= 0 && texture_num < ntex) { + texture_num++; + + poly.material = m->GetMaterials()[texture_num]; + poly.sortval = texture_num; + + if (dummy_flags & 2) { // luminous + Material* mtl = m->GetMaterials()[texture_num]; + + mtl->ambient_value = 0.0f; + mtl->ambient_color = Color::Black; + mtl->diffuse_value = 0.0f; + mtl->diffuse_color = Color::Black; + mtl->specular_value = 0.0f; + mtl->specular_color = Color::Black; + mtl->emissive_value = 1.0f; + mtl->emissive_color = Color::White; + + mtl->Ka = ColorValue(0,0,0,0); + mtl->Kd = ColorValue(0,0,0,0); + mtl->Ks = ColorValue(0,0,0,0); + mtl->Ke = ColorValue(1,1,1,1); + + mtl->tex_emissive = mtl->tex_diffuse; + } + } + else { + poly.material = m->GetMaterials().first(); // default material + poly.sortval = 1000; + } + + // hack: store flat shaded flag in unused visible byte + poly.visible = (BYTE) (dummy_flags & 1); + + fread(&poly_nverts, sizeof(int), 1, fp); + fread(vert_index_buffer, sizeof(int), poly_nverts, fp); + + if (poly_nverts == 3) + s->AddIndices(3); + + else if (poly_nverts == 4) + s->AddIndices(6); + + poly.nverts = poly_nverts; + for (int vi = 0; vi < poly_nverts; vi++) { + int v = vert_index_buffer[vi]; + + if (vset->rw[v] > 0) { + vset->CopyVertex(next_vert, v); + v = next_vert++; + } + + vset->rw[v] = 1; + poly.verts[vi] = v; + } + + fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tu's + for (int vi = 0; vi < poly_nverts; vi++) { + int v = poly.verts[vi]; + vset->tu[v] = texture_index_buffer[vi]; + } + + fread(texture_index_buffer, sizeof(float), poly_nverts, fp); // tv's + for (int vi = 0; vi < poly_nverts; vi++) { + int v = poly.verts[vi]; + vset->tv[v] = texture_index_buffer[vi]; + } + + DWORD unused[32]; + fread(unused, 16, 1, fp); + } + + // pass 2 (adjust vertex normals for flat polys): + for (int n = 0; n < npolys; n++) { + Poly& poly = polys[n]; + + poly.plane = Plane(vset->loc[poly.verts[0]], + vset->loc[poly.verts[2]], + vset->loc[poly.verts[1]]); + + // hack: retrieve flat shaded flag from unused visible byte + if (poly.visible) { + int poly_nverts = poly.nverts; + + for (int vi = 0; vi < poly_nverts; vi++) { + int v = poly.verts[vi]; + vset->nrm[v] = poly.plane.normal; + } + } + } + + // sort the polys by material index: + qsort((void*) polys, npolys, sizeof(Poly), mcomp); + + // then assign them to cohesive segments: + Segment* segment = 0; + + for (int n = 0; n < npolys; n++) { + if (segment && segment->material == polys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new Segment; + + segment->npolys = 1; + segment->polys = &polys[n]; + segment->material = segment->polys->material; + + s->GetSegments().append(segment); + } + } + + s->BuildHull(); + m->GetSurfaces().append(s); + + *pnverts = nverts; + *pnpolys = npolys; + *pradius = (float) radius; + + result = nverts && npolys; + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +ModelFileMAG::LoadMag6(FILE* fp, Model* m, double scale) +{ + bool result = false; + int i = 0; + int ntex = 0; + int nmtls = 0; + int nsurfs = 0; + double radius = 0; + List textures; + + fread(&ntex, sizeof(ntex), 1, fp); // size of texture block + fread(&nmtls, sizeof(nmtls), 1, fp); // number of materials + fread(&nsurfs, sizeof(nsurfs), 1, fp); // number of surfaces + + // read texture list: + if (ntex) { + char* buffer = new char[ntex]; + char* p = buffer; + Bitmap* bmp = 0; + + fread(buffer, ntex, 1, fp); + + while (p < buffer + ntex) { + LoadTexture(p, bmp, Bitmap::BMP_SOLID); + textures.append(bmp); + + p += strlen(p) + 1; + } + + delete [] buffer; + } + + for (i = 0; i < nmtls; i++) { + MaterialMag6 m6; + Material* mtl = new Material; + + fread(&m6, sizeof(m6), 1, fp); + + if (mtl) { + CopyMemory(mtl->name, m6.name, Material::NAMELEN); + CopyMemory(mtl->shader, m6.shader, Material::NAMELEN); + + mtl->ambient_value = m6.ambient_value; + mtl->ambient_color = m6.ambient_color; + mtl->diffuse_value = m6.diffuse_value; + mtl->diffuse_color = m6.diffuse_color; + mtl->specular_value = m6.specular_value; + mtl->specular_color = m6.specular_color; + mtl->emissive_value = m6.emissive_value; + mtl->emissive_color = m6.emissive_color; + + mtl->Ka = ColorValue(mtl->ambient_color) * mtl->ambient_value; + mtl->Kd = ColorValue(mtl->diffuse_color) * mtl->diffuse_value; + mtl->Ks = ColorValue(mtl->specular_color) * mtl->specular_value; + mtl->Ke = ColorValue(mtl->emissive_color) * mtl->emissive_value; + + mtl->power = m6.power; + mtl->brilliance = m6.brilliance; + mtl->bump = m6.bump; + mtl->blend = m6.blend; + mtl->shadow = m6.shadow; + mtl->luminous = m6.luminous; + + if (m6.tex_diffuse && m6.tex_diffuse <= textures.size()) + mtl->tex_diffuse = textures[m6.tex_diffuse - 1]; + + if (m6.tex_specular && m6.tex_specular <= textures.size()) + mtl->tex_specular = textures[m6.tex_specular - 1]; + + if (m6.tex_emissive && m6.tex_emissive <= textures.size()) + mtl->tex_emissive = textures[m6.tex_emissive - 1]; + + if (m6.tex_bumpmap && m6.tex_bumpmap <= textures.size()) + mtl->tex_bumpmap = textures[m6.tex_bumpmap - 1]; + + m->GetMaterials().append(mtl); + } + } + + for (i = 0; i < nsurfs; i++) { + int nverts = 0; + int npolys = 0; + BYTE namelen = 0; + char name[128]; + + fread(&nverts, 4, 1, fp); + fread(&npolys, 4, 1, fp); + fread(&namelen, 1, 1, fp); + fread(name, 1, namelen, fp); + + Surface* surface = new Surface; + surface->SetName(name); + surface->CreateVerts(nverts); + surface->CreatePolys(npolys); + + VertexSet* vset = surface->GetVertexSet(); + Poly* polys = surface->GetPolys(); + + ZeroMemory(polys, sizeof(Poly) * npolys); + + // read vertex set: + for (int v = 0; v < nverts; v++) { + fread(&vset->loc[v], sizeof(float), 3, fp); + fread(&vset->nrm[v], sizeof(float), 3, fp); + fread(&vset->tu[v], sizeof(float), 1, fp); + fread(&vset->tv[v], sizeof(float), 1, fp); + + double d = vset->loc[v].length(); + if (d > radius) + radius = d; + } + + // read polys: + for (int n = 0; n < npolys; n++) { + Poly& poly = polys[n]; + BYTE poly_nverts = 0; + BYTE material_index = 0; + WORD poly_verts[8]; + + fread(&poly_nverts, sizeof(BYTE), 1, fp); + fread(&material_index, sizeof(BYTE), 1, fp); + fread(&poly_verts[0], sizeof(WORD), poly_nverts, fp); + + if (poly_nverts >= 3) { + poly.nverts = poly_nverts; + + for (int i = 0; i < poly_nverts; i++) { + poly.verts[i] = poly_verts[i]; + } + } + else { + poly.sortval = 666; + } + + if (material_index > 0) { + poly.material = m->GetMaterials()[material_index-1]; + poly.sortval = material_index; + } + else if (m->NumMaterials()) { + poly.material = m->GetMaterials().first(); + poly.sortval = 1; + } + else { + poly.sortval = 1000; + } + + if (poly.nverts == 3) + surface->AddIndices(3); + + else if (poly.nverts == 4) + surface->AddIndices(6); + + poly.vertex_set = vset; + poly.plane = Plane(vset->loc[poly.verts[0]], + vset->loc[poly.verts[2]], + vset->loc[poly.verts[1]]); + } + + // sort the polys by material index: + qsort((void*) polys, npolys, sizeof(Poly), mcomp); + + // then assign them to cohesive segments: + Segment* segment = 0; + + for (int n = 0; n < npolys; n++) { + if (segment && segment->material == polys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new Segment; + + segment->npolys = 1; + segment->polys = &polys[n]; + segment->material = segment->polys->material; + + surface->GetSegments().append(segment); + } + } + + surface->ComputeTangents(); + surface->BuildHull(); + m->GetSurfaces().append(surface); + + *pnverts = nverts; + *pnpolys = npolys; + *pradius = (float) radius; + + result = nverts && npolys; + } + + return result; +} + diff --git a/Magic2/ModelFileMAG.h b/Magic2/ModelFileMAG.h index cf3d6de..e693e71 100644 --- a/Magic2/ModelFileMAG.h +++ b/Magic2/ModelFileMAG.h @@ -1,39 +1,63 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFileMAG.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for MAG format models -*/ - -#ifndef ModelFileMAG_h -#define ModelFileMAG_h - -#include "Solid.h" - -// +--------------------------------------------------------------------+ - -class ModelFileMAG : public ModelFile -{ -public: - ModelFileMAG(const char* fname); - virtual ~ModelFileMAG(); - - virtual bool Load(Model* m, double scale=1.0); - virtual bool Save(Model* m); - -protected: - virtual bool LoadMag5(FILE* fp, Model* m, double scale); - virtual bool LoadMag6(FILE* fp, Model* m, double scale); -}; - -// +--------------------------------------------------------------------+ - -#endif ModelFileMAG_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFileMAG.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for MAG format models +*/ + +#ifndef ModelFileMAG_h +#define ModelFileMAG_h + +#include "Solid.h" + +// +--------------------------------------------------------------------+ + +class ModelFileMAG : public ModelFile +{ +public: + ModelFileMAG(const char* fname); + virtual ~ModelFileMAG(); + + virtual bool Load(Model* m, double scale=1.0); + virtual bool Save(Model* m); + +protected: + virtual bool LoadMag5(FILE* fp, Model* m, double scale); + virtual bool LoadMag6(FILE* fp, Model* m, double scale); +}; + +// +--------------------------------------------------------------------+ + +#endif ModelFileMAG_h + diff --git a/Magic2/ModelFileOBJ.cpp b/Magic2/ModelFileOBJ.cpp index e3e35de..f27a2bd 100644 --- a/Magic2/ModelFileOBJ.cpp +++ b/Magic2/ModelFileOBJ.cpp @@ -1,790 +1,814 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFileOBJ.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for Wavefront/OBJ format models -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "ModelFileOBJ.h" - -#include "Bitmap.h" -#include "Polygon.h" -#include "List.h" -#include "Text.h" - -// +--------------------------------------------------------------------+ - -ModelFileOBJ::ModelFileOBJ(const char* fname) - : ModelFile(fname) -{ -} - -ModelFileOBJ::~ModelFileOBJ() -{ -} - -// +--------------------------------------------------------------------+ - -const int MAX_OBJ_FACE_VERTS = 32; - -struct ObjFace { - int v[MAX_OBJ_FACE_VERTS]; - int n[MAX_OBJ_FACE_VERTS]; - int t[MAX_OBJ_FACE_VERTS]; - - int nverts; - - ObjFace() { - nverts = 0; - - for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) - v[i] = n[i] = t[i] = 0; - } - - ObjFace(const ObjFace& f) { - nverts = f.nverts; - - for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) { - v[i] = f.v[i]; - n[i] = f.n[i]; - t[i] = f.t[i]; - } - } - - void ReverseOrder() { - int i, tmp[MAX_OBJ_FACE_VERTS]; - - for (i = 0; i < nverts; i++) tmp[i] = v[i]; - for (i = 0; i < nverts; i++) v[i] = tmp[nverts-1-i]; - - for (i = 0; i < nverts; i++) tmp[i] = n[i]; - for (i = 0; i < nverts; i++) n[i] = tmp[nverts-1-i]; - - for (i = 0; i < nverts; i++) tmp[i] = t[i]; - for (i = 0; i < nverts; i++) t[i] = tmp[nverts-1-i]; - } -}; - -static void ParsePoly(const char* line, ObjFace* face) -{ - int v[MAX_OBJ_FACE_VERTS]; - int n[MAX_OBJ_FACE_VERTS]; - int t[MAX_OBJ_FACE_VERTS]; - - for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) { - v[i] = n[i] = t[i] = 0; - } - - const char* p = line + 1; - - while (isspace(*p)) - p++; - - int i = 0; - while (*p && i < MAX_OBJ_FACE_VERTS) { - int factor = 1; - - if (*p == '-') { - factor = -1; - p++; - } - - while (isdigit(*p)) { - v[i] = v[i]*10 + *p - '0'; - p++; - } - v[i] *= factor; - - if (*p == '/') { p++; // slash one - - factor = 1; - - if (*p == '-') { - factor = -1; - p++; - } - - while (isdigit(*p)) { - t[i] = t[i]*10 + *p - '0'; - p++; - } - t[i] *= factor; - - if (*p == '/') { p++; // slash two - - factor = 1; - - if (*p == '-') { - factor = -1; - p++; - } - - while (isdigit(*p)) { - n[i] = n[i]*10 + *p - '0'; - p++; - } - n[i] *= factor; - }} - - while (isspace(*p)) p++; - i++; - } - - face->nverts = i; - - for (i = 0; i < MAX_OBJ_FACE_VERTS; i++) { - face->v[i] = v[i]; - face->n[i] = n[i]; - face->t[i] = t[i]; - } -} - -static int LoadMatls(const char* lpszPathName, Model* m) -{ - int nmatls = 0; - - FILE* fp = fopen(lpszPathName, "r"); - if (!fp) { - ::MessageBox(0, "Open Failed: could not open file", "ERROR", MB_OK); - return 0; - } - - Material* mtl = 0; - - while (!feof(fp)) { - char raw_line[512]; - char line[512]; - fgets(raw_line, 512, fp); - - strcpy(line, Text(raw_line).trim().data()); - - if (strstr(line, "newmtl")) { - mtl = new Material; - strncpy(mtl->name, line+7, Material::NAMELEN - 1); - - m->GetMaterials().append(mtl); - } - - else if (line[0] == 'K' && line[1] == 'a') { - float r,g,b; - sscanf(line, "Ka %f %f %f", &r, &g, &b); - mtl->Ka = ColorValue(r,g,b); - - mtl->ambient_value = 1.0f; - mtl->ambient_color = mtl->Ka.ToColor(); - } - - else if (line[0] == 'K' && line[1] == 'd') { - float r,g,b; - sscanf(line, "Kd %f %f %f", &r, &g, &b); - mtl->Kd = ColorValue(r,g,b); - - mtl->diffuse_value = 1.0f; - mtl->diffuse_color = mtl->Kd.ToColor(); - } - - else if (line[0] == 'K' && line[1] == 's') { - float r,g,b; - sscanf(line, "Ks %f %f %f", &r, &g, &b); - mtl->Ks = ColorValue(r,g,b); - - mtl->specular_value = 1.0f; - mtl->specular_color = mtl->Ks.ToColor(); - } - - else if (line[0] == 'N' && line[1] == 's') { - float ns; - sscanf(line, "Ns %f", &ns); - mtl->power = ns; - } - - else if (strstr(line, "map_Kd")) { - const char* src = strstr(line, "map_Kd") + 7; - while (!isalnum(*src)) src++; - - LoadTexture(src, mtl->tex_diffuse, Bitmap::BMP_SOLID); - } - } - - fclose(fp); - return nmatls; -} - -static Material* FindMatl(const char* mtl_name, Model* model) -{ - ListIter iter = model->GetMaterials(); - while (++iter) { - Material* m = iter.value(); - if (!strcmp(m->name, mtl_name)) - return m; - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -static int mcomp(const void* a, const void* b) -{ - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; - - if (pa->sortval == pb->sortval) - return 0; - - if (pa->sortval < pb->sortval) - return 1; - - return -1; -} - -bool -ModelFileOBJ::Load(Model* m, double scale) -{ - if (m && scale > 0 && strlen(filename) > 0) { - ModelFile::Load(m, scale); - - FILE* fp = fopen(filename, "rb"); - - if (fp == NULL) { - ::MessageBox(0, "Wavefront/OBJ Import Failed: Unable to open file", "ERROR", MB_OK); - return false; - } - - // ok, now start reading the data: - int ntex = 0; - int nverts = 0; - int npv = 0; - int npolys = 0; - int vi = 0; - int vn = 0; - int vt = 0; - - char root_path[256]; - ZeroMemory(root_path, 256); - - if (strrchr(filename, '\\')) { - strcpy(root_path, filename); - char* p = strrchr(root_path, '\\'); - if (p) - *(p+1) = 0; - } - - else if (strrchr(filename, '/')) { - strcpy(root_path, filename); - char* p = strrchr(root_path, '/'); - if (p) - *(p+1) = 0; - } - - // count verts and polys: - while (!feof(fp)) { - char line[256]; - fgets(line, 255, fp); - - if (line[0] == 'v') { - switch (line[1]) { - case ' ': vi++; break; - case 'n': vn++; break; - case 't': vt++; break; - } - } - - else if (line[0] == 'f' && line[1] == ' ') { - npolys++; - - ObjFace f; - ParsePoly(line, &f); - f.ReverseOrder(); - - npv += f.nverts; - } - - else if (strstr(line, "mtllib")) { - const char* libname = strstr(line, "mtllib"); - libname += 7; - while (isspace(*libname)) - libname++; - - char libpath[256]; - strcpy(libpath, root_path); - strcat(libpath, libname); - int n = strlen(libpath); - if (n > 0) { - char* p = &libpath[n-1]; - while (isspace(*p)) *p-- = 0; - } - - int nmatls = LoadMatls(libpath, model); - } - } - - nverts = npv; - if (vi > nverts) nverts = vi; - if (vn > nverts) nverts = vn; - if (vt > nverts) nverts = vt; - - if (nverts > Model::MAX_VERTS || npolys > Model::MAX_POLYS) { - ::MessageBox(0, "Wavefront/OBJ Import Failed: that model is just too darn complicated!", "ERROR", MB_OK); - return false; - } - - vi = 0; - vn = 0; - vt = 0; - - fseek(fp, 0, SEEK_SET); - - Surface* surface = new Surface; - m->GetSurfaces().append(surface); - - surface->CreateVerts(nverts); - surface->CreatePolys(npolys); - - VertexSet* vset = surface->GetVertexSet(); - Poly* polys = surface->GetPolys(); - - // read vertex set: - Vec3* vloc = new Vec3[nverts]; - Vec3* vnrm = new Vec3[nverts]; - float* vtu = new float[nverts]; - float* vtv = new float[nverts]; - - float radius = 0; - - while (!feof(fp)) { - char line[256]; - fgets(line, 255, fp); - - if (line[0] == 'v') { - if (line[1] == ' ') { - const char* p = line + 2; - - while (isspace(*p)) p++; - sscanf(p, "%f", &vloc[vi].x); - - while (!isspace(*p)) p++; - while (isspace(*p)) p++; - sscanf(p, "%f", &vloc[vi].y); - - while (!isspace(*p)) p++; - while (isspace(*p)) p++; - sscanf(p, "%f", &vloc[vi].z); - - float d = vloc[vi].length(); - if (d > radius) - radius = d; - - vi++; - } - - else if (line[1] == 'n') { - const char* p = line + 2; - - while (isspace(*p)) p++; - sscanf(p, "%f", &vnrm[vn].x); - - while (!isspace(*p)) p++; - while (isspace(*p)) p++; - sscanf(p, "%f", &vnrm[vn].y); - - while (!isspace(*p)) p++; - while (isspace(*p)) p++; - sscanf(p, "%f", &vnrm[vn].z); - - vn++; - } - - else if (line[1] == 't') { - const char* p = line + 2; - - while (isspace(*p)) p++; - sscanf(p, "%f", &vtu[vt]); - - while (!isspace(*p)) p++; - while (isspace(*p)) p++; - sscanf(p, "%f", &vtv[vt]); - - vtv[vt] = 1.0f - vtv[vt]; - - vt++; - } - } - } - - fseek(fp, 0, SEEK_SET); - - // read polys: - int poly = 0; - char line[256]; - ObjFace face; - Material* material = 0; - int mtl_index = 0; - - if (m->NumMaterials()) - material = m->GetMaterials().first(); - - int current_v = 1; - int current_vn = 1; - int current_vt = 1; - int v = 0; // vset index pointer - - while (!feof(fp)) { - char raw_line[256]; - fgets(raw_line, 256, fp); - - strcpy(line, Text(raw_line).trim().data()); - - if (strstr(line, "usemtl")) { - material = FindMatl(line + 7, model); - ListIter iter = model->GetMaterials(); - while (++iter) - if (material == iter.value()) - mtl_index = iter.index(); - } - - else if (line[0] == 'v') { - if (line[1] == ' ') current_v++; - else if (line[1] == 'n') current_vn++; - else if (line[1] == 't') current_vt++; - } - - else if (line[0] == 'f') { - ParsePoly(line, &face); - face.ReverseOrder(); - - for (int n = 0; n < face.nverts; n++) { - if (face.v[n] < 0) - face.v[n] += current_v; - - if (face.n[n] < 0) - face.n[n] += current_vn; - - if (face.t[n] < 0) - face.t[n] += current_vt; - } - - if (face.nverts > 4) { - npolys += face.nverts - 3; - - for (int tri = 2; tri < face.nverts; tri++) { - Poly* p = polys + poly; - poly++; - - p->nverts = 3; - - vset->loc[v+0] = vloc[face.v[ tri ] -1]; - vset->loc[v+1] = vloc[face.v[ tri-1 ] -1]; - vset->loc[v+2] = vloc[face.v[ 0] -1]; - - if (face.n[0] > 0) { - vset->nrm[v+0] = vnrm[face.n[ tri ] -1]; - vset->nrm[v+1] = vnrm[face.n[ tri-1 ] -1]; - vset->nrm[v+2] = vnrm[face.n[ 0] -1]; - } - else { - vset->nrm[v+0] = vloc[v+0]; vset->nrm[v+0].Normalize(); - vset->nrm[v+1] = vloc[v+1]; vset->nrm[v+1].Normalize(); - vset->nrm[v+2] = vloc[v+2]; vset->nrm[v+2].Normalize(); - } - - if (face.t[0] > 0) { - vset->tu[v+0] = vtu[face.t[ tri ] -1]; - vset->tv[v+0] = vtv[face.t[ tri ] -1]; - vset->tu[v+1] = vtu[face.t[ tri-1 ] -1]; - vset->tv[v+1] = vtv[face.t[ tri-1 ] -1]; - vset->tu[v+2] = vtu[face.t[ 0 ] -1]; - vset->tv[v+2] = vtv[face.t[ 0 ] -1]; - } - - p->verts[0] = v+0; - p->verts[1] = v+1; - p->verts[2] = v+2; - - p->material = material; - p->sortval = mtl_index; - p->vertex_set = vset; - - p->plane = Plane(vset->loc[p->verts[0]], - vset->loc[p->verts[2]], - vset->loc[p->verts[1]]); - - v += p->nverts; - } - } - - else if (face.nverts == 3 || face.nverts == 4) { - Poly* p = polys + poly; - poly++; - - p->nverts = face.nverts; - - bool flat = true; - int first = v; - - for (int i = 0; i < p->nverts; i++) { - int face_index = i; - - vset->loc[v] = vloc[face.v[face_index]-1]; - - if (face.n[face_index] > 0) - vset->nrm[v] = vnrm[face.n[face_index]-1]; - else - vset->nrm[v] = vset->loc[v]; - - vset->nrm[v].Normalize(); - - if (vset->nrm[v] != vset->nrm[first]) - flat = false; - - if (face.t[face_index] > 0) { - vset->tu[v] = vtu [face.t[face_index]-1]; - vset->tv[v] = vtv [face.t[face_index]-1]; - } - - p->verts[i] = v++; - } - - p->material = material; - p->sortval = mtl_index; - p->flatness = flat ? 1.0f : 0.0f; - - if (p->nverts == 3) - surface->AddIndices(3); - - else if (p->nverts == 4) - surface->AddIndices(6); - - p->vertex_set = vset; - p->plane = Plane(vset->loc[p->verts[0]], - vset->loc[p->verts[2]], - vset->loc[p->verts[1]]); - } - - if (poly >= npolys) - break; - } - } - - // sort the polys by material index: - qsort((void*) polys, npolys, sizeof(Poly), mcomp); - - // then assign them to cohesive segments: - Segment* segment = 0; - - for (int n = 0; n < npolys; n++) { - if (segment && segment->material == polys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new Segment; - - segment->npolys = 1; - segment->polys = &polys[n]; - segment->material = segment->polys->material; - - surface->GetSegments().append(segment); - } - } - - delete [] vloc; - delete [] vnrm; - delete [] vtu; - delete [] vtv; - - *pnverts = nverts; - *pnpolys = npolys; - *pradius = radius; - - fclose(fp); - - m->Normalize(); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -static bool -SaveWaveFrontMatLib(const char* path, const char* root, Model* model) -{ - char filename[256]; - sprintf(filename, "%s%s.mtl", path, root); - - FILE* f = fopen(filename, "w"); - if (f) { - fprintf(f, "#\n# %s Material Library exported by Magic 2.0\n#\n\n", root); - - ListIter iter = model->GetMaterials(); - while (++iter) { - Material* mtl = iter.value(); - - fprintf(f, "newmtl %s\n", mtl->name); - fprintf(f, "Ka %.5f %.5f %.5f\n", mtl->Ka.Red(), mtl->Ka.Green(), mtl->Ka.Blue()); - fprintf(f, "Kd %.5f %.5f %.5f\n", mtl->Kd.Red(), mtl->Kd.Green(), mtl->Kd.Blue()); - fprintf(f, "Ks %.5f %.5f %.5f\n", mtl->Ks.Red(), mtl->Ks.Green(), mtl->Ks.Blue()); - fprintf(f, "Ns %.5f\n", mtl->power); - fprintf(f, "illum 2\n"); - if (mtl->tex_diffuse) - fprintf(f, "map_Kd %s\n", mtl->tex_diffuse->GetFilename()); - fprintf(f, "\n"); - } - - fclose(f); - return true; - } - - return false; -} - -bool -ModelFileOBJ::Save(Model* m) -{ - if (m) { - ModelFile::Save(m); - char pathname[256]; - char rootname[256]; - - ZeroMemory(pathname, sizeof(pathname)); - ZeroMemory(rootname, sizeof(rootname)); - - const char* ext = strstr(filename, ".obj"); - if (!ext) - ext = strstr(filename, ".OBJ"); - - const char* sep = strrchr(filename, '/'); - if (!sep) - sep = strrchr(filename, '\\'); - - const char* src = filename; - char* dst = pathname; - - if (sep) { - while (src != sep) - *dst++ = *src++; - *dst++ = *src++; - } - - if (ext) { - dst = rootname; - while (src != ext) - *dst++ = *src++; - } - else { - strcpy(rootname, src); - } - - strcpy(filename, pathname); - strcat(filename, rootname); - strcat(filename, ".obj"); - - FILE* f = fopen(filename, "w"); - if (!f) { - ::MessageBox(0, "Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); - return false; - } - - fprintf(f, "# Wavefront OBJ exported by Magic 2.0\n\n"); - fprintf(f, "mtllib %s.mtl\n", rootname); - - ListIter s_iter = m->GetSurfaces(); - - // vertex locations - fprintf(f, "\n# VERTEX LOCATIONS: %d\n", m->NumVerts()); - while (++s_iter) { - Surface* s = s_iter.value(); - VertexSet* vset = s->GetVertexSet(); - - for (int n = 0; n < vset->nverts; n++) { - fprintf(f, "v %12.5f %12.5f %12.5f\n", - vset->loc[n].x, - vset->loc[n].y, - vset->loc[n].z); - } - } - - s_iter.reset(); - - // vertex normals - fprintf(f, "\n# VERTEX NORMALS: %d\n", m->NumVerts()); - while (++s_iter) { - Surface* s = s_iter.value(); - VertexSet* vset = s->GetVertexSet(); - - for (int n = 0; n < vset->nverts; n++) { - fprintf(f, "vn %8.3f %8.3f %8.3f\n", - vset->nrm[n].x, - vset->nrm[n].y, - vset->nrm[n].z); - } - } - - s_iter.reset(); - - // texture coordinates - fprintf(f, "\n# TEXTURE COORDINATES: %d\n", m->NumVerts()); - while (++s_iter) { - Surface* s = s_iter.value(); - VertexSet* vset = s->GetVertexSet(); - - for (int n = 0; n < vset->nverts; n++) { - fprintf(f, "vt %8.3f %8.3f\n", - vset->tu[n], 1 - vset->tv[n]); - } - } - - s_iter.reset(); - - // faces - Material* current_material = 0; - - fprintf(f, "\n# FACES: %d\n", m->NumPolys()); - while (++s_iter) { - Surface* s = s_iter.value(); - - for (int n = 0; n < s->NumPolys(); n++) { - const Poly* p = s->GetPolys() + n; - int nv = p->nverts; - Material* mtl = p->material; - - if (current_material != mtl) { - fprintf(f, "\n\nusemtl %s\n", mtl->name); - current_material = mtl; - } - - fprintf(f, "\nf "); - for (int v = nv-1; v >= 0; v--) { - fprintf(f, "%d/%d/%d ", - p->verts[v] + 1, - p->verts[v] + 1, - p->verts[v] + 1); - } - } - } - - fprintf(f, "\n\n\n# END OF FILE.\n"); - fclose(f); - - return SaveWaveFrontMatLib(pathname, rootname, m); - } - - return false; -} - -// +--------------------------------------------------------------------+ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFileOBJ.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for Wavefront/OBJ format models +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "ModelFileOBJ.h" + +#include "Bitmap.h" +#include "Polygon.h" +#include "List.h" +#include "Text.h" + +// +--------------------------------------------------------------------+ + +ModelFileOBJ::ModelFileOBJ(const char* fname) + : ModelFile(fname) +{ +} + +ModelFileOBJ::~ModelFileOBJ() +{ +} + +// +--------------------------------------------------------------------+ + +const int MAX_OBJ_FACE_VERTS = 32; + +struct ObjFace { + int v[MAX_OBJ_FACE_VERTS]; + int n[MAX_OBJ_FACE_VERTS]; + int t[MAX_OBJ_FACE_VERTS]; + + int nverts; + + ObjFace() { + nverts = 0; + + for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) + v[i] = n[i] = t[i] = 0; + } + + ObjFace(const ObjFace& f) { + nverts = f.nverts; + + for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) { + v[i] = f.v[i]; + n[i] = f.n[i]; + t[i] = f.t[i]; + } + } + + void ReverseOrder() { + int i, tmp[MAX_OBJ_FACE_VERTS]; + + for (i = 0; i < nverts; i++) tmp[i] = v[i]; + for (i = 0; i < nverts; i++) v[i] = tmp[nverts-1-i]; + + for (i = 0; i < nverts; i++) tmp[i] = n[i]; + for (i = 0; i < nverts; i++) n[i] = tmp[nverts-1-i]; + + for (i = 0; i < nverts; i++) tmp[i] = t[i]; + for (i = 0; i < nverts; i++) t[i] = tmp[nverts-1-i]; + } +}; + +static void ParsePoly(const char* line, ObjFace* face) +{ + int v[MAX_OBJ_FACE_VERTS]; + int n[MAX_OBJ_FACE_VERTS]; + int t[MAX_OBJ_FACE_VERTS]; + + for (int i = 0; i < MAX_OBJ_FACE_VERTS; i++) { + v[i] = n[i] = t[i] = 0; + } + + const char* p = line + 1; + + while (isspace(*p)) + p++; + + int i = 0; + while (*p && i < MAX_OBJ_FACE_VERTS) { + int factor = 1; + + if (*p == '-') { + factor = -1; + p++; + } + + while (isdigit(*p)) { + v[i] = v[i]*10 + *p - '0'; + p++; + } + v[i] *= factor; + + if (*p == '/') { p++; // slash one + + factor = 1; + + if (*p == '-') { + factor = -1; + p++; + } + + while (isdigit(*p)) { + t[i] = t[i]*10 + *p - '0'; + p++; + } + t[i] *= factor; + + if (*p == '/') { p++; // slash two + + factor = 1; + + if (*p == '-') { + factor = -1; + p++; + } + + while (isdigit(*p)) { + n[i] = n[i]*10 + *p - '0'; + p++; + } + n[i] *= factor; + }} + + while (isspace(*p)) p++; + i++; + } + + face->nverts = i; + + for (i = 0; i < MAX_OBJ_FACE_VERTS; i++) { + face->v[i] = v[i]; + face->n[i] = n[i]; + face->t[i] = t[i]; + } +} + +static int LoadMatls(const char* lpszPathName, Model* m) +{ + int nmatls = 0; + + FILE* fp = fopen(lpszPathName, "r"); + if (!fp) { + ::MessageBox(0, "Open Failed: could not open file", "ERROR", MB_OK); + return 0; + } + + Material* mtl = 0; + + while (!feof(fp)) { + char raw_line[512]; + char line[512]; + fgets(raw_line, 512, fp); + + strcpy(line, Text(raw_line).trim().data()); + + if (strstr(line, "newmtl")) { + mtl = new Material; + strncpy(mtl->name, line+7, Material::NAMELEN - 1); + + m->GetMaterials().append(mtl); + } + + else if (line[0] == 'K' && line[1] == 'a') { + float r,g,b; + sscanf(line, "Ka %f %f %f", &r, &g, &b); + mtl->Ka = ColorValue(r,g,b); + + mtl->ambient_value = 1.0f; + mtl->ambient_color = mtl->Ka.ToColor(); + } + + else if (line[0] == 'K' && line[1] == 'd') { + float r,g,b; + sscanf(line, "Kd %f %f %f", &r, &g, &b); + mtl->Kd = ColorValue(r,g,b); + + mtl->diffuse_value = 1.0f; + mtl->diffuse_color = mtl->Kd.ToColor(); + } + + else if (line[0] == 'K' && line[1] == 's') { + float r,g,b; + sscanf(line, "Ks %f %f %f", &r, &g, &b); + mtl->Ks = ColorValue(r,g,b); + + mtl->specular_value = 1.0f; + mtl->specular_color = mtl->Ks.ToColor(); + } + + else if (line[0] == 'N' && line[1] == 's') { + float ns; + sscanf(line, "Ns %f", &ns); + mtl->power = ns; + } + + else if (strstr(line, "map_Kd")) { + const char* src = strstr(line, "map_Kd") + 7; + while (!isalnum(*src)) src++; + + LoadTexture(src, mtl->tex_diffuse, Bitmap::BMP_SOLID); + } + } + + fclose(fp); + return nmatls; +} + +static Material* FindMatl(const char* mtl_name, Model* model) +{ + ListIter iter = model->GetMaterials(); + while (++iter) { + Material* m = iter.value(); + if (!strcmp(m->name, mtl_name)) + return m; + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +static int mcomp(const void* a, const void* b) +{ + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; + + if (pa->sortval == pb->sortval) + return 0; + + if (pa->sortval < pb->sortval) + return 1; + + return -1; +} + +bool +ModelFileOBJ::Load(Model* m, double scale) +{ + if (m && scale > 0 && strlen(filename) > 0) { + ModelFile::Load(m, scale); + + FILE* fp = fopen(filename, "rb"); + + if (fp == NULL) { + ::MessageBox(0, "Wavefront/OBJ Import Failed: Unable to open file", "ERROR", MB_OK); + return false; + } + + // ok, now start reading the data: + int ntex = 0; + int nverts = 0; + int npv = 0; + int npolys = 0; + int vi = 0; + int vn = 0; + int vt = 0; + + char root_path[256]; + ZeroMemory(root_path, 256); + + if (strrchr(filename, '\\')) { + strcpy(root_path, filename); + char* p = strrchr(root_path, '\\'); + if (p) + *(p+1) = 0; + } + + else if (strrchr(filename, '/')) { + strcpy(root_path, filename); + char* p = strrchr(root_path, '/'); + if (p) + *(p+1) = 0; + } + + // count verts and polys: + while (!feof(fp)) { + char line[256]; + fgets(line, 255, fp); + + if (line[0] == 'v') { + switch (line[1]) { + case ' ': vi++; break; + case 'n': vn++; break; + case 't': vt++; break; + } + } + + else if (line[0] == 'f' && line[1] == ' ') { + npolys++; + + ObjFace f; + ParsePoly(line, &f); + f.ReverseOrder(); + + npv += f.nverts; + } + + else if (strstr(line, "mtllib")) { + const char* libname = strstr(line, "mtllib"); + libname += 7; + while (isspace(*libname)) + libname++; + + char libpath[256]; + strcpy(libpath, root_path); + strcat(libpath, libname); + int n = strlen(libpath); + if (n > 0) { + char* p = &libpath[n-1]; + while (isspace(*p)) *p-- = 0; + } + + int nmatls = LoadMatls(libpath, model); + } + } + + nverts = npv; + if (vi > nverts) nverts = vi; + if (vn > nverts) nverts = vn; + if (vt > nverts) nverts = vt; + + if (nverts > Model::MAX_VERTS || npolys > Model::MAX_POLYS) { + ::MessageBox(0, "Wavefront/OBJ Import Failed: that model is just too darn complicated!", "ERROR", MB_OK); + return false; + } + + vi = 0; + vn = 0; + vt = 0; + + fseek(fp, 0, SEEK_SET); + + Surface* surface = new Surface; + m->GetSurfaces().append(surface); + + surface->CreateVerts(nverts); + surface->CreatePolys(npolys); + + VertexSet* vset = surface->GetVertexSet(); + Poly* polys = surface->GetPolys(); + + // read vertex set: + Vec3* vloc = new Vec3[nverts]; + Vec3* vnrm = new Vec3[nverts]; + float* vtu = new float[nverts]; + float* vtv = new float[nverts]; + + float radius = 0; + + while (!feof(fp)) { + char line[256]; + fgets(line, 255, fp); + + if (line[0] == 'v') { + if (line[1] == ' ') { + const char* p = line + 2; + + while (isspace(*p)) p++; + sscanf(p, "%f", &vloc[vi].x); + + while (!isspace(*p)) p++; + while (isspace(*p)) p++; + sscanf(p, "%f", &vloc[vi].y); + + while (!isspace(*p)) p++; + while (isspace(*p)) p++; + sscanf(p, "%f", &vloc[vi].z); + + float d = vloc[vi].length(); + if (d > radius) + radius = d; + + vi++; + } + + else if (line[1] == 'n') { + const char* p = line + 2; + + while (isspace(*p)) p++; + sscanf(p, "%f", &vnrm[vn].x); + + while (!isspace(*p)) p++; + while (isspace(*p)) p++; + sscanf(p, "%f", &vnrm[vn].y); + + while (!isspace(*p)) p++; + while (isspace(*p)) p++; + sscanf(p, "%f", &vnrm[vn].z); + + vn++; + } + + else if (line[1] == 't') { + const char* p = line + 2; + + while (isspace(*p)) p++; + sscanf(p, "%f", &vtu[vt]); + + while (!isspace(*p)) p++; + while (isspace(*p)) p++; + sscanf(p, "%f", &vtv[vt]); + + vtv[vt] = 1.0f - vtv[vt]; + + vt++; + } + } + } + + fseek(fp, 0, SEEK_SET); + + // read polys: + int poly = 0; + char line[256]; + ObjFace face; + Material* material = 0; + int mtl_index = 0; + + if (m->NumMaterials()) + material = m->GetMaterials().first(); + + int current_v = 1; + int current_vn = 1; + int current_vt = 1; + int v = 0; // vset index pointer + + while (!feof(fp)) { + char raw_line[256]; + fgets(raw_line, 256, fp); + + strcpy(line, Text(raw_line).trim().data()); + + if (strstr(line, "usemtl")) { + material = FindMatl(line + 7, model); + ListIter iter = model->GetMaterials(); + while (++iter) + if (material == iter.value()) + mtl_index = iter.index(); + } + + else if (line[0] == 'v') { + if (line[1] == ' ') current_v++; + else if (line[1] == 'n') current_vn++; + else if (line[1] == 't') current_vt++; + } + + else if (line[0] == 'f') { + ParsePoly(line, &face); + face.ReverseOrder(); + + for (int n = 0; n < face.nverts; n++) { + if (face.v[n] < 0) + face.v[n] += current_v; + + if (face.n[n] < 0) + face.n[n] += current_vn; + + if (face.t[n] < 0) + face.t[n] += current_vt; + } + + if (face.nverts > 4) { + npolys += face.nverts - 3; + + for (int tri = 2; tri < face.nverts; tri++) { + Poly* p = polys + poly; + poly++; + + p->nverts = 3; + + vset->loc[v+0] = vloc[face.v[ tri ] -1]; + vset->loc[v+1] = vloc[face.v[ tri-1 ] -1]; + vset->loc[v+2] = vloc[face.v[ 0] -1]; + + if (face.n[0] > 0) { + vset->nrm[v+0] = vnrm[face.n[ tri ] -1]; + vset->nrm[v+1] = vnrm[face.n[ tri-1 ] -1]; + vset->nrm[v+2] = vnrm[face.n[ 0] -1]; + } + else { + vset->nrm[v+0] = vloc[v+0]; vset->nrm[v+0].Normalize(); + vset->nrm[v+1] = vloc[v+1]; vset->nrm[v+1].Normalize(); + vset->nrm[v+2] = vloc[v+2]; vset->nrm[v+2].Normalize(); + } + + if (face.t[0] > 0) { + vset->tu[v+0] = vtu[face.t[ tri ] -1]; + vset->tv[v+0] = vtv[face.t[ tri ] -1]; + vset->tu[v+1] = vtu[face.t[ tri-1 ] -1]; + vset->tv[v+1] = vtv[face.t[ tri-1 ] -1]; + vset->tu[v+2] = vtu[face.t[ 0 ] -1]; + vset->tv[v+2] = vtv[face.t[ 0 ] -1]; + } + + p->verts[0] = v+0; + p->verts[1] = v+1; + p->verts[2] = v+2; + + p->material = material; + p->sortval = mtl_index; + p->vertex_set = vset; + + p->plane = Plane(vset->loc[p->verts[0]], + vset->loc[p->verts[2]], + vset->loc[p->verts[1]]); + + v += p->nverts; + } + } + + else if (face.nverts == 3 || face.nverts == 4) { + Poly* p = polys + poly; + poly++; + + p->nverts = face.nverts; + + bool flat = true; + int first = v; + + for (int i = 0; i < p->nverts; i++) { + int face_index = i; + + vset->loc[v] = vloc[face.v[face_index]-1]; + + if (face.n[face_index] > 0) + vset->nrm[v] = vnrm[face.n[face_index]-1]; + else + vset->nrm[v] = vset->loc[v]; + + vset->nrm[v].Normalize(); + + if (vset->nrm[v] != vset->nrm[first]) + flat = false; + + if (face.t[face_index] > 0) { + vset->tu[v] = vtu [face.t[face_index]-1]; + vset->tv[v] = vtv [face.t[face_index]-1]; + } + + p->verts[i] = v++; + } + + p->material = material; + p->sortval = mtl_index; + p->flatness = flat ? 1.0f : 0.0f; + + if (p->nverts == 3) + surface->AddIndices(3); + + else if (p->nverts == 4) + surface->AddIndices(6); + + p->vertex_set = vset; + p->plane = Plane(vset->loc[p->verts[0]], + vset->loc[p->verts[2]], + vset->loc[p->verts[1]]); + } + + if (poly >= npolys) + break; + } + } + + // sort the polys by material index: + qsort((void*) polys, npolys, sizeof(Poly), mcomp); + + // then assign them to cohesive segments: + Segment* segment = 0; + + for (int n = 0; n < npolys; n++) { + if (segment && segment->material == polys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new Segment; + + segment->npolys = 1; + segment->polys = &polys[n]; + segment->material = segment->polys->material; + + surface->GetSegments().append(segment); + } + } + + delete [] vloc; + delete [] vnrm; + delete [] vtu; + delete [] vtv; + + *pnverts = nverts; + *pnpolys = npolys; + *pradius = radius; + + fclose(fp); + + m->Normalize(); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +static bool +SaveWaveFrontMatLib(const char* path, const char* root, Model* model) +{ + char filename[256]; + sprintf(filename, "%s%s.mtl", path, root); + + FILE* f = fopen(filename, "w"); + if (f) { + fprintf(f, "#\n# %s Material Library exported by Magic 2.0\n#\n\n", root); + + ListIter iter = model->GetMaterials(); + while (++iter) { + Material* mtl = iter.value(); + + fprintf(f, "newmtl %s\n", mtl->name); + fprintf(f, "Ka %.5f %.5f %.5f\n", mtl->Ka.Red(), mtl->Ka.Green(), mtl->Ka.Blue()); + fprintf(f, "Kd %.5f %.5f %.5f\n", mtl->Kd.Red(), mtl->Kd.Green(), mtl->Kd.Blue()); + fprintf(f, "Ks %.5f %.5f %.5f\n", mtl->Ks.Red(), mtl->Ks.Green(), mtl->Ks.Blue()); + fprintf(f, "Ns %.5f\n", mtl->power); + fprintf(f, "illum 2\n"); + if (mtl->tex_diffuse) + fprintf(f, "map_Kd %s\n", mtl->tex_diffuse->GetFilename()); + fprintf(f, "\n"); + } + + fclose(f); + return true; + } + + return false; +} + +bool +ModelFileOBJ::Save(Model* m) +{ + if (m) { + ModelFile::Save(m); + char pathname[256]; + char rootname[256]; + + ZeroMemory(pathname, sizeof(pathname)); + ZeroMemory(rootname, sizeof(rootname)); + + const char* ext = strstr(filename, ".obj"); + if (!ext) + ext = strstr(filename, ".OBJ"); + + const char* sep = strrchr(filename, '/'); + if (!sep) + sep = strrchr(filename, '\\'); + + const char* src = filename; + char* dst = pathname; + + if (sep) { + while (src != sep) + *dst++ = *src++; + *dst++ = *src++; + } + + if (ext) { + dst = rootname; + while (src != ext) + *dst++ = *src++; + } + else { + strcpy(rootname, src); + } + + strcpy(filename, pathname); + strcat(filename, rootname); + strcat(filename, ".obj"); + + FILE* f = fopen(filename, "w"); + if (!f) { + ::MessageBox(0, "Export Failed: Magic could not open the file for writing", "ERROR", MB_OK); + return false; + } + + fprintf(f, "# Wavefront OBJ exported by Magic 2.0\n\n"); + fprintf(f, "mtllib %s.mtl\n", rootname); + + ListIter s_iter = m->GetSurfaces(); + + // vertex locations + fprintf(f, "\n# VERTEX LOCATIONS: %d\n", m->NumVerts()); + while (++s_iter) { + Surface* s = s_iter.value(); + VertexSet* vset = s->GetVertexSet(); + + for (int n = 0; n < vset->nverts; n++) { + fprintf(f, "v %12.5f %12.5f %12.5f\n", + vset->loc[n].x, + vset->loc[n].y, + vset->loc[n].z); + } + } + + s_iter.reset(); + + // vertex normals + fprintf(f, "\n# VERTEX NORMALS: %d\n", m->NumVerts()); + while (++s_iter) { + Surface* s = s_iter.value(); + VertexSet* vset = s->GetVertexSet(); + + for (int n = 0; n < vset->nverts; n++) { + fprintf(f, "vn %8.3f %8.3f %8.3f\n", + vset->nrm[n].x, + vset->nrm[n].y, + vset->nrm[n].z); + } + } + + s_iter.reset(); + + // texture coordinates + fprintf(f, "\n# TEXTURE COORDINATES: %d\n", m->NumVerts()); + while (++s_iter) { + Surface* s = s_iter.value(); + VertexSet* vset = s->GetVertexSet(); + + for (int n = 0; n < vset->nverts; n++) { + fprintf(f, "vt %8.3f %8.3f\n", + vset->tu[n], 1 - vset->tv[n]); + } + } + + s_iter.reset(); + + // faces + Material* current_material = 0; + + fprintf(f, "\n# FACES: %d\n", m->NumPolys()); + while (++s_iter) { + Surface* s = s_iter.value(); + + for (int n = 0; n < s->NumPolys(); n++) { + const Poly* p = s->GetPolys() + n; + int nv = p->nverts; + Material* mtl = p->material; + + if (current_material != mtl) { + fprintf(f, "\n\nusemtl %s\n", mtl->name); + current_material = mtl; + } + + fprintf(f, "\nf "); + for (int v = nv-1; v >= 0; v--) { + fprintf(f, "%d/%d/%d ", + p->verts[v] + 1, + p->verts[v] + 1, + p->verts[v] + 1); + } + } + } + + fprintf(f, "\n\n\n# END OF FILE.\n"); + fclose(f); + + return SaveWaveFrontMatLib(pathname, rootname, m); + } + + return false; +} + +// +--------------------------------------------------------------------+ diff --git a/Magic2/ModelFileOBJ.h b/Magic2/ModelFileOBJ.h index 1fe123b..3c13a45 100644 --- a/Magic2/ModelFileOBJ.h +++ b/Magic2/ModelFileOBJ.h @@ -1,37 +1,61 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelFileOBJ.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - File loader for Wavefront/OBJ format models -*/ - -#ifndef ModelFileOBJ_h -#define ModelFileOBJ_h - -#include "Solid.h" - -// +--------------------------------------------------------------------+ - -class ModelFileOBJ : public ModelFile -{ -public: - ModelFileOBJ(const char* fname); - virtual ~ModelFileOBJ(); - - virtual bool Load(Model* m, double scale=1.0); - virtual bool Save(Model* m); - -protected: -}; - -// +--------------------------------------------------------------------+ - -#endif ModelFileOBJ_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelFileOBJ.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + File loader for Wavefront/OBJ format models +*/ + +#ifndef ModelFileOBJ_h +#define ModelFileOBJ_h + +#include "Solid.h" + +// +--------------------------------------------------------------------+ + +class ModelFileOBJ : public ModelFile +{ +public: + ModelFileOBJ(const char* fname); + virtual ~ModelFileOBJ(); + + virtual bool Load(Model* m, double scale=1.0); + virtual bool Save(Model* m); + +protected: +}; + +// +--------------------------------------------------------------------+ + +#endif ModelFileOBJ_h + diff --git a/Magic2/ModelView.cpp b/Magic2/ModelView.cpp index 21feaa8..68ab304 100644 --- a/Magic2/ModelView.cpp +++ b/Magic2/ModelView.cpp @@ -1,417 +1,441 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelView.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the ModelView class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MagicDoc.h" -#include "ModelView.h" -#include "Grid.h" -#include "Selector.h" -#include "Selection.h" - -#include "ActiveWindow.h" -#include "Color.h" -#include "Light.h" -#include "Scene.h" -#include "Screen.h" -#include "Shadow.h" -#include "Solid.h" -#include "Video.h" - -DWORD GetRealTime(); - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -static ModelView* views[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -// +--------------------------------------------------------------------+ - -ModelView::ModelView(Window* c, Scene* s, DWORD m) - : CameraView(c, 0, s), view_mode(100), fill_mode(FILL_WIRE), - grid(0), az(-PI/4), el(PI/4) -{ - UseCamera(&cam); - SetViewMode(m); -} - -ModelView::~ModelView() -{ - if (views[view_mode] == this) - views[view_mode] = 0; -} - -// +--------------------------------------------------------------------+ - -void -ModelView::SetViewMode(DWORD m) -{ - if (view_mode != m) { - view_mode = m; - - double x = 1e3 * sin(az) * cos(el); - double y = 1e3 * cos(az) * cos(el); - double z = 1e3 * sin(el); - - switch (view_mode) { - case VIEW_PLAN: - cam.LookAt(Point(0,0,0), - Point(0,1e3,0), - Point(0,0,1)); - SetProjectionType(Video::PROJECTION_ORTHOGONAL); - SetFieldOfView(1.75); - break; - - case VIEW_FRONT: - cam.LookAt(Point(0,0,0), - Point(0,0,1e3), - Point(0,1,0)); - SetProjectionType(Video::PROJECTION_ORTHOGONAL); - SetFieldOfView(1.75); - break; - - case VIEW_SIDE: - cam.LookAt(Point(0,0,0), - Point(1e3,0,0), - Point(0,1,0)); - SetProjectionType(Video::PROJECTION_ORTHOGONAL); - SetFieldOfView(1.75); - break; - - case VIEW_PROJECT: - cam.LookAt(Point(0,0,0), - Point(x,z,y), - Point(0,1,0)); - SetProjectionType(Video::PROJECTION_PERSPECTIVE); - SetFieldOfView(1.75); - break; - } - - views[view_mode] = this; - } -} - -ModelView* -ModelView::FindView(DWORD mode) -{ - if (mode >= 0 && mode < 8) - return views[mode]; - - return 0; -} - -// +--------------------------------------------------------------------+ - -void -ModelView::MoveTo(Point pos) -{ - switch (view_mode) { - case VIEW_PLAN: - cam.LookAt( pos - Point(0,1e3,0), - pos, - Point(0,0,1)); - break; - - case VIEW_FRONT: - cam.LookAt( pos - Point(0,0,1e3), - pos, - Point(0,1,0)); - break; - - case VIEW_SIDE: - cam.LookAt( pos - Point(1e3,0,0), - pos, - Point(0,1,0)); - break; - } -} - -void -ModelView::MoveBy(double dx, double dy) -{ - Point pos = cam.Pos(); - - dx *= 2.00/GetFieldOfView(); - dy *= 2.00/GetFieldOfView(); - - switch (view_mode) { - case VIEW_PLAN: - pos.x -= dx; - pos.z += dy; - - cam.LookAt( pos - Point(0,1e3,0), - pos, - Point(0,0,1)); - break; - - case VIEW_FRONT: - pos.x += dx; - pos.y += dy; - - cam.LookAt( pos - Point(0,0,1e3), - pos, - Point(0,1,0)); - break; - - case VIEW_SIDE: - pos.z -= dx; - pos.y += dy; - - cam.LookAt( pos - Point(1e3,0,0), - pos, - Point(0,1,0)); - break; - } -} - -void -ModelView::SpinBy(double phi, double theta) -{ - const double limit = (0.43 * PI); - - Point pos = cam.Pos(); - double len = pos.length(); - - az += phi; - el += theta; - - if (az > PI) - az = -2*PI + az; - - else if (az < -PI) - az = 2*PI + az; - - if (el > limit) - el = limit; - else if (el < -limit) - el = -limit; - - double x = len * sin(az) * cos(el); - double y = len * cos(az) * cos(el); - double z = len * sin(el); - - cam.LookAt(Point(0,0,0), Point(x,z,y), Point(0,1,0)); -} - -void -ModelView::UseGrid(Grid* g) -{ - grid = g; -} - -void -ModelView::ZoomNormal() -{ - DWORD v = view_mode; // remember current view mode - view_mode = 100; // force set view mode to setup the view - az = -PI/4; // if this happens to be a perspective view, - el = PI/4; // reset the spin to the original 3/4ths view - - SetViewMode(v); // restore default view params for this mode -} - -// +--------------------------------------------------------------------+ - -void -ModelView::RenderScene() -{ - // activate all lights: - ListIter light_iter = scene->Lights(); - - while (++light_iter) { - Light* light = light_iter.value(); - light->SetActive(true); - } - - video->SetLights(scene->Lights()); - - RenderGrid(); - - - bool old_shadows = video->IsShadowEnabled(); - bool old_bumps = video->IsBumpMapEnabled(); - - if (fill_mode != FILL_TEXTURE) { - video->SetShadowEnabled(false); - video->SetBumpMapEnabled(false); - CameraView::RenderScene(); - } - - else { - CameraView::RenderScene(); - } - - const char* title = "ModelView"; - switch (view_mode) { - case VIEW_PLAN: title = "Top"; break; - case VIEW_FRONT: title = "Front"; break; - case VIEW_SIDE: title = "Right Side"; break; - case VIEW_PROJECT: title = "Perspective"; break; - } - - int len = strlen(title); - Rect r(6,4,200,20); - - r.x += window->GetRect().x; - r.y += window->GetRect().y; - - video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); - - r.x--; - r.y--; - - video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); - video->SetShadowEnabled(old_shadows); - video->SetBumpMapEnabled(old_bumps); -} - -// +--------------------------------------------------------------------+ - -void -ModelView::Render(Graphic* g, DWORD flags) -{ - if (!g) - return; - - if (!strcmp(g->Name(), "Selector")) { - Selector* selector = (Selector*) g; - - if (selector->GetViewMode() != (int) view_mode) - return; - } - - else if (!strcmp(g->Name(), "Selection")) { - Selection* selection = (Selection*) g; - selection->UseView(this); - } - - if (fill_mode == FILL_WIRE) { - Material m; - video->UseMaterial(&m); - video->SetRenderState(Video::Z_ENABLE, FALSE); - - if (g->IsSolid()) { - m.Kd = ColorValue(0.0f, 0.0f, 0.0f, 0.5f); - m.Ke = ColorValue(0.8f, 0.8f, 0.9f, 1.0f); - m.blend = Video::BLEND_ALPHA; - m.luminous = true; - - video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); - g->Render(video, flags); - } - - m.Ka = Color::Black; - m.Kd = Color::Black; - m.Ks = Color::Black; - m.Ke = Color::Black; - m.blend = Video::BLEND_SOLID; - - video->SetRenderState(Video::FILL_MODE, Video::FILL_WIREFRAME); - - g->Render(video, flags); - video->UseMaterial(0); - } - - else if (fill_mode == FILL_SOLID) { - if (g->IsSolid() && flags != Graphic::RENDER_SOLID) - return; - - Material m; - video->UseMaterial(&m); - video->SetRenderState(Video::Z_ENABLE, TRUE); - - m.Kd = ColorValue(0.5f, 0.5f, 0.5f, 1.0f); - m.blend = Video::BLEND_SOLID; - - video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); - - if (g->IsSolid()) { - MarkVisibleLights(g, flags); - video->SetLights(scene->Lights()); - } - - g->Render(video, flags); - video->UseMaterial(0); - } - - else if (fill_mode == FILL_TEXTURE) { - video->SetRenderState(Video::Z_ENABLE, TRUE); - video->UseMaterial(0); - - if (g->IsSolid()) { - MarkVisibleLights(g, flags); - video->SetLights(scene->Lights()); - } - - g->Render(video, flags); - } -} - -void -ModelView::RenderGrid() -{ - if (!grid || !grid->IsShow()) - return; - - int plane = Grid::GRID_XZ; - - if (view_mode == VIEW_FRONT) - plane = Grid::GRID_XY; - - else if (view_mode == VIEW_SIDE) - plane = Grid::GRID_YZ; - - grid->ShowPlane(plane); - grid->MoveTo(camera_loc * -1); - grid->ShowReference(view_mode != VIEW_PROJECT); - grid->Render(video, Graphic::RENDER_SOLID); - - video->SetRenderState(Video::Z_ENABLE, TRUE); - video->SetRenderState(Video::LIGHTING_ENABLE, TRUE); - video->UseMaterial(0); -} - -// +--------------------------------------------------------------------+ - -CPoint -ModelView::ProjectPoint(Vec3& p) -{ - CPoint result; - - switch (view_mode) { - case VIEW_PLAN: - case VIEW_FRONT: - case VIEW_SIDE: - case VIEW_PROJECT: { - Vec3 pt = p; - projector.Transform(pt); - projector.Project(pt, false); - - result.x = (LONG) (pt.x + GetWindow()->X()); - result.y = (LONG) (pt.y + GetWindow()->Y()); - } - break; - - default: - result.x = 0; - result.y = 0; - break; - } - - return result; -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelView.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the ModelView class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "ModelView.h" +#include "Grid.h" +#include "Selector.h" +#include "Selection.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Light.h" +#include "Scene.h" +#include "Screen.h" +#include "Shadow.h" +#include "Solid.h" +#include "Video.h" + +DWORD GetRealTime(); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static ModelView* views[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +// +--------------------------------------------------------------------+ + +ModelView::ModelView(Window* c, Scene* s, DWORD m) + : CameraView(c, 0, s), view_mode(100), fill_mode(FILL_WIRE), + grid(0), az(-PI/4), el(PI/4) +{ + UseCamera(&cam); + SetViewMode(m); +} + +ModelView::~ModelView() +{ + if (views[view_mode] == this) + views[view_mode] = 0; +} + +// +--------------------------------------------------------------------+ + +void +ModelView::SetViewMode(DWORD m) +{ + if (view_mode != m) { + view_mode = m; + + double x = 1e3 * sin(az) * cos(el); + double y = 1e3 * cos(az) * cos(el); + double z = 1e3 * sin(el); + + switch (view_mode) { + case VIEW_PLAN: + cam.LookAt(Point(0,0,0), + Point(0,1e3,0), + Point(0,0,1)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_FRONT: + cam.LookAt(Point(0,0,0), + Point(0,0,1e3), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_SIDE: + cam.LookAt(Point(0,0,0), + Point(1e3,0,0), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_PROJECT: + cam.LookAt(Point(0,0,0), + Point(x,z,y), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_PERSPECTIVE); + SetFieldOfView(1.75); + break; + } + + views[view_mode] = this; + } +} + +ModelView* +ModelView::FindView(DWORD mode) +{ + if (mode >= 0 && mode < 8) + return views[mode]; + + return 0; +} + +// +--------------------------------------------------------------------+ + +void +ModelView::MoveTo(Point pos) +{ + switch (view_mode) { + case VIEW_PLAN: + cam.LookAt( pos - Point(0,1e3,0), + pos, + Point(0,0,1)); + break; + + case VIEW_FRONT: + cam.LookAt( pos - Point(0,0,1e3), + pos, + Point(0,1,0)); + break; + + case VIEW_SIDE: + cam.LookAt( pos - Point(1e3,0,0), + pos, + Point(0,1,0)); + break; + } +} + +void +ModelView::MoveBy(double dx, double dy) +{ + Point pos = cam.Pos(); + + dx *= 2.00/GetFieldOfView(); + dy *= 2.00/GetFieldOfView(); + + switch (view_mode) { + case VIEW_PLAN: + pos.x -= dx; + pos.z += dy; + + cam.LookAt( pos - Point(0,1e3,0), + pos, + Point(0,0,1)); + break; + + case VIEW_FRONT: + pos.x += dx; + pos.y += dy; + + cam.LookAt( pos - Point(0,0,1e3), + pos, + Point(0,1,0)); + break; + + case VIEW_SIDE: + pos.z -= dx; + pos.y += dy; + + cam.LookAt( pos - Point(1e3,0,0), + pos, + Point(0,1,0)); + break; + } +} + +void +ModelView::SpinBy(double phi, double theta) +{ + const double limit = (0.43 * PI); + + Point pos = cam.Pos(); + double len = pos.length(); + + az += phi; + el += theta; + + if (az > PI) + az = -2*PI + az; + + else if (az < -PI) + az = 2*PI + az; + + if (el > limit) + el = limit; + else if (el < -limit) + el = -limit; + + double x = len * sin(az) * cos(el); + double y = len * cos(az) * cos(el); + double z = len * sin(el); + + cam.LookAt(Point(0,0,0), Point(x,z,y), Point(0,1,0)); +} + +void +ModelView::UseGrid(Grid* g) +{ + grid = g; +} + +void +ModelView::ZoomNormal() +{ + DWORD v = view_mode; // remember current view mode + view_mode = 100; // force set view mode to setup the view + az = -PI/4; // if this happens to be a perspective view, + el = PI/4; // reset the spin to the original 3/4ths view + + SetViewMode(v); // restore default view params for this mode +} + +// +--------------------------------------------------------------------+ + +void +ModelView::RenderScene() +{ + // activate all lights: + ListIter light_iter = scene->Lights(); + + while (++light_iter) { + Light* light = light_iter.value(); + light->SetActive(true); + } + + video->SetLights(scene->Lights()); + + RenderGrid(); + + + bool old_shadows = video->IsShadowEnabled(); + bool old_bumps = video->IsBumpMapEnabled(); + + if (fill_mode != FILL_TEXTURE) { + video->SetShadowEnabled(false); + video->SetBumpMapEnabled(false); + CameraView::RenderScene(); + } + + else { + CameraView::RenderScene(); + } + + const char* title = "ModelView"; + switch (view_mode) { + case VIEW_PLAN: title = "Top"; break; + case VIEW_FRONT: title = "Front"; break; + case VIEW_SIDE: title = "Right Side"; break; + case VIEW_PROJECT: title = "Perspective"; break; + } + + int len = strlen(title); + Rect r(6,4,200,20); + + r.x += window->GetRect().x; + r.y += window->GetRect().y; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); + + r.x--; + r.y--; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); + video->SetShadowEnabled(old_shadows); + video->SetBumpMapEnabled(old_bumps); +} + +// +--------------------------------------------------------------------+ + +void +ModelView::Render(Graphic* g, DWORD flags) +{ + if (!g) + return; + + if (!strcmp(g->Name(), "Selector")) { + Selector* selector = (Selector*) g; + + if (selector->GetViewMode() != (int) view_mode) + return; + } + + else if (!strcmp(g->Name(), "Selection")) { + Selection* selection = (Selection*) g; + selection->UseView(this); + } + + if (fill_mode == FILL_WIRE) { + Material m; + video->UseMaterial(&m); + video->SetRenderState(Video::Z_ENABLE, FALSE); + + if (g->IsSolid()) { + m.Kd = ColorValue(0.0f, 0.0f, 0.0f, 0.5f); + m.Ke = ColorValue(0.8f, 0.8f, 0.9f, 1.0f); + m.blend = Video::BLEND_ALPHA; + m.luminous = true; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + g->Render(video, flags); + } + + m.Ka = Color::Black; + m.Kd = Color::Black; + m.Ks = Color::Black; + m.Ke = Color::Black; + m.blend = Video::BLEND_SOLID; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_WIREFRAME); + + g->Render(video, flags); + video->UseMaterial(0); + } + + else if (fill_mode == FILL_SOLID) { + if (g->IsSolid() && flags != Graphic::RENDER_SOLID) + return; + + Material m; + video->UseMaterial(&m); + video->SetRenderState(Video::Z_ENABLE, TRUE); + + m.Kd = ColorValue(0.5f, 0.5f, 0.5f, 1.0f); + m.blend = Video::BLEND_SOLID; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + + if (g->IsSolid()) { + MarkVisibleLights(g, flags); + video->SetLights(scene->Lights()); + } + + g->Render(video, flags); + video->UseMaterial(0); + } + + else if (fill_mode == FILL_TEXTURE) { + video->SetRenderState(Video::Z_ENABLE, TRUE); + video->UseMaterial(0); + + if (g->IsSolid()) { + MarkVisibleLights(g, flags); + video->SetLights(scene->Lights()); + } + + g->Render(video, flags); + } +} + +void +ModelView::RenderGrid() +{ + if (!grid || !grid->IsShow()) + return; + + int plane = Grid::GRID_XZ; + + if (view_mode == VIEW_FRONT) + plane = Grid::GRID_XY; + + else if (view_mode == VIEW_SIDE) + plane = Grid::GRID_YZ; + + grid->ShowPlane(plane); + grid->MoveTo(camera_loc * -1); + grid->ShowReference(view_mode != VIEW_PROJECT); + grid->Render(video, Graphic::RENDER_SOLID); + + video->SetRenderState(Video::Z_ENABLE, TRUE); + video->SetRenderState(Video::LIGHTING_ENABLE, TRUE); + video->UseMaterial(0); +} + +// +--------------------------------------------------------------------+ + +CPoint +ModelView::ProjectPoint(Vec3& p) +{ + CPoint result; + + switch (view_mode) { + case VIEW_PLAN: + case VIEW_FRONT: + case VIEW_SIDE: + case VIEW_PROJECT: { + Vec3 pt = p; + projector.Transform(pt); + projector.Project(pt, false); + + result.x = (LONG) (pt.x + GetWindow()->X()); + result.y = (LONG) (pt.y + GetWindow()->Y()); + } + break; + + default: + result.x = 0; + result.y = 0; + break; + } + + return result; +} diff --git a/Magic2/ModelView.h b/Magic2/ModelView.h index 27fc9b6..58c2924 100644 --- a/Magic2/ModelView.h +++ b/Magic2/ModelView.h @@ -1,64 +1,88 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: ModelView.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the ModelView class -*/ - - -#ifndef ModelView_h -#define ModelView_h - -#include "CameraView.h" -#include "Grid.h" - -// +--------------------------------------------------------------------+ - -class ModelView : public CameraView -{ -public: - enum VIEW_MODE { VIEW_PLAN=1, VIEW_FRONT, VIEW_SIDE, VIEW_PROJECT }; - enum FILL_MODE { FILL_WIRE=1, FILL_SOLID, FILL_TEXTURE }; - - ModelView(Window* c, Scene* s, DWORD m); - virtual ~ModelView(); - - virtual void RenderScene(); - virtual void Render(Graphic* g, DWORD flags); - - DWORD GetViewMode() const { return view_mode; } - void SetViewMode(DWORD m); - DWORD GetFillMode() const { return fill_mode; } - void SetFillMode(DWORD m) { fill_mode = m; } - - void MoveTo(Point origin); - void MoveBy(double dx, double dy); - void SpinBy(double phi, double theta); - - void UseGrid(Grid* g); - void RenderGrid(); - void ZoomNormal(); - - CPoint ProjectPoint(Vec3& p); - - static ModelView* FindView(DWORD mode); - -protected: - Camera cam; - DWORD view_mode; - DWORD fill_mode; - double az; - double el; - Grid* grid; -}; - -// +--------------------------------------------------------------------+ - -#endif ModelView_h +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelView.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the ModelView class +*/ + + +#ifndef ModelView_h +#define ModelView_h + +#include "CameraView.h" +#include "Grid.h" + +// +--------------------------------------------------------------------+ + +class ModelView : public CameraView +{ +public: + enum VIEW_MODE { VIEW_PLAN=1, VIEW_FRONT, VIEW_SIDE, VIEW_PROJECT }; + enum FILL_MODE { FILL_WIRE=1, FILL_SOLID, FILL_TEXTURE }; + + ModelView(Window* c, Scene* s, DWORD m); + virtual ~ModelView(); + + virtual void RenderScene(); + virtual void Render(Graphic* g, DWORD flags); + + DWORD GetViewMode() const { return view_mode; } + void SetViewMode(DWORD m); + DWORD GetFillMode() const { return fill_mode; } + void SetFillMode(DWORD m) { fill_mode = m; } + + void MoveTo(Point origin); + void MoveBy(double dx, double dy); + void SpinBy(double phi, double theta); + + void UseGrid(Grid* g); + void RenderGrid(); + void ZoomNormal(); + + CPoint ProjectPoint(Vec3& p); + + static ModelView* FindView(DWORD mode); + +protected: + Camera cam; + DWORD view_mode; + DWORD fill_mode; + double az; + double el; + Grid* grid; +}; + +// +--------------------------------------------------------------------+ + +#endif ModelView_h diff --git a/Magic2/Primitives.cpp b/Magic2/Primitives.cpp index 8846646..d1ae4e2 100644 --- a/Magic2/Primitives.cpp +++ b/Magic2/Primitives.cpp @@ -1,52 +1,76 @@ -/* Project MAGIC - John DiCamillo Software Consulting - Copyright © 1994-1997. All Rights Reserved. - - SUBSYSTEM: Magic.exe Application - FILE: Primitives.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Commands for adding basic geometric primitives to a mesh -*/ - - -#include "stdafx.h" -#include "Primitives.h" -#include "MagicDoc.h" -#include "ModelView.h" -#include "Selection.h" - -// +----------------------------------------------------------------------+ -// +----------------------------------------------------------------------+ -// +----------------------------------------------------------------------+ - -CreatePolyCommand::CreatePolyCommand(MagicDoc* d) - : Command(n, d) -{ -} - -CreatePolyCommand::~CreatePolyCommand() -{ -} - -// +----------------------------------------------------------------------+ - -void -CreatePolyCommand::Do() -{ - if (document) { - } -} - -// +----------------------------------------------------------------------+ - -void -EditCommand::Undo() -{ - if (document) { - } -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe Application + FILE: Primitives.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Commands for adding basic geometric primitives to a mesh +*/ + + +#include "stdafx.h" +#include "Primitives.h" +#include "MagicDoc.h" +#include "ModelView.h" +#include "Selection.h" + +// +----------------------------------------------------------------------+ +// +----------------------------------------------------------------------+ +// +----------------------------------------------------------------------+ + +CreatePolyCommand::CreatePolyCommand(MagicDoc* d) + : Command(n, d) +{ +} + +CreatePolyCommand::~CreatePolyCommand() +{ +} + +// +----------------------------------------------------------------------+ + +void +CreatePolyCommand::Do() +{ + if (document) { + } +} + +// +----------------------------------------------------------------------+ + +void +EditCommand::Undo() +{ + if (document) { + } +} + diff --git a/Magic2/Primitives.h b/Magic2/Primitives.h index 2da16fe..56cf26c 100644 --- a/Magic2/Primitives.h +++ b/Magic2/Primitives.h @@ -1,55 +1,79 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Primitives.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Commands for adding basic geometric primitives to a mesh -*/ - -#ifndef Primitives_h -#define Primitives_h - -#include "MagicDoc.h" -#include "Command.h" -#include "Polygon.h" -#include "Solid.h" -#include "Video.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -class Selection; -class ModelView; - -// +--------------------------------------------------------------------+ - -class CreatePolyCommand : public Command -{ -public: - CreatePolyCommand(MagicDoc* doc, - int nsides, - double lx, - double ly, - double lz); - virtual ~CreatePolyCommand(); - - virtual void Do(); - virtual void Undo(); - -private: - int nsides; - double lx; - double ly; - double lz; -}; - -// +--------------------------------------------------------------------+ - -#endif Primitives_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Primitives.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Commands for adding basic geometric primitives to a mesh +*/ + +#ifndef Primitives_h +#define Primitives_h + +#include "MagicDoc.h" +#include "Command.h" +#include "Polygon.h" +#include "Solid.h" +#include "Video.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +class Selection; +class ModelView; + +// +--------------------------------------------------------------------+ + +class CreatePolyCommand : public Command +{ +public: + CreatePolyCommand(MagicDoc* doc, + int nsides, + double lx, + double ly, + double lz); + virtual ~CreatePolyCommand(); + + virtual void Do(); + virtual void Undo(); + +private: + int nsides; + double lx; + double ly; + double lz; +}; + +// +--------------------------------------------------------------------+ + +#endif Primitives_h + diff --git a/Magic2/Selection.cpp b/Magic2/Selection.cpp index 3db43db..570ab21 100644 --- a/Magic2/Selection.cpp +++ b/Magic2/Selection.cpp @@ -1,192 +1,216 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Selection.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Classes for rendering solid meshes of polygons -*/ - -#include "stdafx.h" -#include "Magic.h" -#include "Selection.h" -#include "ModelView.h" -#include "Projector.h" - -#include "Solid.h" -#include "Scene.h" -#include "Bitmap.h" - -#include - -// +--------------------------------------------------------------------+ - -Selection::Selection() - : model(0), model_view(0) -{ - strcpy_s(name, "Selection"); -} - -// +--------------------------------------------------------------------+ - -Selection::~Selection() -{ -} - -// +--------------------------------------------------------------------+ - -void -Selection::Render(Video* video, DWORD flags) -{ - if (video && flags == Graphic::RENDER_ALPHA) { - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - Vec3 vloc[16]; - - if (p->nverts >= 3) { - for (int i = 0; i < p->nverts; i++) { - int n = (i==p->nverts-1) ? 0 : i+1; - - vloc[2*i+0] = loc + p->vertex_set->loc[ p->verts[i] ]; - vloc[2*i+1] = loc + p->vertex_set->loc[ p->verts[n] ]; - } - - video->SetRenderState(Video::Z_ENABLE, FALSE); - video->DrawLines(p->nverts, vloc, Color(255,255,128)); - } - } - - if (model) { - for (size_t i = 0; i < verts.size(); i++) { - DWORD value = verts[i]; - WORD index = (WORD) (value >> 16); - WORD vert = (WORD) (value & 0xffff); - - if (index < model->NumSurfaces()) { - Surface* s = model->GetSurfaces()[index]; - Vec3 v = loc + s->GetVertexSet()->loc[vert]; - - if (model_view) { - CPoint p = model_view->ProjectPoint(v); - float handle[16]; - int x1 = p.x-1; - int y1 = p.y-1; - int x2 = p.x+1; - int y2 = p.y+1; - - handle[ 0] = (float) x1; - handle[ 1] = (float) y1; - handle[ 2] = (float) x2; - handle[ 3] = (float) y1; - - handle[ 4] = (float) x2; - handle[ 5] = (float) y1; - handle[ 6] = (float) x2; - handle[ 7] = (float) y2; - - handle[ 8] = (float) x2; - handle[ 9] = (float) y2; - handle[10] = (float) x1; - handle[11] = (float) y2; - - handle[12] = (float) x1; - handle[13] = (float) y2; - handle[14] = (float) x1; - handle[15] = (float) y1; - - video->DrawScreenLines(4, handle, Color(255,255,128)); - } - - else { - Vec3 vloc[8]; - - vloc[0] = v + Vec3(-1.0f, -1.0f, 0.0f); - vloc[1] = v + Vec3( 1.0f, -1.0f, 0.0f); - vloc[2] = v + Vec3( 1.0f, -1.0f, 0.0f); - vloc[3] = v + Vec3( 1.0f, 1.0f, 0.0f); - vloc[4] = v + Vec3( 1.0f, 1.0f, 0.0f); - vloc[5] = v + Vec3(-1.0f, 1.0f, 0.0f); - vloc[6] = v + Vec3(-1.0f, 1.0f, 0.0f); - vloc[7] = v + Vec3(-1.0f, -1.0f, 0.0f); - - video->SetRenderState(Video::Z_ENABLE, FALSE); - video->DrawLines(4, vloc, Color(255,255,128)); - } - } - } - } - - video->UseMaterial(0); - } -} - -// +--------------------------------------------------------------------+ - -void -Selection::AddPoly(Poly* p) -{ - if (!polys.contains(p)) - polys.append(p); -} - -void -Selection::RemovePoly(Poly* p) -{ - polys.remove(p); -} - -bool -Selection::Contains(Poly* p) const -{ - return polys.contains(p); -} - -void -Selection::AddVert(WORD s, WORD v) -{ - DWORD value = (s << 16) | v; - - bool contains = false; - for (auto vi = verts.begin(); vi != verts.end(); ++vi) { - if (*vi == value) { - contains = true; - break; - } - } - - if (!contains) - verts.push_back(value); -} - -void -Selection::RemoveVert(WORD s, WORD v) -{ - DWORD value = (s << 16) | v; - - for (auto vi = verts.begin(); vi != verts.end(); ++vi) { - if (*vi == value) { - verts.erase(vi); - return; - } - } -} - -bool -Selection::Contains(WORD s, WORD v) const -{ - DWORD value = (s << 16) | v; - - for (auto vi = verts.begin(); vi != verts.end(); ++vi) { - if (*vi == value) { - return true; - } - } - - return false; +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Selection.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Classes for rendering solid meshes of polygons +*/ + +#include "stdafx.h" +#include "Magic.h" +#include "Selection.h" +#include "ModelView.h" +#include "Projector.h" + +#include "Solid.h" +#include "Scene.h" +#include "Bitmap.h" + +#include + +// +--------------------------------------------------------------------+ + +Selection::Selection() + : model(0), model_view(0) +{ + strcpy_s(name, "Selection"); +} + +// +--------------------------------------------------------------------+ + +Selection::~Selection() +{ +} + +// +--------------------------------------------------------------------+ + +void +Selection::Render(Video* video, DWORD flags) +{ + if (video && flags == Graphic::RENDER_ALPHA) { + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + Vec3 vloc[16]; + + if (p->nverts >= 3) { + for (int i = 0; i < p->nverts; i++) { + int n = (i==p->nverts-1) ? 0 : i+1; + + vloc[2*i+0] = loc + p->vertex_set->loc[ p->verts[i] ]; + vloc[2*i+1] = loc + p->vertex_set->loc[ p->verts[n] ]; + } + + video->SetRenderState(Video::Z_ENABLE, FALSE); + video->DrawLines(p->nverts, vloc, Color(255,255,128)); + } + } + + if (model) { + for (size_t i = 0; i < verts.size(); i++) { + DWORD value = verts[i]; + WORD index = (WORD) (value >> 16); + WORD vert = (WORD) (value & 0xffff); + + if (index < model->NumSurfaces()) { + Surface* s = model->GetSurfaces()[index]; + Vec3 v = loc + s->GetVertexSet()->loc[vert]; + + if (model_view) { + CPoint p = model_view->ProjectPoint(v); + float handle[16]; + int x1 = p.x-1; + int y1 = p.y-1; + int x2 = p.x+1; + int y2 = p.y+1; + + handle[ 0] = (float) x1; + handle[ 1] = (float) y1; + handle[ 2] = (float) x2; + handle[ 3] = (float) y1; + + handle[ 4] = (float) x2; + handle[ 5] = (float) y1; + handle[ 6] = (float) x2; + handle[ 7] = (float) y2; + + handle[ 8] = (float) x2; + handle[ 9] = (float) y2; + handle[10] = (float) x1; + handle[11] = (float) y2; + + handle[12] = (float) x1; + handle[13] = (float) y2; + handle[14] = (float) x1; + handle[15] = (float) y1; + + video->DrawScreenLines(4, handle, Color(255,255,128)); + } + + else { + Vec3 vloc[8]; + + vloc[0] = v + Vec3(-1.0f, -1.0f, 0.0f); + vloc[1] = v + Vec3( 1.0f, -1.0f, 0.0f); + vloc[2] = v + Vec3( 1.0f, -1.0f, 0.0f); + vloc[3] = v + Vec3( 1.0f, 1.0f, 0.0f); + vloc[4] = v + Vec3( 1.0f, 1.0f, 0.0f); + vloc[5] = v + Vec3(-1.0f, 1.0f, 0.0f); + vloc[6] = v + Vec3(-1.0f, 1.0f, 0.0f); + vloc[7] = v + Vec3(-1.0f, -1.0f, 0.0f); + + video->SetRenderState(Video::Z_ENABLE, FALSE); + video->DrawLines(4, vloc, Color(255,255,128)); + } + } + } + } + + video->UseMaterial(0); + } +} + +// +--------------------------------------------------------------------+ + +void +Selection::AddPoly(Poly* p) +{ + if (!polys.contains(p)) + polys.append(p); +} + +void +Selection::RemovePoly(Poly* p) +{ + polys.remove(p); +} + +bool +Selection::Contains(Poly* p) const +{ + return polys.contains(p); +} + +void +Selection::AddVert(WORD s, WORD v) +{ + DWORD value = (s << 16) | v; + + bool contains = false; + for (auto vi = verts.begin(); vi != verts.end(); ++vi) { + if (*vi == value) { + contains = true; + break; + } + } + + if (!contains) + verts.push_back(value); +} + +void +Selection::RemoveVert(WORD s, WORD v) +{ + DWORD value = (s << 16) | v; + + for (auto vi = verts.begin(); vi != verts.end(); ++vi) { + if (*vi == value) { + verts.erase(vi); + return; + } + } +} + +bool +Selection::Contains(WORD s, WORD v) const +{ + DWORD value = (s << 16) | v; + + for (auto vi = verts.begin(); vi != verts.end(); ++vi) { + if (*vi == value) { + return true; + } + } + + return false; } \ No newline at end of file diff --git a/Magic2/Selection.h b/Magic2/Selection.h index aba249a..e70a3b3 100644 --- a/Magic2/Selection.h +++ b/Magic2/Selection.h @@ -1,74 +1,98 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Selection.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Classes for rendering solid meshes of polygons -*/ - -#ifndef Selection_h -#define Selection_h - -#include -#include "Polygon.h" -#include "Graphic.h" -#include "Video.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -class Selection; -class Solid; -class Model; -class ModelView; -class Surface; -class Segment; - -// +--------------------------------------------------------------------+ - -class Selection : public Graphic -{ -public: - static const char* TYPENAME() { return "Selection"; } - - Selection(); - virtual ~Selection(); - - // operations - virtual void Render(Video* video, DWORD flags); - virtual bool CheckVisibility(Projector& projector) { return true; } - - // accessors / mutators - void UseModel(Model* m) { model = m; } - void UseView(ModelView* v){ model_view = v; } - Model* GetModel() const { return model; } - List& GetPolys() { return polys; } - std::vector& GetVerts() { return verts; } - - virtual void Clear() { polys.clear(); - verts.clear(); } - - void AddPoly(Poly* p); - void AddVert(WORD s, WORD v); - void RemovePoly(Poly* p); - void RemoveVert(WORD s, WORD v); - bool Contains(Poly* p) const; - bool Contains(WORD s, WORD v) const; - -protected: - Model* model; - ModelView* model_view; - List polys; - std::vector verts; -}; - -// +--------------------------------------------------------------------+ - -#endif Selection_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Selection.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Classes for rendering solid meshes of polygons +*/ + +#ifndef Selection_h +#define Selection_h + +#include +#include "Polygon.h" +#include "Graphic.h" +#include "Video.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +class Selection; +class Solid; +class Model; +class ModelView; +class Surface; +class Segment; + +// +--------------------------------------------------------------------+ + +class Selection : public Graphic +{ +public: + static const char* TYPENAME() { return "Selection"; } + + Selection(); + virtual ~Selection(); + + // operations + virtual void Render(Video* video, DWORD flags); + virtual bool CheckVisibility(Projector& projector) { return true; } + + // accessors / mutators + void UseModel(Model* m) { model = m; } + void UseView(ModelView* v){ model_view = v; } + Model* GetModel() const { return model; } + List& GetPolys() { return polys; } + std::vector& GetVerts() { return verts; } + + virtual void Clear() { polys.clear(); + verts.clear(); } + + void AddPoly(Poly* p); + void AddVert(WORD s, WORD v); + void RemovePoly(Poly* p); + void RemoveVert(WORD s, WORD v); + bool Contains(Poly* p) const; + bool Contains(WORD s, WORD v) const; + +protected: + Model* model; + ModelView* model_view; + List polys; + std::vector verts; +}; + +// +--------------------------------------------------------------------+ + +#endif Selection_h + diff --git a/Magic2/Selector.cpp b/Magic2/Selector.cpp index 898355e..0b37f83 100644 --- a/Magic2/Selector.cpp +++ b/Magic2/Selector.cpp @@ -1,390 +1,414 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Selector.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Source file for implementation of Selector -*/ - - -#include "stdafx.h" -#include "Selector.h" -#include "MagicDoc.h" -#include "ModelView.h" -#include "Selection.h" - -#include "Solid.h" - -// +----------------------------------------------------------------------+ - -Selector::Selector(Selection* s) - : nmarks(0), view_mode(0), select_mode(SELECT_REPLACE), model(0) -{ - if (s) { - selection = s; - own_selection = false; - } - else { - selection = new Selection; - own_selection = true; - } - - strcpy_s(name, "Selector"); -} - -Selector::~Selector() -{ - if (selection && own_selection) - delete selection; -} - -// +----------------------------------------------------------------------+ - -const int BATCH_SIZE = 64; - -void -Selector::Render(Video* video, DWORD flags) -{ - if (nmarks < 2 || flags == Graphic::RENDER_SOLID) - return; - - float points[4*BATCH_SIZE + 4]; - - for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) { - int end = batch + BATCH_SIZE; - if (end > nmarks-1) - end = nmarks-1; - int nlines = end-batch; - - for (int i = 0; i < nlines; i++) { - points[4*i+0] = (float) marks[batch + i].x; - points[4*i+1] = (float) marks[batch + i].y; - points[4*i+2] = (float) marks[batch + i + 1].x; - points[4*i+3] = (float) marks[batch + i + 1].y; - } - - video->DrawScreenLines(nlines, points, Color::Cyan); - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::Clear() -{ - if (selection) - selection->Clear(); -} - -void -Selector::Begin(Model* m, int mode, int seln_mode) -{ - nmarks = 0; - model = m; - view_mode = mode; - select_mode = seln_mode; -} - -void -Selector::AddMark(CPoint& p) -{ - if (nmarks < MAX_MARK) - marks[nmarks++] = p; -} - -void -Selector::End() -{ - ModelView* view = ModelView::FindView(view_mode); - view_mode = 0; - - // get the model: - if (!model || !nmarks || !view) return; - - // if not adding to selection: - if (select_mode == SELECT_REPLACE) { - Clear(); - } - - // if only one mark: - if (nmarks < 2) { - CPoint pts[Poly::MAX_VERTS]; - - // find all selected polys: - ListIter s_iter = model->GetSurfaces(); - while (++s_iter) { - Surface* s = s_iter.value(); - - if (s->IsHidden() || s->IsLocked() || s->IsSimplified()) - continue; - - for (int i = 0; i < s->NumPolys(); i++) { - Poly* poly = s->GetPolys() + i; - - if (poly->nverts < 3) - continue; - - for (int v = 0; v < poly->nverts; v++) - pts[v] = view->ProjectPoint(s->GetVertexSet()->loc[poly->verts[v]]); - - CRgn rgn; - rgn.CreatePolygonRgn(pts, poly->nverts, ALTERNATE); - - if (rgn.PtInRegion(marks[0])) { - if (select_mode == SELECT_REMOVE) { - selection->RemovePoly(poly); - } - else { - selection->AddPoly(poly); - } - - for (int v = 0; v < poly->nverts; v++) { - WORD vert = poly->verts[v]; - if (select_mode == SELECT_REMOVE) { - selection->RemoveVert((WORD) s_iter.index(), vert); - } - else { - selection->AddVert((WORD) s_iter.index(), vert); - } - } - } - } - } - } - - // otherwise, build a region: - else { - CRgn rgn; - rgn.CreatePolygonRgn(marks, nmarks, WINDING); - - // find all selected verts: - ListIter s_iter = model->GetSurfaces(); - while (++s_iter) { - Surface* s = s_iter.value(); - VertexSet* vset = s->GetVertexSet(); - - if (s->IsHidden() || s->IsLocked() || s->IsSimplified()) - continue; - - for (WORD i = 0; i < vset->nverts; i++) { - CPoint p = view->ProjectPoint(s->GetVertexSet()->loc[i]); - if (rgn.PtInRegion(p)) { - if (select_mode == SELECT_REMOVE) { - selection->RemoveVert((WORD) s_iter.index(), i); - } - else { - selection->AddVert((WORD) s_iter.index(), i); - } - } - } - - // find all selected polys: - for (int i = 0; i < s->NumPolys(); i++) { - Poly* poly = s->GetPolys() + i; - - bool will_select = true; - for (int v = 0; v < poly->nverts && will_select; v++) - will_select = will_select && - selection->Contains((WORD) s_iter.index(), poly->verts[v]); - - if (will_select) - selection->AddPoly(poly); - else - selection->RemovePoly(poly); - } - } - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::UseModel(Model* m) -{ - model = m; - - if (selection) - selection->UseModel(model); -} - -// +----------------------------------------------------------------------+ - -void -Selector::SelectAll(int select_mode) -{ - Clear(); - - if (model && select_mode != SELECT_REMOVE) { - ListIter iter = model->GetSurfaces(); - - while (++iter) { - Surface* s = iter.value(); - - for (int i = 0; i < s->NumPolys(); i++) { - selection->GetPolys().append(s->GetPolys() + i); - } - - for (int i = 0; i < s->NumVerts(); i++) { - DWORD value = (iter.index() << 16) | i; - selection->GetVerts().push_back(value); - } - } - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::SelectInverse() -{ - if (model && selection) { - ListIter iter = model->GetSurfaces(); - - while (++iter) { - Surface* s = iter.value(); - WORD s_index = iter.index(); - - for (int i = 0; i < s->NumPolys(); i++) { - Poly* p = s->GetPolys() + i; - - if (selection->Contains(p)) - selection->RemovePoly(p); - else - selection->AddPoly(p); - } - - for (int i = 0; i < s->NumVerts(); i++) { - if (selection->Contains(s_index, i)) - selection->RemoveVert(s_index, i); - else - selection->AddVert(s_index, i); - } - } - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::SelectSurface(Surface* s, int select_mode) -{ - if (!s || !model) - return; - - WORD index = (WORD) model->GetSurfaces().index(s); - - if (select_mode == SELECT_REMOVE) { - for (int i = 0; i < s->NumPolys(); i++) { - selection->RemovePoly(s->GetPolys() + i); - } - - for (int i = 0; i < s->NumVerts(); i++) { - selection->RemoveVert(index, i); - } - } - else { - for (WORD i = 0; i < s->NumPolys(); i++) { - selection->AddPoly(s->GetPolys() + i); - } - - for (int i = 0; i < s->NumVerts(); i++) { - selection->AddVert(index, i); - } - } -} - -void -Selector::SelectVert(Surface* s, int v, int select_mode) -{ - if (!s || !model) - return; - - WORD index = (WORD) model->GetSurfaces().index(s); - - if (select_mode == SELECT_REMOVE) { - selection->RemoveVert(index, (WORD) v); - } - else { - selection->AddVert(index, (WORD) v); - } -} - -void -Selector::SelectPoly(Poly* poly, int select_mode) -{ - if (!poly || !model) - return; - - if (select_mode == SELECT_REMOVE) { - selection->RemovePoly(poly); - } - else { - selection->AddPoly(poly); - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::SelectMaterial(Material* m, int select_mode) -{ - if (select_mode == SELECT_REPLACE) - Clear(); - - if (model && select_mode != SELECT_REMOVE) { - ListIter iter = model->GetSurfaces(); - - while (++iter) { - Surface* s = iter.value(); - WORD s_index = iter.index(); - - for (int i = 0; i < s->NumPolys(); i++) { - Poly* p = s->GetPolys() + i; - - if (p->material == m) { - selection->AddPoly(p); - - for (int v = 0; v < p->nverts; v++) { - selection->AddVert(s_index, p->verts[v]); - } - } - } - } - } -} - -// +----------------------------------------------------------------------+ - -void -Selector::Reselect() -{ - selection->GetPolys().clear(); - - if (model) { - ListIter iter = model->GetSurfaces(); - - while (++iter) { - Surface* s = iter.value(); - WORD s_index = iter.index(); - - // find all selected polys: - for (int i = 0; i < s->NumPolys(); i++) { - Poly* poly = s->GetPolys() + i; - - bool will_select = true; - for (int v = 0; v < poly->nverts && will_select; v++) - will_select = will_select && - selection->Contains(s_index, poly->verts[v]); - - if (will_select) - selection->AddPoly(poly); - } - } - } -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Selector.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Source file for implementation of Selector +*/ + + +#include "stdafx.h" +#include "Selector.h" +#include "MagicDoc.h" +#include "ModelView.h" +#include "Selection.h" + +#include "Solid.h" + +// +----------------------------------------------------------------------+ + +Selector::Selector(Selection* s) + : nmarks(0), view_mode(0), select_mode(SELECT_REPLACE), model(0) +{ + if (s) { + selection = s; + own_selection = false; + } + else { + selection = new Selection; + own_selection = true; + } + + strcpy_s(name, "Selector"); +} + +Selector::~Selector() +{ + if (selection && own_selection) + delete selection; +} + +// +----------------------------------------------------------------------+ + +const int BATCH_SIZE = 64; + +void +Selector::Render(Video* video, DWORD flags) +{ + if (nmarks < 2 || flags == Graphic::RENDER_SOLID) + return; + + float points[4*BATCH_SIZE + 4]; + + for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) { + int end = batch + BATCH_SIZE; + if (end > nmarks-1) + end = nmarks-1; + int nlines = end-batch; + + for (int i = 0; i < nlines; i++) { + points[4*i+0] = (float) marks[batch + i].x; + points[4*i+1] = (float) marks[batch + i].y; + points[4*i+2] = (float) marks[batch + i + 1].x; + points[4*i+3] = (float) marks[batch + i + 1].y; + } + + video->DrawScreenLines(nlines, points, Color::Cyan); + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::Clear() +{ + if (selection) + selection->Clear(); +} + +void +Selector::Begin(Model* m, int mode, int seln_mode) +{ + nmarks = 0; + model = m; + view_mode = mode; + select_mode = seln_mode; +} + +void +Selector::AddMark(CPoint& p) +{ + if (nmarks < MAX_MARK) + marks[nmarks++] = p; +} + +void +Selector::End() +{ + ModelView* view = ModelView::FindView(view_mode); + view_mode = 0; + + // get the model: + if (!model || !nmarks || !view) return; + + // if not adding to selection: + if (select_mode == SELECT_REPLACE) { + Clear(); + } + + // if only one mark: + if (nmarks < 2) { + CPoint pts[Poly::MAX_VERTS]; + + // find all selected polys: + ListIter s_iter = model->GetSurfaces(); + while (++s_iter) { + Surface* s = s_iter.value(); + + if (s->IsHidden() || s->IsLocked() || s->IsSimplified()) + continue; + + for (int i = 0; i < s->NumPolys(); i++) { + Poly* poly = s->GetPolys() + i; + + if (poly->nverts < 3) + continue; + + for (int v = 0; v < poly->nverts; v++) + pts[v] = view->ProjectPoint(s->GetVertexSet()->loc[poly->verts[v]]); + + CRgn rgn; + rgn.CreatePolygonRgn(pts, poly->nverts, ALTERNATE); + + if (rgn.PtInRegion(marks[0])) { + if (select_mode == SELECT_REMOVE) { + selection->RemovePoly(poly); + } + else { + selection->AddPoly(poly); + } + + for (int v = 0; v < poly->nverts; v++) { + WORD vert = poly->verts[v]; + if (select_mode == SELECT_REMOVE) { + selection->RemoveVert((WORD) s_iter.index(), vert); + } + else { + selection->AddVert((WORD) s_iter.index(), vert); + } + } + } + } + } + } + + // otherwise, build a region: + else { + CRgn rgn; + rgn.CreatePolygonRgn(marks, nmarks, WINDING); + + // find all selected verts: + ListIter s_iter = model->GetSurfaces(); + while (++s_iter) { + Surface* s = s_iter.value(); + VertexSet* vset = s->GetVertexSet(); + + if (s->IsHidden() || s->IsLocked() || s->IsSimplified()) + continue; + + for (WORD i = 0; i < vset->nverts; i++) { + CPoint p = view->ProjectPoint(s->GetVertexSet()->loc[i]); + if (rgn.PtInRegion(p)) { + if (select_mode == SELECT_REMOVE) { + selection->RemoveVert((WORD) s_iter.index(), i); + } + else { + selection->AddVert((WORD) s_iter.index(), i); + } + } + } + + // find all selected polys: + for (int i = 0; i < s->NumPolys(); i++) { + Poly* poly = s->GetPolys() + i; + + bool will_select = true; + for (int v = 0; v < poly->nverts && will_select; v++) + will_select = will_select && + selection->Contains((WORD) s_iter.index(), poly->verts[v]); + + if (will_select) + selection->AddPoly(poly); + else + selection->RemovePoly(poly); + } + } + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::UseModel(Model* m) +{ + model = m; + + if (selection) + selection->UseModel(model); +} + +// +----------------------------------------------------------------------+ + +void +Selector::SelectAll(int select_mode) +{ + Clear(); + + if (model && select_mode != SELECT_REMOVE) { + ListIter iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + + for (int i = 0; i < s->NumPolys(); i++) { + selection->GetPolys().append(s->GetPolys() + i); + } + + for (int i = 0; i < s->NumVerts(); i++) { + DWORD value = (iter.index() << 16) | i; + selection->GetVerts().push_back(value); + } + } + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::SelectInverse() +{ + if (model && selection) { + ListIter iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + WORD s_index = iter.index(); + + for (int i = 0; i < s->NumPolys(); i++) { + Poly* p = s->GetPolys() + i; + + if (selection->Contains(p)) + selection->RemovePoly(p); + else + selection->AddPoly(p); + } + + for (int i = 0; i < s->NumVerts(); i++) { + if (selection->Contains(s_index, i)) + selection->RemoveVert(s_index, i); + else + selection->AddVert(s_index, i); + } + } + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::SelectSurface(Surface* s, int select_mode) +{ + if (!s || !model) + return; + + WORD index = (WORD) model->GetSurfaces().index(s); + + if (select_mode == SELECT_REMOVE) { + for (int i = 0; i < s->NumPolys(); i++) { + selection->RemovePoly(s->GetPolys() + i); + } + + for (int i = 0; i < s->NumVerts(); i++) { + selection->RemoveVert(index, i); + } + } + else { + for (WORD i = 0; i < s->NumPolys(); i++) { + selection->AddPoly(s->GetPolys() + i); + } + + for (int i = 0; i < s->NumVerts(); i++) { + selection->AddVert(index, i); + } + } +} + +void +Selector::SelectVert(Surface* s, int v, int select_mode) +{ + if (!s || !model) + return; + + WORD index = (WORD) model->GetSurfaces().index(s); + + if (select_mode == SELECT_REMOVE) { + selection->RemoveVert(index, (WORD) v); + } + else { + selection->AddVert(index, (WORD) v); + } +} + +void +Selector::SelectPoly(Poly* poly, int select_mode) +{ + if (!poly || !model) + return; + + if (select_mode == SELECT_REMOVE) { + selection->RemovePoly(poly); + } + else { + selection->AddPoly(poly); + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::SelectMaterial(Material* m, int select_mode) +{ + if (select_mode == SELECT_REPLACE) + Clear(); + + if (model && select_mode != SELECT_REMOVE) { + ListIter iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + WORD s_index = iter.index(); + + for (int i = 0; i < s->NumPolys(); i++) { + Poly* p = s->GetPolys() + i; + + if (p->material == m) { + selection->AddPoly(p); + + for (int v = 0; v < p->nverts; v++) { + selection->AddVert(s_index, p->verts[v]); + } + } + } + } + } +} + +// +----------------------------------------------------------------------+ + +void +Selector::Reselect() +{ + selection->GetPolys().clear(); + + if (model) { + ListIter iter = model->GetSurfaces(); + + while (++iter) { + Surface* s = iter.value(); + WORD s_index = iter.index(); + + // find all selected polys: + for (int i = 0; i < s->NumPolys(); i++) { + Poly* poly = s->GetPolys() + i; + + bool will_select = true; + for (int v = 0; v < poly->nverts && will_select; v++) + will_select = will_select && + selection->Contains(s_index, poly->verts[v]); + + if (will_select) + selection->AddPoly(poly); + } + } + } +} diff --git a/Magic2/Selector.h b/Magic2/Selector.h index 2962b59..524cccb 100644 --- a/Magic2/Selector.h +++ b/Magic2/Selector.h @@ -1,76 +1,100 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Selector.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Class definition for Selector (free-form selection tool) -*/ - -#ifndef Selector_h -#define Selector_h - -#include "Polygon.h" -#include "Graphic.h" -#include "Video.h" - -class ModelView; -class Model; -class Selection; -class Surface; - -// +----------------------------------------------------------------------+ - -class Selector : public Graphic -{ -public: - Selector(Selection* s=0); - virtual ~Selector(); - - enum SELECT_MODE { SELECT_REMOVE=-1, SELECT_REPLACE=0, SELECT_APPEND=1 }; - - // Operations - virtual void Render(Video* video, DWORD flags); - virtual bool CheckVisibility(Projector& projector) { return true; } - - void Clear(); - void Begin(Model* m, int mode, int select_mode = SELECT_REPLACE); - void AddMark(CPoint& p); - void End(); - - bool IsActive() const { return view_mode ? true : false; } - int GetViewMode() const { return view_mode; } - Selection* GetSelection() const { return selection; } - - void UseModel(Model* m); - void SelectAll(int select_mode = SELECT_REPLACE); - void SelectInverse(); - void SelectSurface(Surface* s, int select_mode = SELECT_REPLACE); - void SelectVert(Surface* s, int v, int select_mode = SELECT_REPLACE); - void SelectPoly(Poly* p, int select_mode = SELECT_REPLACE); - void SelectMaterial(Material* m, int select_mode = SELECT_REPLACE); - - void Reselect(); - -protected: - enum { MAX_MARK = 4096 }; - - int view_mode; - int nmarks; - CPoint marks[MAX_MARK]; - int select_mode; - - bool own_selection; - Selection* selection; - Model* model; -}; - - -// +----------------------------------------------------------------------+ - -#endif Selector_h +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Selector.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Class definition for Selector (free-form selection tool) +*/ + +#ifndef Selector_h +#define Selector_h + +#include "Polygon.h" +#include "Graphic.h" +#include "Video.h" + +class ModelView; +class Model; +class Selection; +class Surface; + +// +----------------------------------------------------------------------+ + +class Selector : public Graphic +{ +public: + Selector(Selection* s=0); + virtual ~Selector(); + + enum SELECT_MODE { SELECT_REMOVE=-1, SELECT_REPLACE=0, SELECT_APPEND=1 }; + + // Operations + virtual void Render(Video* video, DWORD flags); + virtual bool CheckVisibility(Projector& projector) { return true; } + + void Clear(); + void Begin(Model* m, int mode, int select_mode = SELECT_REPLACE); + void AddMark(CPoint& p); + void End(); + + bool IsActive() const { return view_mode ? true : false; } + int GetViewMode() const { return view_mode; } + Selection* GetSelection() const { return selection; } + + void UseModel(Model* m); + void SelectAll(int select_mode = SELECT_REPLACE); + void SelectInverse(); + void SelectSurface(Surface* s, int select_mode = SELECT_REPLACE); + void SelectVert(Surface* s, int v, int select_mode = SELECT_REPLACE); + void SelectPoly(Poly* p, int select_mode = SELECT_REPLACE); + void SelectMaterial(Material* m, int select_mode = SELECT_REPLACE); + + void Reselect(); + +protected: + enum { MAX_MARK = 4096 }; + + int view_mode; + int nmarks; + CPoint marks[MAX_MARK]; + int select_mode; + + bool own_selection; + Selection* selection; + Model* model; +}; + + +// +----------------------------------------------------------------------+ + +#endif Selector_h diff --git a/Magic2/StdAfx.cpp b/Magic2/StdAfx.cpp index c2d4ca6..d244fd1 100644 --- a/Magic2/StdAfx.cpp +++ b/Magic2/StdAfx.cpp @@ -1,8 +1,8 @@ -// stdafx.cpp : source file that includes just the standard includes -// Magic.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// stdafx.cpp : source file that includes just the standard includes +// Magic.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/Magic2/StdAfx.h b/Magic2/StdAfx.h index d6a3e3a..36a4cb6 100644 --- a/Magic2/StdAfx.h +++ b/Magic2/StdAfx.h @@ -1,46 +1,46 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_) -#define AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define WIN32_LEAN_AND_MEAN - -#if _MSC_VER <= 1600 -#define _WIN32_WINNT 0x0502 // XP is the lowest supported OS -#else -#define _WIN32_WINNT 0x0600 // VS2012 does not support XP, 0x0600 is Vista -#endif - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -// Enable extra D3D debugging in debug builds if using the debug DirectX runtime. -// This makes D3D objects work well in the debugger watch window, but slows down -// performance slightly. -#if defined(DEBUG) | defined(_DEBUG) -#define D3D_DEBUG_INFO -#endif - -// Direct3D includes -#include -#include -#include -#include - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_) +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_) +#define AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN + +#if _MSC_VER <= 1600 +#define _WIN32_WINNT 0x0502 // XP is the lowest supported OS +#else +#define _WIN32_WINNT 0x0600 // VS2012 does not support XP, 0x0600 is Vista +#endif + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// Enable extra D3D debugging in debug builds if using the debug DirectX runtime. +// This makes D3D objects work well in the debugger watch window, but slows down +// performance slightly. +#if defined(DEBUG) | defined(_DEBUG) +#define D3D_DEBUG_INFO +#endif + +// Direct3D includes +#include +#include +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__E37C2030_8F5E_4A38_92DD_72F0EAE0DA81__INCLUDED_) diff --git a/Magic2/SurfacePropertiesDialog.cpp b/Magic2/SurfacePropertiesDialog.cpp index d6fd7f4..a4a845c 100644 --- a/Magic2/SurfacePropertiesDialog.cpp +++ b/Magic2/SurfacePropertiesDialog.cpp @@ -1,93 +1,119 @@ -// SurfacePropertiesDialog.cpp : implementation file -// - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "MagicView.h" -#include "Solid.h" -#include "SurfacePropertiesDialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// SurfacePropertiesDialog dialog - - -SurfacePropertiesDialog::SurfacePropertiesDialog(MagicView* pParent /*=NULL*/) - : CDialog(SurfacePropertiesDialog::IDD, pParent), doc(0) -{ - //{{AFX_DATA_INIT(SurfacePropertiesDialog) - mSurfaceName = _T(""); - mNumPolys = _T(""); - mNumVerts = _T(""); - mSurfaceHeight = _T(""); - mSurfaceLength = _T(""); - mSurfaceRadius = _T(""); - mSurfaceWidth = _T(""); - //}}AFX_DATA_INIT - - if (pParent) { - doc = pParent->GetDocument(); - - if (doc && doc->GetSolid()) { - Model* model = doc->GetSolid()->GetModel(); - Surface* surface = model->GetSurfaces().first(); - Point plus; - Point minus; - - surface->GetVertexSet()->CalcExtents(plus, minus); - - char buffer[256]; - strcpy_s(buffer, surface->Name()); - mSurfaceName = buffer; - - sprintf_s(buffer, "%d", surface->NumPolys()); - mNumPolys = buffer; - - sprintf_s(buffer, "%d", surface->NumVerts()); - mNumVerts = buffer; - - sprintf_s(buffer, "%.1f", surface->Radius()); - mSurfaceRadius = buffer; - - sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.z-minus.z, minus.z, plus.z); - mSurfaceLength = buffer; - - sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.x-minus.x, minus.x, plus.x); - mSurfaceWidth = buffer; - - sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.y-minus.y, minus.y, plus.y); - mSurfaceHeight = buffer; - } - } -} - - -void SurfacePropertiesDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(SurfacePropertiesDialog) - DDX_CBString(pDX, IDC_SURFACE_NAME, mSurfaceName); - DDX_Text(pDX, IDC_SURFACE_NPOLYS, mNumPolys); - DDX_Text(pDX, IDC_SURFACE_NVERTS, mNumVerts); - DDX_Text(pDX, IDC_SURFACE_HEIGHT, mSurfaceHeight); - DDX_Text(pDX, IDC_SURFACE_LENGTH, mSurfaceLength); - DDX_Text(pDX, IDC_SURFACE_RADIUS, mSurfaceRadius); - DDX_Text(pDX, IDC_SURFACE_WIDTH, mSurfaceWidth); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(SurfacePropertiesDialog, CDialog) - //{{AFX_MSG_MAP(SurfacePropertiesDialog) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// SurfacePropertiesDialog message handlers +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "MagicView.h" +#include "Solid.h" +#include "SurfacePropertiesDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// SurfacePropertiesDialog dialog + + +SurfacePropertiesDialog::SurfacePropertiesDialog(MagicView* pParent /*=NULL*/) + : CDialog(SurfacePropertiesDialog::IDD, pParent), doc(0) +{ + //{{AFX_DATA_INIT(SurfacePropertiesDialog) + mSurfaceName = _T(""); + mNumPolys = _T(""); + mNumVerts = _T(""); + mSurfaceHeight = _T(""); + mSurfaceLength = _T(""); + mSurfaceRadius = _T(""); + mSurfaceWidth = _T(""); + //}}AFX_DATA_INIT + + if (pParent) { + doc = pParent->GetDocument(); + + if (doc && doc->GetSolid()) { + Model* model = doc->GetSolid()->GetModel(); + Surface* surface = model->GetSurfaces().first(); + Point plus; + Point minus; + + surface->GetVertexSet()->CalcExtents(plus, minus); + + char buffer[256]; + strcpy_s(buffer, surface->Name()); + mSurfaceName = buffer; + + sprintf_s(buffer, "%d", surface->NumPolys()); + mNumPolys = buffer; + + sprintf_s(buffer, "%d", surface->NumVerts()); + mNumVerts = buffer; + + sprintf_s(buffer, "%.1f", surface->Radius()); + mSurfaceRadius = buffer; + + sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.z-minus.z, minus.z, plus.z); + mSurfaceLength = buffer; + + sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.x-minus.x, minus.x, plus.x); + mSurfaceWidth = buffer; + + sprintf_s(buffer, "%.1f (%.1f - %.1f)", plus.y-minus.y, minus.y, plus.y); + mSurfaceHeight = buffer; + } + } +} + + +void SurfacePropertiesDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(SurfacePropertiesDialog) + DDX_CBString(pDX, IDC_SURFACE_NAME, mSurfaceName); + DDX_Text(pDX, IDC_SURFACE_NPOLYS, mNumPolys); + DDX_Text(pDX, IDC_SURFACE_NVERTS, mNumVerts); + DDX_Text(pDX, IDC_SURFACE_HEIGHT, mSurfaceHeight); + DDX_Text(pDX, IDC_SURFACE_LENGTH, mSurfaceLength); + DDX_Text(pDX, IDC_SURFACE_RADIUS, mSurfaceRadius); + DDX_Text(pDX, IDC_SURFACE_WIDTH, mSurfaceWidth); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(SurfacePropertiesDialog, CDialog) + //{{AFX_MSG_MAP(SurfacePropertiesDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// SurfacePropertiesDialog message handlers diff --git a/Magic2/SurfacePropertiesDialog.h b/Magic2/SurfacePropertiesDialog.h index ae9f687..71a7703 100644 --- a/Magic2/SurfacePropertiesDialog.h +++ b/Magic2/SurfacePropertiesDialog.h @@ -1,73 +1,97 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2005. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: SurfacePropertiesDialog.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Surface Properties Dialog interface file -*/ - -#if !defined(AFX_SURFACEPROPERTIESDIALOG_H__8121A894_106E_4A17_9CE1_ADDD88F6A0CD__INCLUDED_) -#define AFX_SURFACEPROPERTIESDIALOG_H__8121A894_106E_4A17_9CE1_ADDD88F6A0CD__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// +--------------------------------------------------------------------+ - -class Bitmap; -class MagicDoc; -class MagicView; -class Model; - -// +--------------------------------------------------------------------+ -// SurfacePropertiesDialog dialog -// +--------------------------------------------------------------------+ - -class SurfacePropertiesDialog : public CDialog -{ -// Construction -public: - SurfacePropertiesDialog(MagicView* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(SurfacePropertiesDialog) - enum { IDD = IDD_SURFACE_PROPS }; - CString mSurfaceName; - CString mNumPolys; - CString mNumVerts; - CString mSurfaceHeight; - CString mSurfaceLength; - CString mSurfaceRadius; - CString mSurfaceWidth; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(SurfacePropertiesDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - MagicDoc* doc; - - // Generated message map functions - //{{AFX_MSG(SurfacePropertiesDialog) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: SurfacePropertiesDialog.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Surface Properties Dialog interface file +*/ + +#if !defined(AFX_SURFACEPROPERTIESDIALOG_H__8121A894_106E_4A17_9CE1_ADDD88F6A0CD__INCLUDED_) +#define AFX_SURFACEPROPERTIESDIALOG_H__8121A894_106E_4A17_9CE1_ADDD88F6A0CD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// +--------------------------------------------------------------------+ + +class Bitmap; +class MagicDoc; +class MagicView; +class Model; + +// +--------------------------------------------------------------------+ +// SurfacePropertiesDialog dialog +// +--------------------------------------------------------------------+ + +class SurfacePropertiesDialog : public CDialog +{ +// Construction +public: + SurfacePropertiesDialog(MagicView* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(SurfacePropertiesDialog) + enum { IDD = IDD_SURFACE_PROPS }; + CString mSurfaceName; + CString mNumPolys; + CString mNumVerts; + CString mSurfaceHeight; + CString mSurfaceLength; + CString mSurfaceRadius; + CString mSurfaceWidth; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(SurfacePropertiesDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + MagicDoc* doc; + + // Generated message map functions + //{{AFX_MSG(SurfacePropertiesDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif diff --git a/Magic2/TexCubeDX9.cpp b/Magic2/TexCubeDX9.cpp index c623215..49bb607 100644 --- a/Magic2/TexCubeDX9.cpp +++ b/Magic2/TexCubeDX9.cpp @@ -1,120 +1,144 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: TexDX9.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Direct3D Texture Cache -*/ - -#include "MemDebug.h" -#include "TexCubeDX9.h" -#include "VideoDX9.h" -#include "Bitmap.h" -#include "Color.h" - -// +--------------------------------------------------------------------+ - -void Print(const char* fmt, ...); -void VideoDX9Error(const char* msg, HRESULT err); - -#ifndef RELEASE -#define RELEASE(x) if (x) { x->Release(); x=NULL; } -#endif - -// +--------------------------------------------------------------------+ - -TexCubeDX9::TexCubeDX9(VideoDX9* v) -: video(v), texture(0) -{ - d3d = video->Direct3D(); - d3ddevice = video->D3DDevice(); - - for (int i = 0; i < 6; i++) { - faces[i] = 0; - last_modified[i] = 0; - } -} - -TexCubeDX9::~TexCubeDX9() -{ - RELEASE(texture); -} - -// +--------------------------------------------------------------------+ - -bool -TexCubeDX9::LoadTexture(Bitmap* bmp, int face_index) -{ - if (!d3ddevice) return false; - - if (faces[face_index] == bmp && last_modified[face_index] >= bmp->LastModified()) - return true; // already loaded and hasn't been modified - - HRESULT hr = D3D_OK; - - // create the texture, if necessary - if (!texture) { - hr = d3ddevice->CreateCubeTexture(bmp->Width(), - 1, // one mip level - 0, // no specific usage - D3DFMT_A8R8G8B8, // format matching Color::rgba - D3DPOOL_MANAGED, - &texture, - 0); - - if (FAILED(hr) || !texture) { - VideoDX9Error("LoadTexture - could not create cube texture", hr); - return false; - } - } - - // lock the surface for writing - D3DLOCKED_RECT locked_rect; - D3DCUBEMAP_FACES face = (D3DCUBEMAP_FACES) face_index; - hr = texture->LockRect(face, 0, &locked_rect, 0, 0); - - if (FAILED(hr)) { - VideoDX9Error("LoadTexture - could not lock texture surface", hr); - RELEASE(texture); - return false; - } - - // load the bitmap into the texture surface - for (int i = 0; i < bmp->Height(); i++) { - BYTE* src = (BYTE*) (bmp->HiPixels() + i * bmp->Width()); - BYTE* dst = (BYTE*) locked_rect.pBits + i * locked_rect.Pitch; - - CopyMemory(dst, src, bmp->Width() * sizeof(Color)); - } - - // unlock the surface - texture->UnlockRect(face, 0); - - faces[face_index] = bmp; - last_modified[face_index] = bmp->LastModified(); - - return true; -} - -// +--------------------------------------------------------------------+ - -IDirect3DCubeTexture9* -TexCubeDX9::GetTexture() -{ - if (texture) { - // need to refresh anything? - for (int i = 0; i < 6; i++) { - if (faces[i] && last_modified[i] < faces[i]->LastModified()) { - LoadTexture(faces[i], i); - } - } - } - - return texture; -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: TexDX9.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Direct3D Texture Cache +*/ + +#include "MemDebug.h" +#include "TexCubeDX9.h" +#include "VideoDX9.h" +#include "Bitmap.h" +#include "Color.h" + +// +--------------------------------------------------------------------+ + +void Print(const char* fmt, ...); +void VideoDX9Error(const char* msg, HRESULT err); + +#ifndef RELEASE +#define RELEASE(x) if (x) { x->Release(); x=NULL; } +#endif + +// +--------------------------------------------------------------------+ + +TexCubeDX9::TexCubeDX9(VideoDX9* v) +: video(v), texture(0) +{ + d3d = video->Direct3D(); + d3ddevice = video->D3DDevice(); + + for (int i = 0; i < 6; i++) { + faces[i] = 0; + last_modified[i] = 0; + } +} + +TexCubeDX9::~TexCubeDX9() +{ + RELEASE(texture); +} + +// +--------------------------------------------------------------------+ + +bool +TexCubeDX9::LoadTexture(Bitmap* bmp, int face_index) +{ + if (!d3ddevice) return false; + + if (faces[face_index] == bmp && last_modified[face_index] >= bmp->LastModified()) + return true; // already loaded and hasn't been modified + + HRESULT hr = D3D_OK; + + // create the texture, if necessary + if (!texture) { + hr = d3ddevice->CreateCubeTexture(bmp->Width(), + 1, // one mip level + 0, // no specific usage + D3DFMT_A8R8G8B8, // format matching Color::rgba + D3DPOOL_MANAGED, + &texture, + 0); + + if (FAILED(hr) || !texture) { + VideoDX9Error("LoadTexture - could not create cube texture", hr); + return false; + } + } + + // lock the surface for writing + D3DLOCKED_RECT locked_rect; + D3DCUBEMAP_FACES face = (D3DCUBEMAP_FACES) face_index; + hr = texture->LockRect(face, 0, &locked_rect, 0, 0); + + if (FAILED(hr)) { + VideoDX9Error("LoadTexture - could not lock texture surface", hr); + RELEASE(texture); + return false; + } + + // load the bitmap into the texture surface + for (int i = 0; i < bmp->Height(); i++) { + BYTE* src = (BYTE*) (bmp->HiPixels() + i * bmp->Width()); + BYTE* dst = (BYTE*) locked_rect.pBits + i * locked_rect.Pitch; + + CopyMemory(dst, src, bmp->Width() * sizeof(Color)); + } + + // unlock the surface + texture->UnlockRect(face, 0); + + faces[face_index] = bmp; + last_modified[face_index] = bmp->LastModified(); + + return true; +} + +// +--------------------------------------------------------------------+ + +IDirect3DCubeTexture9* +TexCubeDX9::GetTexture() +{ + if (texture) { + // need to refresh anything? + for (int i = 0; i < 6; i++) { + if (faces[i] && last_modified[i] < faces[i]->LastModified()) { + LoadTexture(faces[i], i); + } + } + } + + return texture; +} diff --git a/Magic2/TexCubeDX9.h b/Magic2/TexCubeDX9.h index 686bcb9..b636677 100644 --- a/Magic2/TexCubeDX9.h +++ b/Magic2/TexCubeDX9.h @@ -1,49 +1,73 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2006. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: TexCubeDX9.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Direct 3D Texture Cube for Env Mapping -*/ - -#ifndef TexCubeDX9_h -#define TexCubeDX9_h - -#include "Bitmap.h" - -// +--------------------------------------------------------------------+ - -class Video; -class VideoDX9; -class Bitmap; -struct VD3D_texture_format; - -// +--------------------------------------------------------------------+ - -class TexCubeDX9 -{ -public: - TexCubeDX9(VideoDX9* video); - virtual ~TexCubeDX9(); - - IDirect3DCubeTexture9* GetTexture(); - bool LoadTexture(Bitmap* bmp, int face); - -private: - VideoDX9* video; - IDirect3D9* d3d; - IDirect3DDevice9* d3ddevice; - - IDirect3DCubeTexture9* texture; - Bitmap* faces[6]; - DWORD last_modified[6]; -}; - -#endif // TexCubeDX9_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: TexCubeDX9.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Direct 3D Texture Cube for Env Mapping +*/ + +#ifndef TexCubeDX9_h +#define TexCubeDX9_h + +#include "Bitmap.h" + +// +--------------------------------------------------------------------+ + +class Video; +class VideoDX9; +class Bitmap; +struct VD3D_texture_format; + +// +--------------------------------------------------------------------+ + +class TexCubeDX9 +{ +public: + TexCubeDX9(VideoDX9* video); + virtual ~TexCubeDX9(); + + IDirect3DCubeTexture9* GetTexture(); + bool LoadTexture(Bitmap* bmp, int face); + +private: + VideoDX9* video; + IDirect3D9* d3d; + IDirect3DDevice9* d3ddevice; + + IDirect3DCubeTexture9* texture; + Bitmap* faces[6]; + DWORD last_modified[6]; +}; + +#endif // TexCubeDX9_h + diff --git a/Magic2/TextureMapDialog.cpp b/Magic2/TextureMapDialog.cpp index e62e066..f7085a1 100644 --- a/Magic2/TextureMapDialog.cpp +++ b/Magic2/TextureMapDialog.cpp @@ -1,185 +1,209 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: TextureMapDialog.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Texture Mapping Dialog implementation file -*/ - - -#include "stdafx.h" -#include "Magic.h" -#include "MagicDoc.h" -#include "MagicView.h" -#include "Selection.h" -#include "TextureMapDialog.h" -#include "Thumbnail.h" - -#include "Bitmap.h" -#include "Solid.h" -#include "Polygon.h" -#include "Pcx.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// +--------------------------------------------------------------------+ -// TextureMapDialog dialog -// +--------------------------------------------------------------------+ - -TextureMapDialog::TextureMapDialog(MagicView* pParent) - : CDialog(TextureMapDialog::IDD, pParent), doc(0), material(0), model(0), blank(0) -{ - //{{AFX_DATA_INIT(TextureMapDialog) - mMaterialIndex = -1; - mFlip = FALSE; - mMirror = FALSE; - mRotate = FALSE; - mScaleV = 0.0; - mAxis = -1; - mScaleU = 0.0; - mMapType = -1; - //}}AFX_DATA_INIT - - Color gray = Color::LightGray; - blank = new Bitmap(1,1,&gray); - blank->ScaleTo(128,128); - - if (pParent) { - doc = pParent->GetDocument(); - - if (doc && doc->GetSolid()) { - model = doc->GetSolid()->GetModel(); - } - - if (doc && doc->GetSelection()) { - Selection* seln = doc->GetSelection(); - - if (seln->GetPolys().size() > 0) { - material = seln->GetPolys().first()->material; - mMaterialIndex = model->GetMaterials().index(material) + 1; - } - } - } -} - -TextureMapDialog::~TextureMapDialog() -{ - delete blank; -} - -void TextureMapDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(TextureMapDialog) - DDX_Control(pDX, IDC_MAPPING, mMapping); - DDX_Control(pDX, IDC_MATERIAL, mMaterialList); - DDX_Control(pDX, IDC_TEXTURE_PREVIEW, mMaterialThumb); - DDX_CBIndex(pDX, IDC_MATERIAL, mMaterialIndex); - DDX_Check(pDX, IDC_ALIGN_FLIP, mFlip); - DDX_Check(pDX, IDC_ALIGN_MIRROR, mMirror); - DDX_Check(pDX, IDC_ALIGN_ROTATE, mRotate); - DDX_Text(pDX, IDC_SCALE_V, mScaleV); - DDX_Radio(pDX, IDC_ALIGN_X, mAxis); - DDX_Text(pDX, IDC_SCALE_U, mScaleU); - DDX_CBIndex(pDX, IDC_MAPPING, mMapType); - //}}AFX_DATA_MAP - - if (pDX->m_bSaveAndValidate) { - mMaterialIndex = mMaterialList.GetCurSel()-1; - } -} - - -BEGIN_MESSAGE_MAP(TextureMapDialog, CDialog) - //{{AFX_MSG_MAP(TextureMapDialog) - ON_WM_PAINT() - ON_CBN_SELCHANGE(IDC_MATERIAL, OnSelectMaterial) - ON_BN_CLICKED(IDC_ALIGN_X, OnAlign) - ON_BN_CLICKED(IDC_ALIGN_Y, OnAlign) - ON_BN_CLICKED(IDC_ALIGN_Z, OnAlign) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// +--------------------------------------------------------------------+ -// TextureMapDialog message handlers -// +--------------------------------------------------------------------+ - -BOOL TextureMapDialog::OnInitDialog() -{ - CDialog::OnInitDialog(); - - mMaterialList.AddString(""); - - if (model && model->NumMaterials()) { - ListIter iter = model->GetMaterials(); - while (++iter) { - Material* mtl = iter.value(); - mMaterialList.AddString(mtl->name); - } - } - - mMaterialList.SetCurSel(mMaterialIndex); - mMapping.SetCurSel(0); - - if (material) { - material->CreateThumbnail(); - ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); - } - - return TRUE; -} - -// +--------------------------------------------------------------------+ - -void TextureMapDialog::OnPaint() -{ - CPaintDC dc(this); // device context for painting - - if (material && material->thumbnail) { - ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); - } - else { - ThumbPreview(mMaterialThumb.GetSafeHwnd(), blank); - } -} - -void TextureMapDialog::OnSelectMaterial() -{ - mMaterialIndex = mMaterialList.GetCurSel()-1; - material = 0; - - if (model && mMaterialIndex >= 0 && mMaterialIndex < model->NumMaterials()) { - material = model->GetMaterials()[mMaterialIndex]; - } - - if (material) { - material->CreateThumbnail(); - ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); - } - else { - ThumbPreview(mMaterialThumb.GetSafeHwnd(), blank); - } -} - -void TextureMapDialog::OnAlign() -{ - if (mMapping.GetCurSel() == 0) { - mMapping.SetCurSel(1); - UpdateData(TRUE); - - mScaleU = 1; - mScaleV = 1; - mMaterialIndex++; - UpdateData(FALSE); - } -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: TextureMapDialog.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Texture Mapping Dialog implementation file +*/ + + +#include "stdafx.h" +#include "Magic.h" +#include "MagicDoc.h" +#include "MagicView.h" +#include "Selection.h" +#include "TextureMapDialog.h" +#include "Thumbnail.h" + +#include "Bitmap.h" +#include "Solid.h" +#include "Polygon.h" +#include "Pcx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ +// TextureMapDialog dialog +// +--------------------------------------------------------------------+ + +TextureMapDialog::TextureMapDialog(MagicView* pParent) + : CDialog(TextureMapDialog::IDD, pParent), doc(0), material(0), model(0), blank(0) +{ + //{{AFX_DATA_INIT(TextureMapDialog) + mMaterialIndex = -1; + mFlip = FALSE; + mMirror = FALSE; + mRotate = FALSE; + mScaleV = 0.0; + mAxis = -1; + mScaleU = 0.0; + mMapType = -1; + //}}AFX_DATA_INIT + + Color gray = Color::LightGray; + blank = new Bitmap(1,1,&gray); + blank->ScaleTo(128,128); + + if (pParent) { + doc = pParent->GetDocument(); + + if (doc && doc->GetSolid()) { + model = doc->GetSolid()->GetModel(); + } + + if (doc && doc->GetSelection()) { + Selection* seln = doc->GetSelection(); + + if (seln->GetPolys().size() > 0) { + material = seln->GetPolys().first()->material; + mMaterialIndex = model->GetMaterials().index(material) + 1; + } + } + } +} + +TextureMapDialog::~TextureMapDialog() +{ + delete blank; +} + +void TextureMapDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(TextureMapDialog) + DDX_Control(pDX, IDC_MAPPING, mMapping); + DDX_Control(pDX, IDC_MATERIAL, mMaterialList); + DDX_Control(pDX, IDC_TEXTURE_PREVIEW, mMaterialThumb); + DDX_CBIndex(pDX, IDC_MATERIAL, mMaterialIndex); + DDX_Check(pDX, IDC_ALIGN_FLIP, mFlip); + DDX_Check(pDX, IDC_ALIGN_MIRROR, mMirror); + DDX_Check(pDX, IDC_ALIGN_ROTATE, mRotate); + DDX_Text(pDX, IDC_SCALE_V, mScaleV); + DDX_Radio(pDX, IDC_ALIGN_X, mAxis); + DDX_Text(pDX, IDC_SCALE_U, mScaleU); + DDX_CBIndex(pDX, IDC_MAPPING, mMapType); + //}}AFX_DATA_MAP + + if (pDX->m_bSaveAndValidate) { + mMaterialIndex = mMaterialList.GetCurSel()-1; + } +} + + +BEGIN_MESSAGE_MAP(TextureMapDialog, CDialog) + //{{AFX_MSG_MAP(TextureMapDialog) + ON_WM_PAINT() + ON_CBN_SELCHANGE(IDC_MATERIAL, OnSelectMaterial) + ON_BN_CLICKED(IDC_ALIGN_X, OnAlign) + ON_BN_CLICKED(IDC_ALIGN_Y, OnAlign) + ON_BN_CLICKED(IDC_ALIGN_Z, OnAlign) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// +--------------------------------------------------------------------+ +// TextureMapDialog message handlers +// +--------------------------------------------------------------------+ + +BOOL TextureMapDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + mMaterialList.AddString(""); + + if (model && model->NumMaterials()) { + ListIter iter = model->GetMaterials(); + while (++iter) { + Material* mtl = iter.value(); + mMaterialList.AddString(mtl->name); + } + } + + mMaterialList.SetCurSel(mMaterialIndex); + mMapping.SetCurSel(0); + + if (material) { + material->CreateThumbnail(); + ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); + } + + return TRUE; +} + +// +--------------------------------------------------------------------+ + +void TextureMapDialog::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + if (material && material->thumbnail) { + ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); + } + else { + ThumbPreview(mMaterialThumb.GetSafeHwnd(), blank); + } +} + +void TextureMapDialog::OnSelectMaterial() +{ + mMaterialIndex = mMaterialList.GetCurSel()-1; + material = 0; + + if (model && mMaterialIndex >= 0 && mMaterialIndex < model->NumMaterials()) { + material = model->GetMaterials()[mMaterialIndex]; + } + + if (material) { + material->CreateThumbnail(); + ThumbPreview(mMaterialThumb.GetSafeHwnd(), material->thumbnail); + } + else { + ThumbPreview(mMaterialThumb.GetSafeHwnd(), blank); + } +} + +void TextureMapDialog::OnAlign() +{ + if (mMapping.GetCurSel() == 0) { + mMapping.SetCurSel(1); + UpdateData(TRUE); + + mScaleU = 1; + mScaleV = 1; + mMaterialIndex++; + UpdateData(FALSE); + } +} diff --git a/Magic2/TextureMapDialog.h b/Magic2/TextureMapDialog.h index 3ca1791..aeb6f30 100644 --- a/Magic2/TextureMapDialog.h +++ b/Magic2/TextureMapDialog.h @@ -1,85 +1,109 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: TextureMapDialog.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Texture Mapping Dialog interface file -*/ - -#if !defined(AFX_TEXTUREMAPDIALOG_H__F8EDA550_FF19_4E91_9A9C_597FC357C563__INCLUDED_) -#define AFX_TEXTUREMAPDIALOG_H__F8EDA550_FF19_4E91_9A9C_597FC357C563__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -// +--------------------------------------------------------------------+ - -class Bitmap; -class MagicDoc; -class MagicView; -struct Material; -class Model; - -// +--------------------------------------------------------------------+ -// TextureMapDialog dialog -// +--------------------------------------------------------------------+ - -class TextureMapDialog : public CDialog -{ -// Construction -public: - TextureMapDialog(MagicView* pParent = NULL); - virtual ~TextureMapDialog(); - -// Dialog Data - //{{AFX_DATA(TextureMapDialog) - enum { IDD = IDD_MODIFY_TEXTURE }; - CComboBox mMapping; - CComboBox mMaterialList; - CStatic mMaterialThumb; - int mMaterialIndex; - BOOL mFlip; - BOOL mMirror; - BOOL mRotate; - double mScaleV; - int mAxis; - double mScaleU; - int mMapType; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(TextureMapDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - MagicDoc* doc; - Material* material; - Model* model; - Bitmap* blank; - - // Generated message map functions - //{{AFX_MSG(TextureMapDialog) - virtual BOOL OnInitDialog(); - afx_msg void OnPaint(); - afx_msg void OnSelectMaterial(); - afx_msg void OnAlign(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: TextureMapDialog.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Texture Mapping Dialog interface file +*/ + +#if !defined(AFX_TEXTUREMAPDIALOG_H__F8EDA550_FF19_4E91_9A9C_597FC357C563__INCLUDED_) +#define AFX_TEXTUREMAPDIALOG_H__F8EDA550_FF19_4E91_9A9C_597FC357C563__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// +--------------------------------------------------------------------+ + +class Bitmap; +class MagicDoc; +class MagicView; +struct Material; +class Model; + +// +--------------------------------------------------------------------+ +// TextureMapDialog dialog +// +--------------------------------------------------------------------+ + +class TextureMapDialog : public CDialog +{ +// Construction +public: + TextureMapDialog(MagicView* pParent = NULL); + virtual ~TextureMapDialog(); + +// Dialog Data + //{{AFX_DATA(TextureMapDialog) + enum { IDD = IDD_MODIFY_TEXTURE }; + CComboBox mMapping; + CComboBox mMaterialList; + CStatic mMaterialThumb; + int mMaterialIndex; + BOOL mFlip; + BOOL mMirror; + BOOL mRotate; + double mScaleV; + int mAxis; + double mScaleU; + int mMapType; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(TextureMapDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + MagicDoc* doc; + Material* material; + Model* model; + Bitmap* blank; + + // Generated message map functions + //{{AFX_MSG(TextureMapDialog) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg void OnSelectMaterial(); + afx_msg void OnAlign(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif diff --git a/Magic2/Thumbnail.cpp b/Magic2/Thumbnail.cpp index f855084..28bacbb 100644 --- a/Magic2/Thumbnail.cpp +++ b/Magic2/Thumbnail.cpp @@ -1,57 +1,81 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Thumbnail.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Thumbnail.cpp : implementation file -*/ - -#include "stdafx.h" -#include "Bitmap.h" - -// +--------------------------------------------------------------------+ -// Preview a bitmap image in the desired window -// +--------------------------------------------------------------------+ - -void ThumbPreview(HWND hprev, Bitmap* bitmap) -{ - HDC hdc = ::GetDC(hprev); - RECT rect; - BITMAPINFO* pbmiDIB = new BITMAPINFO; - - if (!pbmiDIB) - return; - - ::GetClientRect(hprev, &rect); - - pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - pbmiDIB->bmiHeader.biWidth = bitmap->Width(); - pbmiDIB->bmiHeader.biHeight = -bitmap->Height(); - pbmiDIB->bmiHeader.biPlanes = 1; - pbmiDIB->bmiHeader.biBitCount = 32; - pbmiDIB->bmiHeader.biCompression = BI_RGB; - pbmiDIB->bmiHeader.biSizeImage = 0; - pbmiDIB->bmiHeader.biXPelsPerMeter = 0; - pbmiDIB->bmiHeader.biYPelsPerMeter = 0; - pbmiDIB->bmiHeader.biClrUsed = 0; - pbmiDIB->bmiHeader.biClrImportant = 0; - - int result = - ::StretchDIBits(hdc, - 1, 1, 128, 128, - 0, 0, bitmap->Width(), bitmap->Height(), - bitmap->HiPixels(), - pbmiDIB, - DIB_RGB_COLORS, - SRCCOPY); - - ::ReleaseDC(hprev, hdc); - - delete pbmiDIB; -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Thumbnail.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Thumbnail.cpp : implementation file +*/ + +#include "stdafx.h" +#include "Bitmap.h" + +// +--------------------------------------------------------------------+ +// Preview a bitmap image in the desired window +// +--------------------------------------------------------------------+ + +void ThumbPreview(HWND hprev, Bitmap* bitmap) +{ + HDC hdc = ::GetDC(hprev); + RECT rect; + BITMAPINFO* pbmiDIB = new BITMAPINFO; + + if (!pbmiDIB) + return; + + ::GetClientRect(hprev, &rect); + + pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmiDIB->bmiHeader.biWidth = bitmap->Width(); + pbmiDIB->bmiHeader.biHeight = -bitmap->Height(); + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biBitCount = 32; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biSizeImage = 0; + pbmiDIB->bmiHeader.biXPelsPerMeter = 0; + pbmiDIB->bmiHeader.biYPelsPerMeter = 0; + pbmiDIB->bmiHeader.biClrUsed = 0; + pbmiDIB->bmiHeader.biClrImportant = 0; + + int result = + ::StretchDIBits(hdc, + 1, 1, 128, 128, + 0, 0, bitmap->Width(), bitmap->Height(), + bitmap->HiPixels(), + pbmiDIB, + DIB_RGB_COLORS, + SRCCOPY); + + ::ReleaseDC(hprev, hdc); + + delete pbmiDIB; +} diff --git a/Magic2/Thumbnail.h b/Magic2/Thumbnail.h index 1f7acfc..9300fb9 100644 --- a/Magic2/Thumbnail.h +++ b/Magic2/Thumbnail.h @@ -1,31 +1,55 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: Thumbnail.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Function declarations for thumbnail img previewer -*/ - -#ifndef Thumbnail_h -#define Thumbnail_h - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including 'Thumbnail.h' file for PCH -#endif - -// +--------------------------------------------------------------------+ - -class Bitmap; - -// +--------------------------------------------------------------------+ - -void ThumbPreview(HWND hprev, Bitmap* bitmap); - -#endif Thumbnail_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: Thumbnail.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Function declarations for thumbnail img previewer +*/ + +#ifndef Thumbnail_h +#define Thumbnail_h + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including 'Thumbnail.h' file for PCH +#endif + +// +--------------------------------------------------------------------+ + +class Bitmap; + +// +--------------------------------------------------------------------+ + +void ThumbPreview(HWND hprev, Bitmap* bitmap); + +#endif Thumbnail_h + diff --git a/Magic2/UVMapView.cpp b/Magic2/UVMapView.cpp index 673745f..d775b5c 100644 --- a/Magic2/UVMapView.cpp +++ b/Magic2/UVMapView.cpp @@ -1,450 +1,474 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: UVMapView.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the UVMapView class -*/ - -#include "stdafx.h" -#include "Magic.h" - -#include "MagicDoc.h" -#include "UVMapView.h" -#include "Selector.h" -#include "Selection.h" - -#include "ActiveWindow.h" -#include "Color.h" -#include "Screen.h" -#include "Video.h" - -DWORD GetRealTime(); - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// +--------------------------------------------------------------------+ - -UVMapView::UVMapView(Window* c) - : View(c), material(0), zoom(1), x_offset(0), y_offset(0), - nmarks(0), select_mode(SELECT_REPLACE), active(false) -{ -} - -UVMapView::~UVMapView() -{ -} - -// +--------------------------------------------------------------------+ - -const int BATCH_SIZE = 64; - -void -UVMapView::Refresh() -{ - video = Video::GetInstance(); - if (!video) - return; - - window->FillRect(window->GetRect(), Color::LightGray); - - if (material && material->tex_diffuse) { - Bitmap* bmp = material->tex_diffuse; - int w = bmp->Width(); - int h = bmp->Height(); - - double cx = window->Width() / 2 + x_offset; - double cy = window->Height() / 2 + y_offset; - - int x1 = (int) (cx - (zoom * w/2)); - int x2 = (int) (cx + (zoom * w/2)); - int y1 = (int) (cy - (zoom * h/2)); - int y2 = (int) (cy + (zoom * h/2)); - - window->DrawBitmap(x1, y1, x2, y2, bmp); - - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - VertexSet* vset = p->vertex_set; - - if (p->material != material) - continue; - - for (int i = 0; i < p->nverts; i++) { - int n1 = p->verts[i]; - int n2 = p->verts[0]; - if (i < p->nverts-1) - n2 = p->verts[i+1]; - - double tu1 = vset->tu[n1]; - double tv1 = vset->tv[n1]; - double tu2 = vset->tu[n2]; - double tv2 = vset->tv[n2]; - - x1 = (int) (cx + zoom * w * (tu1-0.5)); - x2 = (int) (cx + zoom * w * (tu2-0.5)); - y1 = (int) (cy + zoom * h * (tv1-0.5)); - y2 = (int) (cy + zoom * h * (tv2-0.5)); - - window->DrawLine(x1, y1, x2, y2, Color::Yellow); - - if (IsSelected(p, i)) - window->FillRect(x1-3, y1-3, x1+3, y1+3, Color::Yellow); - else - window->DrawRect(x1-2, y1-2, x1+2, y1+2, Color::Yellow); - } - } - } - - if (active && nmarks > 1) { - float points[4*BATCH_SIZE + 4]; - - for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) { - int end = batch + BATCH_SIZE; - if (end > nmarks-1) - end = nmarks-1; - int nlines = end-batch; - - for (int i = 0; i < nlines; i++) { - points[4*i+0] = (float) marks[batch + i].x; - points[4*i+1] = (float) marks[batch + i].y; - points[4*i+2] = (float) marks[batch + i + 1].x; - points[4*i+3] = (float) marks[batch + i + 1].y; - } - - video->DrawScreenLines(nlines, points, Color::Cyan); - } - } - - const char* title = "UV Editor"; - - int len = strlen(title); - Rect r(6,4,200,20); - - r.x += window->GetRect().x; - r.y += window->GetRect().y; - - video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); - - r.x--; - r.y--; - - video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); -} - -// +--------------------------------------------------------------------+ - -void -UVMapView::UseMaterial(Material* m) -{ - if (material != m) { - material = m; - zoom = 1; - x_offset = 0; - y_offset = 0; - } -} - -void -UVMapView::UsePolys(List& p) -{ - polys.clear(); - polys.append(p); -} - -void -UVMapView::MoveBy(double dx, double dy) -{ - x_offset += dx; - y_offset += dy; -} - -void -UVMapView::DragBy(double dx, double dy) -{ - if (!material || !material->tex_diffuse || selverts.size() < 1) - return; - - Bitmap* bmp = material->tex_diffuse; - double w = zoom * bmp->Width(); - double h = zoom * bmp->Height(); - float du = (float) (dx/w); - float dv = (float) (dy/h); - - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - DWORD value = *svi; - DWORD p = value >> 16; - DWORD n = value & 0xffff; - - Poly* poly = polys[p]; - if (poly && n < poly->nverts) { - VertexSet* vset = poly->vertex_set; - int v = poly->verts[n]; - - vset->tu[v] += du; - vset->tv[v] += dv; - } - } -} - -// +----------------------------------------------------------------------+ - -void -UVMapView::Clear() -{ - selverts.clear(); -} - -void -UVMapView::Begin(int seln_mode) -{ - nmarks = 0; - select_mode = seln_mode; - active = true; -} - -void -UVMapView::AddMark(CPoint& p) -{ - if (nmarks < MAX_MARK) - marks[nmarks++] = p; -} - -void -UVMapView::End() -{ - active = false; - - // get the model: - if (!nmarks || !material || !material->tex_diffuse) return; - - // if not adding to selection: - if (select_mode == SELECT_REPLACE) { - Clear(); - } - - Bitmap* bmp = material->tex_diffuse; - int w = bmp->Width(); - int h = bmp->Height(); - - double cx = window->Width() / 2 + x_offset; - double cy = window->Height() / 2 + y_offset; - - - // if only one mark: - if (nmarks < 2) { - // find all selected verts: - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - VertexSet* vset = p->vertex_set; - - for (int i = 0; i < p->nverts; i++) { - int n1 = p->verts[i]; - double tu1 = vset->tu[n1]; - double tv1 = vset->tv[n1]; - - int x1 = (int) (cx + zoom * w * (tu1-0.5)); - int y1 = (int) (cy + zoom * h * (tv1-0.5)); - - int dx = abs(marks[0].x - x1); - int dy = abs(marks[0].y - y1); - - if (dx < 4 && dy < 4) { - WORD p_index = iter.index(); - DWORD value = (p_index << 16) | i; - - if (select_mode == SELECT_REMOVE) { - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - if (*svi == value) { - selverts.erase(svi); - } - } - } - else { - bool contains = false; - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - if (*svi == value) { - contains = true; - } - } - if (!contains) - selverts.push_back(value); - } - } - } - } - } - - // otherwise, build a region: - else { - CRgn rgn; - rgn.CreatePolygonRgn(marks, nmarks, WINDING); - - // find all selected verts: - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - VertexSet* vset = p->vertex_set; - - for (int i = 0; i < p->nverts; i++) { - int n1 = p->verts[i]; - double tu1 = vset->tu[n1]; - double tv1 = vset->tv[n1]; - - int x1 = (int) (cx + zoom * w * (tu1-0.5)); - int y1 = (int) (cy + zoom * h * (tv1-0.5)); - - CPoint p(x1,y1); - - if (rgn.PtInRegion(p)) { - WORD p_index = iter.index(); - DWORD value = (p_index << 16) | i; - - if (select_mode == SELECT_REMOVE) { - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - if (*svi == value) - selverts.erase(svi); - } - } - else { - bool contains = false; - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - if (*svi == value) - contains = true; - } - if (!contains) - selverts.push_back(value); - } - } - } - } - } - - nmarks = 0; -} - -// +----------------------------------------------------------------------+ - -void -UVMapView::SelectAll() -{ - selverts.clear(); - - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - - if (p->material != material) - continue; - - for (int i = 0; i < p->nverts; i++) { - WORD p_index = iter.index(); - DWORD value = (p_index << 16) | i; - selverts.push_back(value); - } - } -} - -void -UVMapView::SelectNone() -{ - selverts.clear(); -} - -void -UVMapView::SelectInverse() -{ - ListIter iter = polys; - while (++iter) { - Poly* p = iter.value(); - - if (p->material != material) - continue; - - for (int i = 0; i < p->nverts; i++) { - WORD p_index = iter.index(); - DWORD value = (p_index << 16) | i; - - bool contains = false; - auto svi = selverts.begin(); - for (; svi != selverts.end(); ++svi) { - if (*svi == value) { - contains = true; - break; - } - } - - if (contains) - selverts.erase(svi); - else - selverts.push_back(value); - } - } -} - -bool -UVMapView::IsSelected(Poly* poly, WORD v) -{ - WORD p = polys.index(poly); - DWORD value = (p << 16) | v; - - bool contains = false; - - for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { - if (*svi == value) - return true; - } - - return false; -} - -bool -UVMapView::WillSelect(CPoint& p) -{ - if (!material || !material->tex_diffuse) - return false; - - Bitmap* bmp = material->tex_diffuse; - int w = bmp->Width(); - int h = bmp->Height(); - - double cx = window->Width() / 2 + x_offset; - double cy = window->Height() / 2 + y_offset; - - // find first selected vert: - ListIter iter = polys; - while (++iter) { - Poly* poly = iter.value(); - VertexSet* vset = poly->vertex_set; - - for (int i = 0; i < poly->nverts; i++) { - int n1 = poly->verts[i]; - double tu1 = vset->tu[n1]; - double tv1 = vset->tv[n1]; - - int x1 = (int) (cx + zoom * w * (tu1-0.5)); - int y1 = (int) (cy + zoom * h * (tv1-0.5)); - - int dx = abs(p.x - x1); - int dy = abs(p.y - y1); - - if (dx < 4 && dy < 4) { - return true; - } - } - } - - return false; -} +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: UVMapView.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the UVMapView class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "UVMapView.h" +#include "Selector.h" +#include "Selection.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Screen.h" +#include "Video.h" + +DWORD GetRealTime(); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// +--------------------------------------------------------------------+ + +UVMapView::UVMapView(Window* c) + : View(c), material(0), zoom(1), x_offset(0), y_offset(0), + nmarks(0), select_mode(SELECT_REPLACE), active(false) +{ +} + +UVMapView::~UVMapView() +{ +} + +// +--------------------------------------------------------------------+ + +const int BATCH_SIZE = 64; + +void +UVMapView::Refresh() +{ + video = Video::GetInstance(); + if (!video) + return; + + window->FillRect(window->GetRect(), Color::LightGray); + + if (material && material->tex_diffuse) { + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + int x1 = (int) (cx - (zoom * w/2)); + int x2 = (int) (cx + (zoom * w/2)); + int y1 = (int) (cy - (zoom * h/2)); + int y2 = (int) (cy + (zoom * h/2)); + + window->DrawBitmap(x1, y1, x2, y2, bmp); + + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + int n2 = p->verts[0]; + if (i < p->nverts-1) + n2 = p->verts[i+1]; + + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + double tu2 = vset->tu[n2]; + double tv2 = vset->tv[n2]; + + x1 = (int) (cx + zoom * w * (tu1-0.5)); + x2 = (int) (cx + zoom * w * (tu2-0.5)); + y1 = (int) (cy + zoom * h * (tv1-0.5)); + y2 = (int) (cy + zoom * h * (tv2-0.5)); + + window->DrawLine(x1, y1, x2, y2, Color::Yellow); + + if (IsSelected(p, i)) + window->FillRect(x1-3, y1-3, x1+3, y1+3, Color::Yellow); + else + window->DrawRect(x1-2, y1-2, x1+2, y1+2, Color::Yellow); + } + } + } + + if (active && nmarks > 1) { + float points[4*BATCH_SIZE + 4]; + + for (int batch = 0; batch < nmarks; batch += BATCH_SIZE) { + int end = batch + BATCH_SIZE; + if (end > nmarks-1) + end = nmarks-1; + int nlines = end-batch; + + for (int i = 0; i < nlines; i++) { + points[4*i+0] = (float) marks[batch + i].x; + points[4*i+1] = (float) marks[batch + i].y; + points[4*i+2] = (float) marks[batch + i + 1].x; + points[4*i+3] = (float) marks[batch + i + 1].y; + } + + video->DrawScreenLines(nlines, points, Color::Cyan); + } + } + + const char* title = "UV Editor"; + + int len = strlen(title); + Rect r(6,4,200,20); + + r.x += window->GetRect().x; + r.y += window->GetRect().y; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); + + r.x--; + r.y--; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); +} + +// +--------------------------------------------------------------------+ + +void +UVMapView::UseMaterial(Material* m) +{ + if (material != m) { + material = m; + zoom = 1; + x_offset = 0; + y_offset = 0; + } +} + +void +UVMapView::UsePolys(List& p) +{ + polys.clear(); + polys.append(p); +} + +void +UVMapView::MoveBy(double dx, double dy) +{ + x_offset += dx; + y_offset += dy; +} + +void +UVMapView::DragBy(double dx, double dy) +{ + if (!material || !material->tex_diffuse || selverts.size() < 1) + return; + + Bitmap* bmp = material->tex_diffuse; + double w = zoom * bmp->Width(); + double h = zoom * bmp->Height(); + float du = (float) (dx/w); + float dv = (float) (dy/h); + + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + DWORD value = *svi; + DWORD p = value >> 16; + DWORD n = value & 0xffff; + + Poly* poly = polys[p]; + if (poly && n < poly->nverts) { + VertexSet* vset = poly->vertex_set; + int v = poly->verts[n]; + + vset->tu[v] += du; + vset->tv[v] += dv; + } + } +} + +// +----------------------------------------------------------------------+ + +void +UVMapView::Clear() +{ + selverts.clear(); +} + +void +UVMapView::Begin(int seln_mode) +{ + nmarks = 0; + select_mode = seln_mode; + active = true; +} + +void +UVMapView::AddMark(CPoint& p) +{ + if (nmarks < MAX_MARK) + marks[nmarks++] = p; +} + +void +UVMapView::End() +{ + active = false; + + // get the model: + if (!nmarks || !material || !material->tex_diffuse) return; + + // if not adding to selection: + if (select_mode == SELECT_REPLACE) { + Clear(); + } + + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + + // if only one mark: + if (nmarks < 2) { + // find all selected verts: + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + int dx = abs(marks[0].x - x1); + int dy = abs(marks[0].y - y1); + + if (dx < 4 && dy < 4) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + if (select_mode == SELECT_REMOVE) { + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) { + selverts.erase(svi); + } + } + } + else { + bool contains = false; + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) { + contains = true; + } + } + if (!contains) + selverts.push_back(value); + } + } + } + } + } + + // otherwise, build a region: + else { + CRgn rgn; + rgn.CreatePolygonRgn(marks, nmarks, WINDING); + + // find all selected verts: + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + VertexSet* vset = p->vertex_set; + + for (int i = 0; i < p->nverts; i++) { + int n1 = p->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + CPoint p(x1,y1); + + if (rgn.PtInRegion(p)) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + if (select_mode == SELECT_REMOVE) { + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + selverts.erase(svi); + } + } + else { + bool contains = false; + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + contains = true; + } + if (!contains) + selverts.push_back(value); + } + } + } + } + } + + nmarks = 0; +} + +// +----------------------------------------------------------------------+ + +void +UVMapView::SelectAll() +{ + selverts.clear(); + + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + selverts.push_back(value); + } + } +} + +void +UVMapView::SelectNone() +{ + selverts.clear(); +} + +void +UVMapView::SelectInverse() +{ + ListIter iter = polys; + while (++iter) { + Poly* p = iter.value(); + + if (p->material != material) + continue; + + for (int i = 0; i < p->nverts; i++) { + WORD p_index = iter.index(); + DWORD value = (p_index << 16) | i; + + bool contains = false; + auto svi = selverts.begin(); + for (; svi != selverts.end(); ++svi) { + if (*svi == value) { + contains = true; + break; + } + } + + if (contains) + selverts.erase(svi); + else + selverts.push_back(value); + } + } +} + +bool +UVMapView::IsSelected(Poly* poly, WORD v) +{ + WORD p = polys.index(poly); + DWORD value = (p << 16) | v; + + bool contains = false; + + for (auto svi = selverts.begin(); svi != selverts.end(); ++svi) { + if (*svi == value) + return true; + } + + return false; +} + +bool +UVMapView::WillSelect(CPoint& p) +{ + if (!material || !material->tex_diffuse) + return false; + + Bitmap* bmp = material->tex_diffuse; + int w = bmp->Width(); + int h = bmp->Height(); + + double cx = window->Width() / 2 + x_offset; + double cy = window->Height() / 2 + y_offset; + + // find first selected vert: + ListIter iter = polys; + while (++iter) { + Poly* poly = iter.value(); + VertexSet* vset = poly->vertex_set; + + for (int i = 0; i < poly->nverts; i++) { + int n1 = poly->verts[i]; + double tu1 = vset->tu[n1]; + double tv1 = vset->tv[n1]; + + int x1 = (int) (cx + zoom * w * (tu1-0.5)); + int y1 = (int) (cy + zoom * h * (tv1-0.5)); + + int dx = abs(p.x - x1); + int dy = abs(p.y - y1); + + if (dx < 4 && dy < 4) { + return true; + } + } + } + + return false; +} diff --git a/Magic2/UVMapView.h b/Magic2/UVMapView.h index fb40cbf..10e63c7 100644 --- a/Magic2/UVMapView.h +++ b/Magic2/UVMapView.h @@ -1,82 +1,106 @@ -/* Project Magic 2.0 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Magic.exe - FILE: UVMapView.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Interface of the UVMapView class -*/ - - -#ifndef UVMapView_h -#define UVMapView_h - -#include -#include "View.h" -#include "Polygon.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -class Video; - -// +--------------------------------------------------------------------+ - -class UVMapView : public View -{ -public: - UVMapView(Window* c); - virtual ~UVMapView(); - - enum SELECT_MODE { SELECT_REMOVE=-1, SELECT_REPLACE=0, SELECT_APPEND=1 }; - - virtual void Refresh(); - - void UseMaterial(Material* m); - void UsePolys(List& p); - - void MoveBy(double dx, double dy); - void DragBy(double dx, double dy); - void ZoomIn() { zoom *= 1.15; } - void ZoomOut() { zoom *= 0.85; } - - void Clear(); - void Begin(int select_mode = SELECT_REPLACE); - void AddMark(CPoint& p); - void End(); - - bool IsActive() const { return active; } - void SelectAll(); - void SelectNone(); - void SelectInverse(); - - bool IsSelected(Poly* p, WORD v); - bool WillSelect(CPoint& p); - -protected: - enum { MAX_MARK = 4096 }; - - Material* material; - List polys; - Video* video; - - double zoom; - double x_offset; - double y_offset; - - int nmarks; - CPoint marks[MAX_MARK]; - int select_mode; - bool active; - - std::vector selverts; -}; - -// +--------------------------------------------------------------------+ - -#endif UVMapView_h +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: UVMapView.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Interface of the UVMapView class +*/ + + +#ifndef UVMapView_h +#define UVMapView_h + +#include +#include "View.h" +#include "Polygon.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +class Video; + +// +--------------------------------------------------------------------+ + +class UVMapView : public View +{ +public: + UVMapView(Window* c); + virtual ~UVMapView(); + + enum SELECT_MODE { SELECT_REMOVE=-1, SELECT_REPLACE=0, SELECT_APPEND=1 }; + + virtual void Refresh(); + + void UseMaterial(Material* m); + void UsePolys(List& p); + + void MoveBy(double dx, double dy); + void DragBy(double dx, double dy); + void ZoomIn() { zoom *= 1.15; } + void ZoomOut() { zoom *= 0.85; } + + void Clear(); + void Begin(int select_mode = SELECT_REPLACE); + void AddMark(CPoint& p); + void End(); + + bool IsActive() const { return active; } + void SelectAll(); + void SelectNone(); + void SelectInverse(); + + bool IsSelected(Poly* p, WORD v); + bool WillSelect(CPoint& p); + +protected: + enum { MAX_MARK = 4096 }; + + Material* material; + List polys; + Video* video; + + double zoom; + double x_offset; + double y_offset; + + int nmarks; + CPoint marks[MAX_MARK]; + int select_mode; + bool active; + + std::vector selverts; +}; + +// +--------------------------------------------------------------------+ + +#endif UVMapView_h diff --git a/Magic2/VideoDX9.cpp b/Magic2/VideoDX9.cpp index d3c623c..0c9e24d 100644 --- a/Magic2/VideoDX9.cpp +++ b/Magic2/VideoDX9.cpp @@ -1,3617 +1,3641 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: VideoDX9.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Direct3D Video class for DirectX 9 -*/ - -#include "MemDebug.h" -#include "VideoDX9.h" -#include "VideoDX9Enum.h" -#include "VideoDX9VertexBuffer.h" -#include "TexDX9.h" -#include "TexCubeDX9.h" -#include "Camera.h" -#include "Color.h" -#include "DataLoader.h" -#include "Polygon.h" -#include "Light.h" -#include "Solid.h" - -// +--------------------------------------------------------------------+ - -void Print(const char* msg, ...); -char* D3DErrStr(HRESULT dderr); -void VideoDX9Error(const char* msg, HRESULT dderr); -static TexCacheDX9* texcache = 0; -static TexCubeDX9* environment_cube = 0; -static bool surface_has_tangent_data = false; -static Light* main_light; -static Light* back_light; -static D3DXMATRIX matrixWorld; -static D3DXMATRIX matrixView; -static D3DXMATRIX matrixProj; -static D3DXMATRIX matrixWorldInverse; - -extern int VD3D_describe_things; - -#ifndef RELEASE -#define RELEASE(x) if (x) { x->Release(); x=NULL; } -#endif - -#ifndef F2DW -#define F2DW(x) (*(DWORD*)(&x)) -#endif - -#ifndef DW2I -#define DW2I(x) (*(int*)(&x)) -#endif - -// +--------------------------------------------------------------------+ - -typedef HRESULT (WINAPI * LPDDCE)(GUID FAR *, LPVOID *, REFIID , IUnknown FAR *); - -static D3DMATRIX identity_matrix = { - FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), - FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), FLOAT(1.0) -}; - -// +--------------------------------------------------------------------+ - -List model_clients; - -class VideoDX9SurfaceData : public VideoPrivateData -{ -public: - VideoDX9SurfaceData(Model* m) : model(m), vertex_buffer(0), index_buffer(0) { - if (!model_clients.contains(model)) - model_clients.append(model); - } - - virtual ~VideoDX9SurfaceData() { - model_clients.remove(model); - - delete vertex_buffer; - delete index_buffer; - } - - enum { TYPE = 9001 }; - virtual int GetType() const { return TYPE; } - - Model* model; - VideoDX9VertexBuffer* vertex_buffer; - VideoDX9IndexBuffer* index_buffer; -}; - -class VideoDX9SegmentData : public VideoPrivateData -{ -public: - VideoDX9SegmentData() : first_vert(0), num_verts(0), first_index(0), num_tris(0) { } - virtual ~VideoDX9SegmentData() { } - - enum { TYPE = 9002 }; - virtual int GetType() const { return TYPE; } - - int first_vert; - int num_verts; - int first_index; - int num_tris; -}; - -// +--------------------------------------------------------------------+ - -static int d3dstate_table[] = { - D3DRS_FILLMODE, // FILL_MODE - D3DRS_SHADEMODE, // SHADE_MODE - D3DRS_LIGHTING, // LIGHTING_ENABLE - D3DRS_ZENABLE, // Z_ENABLE - D3DRS_ZWRITEENABLE, // Z_WRITE_ENABLE - D3DRS_DEPTHBIAS, // Z_BIAS - 0, // TEXTURE_FILTER - D3DRS_DITHERENABLE, // DITHER_ENABLE - D3DRS_SPECULARENABLE, // SPECULAR_ENABLE - D3DRS_FOGENABLE, // FOG_ENABLE - D3DRS_FOGCOLOR, // FOG_COLOR - D3DRS_FOGDENSITY, // FOG_DENSITY - D3DRS_STENCILENABLE, // STENCIL_ENABLE - 0x11111111, // TEXTURE_WRAP (special case) - 0 // LIGHTING_PASS -}; - -static const int NUM_SCREEN_VERTS = 1024; -static const int NUM_SCREEN_INDICES = NUM_SCREEN_VERTS * 2; - -// +--------------------------------------------------------------------+ - -struct VideoDX9ScreenVertex -{ - FLOAT sx, sy, sz, rhw; - DWORD diffuse; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9ScreenVertex::FVF = D3DFVF_XYZRHW | -D3DFVF_DIFFUSE | -D3DFVF_TEX1; - -struct VideoDX9NormalVertex -{ - FLOAT x, y, z; - FLOAT nx, ny, nz; - FLOAT t0u, t0v; - FLOAT t1u, t1v; - FLOAT tx, ty, tz; - FLOAT bx, by, bz; - - static DWORD FVF; -}; - -DWORD VideoDX9NormalVertex::FVF = 0; - -// Global Vertex Declaration shared by shaders -D3DVERTEXELEMENT9 videoDX9NormalVertexElements[] = -{ - { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, - { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, - { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, - { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 }, - { 0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 }, - D3DDECL_END() -}; - -struct VideoDX9SolidVertex -{ - FLOAT x, y, z; - FLOAT nx, ny, nz; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9SolidVertex::FVF = D3DFVF_XYZ | -D3DFVF_NORMAL | -D3DFVF_TEX1 | -D3DFVF_TEXCOORDSIZE2(0); - -struct VideoDX9LuminousVertex -{ - FLOAT x, y, z; - DWORD diffuse; - FLOAT tu, tv; - - static DWORD FVF; -}; - -DWORD VideoDX9LuminousVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE | -D3DFVF_TEX1 | -D3DFVF_TEXCOORDSIZE2(0); - -struct VideoDX9DetailVertex -{ - FLOAT x, y, z; - DWORD diffuse; - DWORD specular; - FLOAT tu, tv; - FLOAT tu1, tv1; - - static DWORD FVF; -}; - -DWORD VideoDX9DetailVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE | -D3DFVF_SPECULAR | -D3DFVF_TEX2; - -struct VideoDX9LineVertex -{ - FLOAT x, y, z; - DWORD diffuse; - - static DWORD FVF; -}; - -DWORD VideoDX9LineVertex::FVF = D3DFVF_XYZ | -D3DFVF_DIFFUSE; - -enum { - DX9_STRATEGY_NONE, - DX9_STRATEGY_SIMPLE, - DX9_STRATEGY_GLOW, - DX9_STRATEGY_SPECMAP, - DX9_STRATEGY_EMISSIVE, - DX9_STRATEGY_SPEC_EMISSIVE, - DX9_STRATEGY_BLEND, - DX9_STRATEGY_BLEND_DETAIL -}; - -// +--------------------------------------------------------------------+ - -static VideoDX9* video_dx9_instance = 0; - -VideoDX9::VideoDX9(const HWND& window, VideoSettings* vs) -: width(0), height(0), bpp(0), hwnd(window), surface(0), -d3d(0), d3ddevice(0), device_lost(false), fade(0), -zdepth(0), gamma(128), num_verts(0), first_vert(0), -current_texture(0), screen_vbuf(0), screen_ibuf(0), -font_verts(0), font_indices(0), font_nverts(0), -nlights(0), use_material(0), d3dx_font(0), -segment_material(0), strategy(0), passes(0), -screen_line_verts(0), line_verts(0), -vertex_declaration(0), -magic_fx(0), magic_fx_code(0), magic_fx_code_len(0) -{ - video_dx9_instance = this; - - Print("\n********************************\n"); - Print("* Direct 3D version 9 *\n"); - Print("********************************\n\n"); - - status = VIDEO_ERR; - HRESULT err = E_OUTOFMEMORY; - - d3d = Direct3DCreate9(D3D_SDK_VERSION); - dx9enum = new(__FILE__,__LINE__) VideoDX9Enum(d3d); - - if (d3d && dx9enum) { - if (vs) { - dx9enum->req_fullscreen = vs->is_windowed ? false : true; - dx9enum->req_windowed = vs->is_windowed ? true : false; - dx9enum->min_stencil_bits = vs->shadows ? 8 : 0; - dx9enum->uses_depth_buffer = true; - } - else { - dx9enum->req_fullscreen = video_settings.is_windowed ? false : true; - dx9enum->req_windowed = video_settings.is_windowed ? true : false; - dx9enum->min_stencil_bits = video_settings.shadows ? 8 : 0; - dx9enum->uses_depth_buffer = true; - } - - err = dx9enum->Enumerate(); - - if (FAILED(err)) { - VideoDX9Error("(ctor) could not enumerate dx9 properties", err); - delete dx9enum; - return; - } - } - else { - VideoDX9Error("(ctor) could not create enumerator", err); - return; - } - - SetVideoSettings(vs); - - if (video_settings.is_windowed) - dx9enum->SuggestWindowSettings(&video_settings); - else - dx9enum->SuggestFullscreenSettings(&video_settings); - - SetupParams(); - - if (VD3D_describe_things > 2) { - Print("\nD3DPRESENT_PARAMETERS:\n"); - Print(" BackBufferWidth: %d\n", d3dparams.BackBufferWidth); - Print(" BackBufferHeight: %d\n", d3dparams.BackBufferHeight); - Print(" BackBufferCount: %d\n", d3dparams.BackBufferCount); - Print(" BackBufferFormat: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.BackBufferFormat)); - Print(" Multisample Type: %d\n", d3dparams.MultiSampleType); - Print(" Multisample Qual: %d\n", d3dparams.MultiSampleQuality); - Print(" Swap Effect: %d\n", d3dparams.SwapEffect); - Print(" Device Window: %08X\n", d3dparams.hDeviceWindow); - Print(" Windowed: %s\n", d3dparams.Windowed ? "true" : "false"); - Print(" Enable Depth/Stencil: %s\n", d3dparams.EnableAutoDepthStencil ? "true" : "false"); - Print(" Depth/Stencil Format: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.AutoDepthStencilFormat)); - Print(" Flags: %08X\n", d3dparams.Flags); - Print(" Fullscreen Refresh: %d Hz\n", d3dparams.FullScreen_RefreshRateInHz); - - switch (d3dparams.PresentationInterval) { - case D3DPRESENT_INTERVAL_IMMEDIATE: - Print(" Present Interval: IMMEDIATE\n"); - break; - - case D3DPRESENT_INTERVAL_DEFAULT: - Print(" Present Interval: DEFAULT\n"); - break; - - case D3DPRESENT_INTERVAL_ONE: - Print(" Present Interval: ONE\n"); - break; - - case D3DPRESENT_INTERVAL_TWO: - Print(" Present Interval: TWO\n"); - break; - - case D3DPRESENT_INTERVAL_THREE: - Print(" Present Interval: THREE\n"); - break; - - case D3DPRESENT_INTERVAL_FOUR: - Print(" Present Interval: FOUR\n"); - break; - - default: - Print(" Present Interval: Unknown (%d)\n", d3dparams.PresentationInterval); - break; - } - - Print("\n"); - } - - Print(" Creating Video Device for HWND = %08x\n", window); - - err = d3d->CreateDevice(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - window, - D3DCREATE_HARDWARE_VERTEXPROCESSING, - &d3dparams, - &d3ddevice); - - if (FAILED(err)) { - VideoDX9Error("(ctor) could not create device", err); - return; - } - - width = video_settings.GetWidth(); - height = video_settings.GetHeight(); - bpp = video_settings.GetDepth(); - - shadow_enabled = vs->shadows; - bump_enabled = vs->bumpmaps; - spec_enabled = vs->specmaps; - - render_state[FILL_MODE] = FILL_SOLID; - render_state[SHADE_MODE] = SHADE_GOURAUD; - render_state[Z_ENABLE] = false; - render_state[Z_WRITE_ENABLE] = false; - render_state[Z_BIAS] = 0; - render_state[TEXTURE_FILTER] = FILTER_LINEAR; - render_state[DITHER_ENABLE] = false; - render_state[SPECULAR_ENABLE] = true; - render_state[FOG_ENABLE] = false; - render_state[FOG_COLOR] = 0; - render_state[FOG_DENSITY] = 0; - render_state[STENCIL_ENABLE] = false; - render_state[TEXTURE_WRAP] = true; - render_state[LIGHTING_PASS] = 0; - - ZeroMemory(&rect, sizeof(rect)); - - if (!texcache) - texcache = new(__FILE__,__LINE__) TexCacheDX9(this); - - if (texcache) - texcache->count++; - - if (VD3D_describe_things > 0) { - DWORD vmf = VidMemFree() / (1024 * 1024); - Print(" Available Texture Memory: %d MB\n\n", vmf); - } - - if (CreateBuffers()) { - d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - - status = VIDEO_OK; - } - - ZeroMemory(font_name, 64); - font_size = 0; - font_bold = false; - font_ital = false; -} - -// +--------------------------------------------------------------------+ - -VideoDX9::~VideoDX9() -{ - DestroyBuffers(); - - texcache->count--; - if (!texcache->count) { - delete texcache; - texcache = 0; - } - - delete environment_cube; - delete dx9enum; - - RELEASE(d3dx_font); - RELEASE(d3ddevice); - RELEASE(d3d); - - if (magic_fx_code) - delete [] magic_fx_code; - - Print(" VideoDX9: shutdown\n"); - video_dx9_instance = 0; -} - -IDirect3DDevice9* -VideoDX9::GetD3DDevice9() -{ - if (video_dx9_instance) - return video_dx9_instance->d3ddevice; - - return 0; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetupParams() -{ - if (!dx9enum || dx9enum->NumAdapters() < 1) { - status = VIDEO_ERR; - return false; - } - - int adapter_index = video_settings.GetAdapterIndex(); - - if (adapter_index < 0 || adapter_index >= dx9enum->NumAdapters()) { - ::Print("WARNING: VideoDX9 could not select adapter %d (max=%d)\n", - adapter_index, dx9enum->NumAdapters()); - - adapter_index = 0; - } - - dx9enum->SelectAdapter(adapter_index); - - d3dparams.Windowed = video_settings.IsWindowed(); - d3dparams.BackBufferCount = 2; - d3dparams.MultiSampleType = D3DMULTISAMPLE_NONE; - d3dparams.MultiSampleQuality = 0; - d3dparams.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dparams.EnableAutoDepthStencil = dx9enum->uses_depth_buffer; - d3dparams.hDeviceWindow = hwnd; - - if (dx9enum->uses_depth_buffer) { - d3dparams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; - d3dparams.AutoDepthStencilFormat = (D3DFORMAT) video_settings.GetDepthStencilFormat(); - } - else { - d3dparams.Flags = 0; - } - - d3dparams.Flags |= D3DPRESENTFLAG_DEVICECLIP; - - if (video_settings.IsWindowed()) { - d3dparams.BackBufferWidth = video_settings.window_width; - d3dparams.BackBufferHeight = video_settings.window_height; - d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); - d3dparams.FullScreen_RefreshRateInHz = 0; - d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - } - else { - d3dparams.BackBufferWidth = video_settings.GetWidth(); - d3dparams.BackBufferHeight = video_settings.GetHeight(); - d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); - d3dparams.FullScreen_RefreshRateInHz = video_settings.GetRefreshRate(); - d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - } - - return true; -} - - -bool -VideoDX9::IsModeSupported(int w, int h, int b) const -{ - if (dx9enum) - return dx9enum->IsModeSupported(w, h, b); - - return false; -} - -bool -VideoDX9::SetVideoSettings(const VideoSettings* vs) -{ - // custom video settings: - if (vs) { - if (vs != &video_settings) - CopyMemory(&video_settings, vs, sizeof(VideoSettings)); - } - - // default video settings: - else { - ZeroMemory(&video_settings, sizeof(VideoSettings)); - - video_settings.fullscreen_mode.width = 800; - video_settings.fullscreen_mode.height = 600; - video_settings.fullscreen_mode.format = VideoMode::FMT_X8R8G8B8; - } - - return true; -} - -bool -VideoDX9::Reset(const VideoSettings* vs) -{ - if (!d3ddevice || !SetVideoSettings(vs)) { - status = VIDEO_ERR; - return false; - } - - bool using_x_font = (d3dx_font != 0); - - RELEASE(d3dx_font); - InvalidateCache(); - DestroyBuffers(); - SetupParams(); - - HRESULT hr = d3ddevice->Reset(&d3dparams); - - if (FAILED(hr)) { - VideoDX9Error("could not reset d3d device", hr); - status = VIDEO_ERR; - return false; - } - - // Store render target surface desc - IDirect3DSurface9* back_buffer; - d3ddevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer); - back_buffer->GetDesc(&back_buffer_desc); - RELEASE(back_buffer); - - width = video_settings.GetWidth(); - height = video_settings.GetHeight(); - bpp = video_settings.GetDepth(); - - shadow_enabled = vs->shadows; - bump_enabled = vs->bumpmaps; - spec_enabled = vs->specmaps; - - - if (CreateBuffers()) { - d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); - - D3DVIEWPORT9 view; - - hr = d3ddevice->GetViewport(&view); - if (SUCCEEDED(hr)) { - rect.x = view.X; - rect.y = view.Y; - rect.w = view.Width; - rect.h = view.Height; - } - - if (using_x_font) - UseXFont(font_name, font_size, font_bold, font_ital); - - status = VIDEO_OK; - } - - return status == VIDEO_OK; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::CreateBuffers() -{ - if (d3ddevice) { - UINT vertex_size = sizeof(VideoDX9ScreenVertex); - UINT index_size = sizeof(WORD); - - if (!screen_vbuf) { - screen_vbuf = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - NUM_SCREEN_VERTS, - vertex_size, - VideoDX9ScreenVertex::FVF, - D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - } - - if (!screen_ibuf) { - screen_ibuf = new(__FILE__,__LINE__) VideoDX9IndexBuffer( - this, - NUM_SCREEN_INDICES, - D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - } - - screen_line_verts = new(__FILE__,__LINE__) VideoDX9ScreenVertex[256]; - line_verts = new(__FILE__,__LINE__) VideoDX9LineVertex[512]; - - // create effects: - LPD3DXBUFFER code_buffer = 0; - DataLoader* loader = DataLoader::GetLoader(); - HRESULT hr = E_FAIL; - - hr = d3ddevice->CreateVertexDeclaration(videoDX9NormalVertexElements, - &vertex_declaration); - - // The E - We want to load our shader from the standard filesystem by default, to allow for better modding. - if (video_settings.use_effects && !magic_fx_code) { - FILE* f; - ::fopen_s(&f, "magic.fx", "rb"); - - if (f) { - ::fseek(f, 0, SEEK_END); - magic_fx_code_len = ftell(f); - ::fseek(f, 0, SEEK_SET); - - magic_fx_code = new(__FILE__,__LINE__) BYTE[magic_fx_code_len+1]; - if (magic_fx_code) { - ::fread(magic_fx_code, magic_fx_code_len, 1, f); - magic_fx_code[magic_fx_code_len] = 0; - } - ::fclose(f); - } else if (loader) { - magic_fx_code_len = loader->LoadBuffer("magic.fx", magic_fx_code, true, true); - } - } - - if (video_settings.use_effects && magic_fx_code && magic_fx_code_len) { - hr = D3DXCreateEffect(d3ddevice, - magic_fx_code, - magic_fx_code_len, - 0, 0, 0, 0, - &magic_fx, - &code_buffer); - - if (code_buffer) { - ::Print("ERROR - Failed to compile 'magic.fx'\n"); - ::Print((const char*) code_buffer->GetBufferPointer()); - ::Print("\n\n"); - RELEASE(code_buffer); - } - } - } - - return screen_vbuf && screen_ibuf; -} - -bool -VideoDX9::DestroyBuffers() -{ - if (line_verts) { - delete line_verts; - line_verts = 0; - } - - if (screen_line_verts) { - delete screen_line_verts; - screen_line_verts = 0; - } - - if (screen_vbuf) { - delete screen_vbuf; - screen_vbuf = 0; - } - - if (screen_ibuf) { - delete screen_ibuf; - screen_ibuf = 0; - } - - if (font_verts) { - delete [] font_verts; - font_verts = 0; - } - - if (font_indices) { - delete [] font_indices; - font_indices = 0; - } - - font_nverts = 0; - - RELEASE(vertex_declaration); - RELEASE(magic_fx); - - return true; -} - -// +--------------------------------------------------------------------+ - -DWORD -VideoDX9::VidMemFree() const -{ - UINT result = 0; - - if (d3ddevice) - result = d3ddevice->GetAvailableTextureMem(); - - return result; -} - -int -VideoDX9::MaxTexSize() const -{ - if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - return (int) dev_info->caps.MaxTextureWidth; - } - } - - return 0; -} - -int -VideoDX9::MaxTexAspect() const -{ - if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - return (int) dev_info->caps.MaxTextureAspectRatio; - } - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::RecoverSurfaces() -{ - Print("VideoDX9::RecoverSurfaces()\n"); - - HRESULT hr = D3D_OK; - - surface = 0; - - hr = d3ddevice->TestCooperativeLevel(); - - if (hr == D3DERR_DEVICELOST) { - // This means that some app took exclusive mode access - // we need to sit in a loop till we get back to the right mode. - Print("D3DERR_DEVICELOST\n"); - - do { - Sleep(500); - hr = d3ddevice->TestCooperativeLevel(); - } while (hr == D3DERR_DEVICELOST); - } - - if (hr == D3DERR_DEVICENOTRESET) { - if (Reset(&video_settings)) - hr = S_OK; - } - - if (SUCCEEDED(hr)) { - Print("* Invalidating Texture Cache\n"); - // Re-fill the contents of textures which just got restored: - InvalidateCache(); - - device_lost = false; - } - - Print("* Vid Mem Free: %8d\n", VidMemFree()); - Print("* Recover Surfaces Complete.\n\n"); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetBackgroundColor(Color c) -{ - background = c; - return true; -} - -//----------------------------------------------------------------------------- -// RampValue -// -// The gamma function with inputs in [0,255], scaled to a range with the -// default range appropriate for D3DGAMMARAMP. -// -inline WORD -RampValue(UINT i, double recip_gamma, double fade) -{ - return (WORD) (65535.0 * fade * pow((double)i/255.f, recip_gamma)); -} - -//----------------------------------------------------------------------------- -// ReciprocalGamma -// -// Given a gamma corrected i in [0,255], return 1/gamma -// -inline float -ReciprocalGamma(UINT i) -{ - return logf(i/255.f)/logf(0.5f); -} - -//----------------------------------------------------------------------------- -// GammaValue -// -// Given a gamma corrected color channel value in [0,255], return the gamma. -// -inline float -GammaValue(UINT i) -{ - return logf(0.5f)/logf(i/255.f); -} - -bool -VideoDX9::SetGammaLevel(int g) -{ - HRESULT hr = E_FAIL; - double f = Color::GetFade(); - - if (gamma != g || fade != f) { - if (d3ddevice) { - //::Print("VideoDX9 - SetGammaLevel(%d) fade = %f\n", g, f); - - // compute 1/gamma - float recip_gray = ReciprocalGamma(g); - - // compute i**(1/gamma) for all i and scale to range - for (UINT i = 0; i < 256; i++) { - int val = RampValue(i, recip_gray, f); - - gamma_ramp.red[i] = val; - gamma_ramp.green[i] = val; - gamma_ramp.blue[i] = val; - } - - d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp); - hr = D3D_OK; - } - - gamma = g; - fade = f; - } - - return SUCCEEDED(hr); -} - -bool -VideoDX9::SetObjTransform(const Matrix& orient, const Point& loc) -{ - HRESULT hr = E_FAIL; - - if (d3ddevice) { - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, loc); - hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - - matrixWorld = world_matrix; - D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); - } - - return SUCCEEDED(hr); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::ClearAll() -{ - HRESULT err; - - err = d3ddevice->Clear(0, - NULL, - D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, - background.Value(), - 1.0f, - 0); - - if (FAILED(err)) { - static int report = 10; - if (report > 0) { - VideoDX9Error("Failed to clear device", err); - report--; - } - } - - return true; -} - -bool -VideoDX9::ClearDepthBuffer() -{ - HRESULT err; - - err = d3ddevice->Clear(0, - NULL, - D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, - 0, - 1.0f, - 0); - - if (FAILED(err)) { - static int report = 10; - if (report > 0) { - VideoDX9Error("Failed to clear depth buffer", err); - report--; - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Present() -{ - // Show the frame on the primary surface. - HRESULT err = d3ddevice->Present( NULL, NULL, NULL, NULL ); - - if (FAILED(err)) { - if (err == D3DERR_DEVICELOST) { - device_lost = true; - } - - else { - static int report = 10; - if (report > 0) { - VideoDX9Error("Could not present frame", err); - report--; - } - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Pause() -{ - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Resume() -{ - return true; -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::PreloadSurface(Surface* s) -{ - if (s) - PrepareSurface(s); -} - -void -VideoDX9::PreloadTexture(Bitmap* tex) -{ - if (texcache && tex) - texcache->FindTexture(tex); -} - -void -VideoDX9::InvalidateCache() -{ - ListIter iter = model_clients; - while (++iter) { - // remove each model from the list... - Model* model = iter.removeItem(); - - // ...so that the buffer destructor doesn't - // do it and mess up the iterator. - model->DeletePrivateData(); - } - - if (texcache) - texcache->InvalidateCache(); -} - -// +--------------------------------------------------------------------+ - -void -VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p) -{ - result._11 = (float) m.elem[0][0]; - result._12 = (float) m.elem[1][0]; - result._13 = (float) m.elem[2][0]; - result._14 = 0.0f; - - result._21 = (float) m.elem[0][1]; - result._22 = (float) m.elem[1][1]; - result._23 = (float) m.elem[2][1]; - result._24 = 0.0f; - - result._31 = (float) m.elem[0][2]; - result._32 = (float) m.elem[1][2]; - result._33 = (float) m.elem[2][2]; - result._34 = 0.0f; - - result._41 = (float) p.x; - result._42 = (float) p.y; - result._43 = (float) p.z; - result._44 = 1.0f; -} - -void -VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v) -{ - result._11 = (float) m.elem[0][0]; - result._12 = (float) m.elem[1][0]; - result._13 = (float) m.elem[2][0]; - result._14 = 0.0f; - - result._21 = (float) m.elem[0][1]; - result._22 = (float) m.elem[1][1]; - result._23 = (float) m.elem[2][1]; - result._24 = 0.0f; - - result._31 = (float) m.elem[0][2]; - result._32 = (float) m.elem[1][2]; - result._33 = (float) m.elem[2][2]; - result._34 = 0.0f; - - result._41 = v.x; - result._42 = v.y; - result._43 = v.z; - result._44 = 1.0f; -} - -void -VideoDX9::CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl) -{ - CopyMemory(&result.Diffuse, &mtl.Kd, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Ambient, &mtl.Ka, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Specular, &mtl.Ks, sizeof(D3DCOLORVALUE)); - CopyMemory(&result.Emissive, &mtl.Ke, sizeof(D3DCOLORVALUE)); - - result.Power = mtl.power; -} - - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::Capture(Bitmap& bmp) -{ - if (d3ddevice) { - HRESULT hr = E_FAIL; - LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL; - D3DSURFACE_DESC desc; - D3DDISPLAYMODE dm; - - // get display dimensions - // this will be the dimensions of the front buffer - hr = d3ddevice->GetDisplayMode(0, &dm); - - if (FAILED(hr)) - VideoDX9Error("VideoDX9::Capture - Can't get display mode!", hr); - - desc.Width = dm.Width; - desc.Height = dm.Height; - desc.Format = D3DFMT_A8R8G8B8; - - hr = d3ddevice->CreateOffscreenPlainSurface( - desc.Width, - desc.Height, - desc.Format, - D3DPOOL_SYSTEMMEM, - &pTempSurf, - NULL); - - if (FAILED(hr)) { - VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 1", hr); - return false; - } - - hr = d3ddevice->GetFrontBufferData(0, pTempSurf); - - if (FAILED(hr)) { - RELEASE(pTempSurf); - VideoDX9Error("VideoDX9::Capture - Can't get front buffer", hr); - return false; - } - - - if (video_settings.IsWindowed()) { - POINT pt={0, 0}; - RECT srcRect; - - // capture only the client area of the screen: - ::GetClientRect(hwnd, &srcRect); - ::ClientToScreen(hwnd, (LPPOINT) &srcRect); - srcRect.right += srcRect.left; - srcRect.bottom += srcRect.top; - - desc.Width = srcRect.right - srcRect.left; - desc.Height = srcRect.bottom - srcRect.top; - desc.Format = D3DFMT_A8R8G8B8; // this is what we get from the screen, so stick with it - - // NB we can't lock the back buffer direct because it's no created that way - // and to do so hits performance, so copy to another surface - // Must be the same format as the source surface - hr = d3ddevice->CreateOffscreenPlainSurface( - desc.Width, - desc.Height, - desc.Format, - D3DPOOL_DEFAULT, - &pSurf, - NULL); - - if (FAILED(hr)) { - RELEASE(pSurf); - VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 2", hr); - return false; - } - - // Copy - hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt); - - if (FAILED(hr)) { - RELEASE(pTempSurf); - RELEASE(pSurf); - VideoDX9Error("VideoDX9::Capture - Cannot update surface", hr); - return false; - } - - RELEASE(pTempSurf); - pTempSurf = pSurf; - pSurf = NULL; - } - - D3DLOCKED_RECT lockedRect; - hr = pTempSurf->LockRect(&lockedRect, NULL, - D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); - - if (FAILED(hr)) { - VideoDX9Error("VideoDX9::Capture - can't lock rect", hr); - RELEASE(pTempSurf); - return false; - } - - // Allocate color buffer - DWORD* buffer = new DWORD[desc.Width * desc.Height]; - BYTE* src = (BYTE*) lockedRect.pBits; - BYTE* dst = (BYTE*) buffer; - Color clr; - - for (DWORD y = 0; y < desc.Height; y++) { - BYTE *pRow = src; - - for (DWORD x = 0; x < desc.Width; x++) { - switch(desc.Format) { - case D3DFMT_R5G6B5: - clr = Color::Unformat(*((WORD*) (pRow))); - - *dst++ = (BYTE) clr.Red(); - *dst++ = (BYTE) clr.Green(); - *dst++ = (BYTE) clr.Blue(); - *dst++ = 255; - break; - - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - *dst++ = pRow[0]; // R - *dst++ = pRow[1]; // G - *dst++ = pRow[2]; // B - *dst++ = 255; - - pRow += 4; - break; - - case D3DFMT_R8G8B8: - *dst++ = pRow[0]; // R - *dst++ = pRow[1]; // G - *dst++ = pRow[2]; // B - *dst++ = 255; - - pRow += 3; - break; - } - - } - - src += lockedRect.Pitch; - } - - bmp.CopyHighColorImage(desc.Width, desc.Height, buffer); - - delete [] buffer; - - RELEASE(pTempSurf); - RELEASE(pSurf); - - return SUCCEEDED(hr); - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::GetWindowRect(Rect& r) -{ - if (d3ddevice && (rect.w < 1 || rect.h < 1)) { - D3DVIEWPORT9 view; - HRESULT hr = d3ddevice->GetViewport(&view); - if (SUCCEEDED(hr)) { - rect.x = view.X; - rect.y = view.Y; - rect.w = view.Width; - rect.h = view.Height; - } - } - - r = rect; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetWindowRect(const Rect& r) -{ - return SetViewport(r.x, r.y, r.w, r.h); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetViewport(int x, int y, int w, int h) -{ - if (!d3d || !d3ddevice) - return false; - - HRESULT hr; - - // set up the viewport according to args: - D3DVIEWPORT9 view; - - view.X = x; - view.Y = y; - view.Width = w; - view.Height = h; - view.MinZ = 0.0f; - view.MaxZ = 1.0f; - - hr = d3ddevice->SetViewport(&view); - if (FAILED(hr)) { - VideoDX9Error("could not initialize viewport", hr); - return false; - } - - // set up the render state: - for (int i = FILL_MODE; i < TEXTURE_WRAP; i++) { - if (d3dstate_table[i]) { - d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]); - } - } - - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - - rect.x = x; - rect.y = y; - rect.w = w; - rect.h = h; - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetAmbient(Color c) -{ - ambient = c; - return true; -} - -bool -VideoDX9::SetLights(const List& lights) -{ - if (d3ddevice) { - main_light = 0; - back_light = 0; - - ListIter iter = (List&) lights; - int index = -1; - - while (++iter) { - Light* light = iter.value(); - - if (light->IsActive()) { - D3DLIGHT9 d3d_light; - ZeroMemory(&d3d_light, sizeof(d3d_light)); - d3d_light.Type = (D3DLIGHTTYPE) light->Type(); - - if (light->Type() == Light::LIGHT_DIRECTIONAL) { - d3d_light.Direction.x = (float) (-light->Location().x); - d3d_light.Direction.y = (float) (-light->Location().y); - d3d_light.Direction.z = (float) (-light->Location().z); - - if (d3d_light.Direction.x == 0 && - d3d_light.Direction.y == 0 && - d3d_light.Direction.z == 0) { - - d3d_light.Direction.y = -1; - } - - if (light->CastsShadow()) { - if (!main_light || light->Intensity() > main_light->Intensity()) - main_light = light; - } - else if (!back_light) { - back_light = light; - } - } - else { - d3d_light.Position.x = (float) ( light->Location().x); - d3d_light.Position.y = (float) ( light->Location().y); - d3d_light.Position.z = (float) ( light->Location().z); - } - - float r = (light->GetColor().Red() / 255.0f) * light->Intensity(); - float g = (light->GetColor().Green() / 255.0f) * light->Intensity(); - float b = (light->GetColor().Blue() / 255.0f) * light->Intensity(); - - d3d_light.Diffuse.r = r; - d3d_light.Diffuse.g = g; - d3d_light.Diffuse.b = b; - - d3d_light.Specular.r = r; - d3d_light.Specular.g = g; - d3d_light.Specular.b = b; - - d3d_light.Range = light->Intensity() * 10.0f; - d3d_light.Attenuation0 = 0.1f; - d3d_light.Attenuation1 = 0.7f; - d3d_light.Attenuation2 = 0.0f; - - index++; - d3ddevice->SetLight(index, &d3d_light); - d3ddevice->LightEnable(index, TRUE); - } - } - - // turn off any unused lights from before: - while (nlights > index+1) { - d3ddevice->LightEnable(--nlights, FALSE); - } - - nlights = index + 1; - - return true; - } - - return false; -} - -bool -VideoDX9::SetCamera(const Camera* cam) -{ - if (d3ddevice) { - camera = cam; - - D3DMATRIX m; - CreateD3DMatrix(m, cam->Orientation(), cam->Pos()); - d3ddevice->SetTransform(D3DTS_VIEW, &m); - matrixView = m; - - return true; - } - - return false; -} - -bool -VideoDX9::SetProjection(float fov, float znear, float zfar, DWORD type) -{ - if (d3ddevice && zfar > znear) { - D3DMATRIX m; - float h, w, Q; - - double width = (float) (rect.w); - double height = (float) (rect.h); - ZeroMemory(&m, sizeof(m)); - - /*** - *** PERSPECTIVE PROJECTION: - ***/ - - if (type == PROJECTION_PERSPECTIVE) { - double xscale = width / fov; - double yscale = height / fov; - - double maxscale = xscale; - if (yscale > xscale) maxscale = yscale; - - double xangle = atan(fov/2 * maxscale/xscale); - - w = (float) (2/tan(xangle)); // 1/tan(x) == cot(x) - h = (float) (w * width/height); - Q = zfar/(zfar - znear); - - m._11 = w; - m._22 = h; - m._33 = Q; - m._43 = -Q*znear; - m._34 = 1; - } - - /*** - *** ORTHOGONAL PROJECTION: - ***/ - - else if (type == PROJECTION_ORTHOGONAL) { - m._11 = (float) (fov/width); - m._22 = (float) (fov/height); - m._33 = (float) (1/(zfar-znear)); - m._43 = (float) (znear/(znear-zfar)); - m._44 = (float) (1); - } - - else { - return false; - } - - d3ddevice->SetTransform(D3DTS_PROJECTION, &m); - matrixProj = m; - - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetEnvironment(Bitmap** faces) -{ - if (environment_cube && !faces) { - delete environment_cube; - environment_cube = 0; - return true; - } - - if (!environment_cube) { - environment_cube = new(__FILE__,__LINE__) TexCubeDX9(this); - } - - if (environment_cube) { - bool ok = true; - for (int i = 0; i < 6; i++) - ok = ok && environment_cube->LoadTexture(faces[i], i); - return ok; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::SetRenderState(RENDER_STATE state, DWORD value) -{ - if (!d3ddevice) - return false; - - if (render_state[state] == value || d3dstate_table[state] == 0) { - render_state[state] = value; - return true; - } - - HRESULT hr = E_FAIL; - - // special case for texture wrapping: - if (state == TEXTURE_WRAP) { - DWORD wrap = D3DTADDRESS_CLAMP; - - if (value) - wrap = D3DTADDRESS_WRAP; - - hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap); - hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap); - } - - // special case for fog enable: - else if (state == FOG_ENABLE) { - if (value) { - hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); - hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); - } - - hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value); - } - - // special case for z bias - else if (state == Z_BIAS) { - if (value) { - FLOAT bias_scale = 1.0f; - FLOAT depth_bias = (FLOAT) (DW2I(value) / -10000.0); - - hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(bias_scale)); - hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(depth_bias)); - } - else { - hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - } - - // set default z func along with z enable - else if (state == Z_ENABLE) { - hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value); - } - - // all other render states: - else { - hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value); - } - - if (FAILED(hr)) { - VideoDX9Error("could not SetRenderState", hr); - return false; - } - else { - render_state[state] = value; - } - - return true; -} - -bool -VideoDX9::SetBlendType(int blend_type) -{ - if (blend_type == current_blend_state) - return true; - - switch (blend_type) { - default: - // map misc blend types to SOLID - // and fall through to that case - - blend_type = BLEND_SOLID; - - case BLEND_SOLID: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); - break; - - case BLEND_ALPHA: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - break; - - case BLEND_ADDITIVE: - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - break; - } - - current_blend_state = blend_type; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::StartFrame() -{ - if (device_lost) { - RecoverSurfaces(); - - if (status != VIDEO_OK) - return false; - } - - stats.Clear(); - - HRESULT err = 0; - static int frame_number = 1; - static int report_errs = 100; - - stats.nframe = frame_number; - texcache->FrameNumber(frame_number++); - - // update gamma ramp for global fade value: - SetGammaLevel(gamma); - - ClearAll(); - - err = d3ddevice->BeginScene(); - - if (FAILED(err)) { - if (report_errs > 0) { - report_errs--; - VideoDX9Error("could not begin scene", err); - } - - return false; - } - - scene_active = 1; - current_blend_state = -1; - - SetRenderState(LIGHTING_PASS, 0); - SetRenderState(STENCIL_ENABLE, false); - - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::EndFrame() -{ - HRESULT err = 0; - - if (scene_active) { - err = d3ddevice->EndScene(); - - if (FAILED(err)) { - VideoDX9Error("could not end scene", err); - return false; - } - } - - scene_active = 0; - return true; -} - -// +--------------------------------------------------------------------+ - -static DWORD ColorModulate(DWORD a, DWORD b) -{ - float a0 = (float) ((a ) & 0xff)/255.0f; - float a1 = (float) ((a>> 8) & 0xff)/255.0f; - float a2 = (float) ((a>>16) & 0xff)/255.0f; - float a3 = (float) ((a>>24) & 0xff)/255.0f; - - float b0 = (float) ((b ) & 0xff)/255.0f; - float b1 = (float) ((b>> 8) & 0xff)/255.0f; - float b2 = (float) ((b>>16) & 0xff)/255.0f; - float b3 = (float) ((b>>24) & 0xff)/255.0f; - - return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) | - ((BYTE)(a2*b2*255.0f) << 16) | - ((BYTE)(a1*b1*255.0f) << 8) | - ((BYTE)(a0*b0*255.0f)); -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::PopulateScreenVerts(VertexSet* vset) -{ - if (!vset || !screen_vbuf) - return false; - - num_verts = vset->nverts; - - VideoDX9ScreenVertex* v = (VideoDX9ScreenVertex*) screen_vbuf->Lock(num_verts); - - if (v) { - first_vert = screen_vbuf->GetNextVert(); - - for (int i = 0; i < num_verts; i++) { - v->sx = vset->s_loc[i].x; - v->sy = vset->s_loc[i].y; - v->sz = vset->s_loc[i].z; - v->rhw = vset->rw[i]; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - screen_vbuf->Unlock(); - return true; - } - - Print(" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts); - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawPolys(int npolys, Poly* polys) -{ - bool result = false; - - if (d3ddevice && polys && npolys > 0) { - // screen space polys: - if (polys->vertex_set->space == VertexSet::SCREEN_SPACE) - return DrawScreenPolys(npolys, polys); - - // world space polys: - stats.ncalls++; - - VertexSet* vset = polys->vertex_set; - int nverts = vset->nverts; - bool luminous = false; - bool detail = false; - DWORD fvf = 0; - void* verts = 0; - int vsize = 0; - WORD* indices = new(__FILE__,__LINE__) WORD[npolys*6]; - - if (polys->material) { - luminous = polys->material->luminous; - } - - if (vset->tu1 != 0) { - VideoDX9DetailVertex* v = new(__FILE__,__LINE__) VideoDX9DetailVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9DetailVertex); - fvf = VideoDX9DetailVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - v->specular = vset->specular[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - v->tu1 = vset->tu1[i]; - v->tv1 = vset->tv1[i]; - - v++; - } - } - - else if (luminous) { - VideoDX9LuminousVertex* v = new(__FILE__,__LINE__) VideoDX9LuminousVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9LuminousVertex); - fvf = VideoDX9LuminousVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - } - - else { - VideoDX9SolidVertex* v = new(__FILE__,__LINE__) VideoDX9SolidVertex[nverts]; - verts = v; - vsize = sizeof(VideoDX9SolidVertex); - fvf = VideoDX9SolidVertex::FVF; - - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - } - - if (verts && indices) { - HRESULT hr = E_FAIL; - - // fill index array - int num_indices = 0; - int num_tris = 0; - - WORD* s = indices; - Poly* p = polys; - - for (int i = 0; i < npolys; i++) { - if (p->nverts == 3) { - num_indices += 3; - num_tris += 1; - - *s++ = p->verts[0]; - *s++ = p->verts[1]; - *s++ = p->verts[2]; - } - - else if (p->nverts == 4) { - num_indices += 6; - num_tris += 2; - - *s++ = p->verts[0]; - *s++ = p->verts[1]; - *s++ = p->verts[2]; - - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[3]; - } - - p++; - } - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(fvf); - - // send primitives to the device - Material* mtl = polys->material; - IDirect3DTexture9* texture = 0; - - if (mtl && texcache && mtl->tex_diffuse) { - texture = texcache->FindTexture(mtl->tex_diffuse); - } - - if (current_texture != texture) { - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - } - - if (mtl && texcache && mtl->tex_detail) { - texture = texcache->FindTexture(mtl->tex_detail); - hr = d3ddevice->SetTexture(1, texture); - } - - if (mtl && !luminous) { - D3DMATERIAL9 d3dmtl; - CreateD3DMaterial(d3dmtl, *mtl); - - hr = d3ddevice->SetMaterial(&d3dmtl); - hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); - } - - // set render states and select buffers - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(LIGHTING_ENABLE, luminous ? FALSE : TRUE); - SetBlendType(mtl->blend); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - - hr = d3ddevice->DrawIndexedPrimitiveUP( - D3DPT_TRIANGLELIST, - 0, - nverts, - num_tris, - indices, - D3DFMT_INDEX16, - verts, - vsize); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw 3D polys.", hr); - } - - delete [] verts; - delete [] indices; - - if (SUCCEEDED(hr)) { - stats.nverts += nverts; - stats.npolys += num_tris; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawScreenPolys(int npolys, Poly* polys, int blend) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) { - stats.ncalls++; - - // fill screen vertex buffer - if (!PopulateScreenVerts(polys->vertex_set)) - return false; - - // fill screen index buffer - int num_indices = 0; - int num_tris = 0; - - // count the number of indices needed for these polys - for (int i = 0; i < npolys; i++) { - Poly* p = polys + i; - - if (p->nverts == 3) { - num_indices += 3; - num_tris += 1; - } - - else if (p->nverts == 4) { - num_indices += 6; - num_tris += 2; - } - } - - WORD* screen_indices = screen_ibuf->Lock(num_indices); - int first_index = screen_ibuf->GetNextIndex(); - - if (!screen_indices) { - Print(" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices); - return false; - } - - // copy the indices into the locked index buffer - WORD* s = screen_indices; - Poly* p = polys; - - for (int i = 0; i < npolys; i++) { - if (p->nverts == 3) { - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[1] + first_vert; - *s++ = p->verts[2] + first_vert; - } - else if (p->nverts == 4) { - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[1] + first_vert; - *s++ = p->verts[2] + first_vert; - - *s++ = p->verts[0] + first_vert; - *s++ = p->verts[2] + first_vert; - *s++ = p->verts[3] + first_vert; - } - - p++; - } - - screen_ibuf->Unlock(); - - // set render states and select buffers - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(Z_ENABLE, D3DZB_FALSE); - SetRenderState(Z_WRITE_ENABLE, D3DZB_FALSE); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - // send primitives to the device - Material* mtl = polys->material; - IDirect3DTexture9* texture = 0; - - if (mtl && texcache && mtl->tex_diffuse) { - texture = texcache->FindTexture(mtl->tex_diffuse); - } - - if (current_texture != texture) { - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - } - - screen_vbuf->Select(0); - screen_ibuf->Select(); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw screen polys.", hr); - } - else { - stats.nverts += num_verts; - stats.npolys += num_tris; - result = true; - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawSolid(Solid* s, DWORD blend_modes) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && s && s->GetModel()) { - Model* model = s->GetModel(); - Matrix orient = s->Orientation(); - orient.Transpose(); - - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, s->Location()); - d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - matrixWorld = world_matrix; - D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); - - ListIter surf_iter = model->GetSurfaces(); - while (++surf_iter) { - Surface* surf = surf_iter.value(); - - if (surf->IsHidden() || surf->IsSimplified()) - continue; - - if (PrepareSurface(surf)) { - result = true; - - VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); - surf_data->vertex_buffer->Select(0); - surf_data->index_buffer->Select(); - - ListIter seg_iter = surf->GetSegments(); - while (++seg_iter) { - Segment* segment = seg_iter.value(); - Material* mtl = segment->material; - - if (mtl && (blend_modes & mtl->blend)) { - result = result && DrawSegment(segment); - } - } - } - } - } - - surface_has_tangent_data = false; - - return result; -} - -bool -VideoDX9::DrawSegment(Segment* segment) -{ - bool result = false; - bool detail = false; - bool luminous = false; - HRESULT hr = E_FAIL; - - if (segment && segment->video_data) { - stats.ncalls++; - - VideoDX9SegmentData* seg_data = (VideoDX9SegmentData*) segment->video_data; - int first_vert = seg_data->first_vert; - int num_verts = seg_data->num_verts; - int first_index = seg_data->first_index; - int num_tris = seg_data->num_tris; - - if (segment->model) - luminous = segment->model->IsLuminous(); - - // set render states and select buffers - d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); - - Material* mtl = segment->material; - - if (use_material) - mtl = use_material; - - if (segment->polys && segment->polys->vertex_set && segment->polys->vertex_set->tu1) - detail = true; - - // send primitives to the device - if (detail) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); - } - - else if (luminous) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); - } - - else if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - hr = d3ddevice->SetVertexShader(NULL); - } - - else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - - if (render_state[FILL_MODE] == FILL_WIREFRAME) { - PrepareMaterial(mtl); - SetupPass(0); - - for (int i = 0; i < segment->npolys; i++) { - DrawPolyOutline(segment->polys + i); - } - } - - else if (luminous) { - PrepareMaterial(mtl); - - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(mtl->blend); - - for (int pass = 0; pass < passes; pass++) { - SetupPass(pass); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - } - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - - else { - PrepareMaterial(mtl); - - if (strategy == DX9_STRATEGY_GLOW && render_state[LIGHTING_PASS] > 0) { - hr = 0; - } - - else if (magic_fx && strategy < DX9_STRATEGY_BLEND && !detail) { - DWORD vs_version = 0; - DWORD ps_version = 0; - bool shaders_ok = false; - - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; - ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; - - if (vs_version >= D3DVS_VERSION(1,1)) - shaders_ok = true; - } - - if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - } - - else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - - bool would_bump = !IsBumpMapEnabled() && mtl->bump > 0.5; - - bool will_bump = IsBumpMapEnabled() && surface_has_tangent_data && shaders_ok && camera; - - bool do_pix = will_bump && render_state[LIGHTING_PASS] == 0; - bool do_bump = will_bump && render_state[LIGHTING_PASS] > 0; - - D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj; - - D3DXVECTOR4 eyePos( (float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f); - - D3DXVECTOR4 eyeObj; - D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse); - - D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f); - D3DXVECTOR4 lightColor(1,1,1,1); - D3DXVECTOR4 ambientColor(0,0,0,1); - - ambientColor.x = ambient.fRed(); - ambientColor.y = ambient.fGreen(); - ambientColor.z = ambient.fBlue(); - - if (main_light && (render_state[LIGHTING_PASS] > 0 || mtl->blend > Material::MTL_SOLID)) { - lightPos.x = (float) main_light->Location().x; - lightPos.y = (float) main_light->Location().y; - lightPos.z = (float) main_light->Location().z; - - if (mtl->tex_bumpmap && do_bump) - D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse); - - lightColor.x = main_light->GetColor().fRed() * main_light->Intensity(); - lightColor.y = main_light->GetColor().fGreen() * main_light->Intensity(); - lightColor.z = main_light->GetColor().fBlue() * main_light->Intensity(); - lightColor.w = 1.0f; - } - - else if (back_light && render_state[LIGHTING_PASS] == 0) { - lightPos.x = (float) back_light->Location().x; - lightPos.y = (float) back_light->Location().y; - lightPos.z = (float) back_light->Location().z; - - lightColor.x = back_light->GetColor().fRed() * back_light->Intensity(); - lightColor.y = back_light->GetColor().fGreen() * back_light->Intensity(); - lightColor.z = back_light->GetColor().fBlue() * back_light->Intensity(); - lightColor.w = 1.0f; - } - - D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos; - D3DXVec4Normalize(&lightDir, &lightDir); - - magic_fx->SetMatrix("wvp", &matrixWVP); - magic_fx->SetMatrix("world", &matrixWorld); - magic_fx->SetMatrix("view", &matrixView); - magic_fx->SetMatrix("proj", &matrixProj); - magic_fx->SetMatrix("worldInv", &matrixWorldInverse); - - magic_fx->SetVector("light1Pos", &lightPos); - magic_fx->SetVector("light1Dir", &lightDir); - magic_fx->SetVector("light1Color", &lightColor); - magic_fx->SetVector("ambientColor", &ambientColor); - magic_fx->SetVector("eyeObj", &eyeObj); - - FLOAT base_bias = (FLOAT) (DW2I(render_state[Z_BIAS]) / -10000.0); - magic_fx->SetFloat("bias", base_bias + video_settings.depth_bias); - - ColorValue orig_ks = mtl->Ks; - - if (would_bump && mtl->specular_value >= 0.5) - mtl->Ks = mtl->Ks * 0.3; - - magic_fx->SetValue("Ka", &mtl->Ka, sizeof(ColorValue)); - magic_fx->SetValue("Kd", &mtl->Kd, sizeof(ColorValue)); - magic_fx->SetValue("Ke", &mtl->Ke, sizeof(ColorValue)); - magic_fx->SetValue("Ks", &mtl->Ks, sizeof(ColorValue)); - magic_fx->SetFloat("Ns", mtl->power); - - if (would_bump && mtl->specular_value >= 0.5) - mtl->Ks = orig_ks; - - if (mtl->tex_diffuse) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_diffuse); - magic_fx->SetTexture("tex_d", texture); - } else { - magic_fx->SetTexture("tex_d", 0); - } - - if (mtl->tex_emissive) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_emissive); - magic_fx->SetTexture("tex_e", texture); - } else { - magic_fx->SetTexture("tex_e", 0); - } - - if (mtl->tex_specular && IsSpecMapEnabled()) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_specular); - magic_fx->SetTexture("tex_s", texture); - } else { - magic_fx->SetTexture("tex_s", 0); - } - - if (mtl->tex_bumpmap && do_bump) { - IDirect3DTexture9* texture = texcache->FindNormalMap(mtl->tex_bumpmap, mtl->bump); - magic_fx->SetTexture("tex_n", texture); - magic_fx->SetFloat("offsetAmp", mtl->bump / mtl->tex_bumpmap->Height()); - } else if (mtl->tex_bumpmap && !do_bump) { - IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_bumpmap); - magic_fx->SetTexture("tex_x", texture); - } else { - magic_fx->SetTexture("tex_x", 0); - } - - const char* mtl_shader = mtl->GetShader(render_state[LIGHTING_PASS]); - D3DXHANDLE hnd_shader = 0; - - if (mtl_shader) { - if (!strcmp(mtl_shader, "null")) - return true; - - hnd_shader = magic_fx->GetTechniqueByName(mtl_shader); - } - - if (hnd_shader) { - hr = magic_fx->SetTechnique(hnd_shader); - } else { - if (will_bump) { - if (mtl->tex_specular && IsSpecMapEnabled()) { - if (mtl->tex_bumpmap && do_bump) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("BumpSpecMapPix"); - else - hr = magic_fx->SetTechnique("BumpSpecMap"); - } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("EmissiveSpecMapPix"); - else - hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); - } else { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("SpecMapPix"); - else - hr = magic_fx->SetTechnique("SpecularTexture"); - } - } else { - if (mtl->tex_bumpmap && do_bump) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("BumpMapPix"); - else - hr = magic_fx->SetTechnique("BumpMap"); - } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("EmissivePix"); - else - hr = magic_fx->SetTechnique("EmissiveTexture"); - } else { - if (ps_version >= D3DPS_VERSION(2,0)) - hr = magic_fx->SetTechnique("SimplePix"); - else - hr = magic_fx->SetTechnique("SimpleTexture"); - } - } - } - - else if (texcache && mtl->tex_diffuse) { - if (mtl->tex_specular && IsSpecMapEnabled()) { - if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); - } else { - hr = magic_fx->SetTechnique("SpecularTexture"); - } - } - - else { - if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { - hr = magic_fx->SetTechnique("EmissiveTexture"); - } else { - hr = magic_fx->SetTechnique("SimpleTexture"); - } - } - } else { - hr = magic_fx->SetTechnique("SimpleMaterial"); - } - } - - if (environment_cube != 0 && magic_fx->IsParameterUsed("env_cube", hnd_shader)) { - D3DXMATRIX env_matrix; - D3DXMatrixIdentity(&env_matrix); - - magic_fx->SetMatrix("env_matrix", &env_matrix); - magic_fx->SetTexture("env_cube", environment_cube->GetTexture()); - } - - if (render_state[STENCIL_ENABLE]) { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); - } else { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - if (render_state[LIGHTING_PASS] > 0) { - current_blend_state = 100; - SetBlendType(BLEND_ADDITIVE); - SetRenderState(Z_WRITE_ENABLE, FALSE); - } else { - current_blend_state = 100; - SetBlendType(mtl->blend); - } - - UINT nPasses = 0; - - hr = magic_fx->Begin(&nPasses, 0); - - for (UINT i = 0; i < nPasses; i++) { - hr = magic_fx->BeginPass(i); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - hr = magic_fx->EndPass(); - } - - hr = magic_fx->End(); - } else { - for (int pass = 0; pass < passes; pass++) { - SetupPass(pass); - - hr = d3ddevice->DrawIndexedPrimitive( - D3DPT_TRIANGLELIST, - 0, - first_vert, - num_verts, - first_index, - num_tris); - - if (detail) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); - } else if (luminous) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); - } else if (surface_has_tangent_data && vertex_declaration) { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetVertexDeclaration(vertex_declaration); - } else { - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); - } - } - } - } - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw solid polys.", hr); - } else { - stats.nverts += num_verts; - stats.npolys += num_tris; - result = true; - } - } - - return result; -} - -bool -VideoDX9::DrawPolyOutline(Poly* p) -{ - if (d3ddevice && p && p->nverts >= 3) { - static VideoDX9LineVertex verts[8]; - - int nlines = p->nverts; - VertexSet* vset = p->vertex_set; - WORD index = 0; - Color color = Color::Black; - HRESULT hr = E_FAIL; - - ZeroMemory(verts, sizeof(verts)); - - if (p->material) - color = p->material->Kd.ToColor(); - - for (int i = 0; i < p->nverts; i++) { - index = p->verts[i]; - - verts[i].x = vset->loc[index].x; - verts[i].y = vset->loc[index].y; - verts[i].z = vset->loc[index].z; - verts[i].diffuse = color.Value(); - } - - // last vertex, to close the loop - index = p->verts[0]; - int i = p->nverts; - - verts[i].x = vset->loc[index].x; - verts[i].y = vset->loc[index].y; - verts[i].z = vset->loc[index].z; - verts[i].diffuse = color.Value(); - - current_texture = 0; - - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - hr = d3ddevice->SetTexture(0, 0); - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINESTRIP, - nlines, - verts, - sizeof(VideoDX9LineVertex)); - return true; - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawShadow(Solid* s, int nverts, Vec3* shadow_verts, bool visible) -{ - bool result = false; - HRESULT hr = E_FAIL; - - if (d3ddevice && s && nverts && shadow_verts && IsShadowEnabled()) { - Matrix orient = s->Orientation(); - orient.Transpose(); - - D3DMATRIX world_matrix; - CreateD3DMatrix(world_matrix, orient, s->Location()); - d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); - matrixWorld = world_matrix; - - // show shadow outlines: - if (visible) { - static VideoDX9LineVertex verts[4]; - - d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE); - d3ddevice->SetVertexShader(NULL); - d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - d3ddevice->SetTexture(0, 0); - - SetBlendType(BLEND_ALPHA); - - for (int i = 0; i < nverts; i+=3) { - DWORD c = 0xa0ffff80; - - verts[0].x = shadow_verts[i+0].x; - verts[0].y = shadow_verts[i+0].y; - verts[0].z = shadow_verts[i+0].z; - verts[0].diffuse = c; - - verts[1].x = shadow_verts[i+1].x; - verts[1].y = shadow_verts[i+1].y; - verts[1].z = shadow_verts[i+1].z; - verts[1].diffuse = c; - - verts[2].x = shadow_verts[i+2].x; - verts[2].y = shadow_verts[i+2].y; - verts[2].z = shadow_verts[i+2].z; - verts[2].diffuse = c; - - verts[3].x = shadow_verts[i+0].x; - verts[3].y = shadow_verts[i+0].y; - verts[3].z = shadow_verts[i+0].z; - verts[3].diffuse = c; - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINESTRIP, - 3, - verts, - sizeof(VideoDX9LineVertex)); - } - - // restore lighting state - d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[LIGHTING_ENABLE]); - } - - // render shadows into stencil buffer: - - // Disable z-buffer writes (note: z-testing still occurs), and enable the - // stencil-buffer - d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - - // Dont bother with interpolating color - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); - - // Set up stencil compare fuction, reference value, and masks. - // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true. - // Note: since we set up the stencil-test to always pass, the STENCILFAIL - // renderstate is really not needed. - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); - d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ); - d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); - - // If z-test passes, inc/decrement stencil buffer value - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 ); - d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff ); - d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff ); - d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR ); - - // Make sure that no pixels get drawn to the frame buffer - d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE ); - d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO ); - d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE ); - - d3ddevice->SetVertexShader(NULL); - d3ddevice->SetFVF(D3DFVF_XYZ); - - // Draw front-side of shadow volume in stencil/z only - hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); - - // Now reverse cull order so back sides of shadow volume are written. - d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW ); - - // Decrement stencil buffer value - d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR ); - - // Draw back-side of shadow volume in stencil/z only - hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); - - // restore render states - d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); - d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - - // force restore of current blend type - int type = current_blend_state; - current_blend_state = 100; - SetBlendType(type); - - result = SUCCEEDED(hr); - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawLines(int nlines, Vec3* points, Color c, int blend) -{ - bool result = false; - - if (d3ddevice && points && nlines > 0 && nlines <= 256) { - stats.ncalls++; - - VideoDX9LineVertex* verts = line_verts; - - if (verts) { - HRESULT hr = E_FAIL; - - for (int i = 0; i < 2*nlines; i++) { - VideoDX9LineVertex* v = verts + i; - Vec3* p = points + i; - - v->x = p->x; - v->y = p->y; - v->z = p->z; - v->diffuse = c.Value(); - } - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - - DWORD old_lighting = render_state[LIGHTING_ENABLE]; - - // untextured lines: - if (current_texture) { - d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINELIST, - nlines, - verts, - sizeof(VideoDX9LineVertex)); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw 3D lines.", hr); - } - - SetRenderState(LIGHTING_ENABLE, old_lighting); - - if (SUCCEEDED(hr)) { - stats.nverts += 2*nlines; - stats.nlines += nlines; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawScreenLines(int nlines, float* points, Color c, int blend) -{ - bool result = false; - - if (d3ddevice && points && nlines > 0 && nlines <= 64) { - stats.ncalls++; - - VideoDX9ScreenVertex* verts = screen_line_verts; - - if (verts) { - HRESULT hr = E_FAIL; - - for (int i = 0; i < 2*nlines; i++) { - VideoDX9ScreenVertex* v = verts + i; - - v->sx = points[2*i + 0]; - v->sy = points[2*i + 1]; - v->sz = 0.0f; - v->rhw = 1.0f; - v->diffuse = c.Value(); - v->tu = 0.0f; - v->tv = 0.0f; - } - - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not set FVF for screen lines.", hr); - } - - else { - if (current_texture != 0) { - hr = d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetRenderState(FILL_MODE, D3DFILL_SOLID); - SetRenderState(Z_ENABLE, D3DZB_FALSE); - SetRenderState(LIGHTING_ENABLE, FALSE); - SetBlendType(blend); - - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_LINELIST, - nlines, - verts, - sizeof(VideoDX9ScreenVertex)); - - if (FAILED(hr)) { - static int report = 10; - if (report-- > 0) - VideoDX9Error("Could not draw screen lines.", hr); - } - } - - if (SUCCEEDED(hr)) { - stats.nverts += 2*nlines; - stats.nlines += nlines; - result = true; - } - } - } - - return result; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::DrawPoints(VertexSet* vset) -{ - if (vset && vset->nverts) { - HRESULT hr = E_FAIL; - - int nverts = vset->nverts; - VideoDX9LineVertex* verts = new(__FILE__,__LINE__) VideoDX9LineVertex[nverts]; - - if (verts) { - for (int i = 0; i < nverts; i++) { - VideoDX9LineVertex* v = verts + i; - Vec3* p = vset->loc + i; - - v->x = p->x; - v->y = p->y; - v->z = p->z; - v->diffuse = vset->diffuse[i]; - } - - SetRenderState(LIGHTING_ENABLE, FALSE); - - hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); - hr = d3ddevice->SetVertexShader(NULL); - hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); - hr = d3ddevice->SetTexture(0, 0); - hr = d3ddevice->DrawPrimitiveUP( - D3DPT_POINTLIST, - nverts, - verts, - sizeof(VideoDX9LineVertex)); - - delete [] verts; - return true; - } - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::UseMaterial(Material* m) -{ - use_material = m; - return true; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::UseXFont(const char* name, int size, bool bold, bool ital) -{ - if (d3ddevice && name && *name && size > 4) { - RELEASE(d3dx_font); - - strcpy_s(font_name, name); - font_size = size; - font_bold = bold; - font_ital = ital; - - HRESULT hr = E_FAIL; - HDC hdc = GetDC(NULL); - int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); - - ReleaseDC(NULL, hdc); - - int nHeight = -size * nLogPixelsY / 72; - - hr = D3DXCreateFont(d3ddevice, // D3D device - nHeight, // Height - 0, // Width - bold ? FW_BOLD : FW_NORMAL, // Weight - 1, // MipLevels, 0 = autogen mipmaps - ital, // Italic - DEFAULT_CHARSET, // CharSet - OUT_DEFAULT_PRECIS, // OutputPrecision - DEFAULT_QUALITY, // Quality - DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily - name, // pFaceName - &d3dx_font); // ppFont - - if (SUCCEEDED(hr)) { - return true; - } - } - - RELEASE(d3dx_font); - return false; -} - -bool -VideoDX9::DrawText(const char* text, int count, const Rect& rect, DWORD format, Color c) -{ - if (d3ddevice && text && *text && d3dx_font) { - RECT r; - r.left = rect.x; - r.top = rect.y; - r.right = rect.x + rect.w; - r.bottom = rect.y + rect.h; - - d3dx_font->DrawText(0, text, count, &r, format, c.Value()); - } - - return false; -} - -// +--------------------------------------------------------------------+ - -bool -VideoDX9::PrepareSurface(Surface* surf) -{ - if (surf) { - int nverts = surf->NumVerts(); - int nindices = surf->NumIndices(); - bool detail = surf->GetVertexSet()->tu1 != 0; - bool luminous = false; - DWORD dynamic = 0; - - if (surf->GetModel()) { - luminous = surf->GetModel()->IsLuminous(); - dynamic = surf->GetModel()->IsDynamic() ? D3DUSAGE_DYNAMIC : 0; - } - - surface_has_tangent_data = !luminous && (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal); - - VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); - - if (!surf_data) { - surf_data = new(__FILE__,__LINE__) VideoDX9SurfaceData(surf->GetModel()); - - surface_has_tangent_data = false; - - if (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal) { - surface_has_tangent_data = true; - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9NormalVertex), - 0, // not an FVF vertex buffer - dynamic | D3DUSAGE_WRITEONLY); - } - - else if (detail) { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9DetailVertex), - VideoDX9DetailVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - else if (luminous) { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9LuminousVertex), - VideoDX9LuminousVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - else { - surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( - this, - nverts, - sizeof(VideoDX9SolidVertex), - VideoDX9SolidVertex::FVF, - dynamic | D3DUSAGE_WRITEONLY); - } - - surf_data->index_buffer = new(__FILE__,__LINE__) VideoDX9IndexBuffer( - this, - nindices, - dynamic | D3DUSAGE_WRITEONLY); - - if (!surf_data->vertex_buffer || !surf_data->index_buffer) { - Print("VideoDX9: Unable to prepare surface '%s'\n", surf->Name()); - delete surf_data; - return false; - } - - surf->SetVideoPrivateData(surf_data); - } - - if (surf_data && !surf_data->IsValid()) { - if (detail) { - VideoDX9DetailVertex* v = (VideoDX9DetailVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - v->specular = vset->specular[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - v->tu1 = vset->tu1[i]; - v->tv1 = vset->tv1[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else if (luminous) { - VideoDX9LuminousVertex* v = (VideoDX9LuminousVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->diffuse = vset->diffuse[i]; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else if (surface_has_tangent_data) { - VideoDX9NormalVertex* v = (VideoDX9NormalVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->t0u = vset->tu[i]; - v->t0v = vset->tv[i]; - v->t1u = vset->tu[i]; - v->t1v = vset->tv[i]; - - v->tx = vset->tangent[i].x; - v->ty = vset->tangent[i].y; - v->tz = vset->tangent[i].z; - - v->bx = vset->binormal[i].x; - v->by = vset->binormal[i].y; - v->bz = vset->binormal[i].z; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - else { - VideoDX9SolidVertex* v = (VideoDX9SolidVertex*) surf_data->vertex_buffer->Lock(nverts); - - if (v) { - const VertexSet* vset = surf->GetVertexSet(); - for (int i = 0; i < nverts; i++) { - v->x = vset->loc[i].x; - v->y = vset->loc[i].y; - v->z = vset->loc[i].z; - - v->nx = vset->nrm[i].x; - v->ny = vset->nrm[i].y; - v->nz = vset->nrm[i].z; - - v->tu = vset->tu[i]; - v->tv = vset->tv[i]; - - v++; - } - - surf_data->vertex_buffer->Unlock(); - } - } - - WORD* indices = surf_data->index_buffer->Lock(nindices); - - if (indices) { - // copy the indices into the locked index buffer - WORD* s = indices; - Poly* p = surf->GetPolys(); - - for (int i = 0; i < surf->NumPolys(); i++) { - if (p->nverts == 3) { - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[1]; - } - else if (p->nverts == 4) { - *s++ = p->verts[0]; - *s++ = p->verts[2]; - *s++ = p->verts[1]; - - *s++ = p->verts[0]; - *s++ = p->verts[3]; - *s++ = p->verts[2]; - } - - p++; - } - - surf_data->index_buffer->Unlock(); - } - - surf_data->Validate(); - } - - int first_index = 0; - - ListIter seg_iter = surf->GetSegments(); - while (++seg_iter) { - Segment* segment = seg_iter.value(); - - if (!segment->video_data) { - VideoDX9SegmentData* seg_data = new(__FILE__,__LINE__) VideoDX9SegmentData; - - int num_tris = 0; - for (int i = 0; i < segment->npolys; i++) - num_tris += segment->polys[i].nverts-2; - - seg_data->first_vert = 0; - seg_data->num_verts = surf->NumVerts(); - seg_data->first_index = first_index; - seg_data->num_tris = num_tris; - - segment->video_data = seg_data; - - first_index += num_tris * 3; - } - } - } - - return true; -} - -// +--------------------------------------------------------------------+ - -int -VideoDX9::PrepareMaterial(Material* m) -{ - segment_material = m; - strategy = 0; - passes = 0; - - if (m) { - int max_stages = 1; - int max_textures = 1; - bool multiply_add = false; - bool dotproduct3 = false; - bool vertexshader = false; - bool pixelshader = false; - DWORD vs_version = 0; - DWORD ps_version = 0; - - VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); - - if (dev_info) { - max_stages = (int) dev_info->caps.MaxTextureBlendStages; - max_textures = (int) dev_info->caps.MaxSimultaneousTextures; - multiply_add = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ? true : false; - dotproduct3 = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ? true : false; - - vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; - ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; - - vertexshader = vs_version >= D3DVS_VERSION(1,1); - pixelshader = ps_version >= D3DPS_VERSION(2,0); - } - - strategy = DX9_STRATEGY_SIMPLE; - passes = 1; - - if (m->tex_alternate) { - if (m->tex_detail && max_textures > 2 && max_stages > 4) - strategy = DX9_STRATEGY_BLEND_DETAIL; - - else if (max_textures > 1 && max_stages > 3) - strategy = DX9_STRATEGY_BLEND; - } - - else if (m->tex_emissive && (!m->tex_diffuse || m->tex_diffuse == m->tex_emissive)) { - strategy = DX9_STRATEGY_GLOW; - } - - else if (IsSpecMapEnabled() && m->tex_specular && !m->tex_emissive) { - strategy = DX9_STRATEGY_SPECMAP; - - if (max_textures < 2 || max_stages < 2 || !multiply_add) - passes = 2; - } - - else if ((!IsSpecMapEnabled() || !m->tex_specular) && m->tex_emissive) { - strategy = DX9_STRATEGY_EMISSIVE; - - if (max_textures < 2 || max_stages < 2) - passes = 2; - } - - else if (IsSpecMapEnabled() && m->tex_specular && m->tex_emissive) { - strategy = DX9_STRATEGY_SPEC_EMISSIVE; - - if (max_textures < 2 || max_stages < 2) - passes = 3; - - else if (max_textures < 3 || max_stages < 3 || !multiply_add) - passes = 2; - } - } - - return passes; -} - -bool -VideoDX9::SetupPass(int pass) -{ - if (pass < 0 || pass >= passes) - return false; - - if (pass == 0) { - D3DMATERIAL9 d3dmtl; - IDirect3DTexture9* texture_0 = 0; - IDirect3DTexture9* texture_1 = 0; - IDirect3DTexture9* texture_2 = 0; - Bitmap* tex_bmp_0 = 0; - Bitmap* tex_bmp_1 = 0; - Bitmap* tex_bmp_2 = 0; - ColorValue orig_spec = segment_material->Ks; - HRESULT hr = E_FAIL; - - if (segment_material->tex_specular && passes > 1) - segment_material->Ks = Color::Black; - - CreateD3DMaterial(d3dmtl, *segment_material); - segment_material->Ks = orig_spec; - - hr = d3ddevice->SetMaterial(&d3dmtl); - - if (strategy == DX9_STRATEGY_SIMPLE) { - tex_bmp_0 = segment_material->tex_diffuse; - } - - else if (strategy == DX9_STRATEGY_BLEND) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_alternate; - } - - else if (strategy == DX9_STRATEGY_BLEND_DETAIL) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_alternate; - tex_bmp_2 = segment_material->tex_detail; - } - - else if (strategy == DX9_STRATEGY_SPECMAP) { - if (passes == 1) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_specular; - } - else { - tex_bmp_0 = segment_material->tex_diffuse; - } - } - - else if (strategy == DX9_STRATEGY_EMISSIVE && passes == 1 || - strategy == DX9_STRATEGY_SPEC_EMISSIVE && passes == 2) { - if (segment_material->tex_diffuse) { - tex_bmp_0 = segment_material->tex_diffuse; - tex_bmp_1 = segment_material->tex_emissive; - } - else { - tex_bmp_0 = segment_material->tex_emissive; - } - } - - else { - tex_bmp_0 = segment_material->tex_emissive; - } - - if (texcache && tex_bmp_0) { - texture_0 = texcache->FindTexture(tex_bmp_0); - - hr = d3ddevice->SetTexture(0, texture_0); - current_texture = texture_0; - - if (tex_bmp_1) { - texture_1 = texcache->FindTexture(tex_bmp_1); - hr = d3ddevice->SetTexture(1, texture_1); - - if (tex_bmp_2) { - texture_2 = texcache->FindTexture(tex_bmp_2); - hr = d3ddevice->SetTexture(2, texture_2); - } - } - } - else { - hr = d3ddevice->SetTexture(0, 0); - current_texture = 0; - } - - SetBlendType(segment_material->blend); - - if (texture_0 && texture_1 && strategy == DX9_STRATEGY_BLEND) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - - d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - - else if (texture_0 && texture_1 && texture_2 && strategy == DX9_STRATEGY_BLEND_DETAIL) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - - d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1); - - d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT); - } - - else if (texture_0 && strategy == DX9_STRATEGY_GLOW) { - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_0) { - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - if (texture_1 && strategy == DX9_STRATEGY_SPECMAP) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_1 && strategy == DX9_STRATEGY_EMISSIVE) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (texture_1 && strategy == DX9_STRATEGY_SPEC_EMISSIVE) { - d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); - - d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - } - - else if (strategy < DX9_STRATEGY_BLEND) { - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - } - } - - else if (pass == 1) { - D3DMATERIAL9 d3dmtl; - IDirect3DTexture9* texture = 0; - Bitmap* tex_bmp = 0; - ColorValue orig_Ka = segment_material->Ka; - ColorValue orig_Kd = segment_material->Kd; - HRESULT hr = E_FAIL; - - if (segment_material->tex_specular) { - segment_material->Ka = Color::Black; - segment_material->Kd = Color::Black; - } - - CreateD3DMaterial(d3dmtl, *segment_material); - - segment_material->Ka = orig_Ka; - segment_material->Kd = orig_Kd; - - hr = d3ddevice->SetMaterial(&d3dmtl); - - if (strategy == DX9_STRATEGY_SPECMAP || - strategy == DX9_STRATEGY_SPEC_EMISSIVE) { - tex_bmp = segment_material->tex_specular; - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR); - } - - else if (strategy == DX9_STRATEGY_EMISSIVE) { - tex_bmp = segment_material->tex_emissive; - d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - } - - d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - - if (texcache && tex_bmp) { - texture = texcache->FindTexture(tex_bmp); - hr = d3ddevice->SetTexture(0, texture); - current_texture = texture; - - SetBlendType(BLEND_ADDITIVE); - } - } - - if (render_state[STENCIL_ENABLE]) { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); - d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); - } - else { - d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - if (render_state[LIGHTING_PASS] > 0) { - SetBlendType(BLEND_ADDITIVE); - SetRenderState(Z_WRITE_ENABLE, FALSE); - } - - return true; -} - - -// +--------------------------------------------------------------------+ - -void -VideoDX9Error(const char* msg, HRESULT err) -{ - Print(" VideoDX9: %s. [%s]\n", msg, D3DErrStr(err)); -} - -char* D3DErrStr(HRESULT hr) -{ - static char errstrbuf[128]; - - switch (hr) { - default: - sprintf_s(errstrbuf, "Unrecognized error value = %08x.", hr); - return errstrbuf; - - case D3D_OK: - return "No error."; - - case D3DERR_WRONGTEXTUREFORMAT: - return "Wrong texture format."; - - case D3DERR_UNSUPPORTEDCOLOROPERATION: - return "Unsupported color operation."; - - case D3DERR_UNSUPPORTEDCOLORARG: - return "Unsupported color argument."; - - case D3DERR_UNSUPPORTEDALPHAOPERATION: - return "Unsupported alpha operation."; - - case D3DERR_UNSUPPORTEDALPHAARG: - return "Unsupported alpha argument."; - - case D3DERR_TOOMANYOPERATIONS: - return "Too many operations."; - - case D3DERR_CONFLICTINGTEXTUREFILTER: - return "Conflicting texture filter."; - - case D3DERR_UNSUPPORTEDFACTORVALUE: - return "Unsupported factor value."; - - case D3DERR_CONFLICTINGRENDERSTATE: - return "Conflicting render state."; - - case D3DERR_UNSUPPORTEDTEXTUREFILTER: - return "Unsupported texture filter."; - - case D3DERR_CONFLICTINGTEXTUREPALETTE: - return "Conflicting texture palette."; - - case D3DERR_DRIVERINTERNALERROR: - return "Driver internal error."; - - - case D3DERR_NOTFOUND: - return "Resource was not found."; - - case D3DERR_MOREDATA: - return "More data?"; - - case D3DERR_DEVICELOST: - return "Device lost."; - - case D3DERR_DEVICENOTRESET: - return "Device is not reset."; - - case D3DERR_NOTAVAILABLE: - return "Not available."; - - case D3DERR_OUTOFVIDEOMEMORY: - return "Out of video memory."; - - case E_OUTOFMEMORY: - return "Out of system memory."; - - case D3DERR_INVALIDDEVICE: - return "Invalid device selection."; - - case D3DERR_INVALIDCALL: - return "Invalid call or parameter."; - - case D3DERR_DRIVERINVALIDCALL: - return "Driver invalid call."; - - case D3DERR_WASSTILLDRAWING: - return "The device was still drawing."; - - case D3DOK_NOAUTOGEN: - return "Autogeneration is not supported by this device."; - - } -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: VideoDX9.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Direct3D Video class for DirectX 9 +*/ + +#include "MemDebug.h" +#include "VideoDX9.h" +#include "VideoDX9Enum.h" +#include "VideoDX9VertexBuffer.h" +#include "TexDX9.h" +#include "TexCubeDX9.h" +#include "Camera.h" +#include "Color.h" +#include "DataLoader.h" +#include "Polygon.h" +#include "Light.h" +#include "Solid.h" + +// +--------------------------------------------------------------------+ + +void Print(const char* msg, ...); +char* D3DErrStr(HRESULT dderr); +void VideoDX9Error(const char* msg, HRESULT dderr); +static TexCacheDX9* texcache = 0; +static TexCubeDX9* environment_cube = 0; +static bool surface_has_tangent_data = false; +static Light* main_light; +static Light* back_light; +static D3DXMATRIX matrixWorld; +static D3DXMATRIX matrixView; +static D3DXMATRIX matrixProj; +static D3DXMATRIX matrixWorldInverse; + +extern int VD3D_describe_things; + +#ifndef RELEASE +#define RELEASE(x) if (x) { x->Release(); x=NULL; } +#endif + +#ifndef F2DW +#define F2DW(x) (*(DWORD*)(&x)) +#endif + +#ifndef DW2I +#define DW2I(x) (*(int*)(&x)) +#endif + +// +--------------------------------------------------------------------+ + +typedef HRESULT (WINAPI * LPDDCE)(GUID FAR *, LPVOID *, REFIID , IUnknown FAR *); + +static D3DMATRIX identity_matrix = { + FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), + FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), FLOAT(0.0), + FLOAT(0.0), FLOAT(0.0), FLOAT(1.0), FLOAT(0.0), + FLOAT(0.0), FLOAT(0.0), FLOAT(0.0), FLOAT(1.0) +}; + +// +--------------------------------------------------------------------+ + +List model_clients; + +class VideoDX9SurfaceData : public VideoPrivateData +{ +public: + VideoDX9SurfaceData(Model* m) : model(m), vertex_buffer(0), index_buffer(0) { + if (!model_clients.contains(model)) + model_clients.append(model); + } + + virtual ~VideoDX9SurfaceData() { + model_clients.remove(model); + + delete vertex_buffer; + delete index_buffer; + } + + enum { TYPE = 9001 }; + virtual int GetType() const { return TYPE; } + + Model* model; + VideoDX9VertexBuffer* vertex_buffer; + VideoDX9IndexBuffer* index_buffer; +}; + +class VideoDX9SegmentData : public VideoPrivateData +{ +public: + VideoDX9SegmentData() : first_vert(0), num_verts(0), first_index(0), num_tris(0) { } + virtual ~VideoDX9SegmentData() { } + + enum { TYPE = 9002 }; + virtual int GetType() const { return TYPE; } + + int first_vert; + int num_verts; + int first_index; + int num_tris; +}; + +// +--------------------------------------------------------------------+ + +static int d3dstate_table[] = { + D3DRS_FILLMODE, // FILL_MODE + D3DRS_SHADEMODE, // SHADE_MODE + D3DRS_LIGHTING, // LIGHTING_ENABLE + D3DRS_ZENABLE, // Z_ENABLE + D3DRS_ZWRITEENABLE, // Z_WRITE_ENABLE + D3DRS_DEPTHBIAS, // Z_BIAS + 0, // TEXTURE_FILTER + D3DRS_DITHERENABLE, // DITHER_ENABLE + D3DRS_SPECULARENABLE, // SPECULAR_ENABLE + D3DRS_FOGENABLE, // FOG_ENABLE + D3DRS_FOGCOLOR, // FOG_COLOR + D3DRS_FOGDENSITY, // FOG_DENSITY + D3DRS_STENCILENABLE, // STENCIL_ENABLE + 0x11111111, // TEXTURE_WRAP (special case) + 0 // LIGHTING_PASS +}; + +static const int NUM_SCREEN_VERTS = 1024; +static const int NUM_SCREEN_INDICES = NUM_SCREEN_VERTS * 2; + +// +--------------------------------------------------------------------+ + +struct VideoDX9ScreenVertex +{ + FLOAT sx, sy, sz, rhw; + DWORD diffuse; + FLOAT tu, tv; + + static DWORD FVF; +}; + +DWORD VideoDX9ScreenVertex::FVF = D3DFVF_XYZRHW | +D3DFVF_DIFFUSE | +D3DFVF_TEX1; + +struct VideoDX9NormalVertex +{ + FLOAT x, y, z; + FLOAT nx, ny, nz; + FLOAT t0u, t0v; + FLOAT t1u, t1v; + FLOAT tx, ty, tz; + FLOAT bx, by, bz; + + static DWORD FVF; +}; + +DWORD VideoDX9NormalVertex::FVF = 0; + +// Global Vertex Declaration shared by shaders +D3DVERTEXELEMENT9 videoDX9NormalVertexElements[] = +{ + { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, + { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + { 0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, + { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 2 }, + { 0, 52, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 3 }, + D3DDECL_END() +}; + +struct VideoDX9SolidVertex +{ + FLOAT x, y, z; + FLOAT nx, ny, nz; + FLOAT tu, tv; + + static DWORD FVF; +}; + +DWORD VideoDX9SolidVertex::FVF = D3DFVF_XYZ | +D3DFVF_NORMAL | +D3DFVF_TEX1 | +D3DFVF_TEXCOORDSIZE2(0); + +struct VideoDX9LuminousVertex +{ + FLOAT x, y, z; + DWORD diffuse; + FLOAT tu, tv; + + static DWORD FVF; +}; + +DWORD VideoDX9LuminousVertex::FVF = D3DFVF_XYZ | +D3DFVF_DIFFUSE | +D3DFVF_TEX1 | +D3DFVF_TEXCOORDSIZE2(0); + +struct VideoDX9DetailVertex +{ + FLOAT x, y, z; + DWORD diffuse; + DWORD specular; + FLOAT tu, tv; + FLOAT tu1, tv1; + + static DWORD FVF; +}; + +DWORD VideoDX9DetailVertex::FVF = D3DFVF_XYZ | +D3DFVF_DIFFUSE | +D3DFVF_SPECULAR | +D3DFVF_TEX2; + +struct VideoDX9LineVertex +{ + FLOAT x, y, z; + DWORD diffuse; + + static DWORD FVF; +}; + +DWORD VideoDX9LineVertex::FVF = D3DFVF_XYZ | +D3DFVF_DIFFUSE; + +enum { + DX9_STRATEGY_NONE, + DX9_STRATEGY_SIMPLE, + DX9_STRATEGY_GLOW, + DX9_STRATEGY_SPECMAP, + DX9_STRATEGY_EMISSIVE, + DX9_STRATEGY_SPEC_EMISSIVE, + DX9_STRATEGY_BLEND, + DX9_STRATEGY_BLEND_DETAIL +}; + +// +--------------------------------------------------------------------+ + +static VideoDX9* video_dx9_instance = 0; + +VideoDX9::VideoDX9(const HWND& window, VideoSettings* vs) +: width(0), height(0), bpp(0), hwnd(window), surface(0), +d3d(0), d3ddevice(0), device_lost(false), fade(0), +zdepth(0), gamma(128), num_verts(0), first_vert(0), +current_texture(0), screen_vbuf(0), screen_ibuf(0), +font_verts(0), font_indices(0), font_nverts(0), +nlights(0), use_material(0), d3dx_font(0), +segment_material(0), strategy(0), passes(0), +screen_line_verts(0), line_verts(0), +vertex_declaration(0), +magic_fx(0), magic_fx_code(0), magic_fx_code_len(0) +{ + video_dx9_instance = this; + + Print("\n********************************\n"); + Print("* Direct 3D version 9 *\n"); + Print("********************************\n\n"); + + status = VIDEO_ERR; + HRESULT err = E_OUTOFMEMORY; + + d3d = Direct3DCreate9(D3D_SDK_VERSION); + dx9enum = new(__FILE__,__LINE__) VideoDX9Enum(d3d); + + if (d3d && dx9enum) { + if (vs) { + dx9enum->req_fullscreen = vs->is_windowed ? false : true; + dx9enum->req_windowed = vs->is_windowed ? true : false; + dx9enum->min_stencil_bits = vs->shadows ? 8 : 0; + dx9enum->uses_depth_buffer = true; + } + else { + dx9enum->req_fullscreen = video_settings.is_windowed ? false : true; + dx9enum->req_windowed = video_settings.is_windowed ? true : false; + dx9enum->min_stencil_bits = video_settings.shadows ? 8 : 0; + dx9enum->uses_depth_buffer = true; + } + + err = dx9enum->Enumerate(); + + if (FAILED(err)) { + VideoDX9Error("(ctor) could not enumerate dx9 properties", err); + delete dx9enum; + return; + } + } + else { + VideoDX9Error("(ctor) could not create enumerator", err); + return; + } + + SetVideoSettings(vs); + + if (video_settings.is_windowed) + dx9enum->SuggestWindowSettings(&video_settings); + else + dx9enum->SuggestFullscreenSettings(&video_settings); + + SetupParams(); + + if (VD3D_describe_things > 2) { + Print("\nD3DPRESENT_PARAMETERS:\n"); + Print(" BackBufferWidth: %d\n", d3dparams.BackBufferWidth); + Print(" BackBufferHeight: %d\n", d3dparams.BackBufferHeight); + Print(" BackBufferCount: %d\n", d3dparams.BackBufferCount); + Print(" BackBufferFormat: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.BackBufferFormat)); + Print(" Multisample Type: %d\n", d3dparams.MultiSampleType); + Print(" Multisample Qual: %d\n", d3dparams.MultiSampleQuality); + Print(" Swap Effect: %d\n", d3dparams.SwapEffect); + Print(" Device Window: %08X\n", d3dparams.hDeviceWindow); + Print(" Windowed: %s\n", d3dparams.Windowed ? "true" : "false"); + Print(" Enable Depth/Stencil: %s\n", d3dparams.EnableAutoDepthStencil ? "true" : "false"); + Print(" Depth/Stencil Format: %s\n", VideoDX9DisplayMode::D3DFormatToString(d3dparams.AutoDepthStencilFormat)); + Print(" Flags: %08X\n", d3dparams.Flags); + Print(" Fullscreen Refresh: %d Hz\n", d3dparams.FullScreen_RefreshRateInHz); + + switch (d3dparams.PresentationInterval) { + case D3DPRESENT_INTERVAL_IMMEDIATE: + Print(" Present Interval: IMMEDIATE\n"); + break; + + case D3DPRESENT_INTERVAL_DEFAULT: + Print(" Present Interval: DEFAULT\n"); + break; + + case D3DPRESENT_INTERVAL_ONE: + Print(" Present Interval: ONE\n"); + break; + + case D3DPRESENT_INTERVAL_TWO: + Print(" Present Interval: TWO\n"); + break; + + case D3DPRESENT_INTERVAL_THREE: + Print(" Present Interval: THREE\n"); + break; + + case D3DPRESENT_INTERVAL_FOUR: + Print(" Present Interval: FOUR\n"); + break; + + default: + Print(" Present Interval: Unknown (%d)\n", d3dparams.PresentationInterval); + break; + } + + Print("\n"); + } + + Print(" Creating Video Device for HWND = %08x\n", window); + + err = d3d->CreateDevice(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &d3dparams, + &d3ddevice); + + if (FAILED(err)) { + VideoDX9Error("(ctor) could not create device", err); + return; + } + + width = video_settings.GetWidth(); + height = video_settings.GetHeight(); + bpp = video_settings.GetDepth(); + + shadow_enabled = vs->shadows; + bump_enabled = vs->bumpmaps; + spec_enabled = vs->specmaps; + + render_state[FILL_MODE] = FILL_SOLID; + render_state[SHADE_MODE] = SHADE_GOURAUD; + render_state[Z_ENABLE] = false; + render_state[Z_WRITE_ENABLE] = false; + render_state[Z_BIAS] = 0; + render_state[TEXTURE_FILTER] = FILTER_LINEAR; + render_state[DITHER_ENABLE] = false; + render_state[SPECULAR_ENABLE] = true; + render_state[FOG_ENABLE] = false; + render_state[FOG_COLOR] = 0; + render_state[FOG_DENSITY] = 0; + render_state[STENCIL_ENABLE] = false; + render_state[TEXTURE_WRAP] = true; + render_state[LIGHTING_PASS] = 0; + + ZeroMemory(&rect, sizeof(rect)); + + if (!texcache) + texcache = new(__FILE__,__LINE__) TexCacheDX9(this); + + if (texcache) + texcache->count++; + + if (VD3D_describe_things > 0) { + DWORD vmf = VidMemFree() / (1024 * 1024); + Print(" Available Texture Memory: %d MB\n\n", vmf); + } + + if (CreateBuffers()) { + d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); + d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + + status = VIDEO_OK; + } + + ZeroMemory(font_name, 64); + font_size = 0; + font_bold = false; + font_ital = false; +} + +// +--------------------------------------------------------------------+ + +VideoDX9::~VideoDX9() +{ + DestroyBuffers(); + + texcache->count--; + if (!texcache->count) { + delete texcache; + texcache = 0; + } + + delete environment_cube; + delete dx9enum; + + RELEASE(d3dx_font); + RELEASE(d3ddevice); + RELEASE(d3d); + + if (magic_fx_code) + delete [] magic_fx_code; + + Print(" VideoDX9: shutdown\n"); + video_dx9_instance = 0; +} + +IDirect3DDevice9* +VideoDX9::GetD3DDevice9() +{ + if (video_dx9_instance) + return video_dx9_instance->d3ddevice; + + return 0; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetupParams() +{ + if (!dx9enum || dx9enum->NumAdapters() < 1) { + status = VIDEO_ERR; + return false; + } + + int adapter_index = video_settings.GetAdapterIndex(); + + if (adapter_index < 0 || adapter_index >= dx9enum->NumAdapters()) { + ::Print("WARNING: VideoDX9 could not select adapter %d (max=%d)\n", + adapter_index, dx9enum->NumAdapters()); + + adapter_index = 0; + } + + dx9enum->SelectAdapter(adapter_index); + + d3dparams.Windowed = video_settings.IsWindowed(); + d3dparams.BackBufferCount = 2; + d3dparams.MultiSampleType = D3DMULTISAMPLE_NONE; + d3dparams.MultiSampleQuality = 0; + d3dparams.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dparams.EnableAutoDepthStencil = dx9enum->uses_depth_buffer; + d3dparams.hDeviceWindow = hwnd; + + if (dx9enum->uses_depth_buffer) { + d3dparams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; + d3dparams.AutoDepthStencilFormat = (D3DFORMAT) video_settings.GetDepthStencilFormat(); + } + else { + d3dparams.Flags = 0; + } + + d3dparams.Flags |= D3DPRESENTFLAG_DEVICECLIP; + + if (video_settings.IsWindowed()) { + d3dparams.BackBufferWidth = video_settings.window_width; + d3dparams.BackBufferHeight = video_settings.window_height; + d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); + d3dparams.FullScreen_RefreshRateInHz = 0; + d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + else { + d3dparams.BackBufferWidth = video_settings.GetWidth(); + d3dparams.BackBufferHeight = video_settings.GetHeight(); + d3dparams.BackBufferFormat = (D3DFORMAT) video_settings.GetBackBufferFormat(); + d3dparams.FullScreen_RefreshRateInHz = video_settings.GetRefreshRate(); + d3dparams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + + return true; +} + + +bool +VideoDX9::IsModeSupported(int w, int h, int b) const +{ + if (dx9enum) + return dx9enum->IsModeSupported(w, h, b); + + return false; +} + +bool +VideoDX9::SetVideoSettings(const VideoSettings* vs) +{ + // custom video settings: + if (vs) { + if (vs != &video_settings) + CopyMemory(&video_settings, vs, sizeof(VideoSettings)); + } + + // default video settings: + else { + ZeroMemory(&video_settings, sizeof(VideoSettings)); + + video_settings.fullscreen_mode.width = 800; + video_settings.fullscreen_mode.height = 600; + video_settings.fullscreen_mode.format = VideoMode::FMT_X8R8G8B8; + } + + return true; +} + +bool +VideoDX9::Reset(const VideoSettings* vs) +{ + if (!d3ddevice || !SetVideoSettings(vs)) { + status = VIDEO_ERR; + return false; + } + + bool using_x_font = (d3dx_font != 0); + + RELEASE(d3dx_font); + InvalidateCache(); + DestroyBuffers(); + SetupParams(); + + HRESULT hr = d3ddevice->Reset(&d3dparams); + + if (FAILED(hr)) { + VideoDX9Error("could not reset d3d device", hr); + status = VIDEO_ERR; + return false; + } + + // Store render target surface desc + IDirect3DSurface9* back_buffer; + d3ddevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer); + back_buffer->GetDesc(&back_buffer_desc); + RELEASE(back_buffer); + + width = video_settings.GetWidth(); + height = video_settings.GetHeight(); + bpp = video_settings.GetDepth(); + + shadow_enabled = vs->shadows; + bump_enabled = vs->bumpmaps; + spec_enabled = vs->specmaps; + + + if (CreateBuffers()) { + d3ddevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); + d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + d3ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); + + D3DVIEWPORT9 view; + + hr = d3ddevice->GetViewport(&view); + if (SUCCEEDED(hr)) { + rect.x = view.X; + rect.y = view.Y; + rect.w = view.Width; + rect.h = view.Height; + } + + if (using_x_font) + UseXFont(font_name, font_size, font_bold, font_ital); + + status = VIDEO_OK; + } + + return status == VIDEO_OK; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::CreateBuffers() +{ + if (d3ddevice) { + UINT vertex_size = sizeof(VideoDX9ScreenVertex); + UINT index_size = sizeof(WORD); + + if (!screen_vbuf) { + screen_vbuf = new(__FILE__,__LINE__) VideoDX9VertexBuffer( + this, + NUM_SCREEN_VERTS, + vertex_size, + VideoDX9ScreenVertex::FVF, + D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + } + + if (!screen_ibuf) { + screen_ibuf = new(__FILE__,__LINE__) VideoDX9IndexBuffer( + this, + NUM_SCREEN_INDICES, + D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); + } + + screen_line_verts = new(__FILE__,__LINE__) VideoDX9ScreenVertex[256]; + line_verts = new(__FILE__,__LINE__) VideoDX9LineVertex[512]; + + // create effects: + LPD3DXBUFFER code_buffer = 0; + DataLoader* loader = DataLoader::GetLoader(); + HRESULT hr = E_FAIL; + + hr = d3ddevice->CreateVertexDeclaration(videoDX9NormalVertexElements, + &vertex_declaration); + + // The E - We want to load our shader from the standard filesystem by default, to allow for better modding. + if (video_settings.use_effects && !magic_fx_code) { + FILE* f; + ::fopen_s(&f, "magic.fx", "rb"); + + if (f) { + ::fseek(f, 0, SEEK_END); + magic_fx_code_len = ftell(f); + ::fseek(f, 0, SEEK_SET); + + magic_fx_code = new(__FILE__,__LINE__) BYTE[magic_fx_code_len+1]; + if (magic_fx_code) { + ::fread(magic_fx_code, magic_fx_code_len, 1, f); + magic_fx_code[magic_fx_code_len] = 0; + } + ::fclose(f); + } else if (loader) { + magic_fx_code_len = loader->LoadBuffer("magic.fx", magic_fx_code, true, true); + } + } + + if (video_settings.use_effects && magic_fx_code && magic_fx_code_len) { + hr = D3DXCreateEffect(d3ddevice, + magic_fx_code, + magic_fx_code_len, + 0, 0, 0, 0, + &magic_fx, + &code_buffer); + + if (code_buffer) { + ::Print("ERROR - Failed to compile 'magic.fx'\n"); + ::Print((const char*) code_buffer->GetBufferPointer()); + ::Print("\n\n"); + RELEASE(code_buffer); + } + } + } + + return screen_vbuf && screen_ibuf; +} + +bool +VideoDX9::DestroyBuffers() +{ + if (line_verts) { + delete line_verts; + line_verts = 0; + } + + if (screen_line_verts) { + delete screen_line_verts; + screen_line_verts = 0; + } + + if (screen_vbuf) { + delete screen_vbuf; + screen_vbuf = 0; + } + + if (screen_ibuf) { + delete screen_ibuf; + screen_ibuf = 0; + } + + if (font_verts) { + delete [] font_verts; + font_verts = 0; + } + + if (font_indices) { + delete [] font_indices; + font_indices = 0; + } + + font_nverts = 0; + + RELEASE(vertex_declaration); + RELEASE(magic_fx); + + return true; +} + +// +--------------------------------------------------------------------+ + +DWORD +VideoDX9::VidMemFree() const +{ + UINT result = 0; + + if (d3ddevice) + result = d3ddevice->GetAvailableTextureMem(); + + return result; +} + +int +VideoDX9::MaxTexSize() const +{ + if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { + VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); + + if (dev_info) { + return (int) dev_info->caps.MaxTextureWidth; + } + } + + return 0; +} + +int +VideoDX9::MaxTexAspect() const +{ + if (d3d && dx9enum && dx9enum->GetAdapterInfo()) { + VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); + + if (dev_info) { + return (int) dev_info->caps.MaxTextureAspectRatio; + } + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +void +VideoDX9::RecoverSurfaces() +{ + Print("VideoDX9::RecoverSurfaces()\n"); + + HRESULT hr = D3D_OK; + + surface = 0; + + hr = d3ddevice->TestCooperativeLevel(); + + if (hr == D3DERR_DEVICELOST) { + // This means that some app took exclusive mode access + // we need to sit in a loop till we get back to the right mode. + Print("D3DERR_DEVICELOST\n"); + + do { + Sleep(500); + hr = d3ddevice->TestCooperativeLevel(); + } while (hr == D3DERR_DEVICELOST); + } + + if (hr == D3DERR_DEVICENOTRESET) { + if (Reset(&video_settings)) + hr = S_OK; + } + + if (SUCCEEDED(hr)) { + Print("* Invalidating Texture Cache\n"); + // Re-fill the contents of textures which just got restored: + InvalidateCache(); + + device_lost = false; + } + + Print("* Vid Mem Free: %8d\n", VidMemFree()); + Print("* Recover Surfaces Complete.\n\n"); +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetBackgroundColor(Color c) +{ + background = c; + return true; +} + +//----------------------------------------------------------------------------- +// RampValue +// +// The gamma function with inputs in [0,255], scaled to a range with the +// default range appropriate for D3DGAMMARAMP. +// +inline WORD +RampValue(UINT i, double recip_gamma, double fade) +{ + return (WORD) (65535.0 * fade * pow((double)i/255.f, recip_gamma)); +} + +//----------------------------------------------------------------------------- +// ReciprocalGamma +// +// Given a gamma corrected i in [0,255], return 1/gamma +// +inline float +ReciprocalGamma(UINT i) +{ + return logf(i/255.f)/logf(0.5f); +} + +//----------------------------------------------------------------------------- +// GammaValue +// +// Given a gamma corrected color channel value in [0,255], return the gamma. +// +inline float +GammaValue(UINT i) +{ + return logf(0.5f)/logf(i/255.f); +} + +bool +VideoDX9::SetGammaLevel(int g) +{ + HRESULT hr = E_FAIL; + double f = Color::GetFade(); + + if (gamma != g || fade != f) { + if (d3ddevice) { + //::Print("VideoDX9 - SetGammaLevel(%d) fade = %f\n", g, f); + + // compute 1/gamma + float recip_gray = ReciprocalGamma(g); + + // compute i**(1/gamma) for all i and scale to range + for (UINT i = 0; i < 256; i++) { + int val = RampValue(i, recip_gray, f); + + gamma_ramp.red[i] = val; + gamma_ramp.green[i] = val; + gamma_ramp.blue[i] = val; + } + + d3ddevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &gamma_ramp); + hr = D3D_OK; + } + + gamma = g; + fade = f; + } + + return SUCCEEDED(hr); +} + +bool +VideoDX9::SetObjTransform(const Matrix& orient, const Point& loc) +{ + HRESULT hr = E_FAIL; + + if (d3ddevice) { + D3DMATRIX world_matrix; + CreateD3DMatrix(world_matrix, orient, loc); + hr = d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); + + matrixWorld = world_matrix; + D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); + } + + return SUCCEEDED(hr); +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::ClearAll() +{ + HRESULT err; + + err = d3ddevice->Clear(0, + NULL, + D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, + background.Value(), + 1.0f, + 0); + + if (FAILED(err)) { + static int report = 10; + if (report > 0) { + VideoDX9Error("Failed to clear device", err); + report--; + } + } + + return true; +} + +bool +VideoDX9::ClearDepthBuffer() +{ + HRESULT err; + + err = d3ddevice->Clear(0, + NULL, + D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, + 0, + 1.0f, + 0); + + if (FAILED(err)) { + static int report = 10; + if (report > 0) { + VideoDX9Error("Failed to clear depth buffer", err); + report--; + } + } + + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::Present() +{ + // Show the frame on the primary surface. + HRESULT err = d3ddevice->Present( NULL, NULL, NULL, NULL ); + + if (FAILED(err)) { + if (err == D3DERR_DEVICELOST) { + device_lost = true; + } + + else { + static int report = 10; + if (report > 0) { + VideoDX9Error("Could not present frame", err); + report--; + } + } + } + + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::Pause() +{ + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::Resume() +{ + return true; +} + +// +--------------------------------------------------------------------+ + +void +VideoDX9::PreloadSurface(Surface* s) +{ + if (s) + PrepareSurface(s); +} + +void +VideoDX9::PreloadTexture(Bitmap* tex) +{ + if (texcache && tex) + texcache->FindTexture(tex); +} + +void +VideoDX9::InvalidateCache() +{ + ListIter iter = model_clients; + while (++iter) { + // remove each model from the list... + Model* model = iter.removeItem(); + + // ...so that the buffer destructor doesn't + // do it and mess up the iterator. + model->DeletePrivateData(); + } + + if (texcache) + texcache->InvalidateCache(); +} + +// +--------------------------------------------------------------------+ + +void +VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p) +{ + result._11 = (float) m.elem[0][0]; + result._12 = (float) m.elem[1][0]; + result._13 = (float) m.elem[2][0]; + result._14 = 0.0f; + + result._21 = (float) m.elem[0][1]; + result._22 = (float) m.elem[1][1]; + result._23 = (float) m.elem[2][1]; + result._24 = 0.0f; + + result._31 = (float) m.elem[0][2]; + result._32 = (float) m.elem[1][2]; + result._33 = (float) m.elem[2][2]; + result._34 = 0.0f; + + result._41 = (float) p.x; + result._42 = (float) p.y; + result._43 = (float) p.z; + result._44 = 1.0f; +} + +void +VideoDX9::CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v) +{ + result._11 = (float) m.elem[0][0]; + result._12 = (float) m.elem[1][0]; + result._13 = (float) m.elem[2][0]; + result._14 = 0.0f; + + result._21 = (float) m.elem[0][1]; + result._22 = (float) m.elem[1][1]; + result._23 = (float) m.elem[2][1]; + result._24 = 0.0f; + + result._31 = (float) m.elem[0][2]; + result._32 = (float) m.elem[1][2]; + result._33 = (float) m.elem[2][2]; + result._34 = 0.0f; + + result._41 = v.x; + result._42 = v.y; + result._43 = v.z; + result._44 = 1.0f; +} + +void +VideoDX9::CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl) +{ + CopyMemory(&result.Diffuse, &mtl.Kd, sizeof(D3DCOLORVALUE)); + CopyMemory(&result.Ambient, &mtl.Ka, sizeof(D3DCOLORVALUE)); + CopyMemory(&result.Specular, &mtl.Ks, sizeof(D3DCOLORVALUE)); + CopyMemory(&result.Emissive, &mtl.Ke, sizeof(D3DCOLORVALUE)); + + result.Power = mtl.power; +} + + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::Capture(Bitmap& bmp) +{ + if (d3ddevice) { + HRESULT hr = E_FAIL; + LPDIRECT3DSURFACE9 pSurf=NULL, pTempSurf=NULL; + D3DSURFACE_DESC desc; + D3DDISPLAYMODE dm; + + // get display dimensions + // this will be the dimensions of the front buffer + hr = d3ddevice->GetDisplayMode(0, &dm); + + if (FAILED(hr)) + VideoDX9Error("VideoDX9::Capture - Can't get display mode!", hr); + + desc.Width = dm.Width; + desc.Height = dm.Height; + desc.Format = D3DFMT_A8R8G8B8; + + hr = d3ddevice->CreateOffscreenPlainSurface( + desc.Width, + desc.Height, + desc.Format, + D3DPOOL_SYSTEMMEM, + &pTempSurf, + NULL); + + if (FAILED(hr)) { + VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 1", hr); + return false; + } + + hr = d3ddevice->GetFrontBufferData(0, pTempSurf); + + if (FAILED(hr)) { + RELEASE(pTempSurf); + VideoDX9Error("VideoDX9::Capture - Can't get front buffer", hr); + return false; + } + + + if (video_settings.IsWindowed()) { + POINT pt={0, 0}; + RECT srcRect; + + // capture only the client area of the screen: + ::GetClientRect(hwnd, &srcRect); + ::ClientToScreen(hwnd, (LPPOINT) &srcRect); + srcRect.right += srcRect.left; + srcRect.bottom += srcRect.top; + + desc.Width = srcRect.right - srcRect.left; + desc.Height = srcRect.bottom - srcRect.top; + desc.Format = D3DFMT_A8R8G8B8; // this is what we get from the screen, so stick with it + + // NB we can't lock the back buffer direct because it's no created that way + // and to do so hits performance, so copy to another surface + // Must be the same format as the source surface + hr = d3ddevice->CreateOffscreenPlainSurface( + desc.Width, + desc.Height, + desc.Format, + D3DPOOL_DEFAULT, + &pSurf, + NULL); + + if (FAILED(hr)) { + RELEASE(pSurf); + VideoDX9Error("VideoDX9::Capture - Cannot create offscreen buffer 2", hr); + return false; + } + + // Copy + hr = d3ddevice->UpdateSurface(pTempSurf, &srcRect, pSurf, &pt); + + if (FAILED(hr)) { + RELEASE(pTempSurf); + RELEASE(pSurf); + VideoDX9Error("VideoDX9::Capture - Cannot update surface", hr); + return false; + } + + RELEASE(pTempSurf); + pTempSurf = pSurf; + pSurf = NULL; + } + + D3DLOCKED_RECT lockedRect; + hr = pTempSurf->LockRect(&lockedRect, NULL, + D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK); + + if (FAILED(hr)) { + VideoDX9Error("VideoDX9::Capture - can't lock rect", hr); + RELEASE(pTempSurf); + return false; + } + + // Allocate color buffer + DWORD* buffer = new DWORD[desc.Width * desc.Height]; + BYTE* src = (BYTE*) lockedRect.pBits; + BYTE* dst = (BYTE*) buffer; + Color clr; + + for (DWORD y = 0; y < desc.Height; y++) { + BYTE *pRow = src; + + for (DWORD x = 0; x < desc.Width; x++) { + switch(desc.Format) { + case D3DFMT_R5G6B5: + clr = Color::Unformat(*((WORD*) (pRow))); + + *dst++ = (BYTE) clr.Red(); + *dst++ = (BYTE) clr.Green(); + *dst++ = (BYTE) clr.Blue(); + *dst++ = 255; + break; + + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + *dst++ = pRow[0]; // R + *dst++ = pRow[1]; // G + *dst++ = pRow[2]; // B + *dst++ = 255; + + pRow += 4; + break; + + case D3DFMT_R8G8B8: + *dst++ = pRow[0]; // R + *dst++ = pRow[1]; // G + *dst++ = pRow[2]; // B + *dst++ = 255; + + pRow += 3; + break; + } + + } + + src += lockedRect.Pitch; + } + + bmp.CopyHighColorImage(desc.Width, desc.Height, buffer); + + delete [] buffer; + + RELEASE(pTempSurf); + RELEASE(pSurf); + + return SUCCEEDED(hr); + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::GetWindowRect(Rect& r) +{ + if (d3ddevice && (rect.w < 1 || rect.h < 1)) { + D3DVIEWPORT9 view; + HRESULT hr = d3ddevice->GetViewport(&view); + if (SUCCEEDED(hr)) { + rect.x = view.X; + rect.y = view.Y; + rect.w = view.Width; + rect.h = view.Height; + } + } + + r = rect; + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetWindowRect(const Rect& r) +{ + return SetViewport(r.x, r.y, r.w, r.h); +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetViewport(int x, int y, int w, int h) +{ + if (!d3d || !d3ddevice) + return false; + + HRESULT hr; + + // set up the viewport according to args: + D3DVIEWPORT9 view; + + view.X = x; + view.Y = y; + view.Width = w; + view.Height = h; + view.MinZ = 0.0f; + view.MaxZ = 1.0f; + + hr = d3ddevice->SetViewport(&view); + if (FAILED(hr)) { + VideoDX9Error("could not initialize viewport", hr); + return false; + } + + // set up the render state: + for (int i = FILL_MODE; i < TEXTURE_WRAP; i++) { + if (d3dstate_table[i]) { + d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[i], render_state[i]); + } + } + + d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetAmbient(Color c) +{ + ambient = c; + return true; +} + +bool +VideoDX9::SetLights(const List& lights) +{ + if (d3ddevice) { + main_light = 0; + back_light = 0; + + ListIter iter = (List&) lights; + int index = -1; + + while (++iter) { + Light* light = iter.value(); + + if (light->IsActive()) { + D3DLIGHT9 d3d_light; + ZeroMemory(&d3d_light, sizeof(d3d_light)); + d3d_light.Type = (D3DLIGHTTYPE) light->Type(); + + if (light->Type() == Light::LIGHT_DIRECTIONAL) { + d3d_light.Direction.x = (float) (-light->Location().x); + d3d_light.Direction.y = (float) (-light->Location().y); + d3d_light.Direction.z = (float) (-light->Location().z); + + if (d3d_light.Direction.x == 0 && + d3d_light.Direction.y == 0 && + d3d_light.Direction.z == 0) { + + d3d_light.Direction.y = -1; + } + + if (light->CastsShadow()) { + if (!main_light || light->Intensity() > main_light->Intensity()) + main_light = light; + } + else if (!back_light) { + back_light = light; + } + } + else { + d3d_light.Position.x = (float) ( light->Location().x); + d3d_light.Position.y = (float) ( light->Location().y); + d3d_light.Position.z = (float) ( light->Location().z); + } + + float r = (light->GetColor().Red() / 255.0f) * light->Intensity(); + float g = (light->GetColor().Green() / 255.0f) * light->Intensity(); + float b = (light->GetColor().Blue() / 255.0f) * light->Intensity(); + + d3d_light.Diffuse.r = r; + d3d_light.Diffuse.g = g; + d3d_light.Diffuse.b = b; + + d3d_light.Specular.r = r; + d3d_light.Specular.g = g; + d3d_light.Specular.b = b; + + d3d_light.Range = light->Intensity() * 10.0f; + d3d_light.Attenuation0 = 0.1f; + d3d_light.Attenuation1 = 0.7f; + d3d_light.Attenuation2 = 0.0f; + + index++; + d3ddevice->SetLight(index, &d3d_light); + d3ddevice->LightEnable(index, TRUE); + } + } + + // turn off any unused lights from before: + while (nlights > index+1) { + d3ddevice->LightEnable(--nlights, FALSE); + } + + nlights = index + 1; + + return true; + } + + return false; +} + +bool +VideoDX9::SetCamera(const Camera* cam) +{ + if (d3ddevice) { + camera = cam; + + D3DMATRIX m; + CreateD3DMatrix(m, cam->Orientation(), cam->Pos()); + d3ddevice->SetTransform(D3DTS_VIEW, &m); + matrixView = m; + + return true; + } + + return false; +} + +bool +VideoDX9::SetProjection(float fov, float znear, float zfar, DWORD type) +{ + if (d3ddevice && zfar > znear) { + D3DMATRIX m; + float h, w, Q; + + double width = (float) (rect.w); + double height = (float) (rect.h); + ZeroMemory(&m, sizeof(m)); + + /*** + *** PERSPECTIVE PROJECTION: + ***/ + + if (type == PROJECTION_PERSPECTIVE) { + double xscale = width / fov; + double yscale = height / fov; + + double maxscale = xscale; + if (yscale > xscale) maxscale = yscale; + + double xangle = atan(fov/2 * maxscale/xscale); + + w = (float) (2/tan(xangle)); // 1/tan(x) == cot(x) + h = (float) (w * width/height); + Q = zfar/(zfar - znear); + + m._11 = w; + m._22 = h; + m._33 = Q; + m._43 = -Q*znear; + m._34 = 1; + } + + /*** + *** ORTHOGONAL PROJECTION: + ***/ + + else if (type == PROJECTION_ORTHOGONAL) { + m._11 = (float) (fov/width); + m._22 = (float) (fov/height); + m._33 = (float) (1/(zfar-znear)); + m._43 = (float) (znear/(znear-zfar)); + m._44 = (float) (1); + } + + else { + return false; + } + + d3ddevice->SetTransform(D3DTS_PROJECTION, &m); + matrixProj = m; + + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetEnvironment(Bitmap** faces) +{ + if (environment_cube && !faces) { + delete environment_cube; + environment_cube = 0; + return true; + } + + if (!environment_cube) { + environment_cube = new(__FILE__,__LINE__) TexCubeDX9(this); + } + + if (environment_cube) { + bool ok = true; + for (int i = 0; i < 6; i++) + ok = ok && environment_cube->LoadTexture(faces[i], i); + return ok; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::SetRenderState(RENDER_STATE state, DWORD value) +{ + if (!d3ddevice) + return false; + + if (render_state[state] == value || d3dstate_table[state] == 0) { + render_state[state] = value; + return true; + } + + HRESULT hr = E_FAIL; + + // special case for texture wrapping: + if (state == TEXTURE_WRAP) { + DWORD wrap = D3DTADDRESS_CLAMP; + + if (value) + wrap = D3DTADDRESS_WRAP; + + hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap); + hr = d3ddevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap); + } + + // special case for fog enable: + else if (state == FOG_ENABLE) { + if (value) { + hr = d3ddevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); + hr = d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); + } + + hr = d3ddevice->SetRenderState(D3DRS_FOGENABLE, value); + } + + // special case for z bias + else if (state == Z_BIAS) { + if (value) { + FLOAT bias_scale = 1.0f; + FLOAT depth_bias = (FLOAT) (DW2I(value) / -10000.0); + + hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(bias_scale)); + hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(depth_bias)); + } + else { + hr = d3ddevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + hr = d3ddevice->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + } + + // set default z func along with z enable + else if (state == Z_ENABLE) { + hr = d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + hr = d3ddevice->SetRenderState(D3DRS_ZENABLE, value); + } + + // all other render states: + else { + hr = d3ddevice->SetRenderState((D3DRENDERSTATETYPE) d3dstate_table[state], value); + } + + if (FAILED(hr)) { + VideoDX9Error("could not SetRenderState", hr); + return false; + } + else { + render_state[state] = value; + } + + return true; +} + +bool +VideoDX9::SetBlendType(int blend_type) +{ + if (blend_type == current_blend_state) + return true; + + switch (blend_type) { + default: + // map misc blend types to SOLID + // and fall through to that case + + blend_type = BLEND_SOLID; + + case BLEND_SOLID: + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); + break; + + case BLEND_ALPHA: + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + break; + + case BLEND_ADDITIVE: + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + break; + } + + current_blend_state = blend_type; + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::StartFrame() +{ + if (device_lost) { + RecoverSurfaces(); + + if (status != VIDEO_OK) + return false; + } + + stats.Clear(); + + HRESULT err = 0; + static int frame_number = 1; + static int report_errs = 100; + + stats.nframe = frame_number; + texcache->FrameNumber(frame_number++); + + // update gamma ramp for global fade value: + SetGammaLevel(gamma); + + ClearAll(); + + err = d3ddevice->BeginScene(); + + if (FAILED(err)) { + if (report_errs > 0) { + report_errs--; + VideoDX9Error("could not begin scene", err); + } + + return false; + } + + scene_active = 1; + current_blend_state = -1; + + SetRenderState(LIGHTING_PASS, 0); + SetRenderState(STENCIL_ENABLE, false); + + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::EndFrame() +{ + HRESULT err = 0; + + if (scene_active) { + err = d3ddevice->EndScene(); + + if (FAILED(err)) { + VideoDX9Error("could not end scene", err); + return false; + } + } + + scene_active = 0; + return true; +} + +// +--------------------------------------------------------------------+ + +static DWORD ColorModulate(DWORD a, DWORD b) +{ + float a0 = (float) ((a ) & 0xff)/255.0f; + float a1 = (float) ((a>> 8) & 0xff)/255.0f; + float a2 = (float) ((a>>16) & 0xff)/255.0f; + float a3 = (float) ((a>>24) & 0xff)/255.0f; + + float b0 = (float) ((b ) & 0xff)/255.0f; + float b1 = (float) ((b>> 8) & 0xff)/255.0f; + float b2 = (float) ((b>>16) & 0xff)/255.0f; + float b3 = (float) ((b>>24) & 0xff)/255.0f; + + return (DWORD) ((BYTE)(a3*b3*255.0f) << 24) | + ((BYTE)(a2*b2*255.0f) << 16) | + ((BYTE)(a1*b1*255.0f) << 8) | + ((BYTE)(a0*b0*255.0f)); +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::PopulateScreenVerts(VertexSet* vset) +{ + if (!vset || !screen_vbuf) + return false; + + num_verts = vset->nverts; + + VideoDX9ScreenVertex* v = (VideoDX9ScreenVertex*) screen_vbuf->Lock(num_verts); + + if (v) { + first_vert = screen_vbuf->GetNextVert(); + + for (int i = 0; i < num_verts; i++) { + v->sx = vset->s_loc[i].x; + v->sy = vset->s_loc[i].y; + v->sz = vset->s_loc[i].z; + v->rhw = vset->rw[i]; + + v->diffuse = vset->diffuse[i]; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + + v++; + } + + screen_vbuf->Unlock(); + return true; + } + + Print(" VideoDX9: could not lock screen vbuf for %d verts.\n", num_verts); + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawPolys(int npolys, Poly* polys) +{ + bool result = false; + + if (d3ddevice && polys && npolys > 0) { + // screen space polys: + if (polys->vertex_set->space == VertexSet::SCREEN_SPACE) + return DrawScreenPolys(npolys, polys); + + // world space polys: + stats.ncalls++; + + VertexSet* vset = polys->vertex_set; + int nverts = vset->nverts; + bool luminous = false; + bool detail = false; + DWORD fvf = 0; + void* verts = 0; + int vsize = 0; + WORD* indices = new(__FILE__,__LINE__) WORD[npolys*6]; + + if (polys->material) { + luminous = polys->material->luminous; + } + + if (vset->tu1 != 0) { + VideoDX9DetailVertex* v = new(__FILE__,__LINE__) VideoDX9DetailVertex[nverts]; + verts = v; + vsize = sizeof(VideoDX9DetailVertex); + fvf = VideoDX9DetailVertex::FVF; + + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->diffuse = vset->diffuse[i]; + v->specular = vset->specular[i]; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + v->tu1 = vset->tu1[i]; + v->tv1 = vset->tv1[i]; + + v++; + } + } + + else if (luminous) { + VideoDX9LuminousVertex* v = new(__FILE__,__LINE__) VideoDX9LuminousVertex[nverts]; + verts = v; + vsize = sizeof(VideoDX9LuminousVertex); + fvf = VideoDX9LuminousVertex::FVF; + + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->diffuse = vset->diffuse[i]; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + + v++; + } + } + + else { + VideoDX9SolidVertex* v = new(__FILE__,__LINE__) VideoDX9SolidVertex[nverts]; + verts = v; + vsize = sizeof(VideoDX9SolidVertex); + fvf = VideoDX9SolidVertex::FVF; + + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->nx = vset->nrm[i].x; + v->ny = vset->nrm[i].y; + v->nz = vset->nrm[i].z; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + + v++; + } + } + + if (verts && indices) { + HRESULT hr = E_FAIL; + + // fill index array + int num_indices = 0; + int num_tris = 0; + + WORD* s = indices; + Poly* p = polys; + + for (int i = 0; i < npolys; i++) { + if (p->nverts == 3) { + num_indices += 3; + num_tris += 1; + + *s++ = p->verts[0]; + *s++ = p->verts[1]; + *s++ = p->verts[2]; + } + + else if (p->nverts == 4) { + num_indices += 6; + num_tris += 2; + + *s++ = p->verts[0]; + *s++ = p->verts[1]; + *s++ = p->verts[2]; + + *s++ = p->verts[0]; + *s++ = p->verts[2]; + *s++ = p->verts[3]; + } + + p++; + } + + hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(fvf); + + // send primitives to the device + Material* mtl = polys->material; + IDirect3DTexture9* texture = 0; + + if (mtl && texcache && mtl->tex_diffuse) { + texture = texcache->FindTexture(mtl->tex_diffuse); + } + + if (current_texture != texture) { + hr = d3ddevice->SetTexture(0, texture); + current_texture = texture; + } + + if (mtl && texcache && mtl->tex_detail) { + texture = texcache->FindTexture(mtl->tex_detail); + hr = d3ddevice->SetTexture(1, texture); + } + + if (mtl && !luminous) { + D3DMATERIAL9 d3dmtl; + CreateD3DMaterial(d3dmtl, *mtl); + + hr = d3ddevice->SetMaterial(&d3dmtl); + hr = d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); + } + + // set render states and select buffers + SetRenderState(FILL_MODE, D3DFILL_SOLID); + SetRenderState(LIGHTING_ENABLE, luminous ? FALSE : TRUE); + SetBlendType(mtl->blend); + + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + + + hr = d3ddevice->DrawIndexedPrimitiveUP( + D3DPT_TRIANGLELIST, + 0, + nverts, + num_tris, + indices, + D3DFMT_INDEX16, + verts, + vsize); + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not draw 3D polys.", hr); + } + + delete [] verts; + delete [] indices; + + if (SUCCEEDED(hr)) { + stats.nverts += nverts; + stats.npolys += num_tris; + result = true; + } + } + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawScreenPolys(int npolys, Poly* polys, int blend) +{ + bool result = false; + HRESULT hr = E_FAIL; + + if (d3ddevice && polys && npolys > 0 && screen_vbuf && screen_ibuf) { + stats.ncalls++; + + // fill screen vertex buffer + if (!PopulateScreenVerts(polys->vertex_set)) + return false; + + // fill screen index buffer + int num_indices = 0; + int num_tris = 0; + + // count the number of indices needed for these polys + for (int i = 0; i < npolys; i++) { + Poly* p = polys + i; + + if (p->nverts == 3) { + num_indices += 3; + num_tris += 1; + } + + else if (p->nverts == 4) { + num_indices += 6; + num_tris += 2; + } + } + + WORD* screen_indices = screen_ibuf->Lock(num_indices); + int first_index = screen_ibuf->GetNextIndex(); + + if (!screen_indices) { + Print(" VideoDX9: could not lock screen ibuf for %d indices.\n", num_indices); + return false; + } + + // copy the indices into the locked index buffer + WORD* s = screen_indices; + Poly* p = polys; + + for (int i = 0; i < npolys; i++) { + if (p->nverts == 3) { + *s++ = p->verts[0] + first_vert; + *s++ = p->verts[1] + first_vert; + *s++ = p->verts[2] + first_vert; + } + else if (p->nverts == 4) { + *s++ = p->verts[0] + first_vert; + *s++ = p->verts[1] + first_vert; + *s++ = p->verts[2] + first_vert; + + *s++ = p->verts[0] + first_vert; + *s++ = p->verts[2] + first_vert; + *s++ = p->verts[3] + first_vert; + } + + p++; + } + + screen_ibuf->Unlock(); + + // set render states and select buffers + SetRenderState(FILL_MODE, D3DFILL_SOLID); + SetRenderState(Z_ENABLE, D3DZB_FALSE); + SetRenderState(Z_WRITE_ENABLE, D3DZB_FALSE); + SetRenderState(LIGHTING_ENABLE, FALSE); + SetBlendType(blend); + + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + + // send primitives to the device + Material* mtl = polys->material; + IDirect3DTexture9* texture = 0; + + if (mtl && texcache && mtl->tex_diffuse) { + texture = texcache->FindTexture(mtl->tex_diffuse); + } + + if (current_texture != texture) { + hr = d3ddevice->SetTexture(0, texture); + current_texture = texture; + } + + screen_vbuf->Select(0); + screen_ibuf->Select(); + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); + + hr = d3ddevice->DrawIndexedPrimitive( + D3DPT_TRIANGLELIST, + 0, + first_vert, + num_verts, + first_index, + num_tris); + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not draw screen polys.", hr); + } + else { + stats.nverts += num_verts; + stats.npolys += num_tris; + result = true; + } + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawSolid(Solid* s, DWORD blend_modes) +{ + bool result = false; + HRESULT hr = E_FAIL; + + if (d3ddevice && s && s->GetModel()) { + Model* model = s->GetModel(); + Matrix orient = s->Orientation(); + orient.Transpose(); + + D3DMATRIX world_matrix; + CreateD3DMatrix(world_matrix, orient, s->Location()); + d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); + matrixWorld = world_matrix; + D3DXMatrixInverse(&matrixWorldInverse, 0, &matrixWorld); + + ListIter surf_iter = model->GetSurfaces(); + while (++surf_iter) { + Surface* surf = surf_iter.value(); + + if (surf->IsHidden() || surf->IsSimplified()) + continue; + + if (PrepareSurface(surf)) { + result = true; + + VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); + surf_data->vertex_buffer->Select(0); + surf_data->index_buffer->Select(); + + ListIter seg_iter = surf->GetSegments(); + while (++seg_iter) { + Segment* segment = seg_iter.value(); + Material* mtl = segment->material; + + if (mtl && (blend_modes & mtl->blend)) { + result = result && DrawSegment(segment); + } + } + } + } + } + + surface_has_tangent_data = false; + + return result; +} + +bool +VideoDX9::DrawSegment(Segment* segment) +{ + bool result = false; + bool detail = false; + bool luminous = false; + HRESULT hr = E_FAIL; + + if (segment && segment->video_data) { + stats.ncalls++; + + VideoDX9SegmentData* seg_data = (VideoDX9SegmentData*) segment->video_data; + int first_vert = seg_data->first_vert; + int num_verts = seg_data->num_verts; + int first_index = seg_data->first_index; + int num_tris = seg_data->num_tris; + + if (segment->model) + luminous = segment->model->IsLuminous(); + + // set render states and select buffers + d3ddevice->SetRenderState(D3DRS_AMBIENT, ambient.Value()); + + Material* mtl = segment->material; + + if (use_material) + mtl = use_material; + + if (segment->polys && segment->polys->vertex_set && segment->polys->vertex_set->tu1) + detail = true; + + // send primitives to the device + if (detail) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); + } + + else if (luminous) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); + } + + else if (surface_has_tangent_data && vertex_declaration) { + hr = d3ddevice->SetVertexDeclaration(vertex_declaration); + hr = d3ddevice->SetVertexShader(NULL); + } + + else { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); + } + + if (render_state[FILL_MODE] == FILL_WIREFRAME) { + PrepareMaterial(mtl); + SetupPass(0); + + for (int i = 0; i < segment->npolys; i++) { + DrawPolyOutline(segment->polys + i); + } + } + + else if (luminous) { + PrepareMaterial(mtl); + + SetRenderState(FILL_MODE, D3DFILL_SOLID); + SetRenderState(LIGHTING_ENABLE, FALSE); + SetBlendType(mtl->blend); + + for (int pass = 0; pass < passes; pass++) { + SetupPass(pass); + + hr = d3ddevice->DrawIndexedPrimitive( + D3DPT_TRIANGLELIST, + 0, + first_vert, + num_verts, + first_index, + num_tris); + } + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + } + + else { + PrepareMaterial(mtl); + + if (strategy == DX9_STRATEGY_GLOW && render_state[LIGHTING_PASS] > 0) { + hr = 0; + } + + else if (magic_fx && strategy < DX9_STRATEGY_BLEND && !detail) { + DWORD vs_version = 0; + DWORD ps_version = 0; + bool shaders_ok = false; + + VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); + + if (dev_info) { + vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; + ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; + + if (vs_version >= D3DVS_VERSION(1,1)) + shaders_ok = true; + } + + if (surface_has_tangent_data && vertex_declaration) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetVertexDeclaration(vertex_declaration); + } + + else { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); + } + + bool would_bump = !IsBumpMapEnabled() && mtl->bump > 0.5; + + bool will_bump = IsBumpMapEnabled() && surface_has_tangent_data && shaders_ok && camera; + + bool do_pix = will_bump && render_state[LIGHTING_PASS] == 0; + bool do_bump = will_bump && render_state[LIGHTING_PASS] > 0; + + D3DXMATRIX matrixWVP = matrixWorld * matrixView * matrixProj; + + D3DXVECTOR4 eyePos( (float) camera->Pos().x, (float) camera->Pos().y, (float) camera->Pos().z, 1.0f); + + D3DXVECTOR4 eyeObj; + D3DXVec4Transform(&eyeObj, &eyePos, &matrixWorldInverse); + + D3DXVECTOR4 lightPos(100.0f, 100.0f, 100.0f, 1.0f); + D3DXVECTOR4 lightColor(1,1,1,1); + D3DXVECTOR4 ambientColor(0,0,0,1); + + ambientColor.x = ambient.fRed(); + ambientColor.y = ambient.fGreen(); + ambientColor.z = ambient.fBlue(); + + if (main_light && (render_state[LIGHTING_PASS] > 0 || mtl->blend > Material::MTL_SOLID)) { + lightPos.x = (float) main_light->Location().x; + lightPos.y = (float) main_light->Location().y; + lightPos.z = (float) main_light->Location().z; + + if (mtl->tex_bumpmap && do_bump) + D3DXVec4Transform(&lightPos, &lightPos, &matrixWorldInverse); + + lightColor.x = main_light->GetColor().fRed() * main_light->Intensity(); + lightColor.y = main_light->GetColor().fGreen() * main_light->Intensity(); + lightColor.z = main_light->GetColor().fBlue() * main_light->Intensity(); + lightColor.w = 1.0f; + } + + else if (back_light && render_state[LIGHTING_PASS] == 0) { + lightPos.x = (float) back_light->Location().x; + lightPos.y = (float) back_light->Location().y; + lightPos.z = (float) back_light->Location().z; + + lightColor.x = back_light->GetColor().fRed() * back_light->Intensity(); + lightColor.y = back_light->GetColor().fGreen() * back_light->Intensity(); + lightColor.z = back_light->GetColor().fBlue() * back_light->Intensity(); + lightColor.w = 1.0f; + } + + D3DXVECTOR4 lightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - lightPos; + D3DXVec4Normalize(&lightDir, &lightDir); + + magic_fx->SetMatrix("wvp", &matrixWVP); + magic_fx->SetMatrix("world", &matrixWorld); + magic_fx->SetMatrix("view", &matrixView); + magic_fx->SetMatrix("proj", &matrixProj); + magic_fx->SetMatrix("worldInv", &matrixWorldInverse); + + magic_fx->SetVector("light1Pos", &lightPos); + magic_fx->SetVector("light1Dir", &lightDir); + magic_fx->SetVector("light1Color", &lightColor); + magic_fx->SetVector("ambientColor", &ambientColor); + magic_fx->SetVector("eyeObj", &eyeObj); + + FLOAT base_bias = (FLOAT) (DW2I(render_state[Z_BIAS]) / -10000.0); + magic_fx->SetFloat("bias", base_bias + video_settings.depth_bias); + + ColorValue orig_ks = mtl->Ks; + + if (would_bump && mtl->specular_value >= 0.5) + mtl->Ks = mtl->Ks * 0.3; + + magic_fx->SetValue("Ka", &mtl->Ka, sizeof(ColorValue)); + magic_fx->SetValue("Kd", &mtl->Kd, sizeof(ColorValue)); + magic_fx->SetValue("Ke", &mtl->Ke, sizeof(ColorValue)); + magic_fx->SetValue("Ks", &mtl->Ks, sizeof(ColorValue)); + magic_fx->SetFloat("Ns", mtl->power); + + if (would_bump && mtl->specular_value >= 0.5) + mtl->Ks = orig_ks; + + if (mtl->tex_diffuse) { + IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_diffuse); + magic_fx->SetTexture("tex_d", texture); + } else { + magic_fx->SetTexture("tex_d", 0); + } + + if (mtl->tex_emissive) { + IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_emissive); + magic_fx->SetTexture("tex_e", texture); + } else { + magic_fx->SetTexture("tex_e", 0); + } + + if (mtl->tex_specular && IsSpecMapEnabled()) { + IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_specular); + magic_fx->SetTexture("tex_s", texture); + } else { + magic_fx->SetTexture("tex_s", 0); + } + + if (mtl->tex_bumpmap && do_bump) { + IDirect3DTexture9* texture = texcache->FindNormalMap(mtl->tex_bumpmap, mtl->bump); + magic_fx->SetTexture("tex_n", texture); + magic_fx->SetFloat("offsetAmp", mtl->bump / mtl->tex_bumpmap->Height()); + } else if (mtl->tex_bumpmap && !do_bump) { + IDirect3DTexture9* texture = texcache->FindTexture(mtl->tex_bumpmap); + magic_fx->SetTexture("tex_x", texture); + } else { + magic_fx->SetTexture("tex_x", 0); + } + + const char* mtl_shader = mtl->GetShader(render_state[LIGHTING_PASS]); + D3DXHANDLE hnd_shader = 0; + + if (mtl_shader) { + if (!strcmp(mtl_shader, "null")) + return true; + + hnd_shader = magic_fx->GetTechniqueByName(mtl_shader); + } + + if (hnd_shader) { + hr = magic_fx->SetTechnique(hnd_shader); + } else { + if (will_bump) { + if (mtl->tex_specular && IsSpecMapEnabled()) { + if (mtl->tex_bumpmap && do_bump) { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("BumpSpecMapPix"); + else + hr = magic_fx->SetTechnique("BumpSpecMap"); + } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("EmissiveSpecMapPix"); + else + hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); + } else { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("SpecMapPix"); + else + hr = magic_fx->SetTechnique("SpecularTexture"); + } + } else { + if (mtl->tex_bumpmap && do_bump) { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("BumpMapPix"); + else + hr = magic_fx->SetTechnique("BumpMap"); + } else if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("EmissivePix"); + else + hr = magic_fx->SetTechnique("EmissiveTexture"); + } else { + if (ps_version >= D3DPS_VERSION(2,0)) + hr = magic_fx->SetTechnique("SimplePix"); + else + hr = magic_fx->SetTechnique("SimpleTexture"); + } + } + } + + else if (texcache && mtl->tex_diffuse) { + if (mtl->tex_specular && IsSpecMapEnabled()) { + if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { + hr = magic_fx->SetTechnique("EmissiveSpecularTexture"); + } else { + hr = magic_fx->SetTechnique("SpecularTexture"); + } + } + + else { + if (mtl->tex_emissive && render_state[LIGHTING_PASS] == 0) { + hr = magic_fx->SetTechnique("EmissiveTexture"); + } else { + hr = magic_fx->SetTechnique("SimpleTexture"); + } + } + } else { + hr = magic_fx->SetTechnique("SimpleMaterial"); + } + } + + if (environment_cube != 0 && magic_fx->IsParameterUsed("env_cube", hnd_shader)) { + D3DXMATRIX env_matrix; + D3DXMatrixIdentity(&env_matrix); + + magic_fx->SetMatrix("env_matrix", &env_matrix); + magic_fx->SetTexture("env_cube", environment_cube->GetTexture()); + } + + if (render_state[STENCIL_ENABLE]) { + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); + d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); + } else { + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + if (render_state[LIGHTING_PASS] > 0) { + current_blend_state = 100; + SetBlendType(BLEND_ADDITIVE); + SetRenderState(Z_WRITE_ENABLE, FALSE); + } else { + current_blend_state = 100; + SetBlendType(mtl->blend); + } + + UINT nPasses = 0; + + hr = magic_fx->Begin(&nPasses, 0); + + for (UINT i = 0; i < nPasses; i++) { + hr = magic_fx->BeginPass(i); + + hr = d3ddevice->DrawIndexedPrimitive( + D3DPT_TRIANGLELIST, + 0, + first_vert, + num_verts, + first_index, + num_tris); + + hr = magic_fx->EndPass(); + } + + hr = magic_fx->End(); + } else { + for (int pass = 0; pass < passes; pass++) { + SetupPass(pass); + + hr = d3ddevice->DrawIndexedPrimitive( + D3DPT_TRIANGLELIST, + 0, + first_vert, + num_verts, + first_index, + num_tris); + + if (detail) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9DetailVertex::FVF); + } else if (luminous) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9LuminousVertex::FVF); + } else if (surface_has_tangent_data && vertex_declaration) { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetVertexDeclaration(vertex_declaration); + } else { + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9SolidVertex::FVF); + } + } + } + } + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not draw solid polys.", hr); + } else { + stats.nverts += num_verts; + stats.npolys += num_tris; + result = true; + } + } + + return result; +} + +bool +VideoDX9::DrawPolyOutline(Poly* p) +{ + if (d3ddevice && p && p->nverts >= 3) { + static VideoDX9LineVertex verts[8]; + + int nlines = p->nverts; + VertexSet* vset = p->vertex_set; + WORD index = 0; + Color color = Color::Black; + HRESULT hr = E_FAIL; + + ZeroMemory(verts, sizeof(verts)); + + if (p->material) + color = p->material->Kd.ToColor(); + + for (int i = 0; i < p->nverts; i++) { + index = p->verts[i]; + + verts[i].x = vset->loc[index].x; + verts[i].y = vset->loc[index].y; + verts[i].z = vset->loc[index].z; + verts[i].diffuse = color.Value(); + } + + // last vertex, to close the loop + index = p->verts[0]; + int i = p->nverts; + + verts[i].x = vset->loc[index].x; + verts[i].y = vset->loc[index].y; + verts[i].z = vset->loc[index].z; + verts[i].diffuse = color.Value(); + + current_texture = 0; + + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); + hr = d3ddevice->SetTexture(0, 0); + hr = d3ddevice->DrawPrimitiveUP( + D3DPT_LINESTRIP, + nlines, + verts, + sizeof(VideoDX9LineVertex)); + return true; + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawShadow(Solid* s, int nverts, Vec3* shadow_verts, bool visible) +{ + bool result = false; + HRESULT hr = E_FAIL; + + if (d3ddevice && s && nverts && shadow_verts && IsShadowEnabled()) { + Matrix orient = s->Orientation(); + orient.Transpose(); + + D3DMATRIX world_matrix; + CreateD3DMatrix(world_matrix, orient, s->Location()); + d3ddevice->SetTransform(D3DTS_WORLD, &world_matrix); + matrixWorld = world_matrix; + + // show shadow outlines: + if (visible) { + static VideoDX9LineVertex verts[4]; + + d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); + d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + d3ddevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); + d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE); + d3ddevice->SetVertexShader(NULL); + d3ddevice->SetFVF(VideoDX9LineVertex::FVF); + d3ddevice->SetTexture(0, 0); + + SetBlendType(BLEND_ALPHA); + + for (int i = 0; i < nverts; i+=3) { + DWORD c = 0xa0ffff80; + + verts[0].x = shadow_verts[i+0].x; + verts[0].y = shadow_verts[i+0].y; + verts[0].z = shadow_verts[i+0].z; + verts[0].diffuse = c; + + verts[1].x = shadow_verts[i+1].x; + verts[1].y = shadow_verts[i+1].y; + verts[1].z = shadow_verts[i+1].z; + verts[1].diffuse = c; + + verts[2].x = shadow_verts[i+2].x; + verts[2].y = shadow_verts[i+2].y; + verts[2].z = shadow_verts[i+2].z; + verts[2].diffuse = c; + + verts[3].x = shadow_verts[i+0].x; + verts[3].y = shadow_verts[i+0].y; + verts[3].z = shadow_verts[i+0].z; + verts[3].diffuse = c; + + hr = d3ddevice->DrawPrimitiveUP( + D3DPT_LINESTRIP, + 3, + verts, + sizeof(VideoDX9LineVertex)); + } + + // restore lighting state + d3ddevice->SetRenderState(D3DRS_LIGHTING, render_state[LIGHTING_ENABLE]); + } + + // render shadows into stencil buffer: + + // Disable z-buffer writes (note: z-testing still occurs), and enable the + // stencil-buffer + d3ddevice->SetRenderState(D3DRS_ZENABLE, TRUE); + d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + + // Dont bother with interpolating color + d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); + + // Set up stencil compare fuction, reference value, and masks. + // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true. + // Note: since we set up the stencil-test to always pass, the STENCILFAIL + // renderstate is really not needed. + d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); + d3ddevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ); + d3ddevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); + + // If z-test passes, inc/decrement stencil buffer value + d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x1 ); + d3ddevice->SetRenderState(D3DRS_STENCILMASK, 0xff ); + d3ddevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xff ); + d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_INCR ); + + // Make sure that no pixels get drawn to the frame buffer + d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE ); + d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO ); + d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE ); + + d3ddevice->SetVertexShader(NULL); + d3ddevice->SetFVF(D3DFVF_XYZ); + + // Draw front-side of shadow volume in stencil/z only + hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); + + // Now reverse cull order so back sides of shadow volume are written. + d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW ); + + // Decrement stencil buffer value + d3ddevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_DECR ); + + // Draw back-side of shadow volume in stencil/z only + hr = d3ddevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, nverts/3, shadow_verts, sizeof(Vec3)); + + // restore render states + d3ddevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); + d3ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + + // force restore of current blend type + int type = current_blend_state; + current_blend_state = 100; + SetBlendType(type); + + result = SUCCEEDED(hr); + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawLines(int nlines, Vec3* points, Color c, int blend) +{ + bool result = false; + + if (d3ddevice && points && nlines > 0 && nlines <= 256) { + stats.ncalls++; + + VideoDX9LineVertex* verts = line_verts; + + if (verts) { + HRESULT hr = E_FAIL; + + for (int i = 0; i < 2*nlines; i++) { + VideoDX9LineVertex* v = verts + i; + Vec3* p = points + i; + + v->x = p->x; + v->y = p->y; + v->z = p->z; + v->diffuse = c.Value(); + } + + hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); + + DWORD old_lighting = render_state[LIGHTING_ENABLE]; + + // untextured lines: + if (current_texture) { + d3ddevice->SetTexture(0, 0); + current_texture = 0; + } + + SetRenderState(LIGHTING_ENABLE, FALSE); + SetBlendType(blend); + + hr = d3ddevice->DrawPrimitiveUP( + D3DPT_LINELIST, + nlines, + verts, + sizeof(VideoDX9LineVertex)); + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not draw 3D lines.", hr); + } + + SetRenderState(LIGHTING_ENABLE, old_lighting); + + if (SUCCEEDED(hr)) { + stats.nverts += 2*nlines; + stats.nlines += nlines; + result = true; + } + } + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawScreenLines(int nlines, float* points, Color c, int blend) +{ + bool result = false; + + if (d3ddevice && points && nlines > 0 && nlines <= 64) { + stats.ncalls++; + + VideoDX9ScreenVertex* verts = screen_line_verts; + + if (verts) { + HRESULT hr = E_FAIL; + + for (int i = 0; i < 2*nlines; i++) { + VideoDX9ScreenVertex* v = verts + i; + + v->sx = points[2*i + 0]; + v->sy = points[2*i + 1]; + v->sz = 0.0f; + v->rhw = 1.0f; + v->diffuse = c.Value(); + v->tu = 0.0f; + v->tv = 0.0f; + } + + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9ScreenVertex::FVF); + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not set FVF for screen lines.", hr); + } + + else { + if (current_texture != 0) { + hr = d3ddevice->SetTexture(0, 0); + current_texture = 0; + } + + SetRenderState(FILL_MODE, D3DFILL_SOLID); + SetRenderState(Z_ENABLE, D3DZB_FALSE); + SetRenderState(LIGHTING_ENABLE, FALSE); + SetBlendType(blend); + + hr = d3ddevice->DrawPrimitiveUP( + D3DPT_LINELIST, + nlines, + verts, + sizeof(VideoDX9ScreenVertex)); + + if (FAILED(hr)) { + static int report = 10; + if (report-- > 0) + VideoDX9Error("Could not draw screen lines.", hr); + } + } + + if (SUCCEEDED(hr)) { + stats.nverts += 2*nlines; + stats.nlines += nlines; + result = true; + } + } + } + + return result; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::DrawPoints(VertexSet* vset) +{ + if (vset && vset->nverts) { + HRESULT hr = E_FAIL; + + int nverts = vset->nverts; + VideoDX9LineVertex* verts = new(__FILE__,__LINE__) VideoDX9LineVertex[nverts]; + + if (verts) { + for (int i = 0; i < nverts; i++) { + VideoDX9LineVertex* v = verts + i; + Vec3* p = vset->loc + i; + + v->x = p->x; + v->y = p->y; + v->z = p->z; + v->diffuse = vset->diffuse[i]; + } + + SetRenderState(LIGHTING_ENABLE, FALSE); + + hr = d3ddevice->SetTransform(D3DTS_WORLD, &identity_matrix); + hr = d3ddevice->SetVertexShader(NULL); + hr = d3ddevice->SetFVF(VideoDX9LineVertex::FVF); + hr = d3ddevice->SetTexture(0, 0); + hr = d3ddevice->DrawPrimitiveUP( + D3DPT_POINTLIST, + nverts, + verts, + sizeof(VideoDX9LineVertex)); + + delete [] verts; + return true; + } + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::UseMaterial(Material* m) +{ + use_material = m; + return true; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::UseXFont(const char* name, int size, bool bold, bool ital) +{ + if (d3ddevice && name && *name && size > 4) { + RELEASE(d3dx_font); + + strcpy_s(font_name, name); + font_size = size; + font_bold = bold; + font_ital = ital; + + HRESULT hr = E_FAIL; + HDC hdc = GetDC(NULL); + int nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); + + ReleaseDC(NULL, hdc); + + int nHeight = -size * nLogPixelsY / 72; + + hr = D3DXCreateFont(d3ddevice, // D3D device + nHeight, // Height + 0, // Width + bold ? FW_BOLD : FW_NORMAL, // Weight + 1, // MipLevels, 0 = autogen mipmaps + ital, // Italic + DEFAULT_CHARSET, // CharSet + OUT_DEFAULT_PRECIS, // OutputPrecision + DEFAULT_QUALITY, // Quality + DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily + name, // pFaceName + &d3dx_font); // ppFont + + if (SUCCEEDED(hr)) { + return true; + } + } + + RELEASE(d3dx_font); + return false; +} + +bool +VideoDX9::DrawText(const char* text, int count, const Rect& rect, DWORD format, Color c) +{ + if (d3ddevice && text && *text && d3dx_font) { + RECT r; + r.left = rect.x; + r.top = rect.y; + r.right = rect.x + rect.w; + r.bottom = rect.y + rect.h; + + d3dx_font->DrawText(0, text, count, &r, format, c.Value()); + } + + return false; +} + +// +--------------------------------------------------------------------+ + +bool +VideoDX9::PrepareSurface(Surface* surf) +{ + if (surf) { + int nverts = surf->NumVerts(); + int nindices = surf->NumIndices(); + bool detail = surf->GetVertexSet()->tu1 != 0; + bool luminous = false; + DWORD dynamic = 0; + + if (surf->GetModel()) { + luminous = surf->GetModel()->IsLuminous(); + dynamic = surf->GetModel()->IsDynamic() ? D3DUSAGE_DYNAMIC : 0; + } + + surface_has_tangent_data = !luminous && (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal); + + VideoDX9SurfaceData* surf_data = (VideoDX9SurfaceData*) surf->GetVideoPrivateData(); + + if (!surf_data) { + surf_data = new(__FILE__,__LINE__) VideoDX9SurfaceData(surf->GetModel()); + + surface_has_tangent_data = false; + + if (surf->GetVertexSet()->tangent && surf->GetVertexSet()->binormal) { + surface_has_tangent_data = true; + surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( + this, + nverts, + sizeof(VideoDX9NormalVertex), + 0, // not an FVF vertex buffer + dynamic | D3DUSAGE_WRITEONLY); + } + + else if (detail) { + surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( + this, + nverts, + sizeof(VideoDX9DetailVertex), + VideoDX9DetailVertex::FVF, + dynamic | D3DUSAGE_WRITEONLY); + } + + else if (luminous) { + surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( + this, + nverts, + sizeof(VideoDX9LuminousVertex), + VideoDX9LuminousVertex::FVF, + dynamic | D3DUSAGE_WRITEONLY); + } + + else { + surf_data->vertex_buffer = new(__FILE__,__LINE__) VideoDX9VertexBuffer( + this, + nverts, + sizeof(VideoDX9SolidVertex), + VideoDX9SolidVertex::FVF, + dynamic | D3DUSAGE_WRITEONLY); + } + + surf_data->index_buffer = new(__FILE__,__LINE__) VideoDX9IndexBuffer( + this, + nindices, + dynamic | D3DUSAGE_WRITEONLY); + + if (!surf_data->vertex_buffer || !surf_data->index_buffer) { + Print("VideoDX9: Unable to prepare surface '%s'\n", surf->Name()); + delete surf_data; + return false; + } + + surf->SetVideoPrivateData(surf_data); + } + + if (surf_data && !surf_data->IsValid()) { + if (detail) { + VideoDX9DetailVertex* v = (VideoDX9DetailVertex*) surf_data->vertex_buffer->Lock(nverts); + + if (v) { + const VertexSet* vset = surf->GetVertexSet(); + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->diffuse = vset->diffuse[i]; + v->specular = vset->specular[i]; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + v->tu1 = vset->tu1[i]; + v->tv1 = vset->tv1[i]; + + v++; + } + + surf_data->vertex_buffer->Unlock(); + } + } + + else if (luminous) { + VideoDX9LuminousVertex* v = (VideoDX9LuminousVertex*) surf_data->vertex_buffer->Lock(nverts); + + if (v) { + const VertexSet* vset = surf->GetVertexSet(); + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->diffuse = vset->diffuse[i]; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + + v++; + } + + surf_data->vertex_buffer->Unlock(); + } + } + + else if (surface_has_tangent_data) { + VideoDX9NormalVertex* v = (VideoDX9NormalVertex*) surf_data->vertex_buffer->Lock(nverts); + + if (v) { + const VertexSet* vset = surf->GetVertexSet(); + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->nx = vset->nrm[i].x; + v->ny = vset->nrm[i].y; + v->nz = vset->nrm[i].z; + + v->t0u = vset->tu[i]; + v->t0v = vset->tv[i]; + v->t1u = vset->tu[i]; + v->t1v = vset->tv[i]; + + v->tx = vset->tangent[i].x; + v->ty = vset->tangent[i].y; + v->tz = vset->tangent[i].z; + + v->bx = vset->binormal[i].x; + v->by = vset->binormal[i].y; + v->bz = vset->binormal[i].z; + + v++; + } + + surf_data->vertex_buffer->Unlock(); + } + } + + else { + VideoDX9SolidVertex* v = (VideoDX9SolidVertex*) surf_data->vertex_buffer->Lock(nverts); + + if (v) { + const VertexSet* vset = surf->GetVertexSet(); + for (int i = 0; i < nverts; i++) { + v->x = vset->loc[i].x; + v->y = vset->loc[i].y; + v->z = vset->loc[i].z; + + v->nx = vset->nrm[i].x; + v->ny = vset->nrm[i].y; + v->nz = vset->nrm[i].z; + + v->tu = vset->tu[i]; + v->tv = vset->tv[i]; + + v++; + } + + surf_data->vertex_buffer->Unlock(); + } + } + + WORD* indices = surf_data->index_buffer->Lock(nindices); + + if (indices) { + // copy the indices into the locked index buffer + WORD* s = indices; + Poly* p = surf->GetPolys(); + + for (int i = 0; i < surf->NumPolys(); i++) { + if (p->nverts == 3) { + *s++ = p->verts[0]; + *s++ = p->verts[2]; + *s++ = p->verts[1]; + } + else if (p->nverts == 4) { + *s++ = p->verts[0]; + *s++ = p->verts[2]; + *s++ = p->verts[1]; + + *s++ = p->verts[0]; + *s++ = p->verts[3]; + *s++ = p->verts[2]; + } + + p++; + } + + surf_data->index_buffer->Unlock(); + } + + surf_data->Validate(); + } + + int first_index = 0; + + ListIter seg_iter = surf->GetSegments(); + while (++seg_iter) { + Segment* segment = seg_iter.value(); + + if (!segment->video_data) { + VideoDX9SegmentData* seg_data = new(__FILE__,__LINE__) VideoDX9SegmentData; + + int num_tris = 0; + for (int i = 0; i < segment->npolys; i++) + num_tris += segment->polys[i].nverts-2; + + seg_data->first_vert = 0; + seg_data->num_verts = surf->NumVerts(); + seg_data->first_index = first_index; + seg_data->num_tris = num_tris; + + segment->video_data = seg_data; + + first_index += num_tris * 3; + } + } + } + + return true; +} + +// +--------------------------------------------------------------------+ + +int +VideoDX9::PrepareMaterial(Material* m) +{ + segment_material = m; + strategy = 0; + passes = 0; + + if (m) { + int max_stages = 1; + int max_textures = 1; + bool multiply_add = false; + bool dotproduct3 = false; + bool vertexshader = false; + bool pixelshader = false; + DWORD vs_version = 0; + DWORD ps_version = 0; + + VideoDX9DeviceInfo* dev_info = dx9enum->GetDeviceInfo(video_settings.GetDeviceType()); + + if (dev_info) { + max_stages = (int) dev_info->caps.MaxTextureBlendStages; + max_textures = (int) dev_info->caps.MaxSimultaneousTextures; + multiply_add = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD) ? true : false; + dotproduct3 = (dev_info->caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) ? true : false; + + vs_version = video_settings.enable_vs ? dev_info->caps.VertexShaderVersion : 0; + ps_version = video_settings.enable_ps ? dev_info->caps.PixelShaderVersion : 0; + + vertexshader = vs_version >= D3DVS_VERSION(1,1); + pixelshader = ps_version >= D3DPS_VERSION(2,0); + } + + strategy = DX9_STRATEGY_SIMPLE; + passes = 1; + + if (m->tex_alternate) { + if (m->tex_detail && max_textures > 2 && max_stages > 4) + strategy = DX9_STRATEGY_BLEND_DETAIL; + + else if (max_textures > 1 && max_stages > 3) + strategy = DX9_STRATEGY_BLEND; + } + + else if (m->tex_emissive && (!m->tex_diffuse || m->tex_diffuse == m->tex_emissive)) { + strategy = DX9_STRATEGY_GLOW; + } + + else if (IsSpecMapEnabled() && m->tex_specular && !m->tex_emissive) { + strategy = DX9_STRATEGY_SPECMAP; + + if (max_textures < 2 || max_stages < 2 || !multiply_add) + passes = 2; + } + + else if ((!IsSpecMapEnabled() || !m->tex_specular) && m->tex_emissive) { + strategy = DX9_STRATEGY_EMISSIVE; + + if (max_textures < 2 || max_stages < 2) + passes = 2; + } + + else if (IsSpecMapEnabled() && m->tex_specular && m->tex_emissive) { + strategy = DX9_STRATEGY_SPEC_EMISSIVE; + + if (max_textures < 2 || max_stages < 2) + passes = 3; + + else if (max_textures < 3 || max_stages < 3 || !multiply_add) + passes = 2; + } + } + + return passes; +} + +bool +VideoDX9::SetupPass(int pass) +{ + if (pass < 0 || pass >= passes) + return false; + + if (pass == 0) { + D3DMATERIAL9 d3dmtl; + IDirect3DTexture9* texture_0 = 0; + IDirect3DTexture9* texture_1 = 0; + IDirect3DTexture9* texture_2 = 0; + Bitmap* tex_bmp_0 = 0; + Bitmap* tex_bmp_1 = 0; + Bitmap* tex_bmp_2 = 0; + ColorValue orig_spec = segment_material->Ks; + HRESULT hr = E_FAIL; + + if (segment_material->tex_specular && passes > 1) + segment_material->Ks = Color::Black; + + CreateD3DMaterial(d3dmtl, *segment_material); + segment_material->Ks = orig_spec; + + hr = d3ddevice->SetMaterial(&d3dmtl); + + if (strategy == DX9_STRATEGY_SIMPLE) { + tex_bmp_0 = segment_material->tex_diffuse; + } + + else if (strategy == DX9_STRATEGY_BLEND) { + tex_bmp_0 = segment_material->tex_diffuse; + tex_bmp_1 = segment_material->tex_alternate; + } + + else if (strategy == DX9_STRATEGY_BLEND_DETAIL) { + tex_bmp_0 = segment_material->tex_diffuse; + tex_bmp_1 = segment_material->tex_alternate; + tex_bmp_2 = segment_material->tex_detail; + } + + else if (strategy == DX9_STRATEGY_SPECMAP) { + if (passes == 1) { + tex_bmp_0 = segment_material->tex_diffuse; + tex_bmp_1 = segment_material->tex_specular; + } + else { + tex_bmp_0 = segment_material->tex_diffuse; + } + } + + else if (strategy == DX9_STRATEGY_EMISSIVE && passes == 1 || + strategy == DX9_STRATEGY_SPEC_EMISSIVE && passes == 2) { + if (segment_material->tex_diffuse) { + tex_bmp_0 = segment_material->tex_diffuse; + tex_bmp_1 = segment_material->tex_emissive; + } + else { + tex_bmp_0 = segment_material->tex_emissive; + } + } + + else { + tex_bmp_0 = segment_material->tex_emissive; + } + + if (texcache && tex_bmp_0) { + texture_0 = texcache->FindTexture(tex_bmp_0); + + hr = d3ddevice->SetTexture(0, texture_0); + current_texture = texture_0; + + if (tex_bmp_1) { + texture_1 = texcache->FindTexture(tex_bmp_1); + hr = d3ddevice->SetTexture(1, texture_1); + + if (tex_bmp_2) { + texture_2 = texcache->FindTexture(tex_bmp_2); + hr = d3ddevice->SetTexture(2, texture_2); + } + } + } + else { + hr = d3ddevice->SetTexture(0, 0); + current_texture = 0; + } + + SetBlendType(segment_material->blend); + + if (texture_0 && texture_1 && strategy == DX9_STRATEGY_BLEND) { + d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + + d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + + d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); + } + + else if (texture_0 && texture_1 && texture_2 && strategy == DX9_STRATEGY_BLEND_DETAIL) { + d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + d3ddevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDCURRENTALPHA); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + + d3ddevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); + d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 1); + + d3ddevice->SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + } + + else if (texture_0 && strategy == DX9_STRATEGY_GLOW) { + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + } + + else if (texture_0) { + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + } + + if (texture_1 && strategy == DX9_STRATEGY_SPECMAP) { + d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_SPECULAR); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + } + + else if (texture_1 && strategy == DX9_STRATEGY_EMISSIVE) { + d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + } + + else if (texture_1 && strategy == DX9_STRATEGY_SPEC_EMISSIVE) { + d3ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + d3ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + + d3ddevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0); + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + } + + else if (strategy < DX9_STRATEGY_BLEND) { + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + } + } + + else if (pass == 1) { + D3DMATERIAL9 d3dmtl; + IDirect3DTexture9* texture = 0; + Bitmap* tex_bmp = 0; + ColorValue orig_Ka = segment_material->Ka; + ColorValue orig_Kd = segment_material->Kd; + HRESULT hr = E_FAIL; + + if (segment_material->tex_specular) { + segment_material->Ka = Color::Black; + segment_material->Kd = Color::Black; + } + + CreateD3DMaterial(d3dmtl, *segment_material); + + segment_material->Ka = orig_Ka; + segment_material->Kd = orig_Kd; + + hr = d3ddevice->SetMaterial(&d3dmtl); + + if (strategy == DX9_STRATEGY_SPECMAP || + strategy == DX9_STRATEGY_SPEC_EMISSIVE) { + tex_bmp = segment_material->tex_specular; + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_SPECULAR); + } + + else if (strategy == DX9_STRATEGY_EMISSIVE) { + tex_bmp = segment_material->tex_emissive; + d3ddevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + d3ddevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + } + + d3ddevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + + if (texcache && tex_bmp) { + texture = texcache->FindTexture(tex_bmp); + hr = d3ddevice->SetTexture(0, texture); + current_texture = texture; + + SetBlendType(BLEND_ADDITIVE); + } + } + + if (render_state[STENCIL_ENABLE]) { + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + d3ddevice->SetRenderState(D3DRS_STENCILREF, 0x01); + d3ddevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_GREATER); + } + else { + d3ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + if (render_state[LIGHTING_PASS] > 0) { + SetBlendType(BLEND_ADDITIVE); + SetRenderState(Z_WRITE_ENABLE, FALSE); + } + + return true; +} + + +// +--------------------------------------------------------------------+ + +void +VideoDX9Error(const char* msg, HRESULT err) +{ + Print(" VideoDX9: %s. [%s]\n", msg, D3DErrStr(err)); +} + +char* D3DErrStr(HRESULT hr) +{ + static char errstrbuf[128]; + + switch (hr) { + default: + sprintf_s(errstrbuf, "Unrecognized error value = %08x.", hr); + return errstrbuf; + + case D3D_OK: + return "No error."; + + case D3DERR_WRONGTEXTUREFORMAT: + return "Wrong texture format."; + + case D3DERR_UNSUPPORTEDCOLOROPERATION: + return "Unsupported color operation."; + + case D3DERR_UNSUPPORTEDCOLORARG: + return "Unsupported color argument."; + + case D3DERR_UNSUPPORTEDALPHAOPERATION: + return "Unsupported alpha operation."; + + case D3DERR_UNSUPPORTEDALPHAARG: + return "Unsupported alpha argument."; + + case D3DERR_TOOMANYOPERATIONS: + return "Too many operations."; + + case D3DERR_CONFLICTINGTEXTUREFILTER: + return "Conflicting texture filter."; + + case D3DERR_UNSUPPORTEDFACTORVALUE: + return "Unsupported factor value."; + + case D3DERR_CONFLICTINGRENDERSTATE: + return "Conflicting render state."; + + case D3DERR_UNSUPPORTEDTEXTUREFILTER: + return "Unsupported texture filter."; + + case D3DERR_CONFLICTINGTEXTUREPALETTE: + return "Conflicting texture palette."; + + case D3DERR_DRIVERINTERNALERROR: + return "Driver internal error."; + + + case D3DERR_NOTFOUND: + return "Resource was not found."; + + case D3DERR_MOREDATA: + return "More data?"; + + case D3DERR_DEVICELOST: + return "Device lost."; + + case D3DERR_DEVICENOTRESET: + return "Device is not reset."; + + case D3DERR_NOTAVAILABLE: + return "Not available."; + + case D3DERR_OUTOFVIDEOMEMORY: + return "Out of video memory."; + + case E_OUTOFMEMORY: + return "Out of system memory."; + + case D3DERR_INVALIDDEVICE: + return "Invalid device selection."; + + case D3DERR_INVALIDCALL: + return "Invalid call or parameter."; + + case D3DERR_DRIVERINVALIDCALL: + return "Driver invalid call."; + + case D3DERR_WASSTILLDRAWING: + return "The device was still drawing."; + + case D3DOK_NOAUTOGEN: + return "Autogeneration is not supported by this device."; + + } +} + diff --git a/Magic2/VideoDX9.h b/Magic2/VideoDX9.h index a9e0d6f..fdc37ff 100644 --- a/Magic2/VideoDX9.h +++ b/Magic2/VideoDX9.h @@ -1,195 +1,219 @@ -/* Project nGenEx - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: nGenEx.lib - FILE: VideoDX9.h - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Direct3D and Direct3D Video classes for DirectX 7 -*/ - -#ifndef VideoDX9_h -#define VideoDX9_h - -#include "Video.h" -#include "VideoSettings.h" -#include "List.h" - -// +--------------------------------------------------------------------+ - -class VideoDX9; -class VideoDX9Enum; -class VideoDX9VertexBuffer; -class VideoDX9IndexBuffer; -struct VideoDX9ScreenVertex; -class Surface; -class Segment; - -struct VideoDX9ScreenVertex; -struct VideoDX9SolidVertex; -struct VideoDX9LuminousVertex; -struct VideoDX9LineVertex; - - -// +--------------------------------------------------------------------+ - -class VideoDX9 : public Video -{ -public: - VideoDX9(const HWND& window, VideoSettings* vs); - virtual ~VideoDX9(); - - virtual const VideoSettings* - GetVideoSettings() const { return &video_settings; } - virtual bool SetVideoSettings(const VideoSettings* vs); - - virtual bool SetBackgroundColor(Color c); - virtual bool SetGammaLevel(int g); - virtual bool SetObjTransform(const Matrix& o, const Point& l); - - virtual bool SetupParams(); - virtual bool Reset(const VideoSettings* vs); - - virtual bool StartFrame(); - virtual bool EndFrame(); - - virtual int Width() const { return width; } - virtual int Height() const { return height; } - virtual int Depth() const { return bpp; } - - virtual void RecoverSurfaces(); - - virtual bool ClearAll(); - virtual bool ClearDepthBuffer(); - virtual bool Present(); - virtual bool Pause(); - virtual bool Resume(); - - virtual IDirect3D9* Direct3D() const { return d3d; } - virtual IDirect3DDevice9* D3DDevice() const { return d3ddevice; } - static IDirect3DDevice9* GetD3DDevice9(); - - virtual bool IsModeSupported(int width, int height, int bpp) const; - virtual bool IsHardware() const { return true; } - virtual int ZDepth() const { return zdepth; } - virtual DWORD VidMemFree() const; - virtual int D3DLevel() const { return 9; } - virtual int MaxTexSize() const; - virtual int MaxTexAspect() const; - virtual int GammaLevel() const { return gamma; } - - virtual bool Capture(Bitmap& bmp); - virtual bool GetWindowRect(Rect& r); - virtual bool SetWindowRect(const Rect& r); - virtual bool SetViewport(int x, int y, int w, int h); - virtual bool SetCamera(const Camera* cam); - virtual bool SetEnvironment(Bitmap** faces); - virtual bool SetAmbient(Color c); - virtual bool SetLights(const List& lights); - virtual bool SetProjection(float fov, - float znear=1.0f, - float zfar=1.0e6f, - DWORD type=PROJECTION_PERSPECTIVE); - virtual bool SetRenderState(RENDER_STATE state, DWORD value); - virtual bool SetBlendType(int blend_type); - - virtual bool DrawPolys(int npolys, Poly* p); - virtual bool DrawScreenPolys(int npolys, Poly* p, int blend=0); - virtual bool DrawSolid(Solid* s, DWORD blend_modes=0xf); - virtual bool DrawShadow(Solid* s, int nverts, Vec3* verts, bool vis=false); - virtual bool DrawLines(int nlines, Vec3* v, Color c, int blend=0); - virtual bool DrawScreenLines(int nlines, float* v, Color c, int blend=0); - virtual bool DrawPoints(VertexSet* v); - virtual bool DrawPolyOutline(Poly* p); - virtual bool UseMaterial(Material* m); - - virtual bool UseXFont(const char* name, int size, bool b, bool i); - virtual bool DrawText(const char* text, int count, const Rect& rect, - DWORD format, Color c); - - virtual void PreloadTexture(Bitmap* bmp); - virtual void PreloadSurface(Surface* s); - virtual void InvalidateCache(); - - static void CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p); - static void CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v); - static void CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl); - -private: - bool CreateBuffers(); - bool DestroyBuffers(); - bool PopulateScreenVerts(VertexSet* vset); - bool PrepareSurface(Surface* s); - bool DrawSegment(Segment* s); - - int PrepareMaterial(Material* m); - bool SetupPass(int n); - - HWND hwnd; - int width; - int height; - int bpp; - int gamma; - int zdepth; - Color background; - - VideoDX9Enum* dx9enum; - VideoSettings video_settings; - - IDirect3D9* d3d; - IDirect3DDevice9* d3ddevice; - D3DPRESENT_PARAMETERS d3dparams; - D3DSURFACE_DESC back_buffer_desc; - bool device_lost; - - BYTE* surface; - - DWORD texture_format[3]; - D3DGAMMARAMP gamma_ramp; - double fade; - - Rect rect; - - IDirect3DVertexDeclaration9* vertex_declaration; - ID3DXEffect* magic_fx; - BYTE* magic_fx_code; - int magic_fx_code_len; - - IDirect3DTexture9* current_texture; - int current_blend_state; - int scene_active; - DWORD render_state[RENDER_STATE_MAX]; - Material* use_material; - - Material* segment_material; - int strategy; - int passes; - - ID3DXFont* d3dx_font; - char font_name[64]; - int font_size; - bool font_bold; - bool font_ital; - - Color ambient; - int nlights; - - int first_vert; - int num_verts; - - VideoDX9VertexBuffer* screen_vbuf; - VideoDX9IndexBuffer* screen_ibuf; - VideoDX9ScreenVertex* font_verts; - WORD* font_indices; - int font_nverts; - - VideoDX9ScreenVertex* screen_line_verts; - VideoDX9LineVertex* line_verts; -}; - -#endif VideoDX9_h - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: nGenEx.lib + FILE: VideoDX9.h + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Direct3D and Direct3D Video classes for DirectX 7 +*/ + +#ifndef VideoDX9_h +#define VideoDX9_h + +#include "Video.h" +#include "VideoSettings.h" +#include "List.h" + +// +--------------------------------------------------------------------+ + +class VideoDX9; +class VideoDX9Enum; +class VideoDX9VertexBuffer; +class VideoDX9IndexBuffer; +struct VideoDX9ScreenVertex; +class Surface; +class Segment; + +struct VideoDX9ScreenVertex; +struct VideoDX9SolidVertex; +struct VideoDX9LuminousVertex; +struct VideoDX9LineVertex; + + +// +--------------------------------------------------------------------+ + +class VideoDX9 : public Video +{ +public: + VideoDX9(const HWND& window, VideoSettings* vs); + virtual ~VideoDX9(); + + virtual const VideoSettings* + GetVideoSettings() const { return &video_settings; } + virtual bool SetVideoSettings(const VideoSettings* vs); + + virtual bool SetBackgroundColor(Color c); + virtual bool SetGammaLevel(int g); + virtual bool SetObjTransform(const Matrix& o, const Point& l); + + virtual bool SetupParams(); + virtual bool Reset(const VideoSettings* vs); + + virtual bool StartFrame(); + virtual bool EndFrame(); + + virtual int Width() const { return width; } + virtual int Height() const { return height; } + virtual int Depth() const { return bpp; } + + virtual void RecoverSurfaces(); + + virtual bool ClearAll(); + virtual bool ClearDepthBuffer(); + virtual bool Present(); + virtual bool Pause(); + virtual bool Resume(); + + virtual IDirect3D9* Direct3D() const { return d3d; } + virtual IDirect3DDevice9* D3DDevice() const { return d3ddevice; } + static IDirect3DDevice9* GetD3DDevice9(); + + virtual bool IsModeSupported(int width, int height, int bpp) const; + virtual bool IsHardware() const { return true; } + virtual int ZDepth() const { return zdepth; } + virtual DWORD VidMemFree() const; + virtual int D3DLevel() const { return 9; } + virtual int MaxTexSize() const; + virtual int MaxTexAspect() const; + virtual int GammaLevel() const { return gamma; } + + virtual bool Capture(Bitmap& bmp); + virtual bool GetWindowRect(Rect& r); + virtual bool SetWindowRect(const Rect& r); + virtual bool SetViewport(int x, int y, int w, int h); + virtual bool SetCamera(const Camera* cam); + virtual bool SetEnvironment(Bitmap** faces); + virtual bool SetAmbient(Color c); + virtual bool SetLights(const List& lights); + virtual bool SetProjection(float fov, + float znear=1.0f, + float zfar=1.0e6f, + DWORD type=PROJECTION_PERSPECTIVE); + virtual bool SetRenderState(RENDER_STATE state, DWORD value); + virtual bool SetBlendType(int blend_type); + + virtual bool DrawPolys(int npolys, Poly* p); + virtual bool DrawScreenPolys(int npolys, Poly* p, int blend=0); + virtual bool DrawSolid(Solid* s, DWORD blend_modes=0xf); + virtual bool DrawShadow(Solid* s, int nverts, Vec3* verts, bool vis=false); + virtual bool DrawLines(int nlines, Vec3* v, Color c, int blend=0); + virtual bool DrawScreenLines(int nlines, float* v, Color c, int blend=0); + virtual bool DrawPoints(VertexSet* v); + virtual bool DrawPolyOutline(Poly* p); + virtual bool UseMaterial(Material* m); + + virtual bool UseXFont(const char* name, int size, bool b, bool i); + virtual bool DrawText(const char* text, int count, const Rect& rect, + DWORD format, Color c); + + virtual void PreloadTexture(Bitmap* bmp); + virtual void PreloadSurface(Surface* s); + virtual void InvalidateCache(); + + static void CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Point& p); + static void CreateD3DMatrix(D3DMATRIX& result, const Matrix& m, const Vec3& v); + static void CreateD3DMaterial(D3DMATERIAL9& result, const Material& mtl); + +private: + bool CreateBuffers(); + bool DestroyBuffers(); + bool PopulateScreenVerts(VertexSet* vset); + bool PrepareSurface(Surface* s); + bool DrawSegment(Segment* s); + + int PrepareMaterial(Material* m); + bool SetupPass(int n); + + HWND hwnd; + int width; + int height; + int bpp; + int gamma; + int zdepth; + Color background; + + VideoDX9Enum* dx9enum; + VideoSettings video_settings; + + IDirect3D9* d3d; + IDirect3DDevice9* d3ddevice; + D3DPRESENT_PARAMETERS d3dparams; + D3DSURFACE_DESC back_buffer_desc; + bool device_lost; + + BYTE* surface; + + DWORD texture_format[3]; + D3DGAMMARAMP gamma_ramp; + double fade; + + Rect rect; + + IDirect3DVertexDeclaration9* vertex_declaration; + ID3DXEffect* magic_fx; + BYTE* magic_fx_code; + int magic_fx_code_len; + + IDirect3DTexture9* current_texture; + int current_blend_state; + int scene_active; + DWORD render_state[RENDER_STATE_MAX]; + Material* use_material; + + Material* segment_material; + int strategy; + int passes; + + ID3DXFont* d3dx_font; + char font_name[64]; + int font_size; + bool font_bold; + bool font_ital; + + Color ambient; + int nlights; + + int first_vert; + int num_verts; + + VideoDX9VertexBuffer* screen_vbuf; + VideoDX9IndexBuffer* screen_ibuf; + VideoDX9ScreenVertex* font_verts; + WORD* font_indices; + int font_nverts; + + VideoDX9ScreenVertex* screen_line_verts; + VideoDX9LineVertex* line_verts; +}; + +#endif VideoDX9_h + diff --git a/Magic2/l3ds.cpp b/Magic2/l3ds.cpp index 4f334a5..3cbdcfa 100644 --- a/Magic2/l3ds.cpp +++ b/Magic2/l3ds.cpp @@ -1,1793 +1,1793 @@ -// copyright (c) 2001 Lev Povalahev - - -#include "stdafx.h" - -#include "l3ds.h" - -#include -#include -#include -#include - -//using namespace std; - -//------------------------------------------------------- -// generic stuff -//------------------------------------------------------- - -typedef unsigned long ulong; - -#define SEEK_START 1900 -#define SEEK_CURSOR 1901 - -// common chunks -// colors -#define COLOR_F 0x0010 -#define COLOR_24 0x0011 -#define LIN_COLOR_24 0x0012 -#define LIN_COLOR_F 0x0013 -// percentage -#define INT_PERCENTAGE 0x0030 -#define FLOAT_PERCENTAGE 0x0031 -// ambient light -#define AMBIENT_LIGHT 0x2100 - - -#define MAIN3DS 0x4D4D -#define EDIT3DS 0x3D3D // this is the start of the editor config - -// keyframer chunk ids -#define KFDATA 0xB000 // the keyframer section -#define KFHDR 0xB00A -#define OBJECT_NODE_TAG 0xB002 -#define NODE_HDR 0xB010 -#define PIVOT 0xB013 -#define POS_TRACK_TAG 0xB020 -#define ROT_TRACK_TAG 0xB021 -#define SCL_TRACK_TAG 0xB022 - -// material entries -#define MAT_ENTRY 0xAFFF -#define MAT_NAME 0xA000 -#define MAT_AMBIENT 0xA010 -#define MAT_DIFFUSE 0xA020 -#define MAT_SPECULAR 0xA030 -#define MAT_SHININESS 0xA040 -#define MAT_SHIN2PCT 0xA041 -#define MAT_TRANSPARENCY 0xA050 -#define MAT_SHADING 0xA100 -#define MAT_TWO_SIDE 0xA081 -#define MAT_ADDITIVE 0xA083 -#define MAT_WIRE 0xA085 -#define MAT_FACEMAP 0xA088 -#define MAT_WIRESIZE 0xA087 -#define MAT_DECAL 0xA082 -#define MAT_TEXMAP 0xA200 -#define MAT_MAPNAME 0xA300 -#define MAT_MAP_TILING 0xA351 -#define MAT_MAP_USCALE 0xA354 -#define MAT_MAP_VSCALE 0xA356 -#define MAT_MAP_UOFFSET 0xA358 -#define MAT_MAP_VOFFSET 0xA35A -#define MAT_MAP_ANG 0xA35C -#define MAT_TEX2MAP 0xA33A -#define MAT_OPACMAP 0xA210 -#define MAT_BUMPMAP 0xA230 -#define MAT_SPECMAP 0xA204 -#define MAT_SHINMAP 0xA33C -#define MAT_REFLMAP 0xA220 -#define MAT_ACUBIC 0xA310 - -#define EDIT_OBJECT 0x4000 -#define OBJ_TRIMESH 0x4100 -#define OBJ_LIGHT 0x4600 -#define OBJ_CAMERA 0x4700 -#define LIT_OFF 0x4620 -#define LIT_SPOT 0x4610 -#define TRI_VERTEXLIST 0x4110 -#define TRI_VERTEXOPTIONS 0x4111 - -#define TRI_FACELIST 0x4120 - #define TRI_MAT_GROUP 0x4130 - #define TRI_SMOOTH_GROUP 0x4150 - -#define TRI_FACEMAPPING 0x4140 -#define TRI_MATRIX 0x4160 - -#define SPOTLIGHT 0x4610 - -//---------------------------------- - -#define MAX_SHARED_TRIS 100 - -// the error reporting routine - -void ErrorMsg(const char *msg) -{ - -} - -struct LChunk -{ - unsigned short id; - uint start; - uint end; -}; - -struct LTri -{ - unsigned short a; - unsigned short b; - unsigned short c; - ulong smoothingGroups; - LVector3 normal; - LVector3 tangent; - LVector3 binormal; - uint materialId; -}; - -// globals - -LColor3 black = {0, 0, 0}; - -LVector3 zero3 = {0, 0, 0}; - -LVector4 zero4 = {0, 0, 0, 0}; - -LMap emptyMap = {0, "", 1, 1, 0, 0, 0}; - -LVector3 _4to3(const LVector4 &vec) -{ - LVector3 t; - t.x = vec.x; - t.y = vec.y; - t.z = vec.z; - return t; -} - -LVector3 AddVectors(const LVector3 &a, const LVector3 &b) -{ - LVector3 t; - t.x = a.x+b.x; - t.y = a.y+b.y; - t.z = a.z+b.z; - return t; -} - -LVector3 SubtractVectors(const LVector3 &a, const LVector3 &b) -{ - LVector3 t; - t.x = a.x-b.x; - t.y = a.y-b.y; - t.z = a.z-b.z; - return t; -} - -float VectorLength(const LVector3 &vec) -{ - return (float)sqrt(vec.x*vec.x + vec.y*vec.y+vec.z*vec.z); -} - -LVector3 NormalizeVector(const LVector3 &vec) -{ - float a = VectorLength(vec); - if (a == 0) - return vec; - float b = 1/a; - LVector3 v; - v.x = vec.x*b; - v.y = vec.y*b; - v.z = vec.z*b; - return v; -} - -LVector3 CrossProduct(const LVector3 &a, const LVector3 &b) -{ - LVector3 v; - v.x = a.y*b.z - a.z*b.y; - v.y = a.z*b.x - a.x*b.z; - v.z = a.x*b.y - a.y*b.x; - return v; -} - -void LoadIdentityMatrix(LMatrix4 &m) -{ - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - m.m[i][j] = (i==j) ? 1.0f : 0.0f; -} - -LVector4 VectorByMatrix(const LMatrix4 &m, const LVector4 &vec) -{ - LVector4 res; - - res.x = m.m[0][0]*vec.x + m.m[1][0]*vec.y + m.m[2][0]*vec.z + m.m[3][0]*vec.w; - res.y = m.m[0][1]*vec.x + m.m[1][1]*vec.y + m.m[2][1]*vec.z + m.m[3][1]*vec.w; - res.z = m.m[0][2]*vec.x + m.m[1][2]*vec.y + m.m[2][2]*vec.z + m.m[3][2]*vec.w; - res.w = m.m[0][3]*vec.x + m.m[1][3]*vec.y + m.m[2][3]*vec.z + m.m[3][3]*vec.w; - - if (res.w != 0) { - float b = 1/res.w; - res.x *= b; - res.y *= b; - res.z *= b; - res.w = 1; - } - else { - res.w = 1; - } - - return res; -} - -void QuatToMatrix(const LVector4 &quat, LMatrix4 &m) -{ - -} - -//------------------------------------------------------- -// LObject implementation -//------------------------------------------------------- - -LObject::LObject() -{ - m_name = "";//.clear(); -} - -LObject::~LObject() -{ - // nothing here -} - -void LObject::SetName(const std::string& value) -{ - m_name = value; -} - -const std::string& LObject::GetName() -{ - return m_name; -} - -bool LObject::IsObject(const std::string &name) -{ - return (m_name == name); -} - - -//------------------------------------------------------- -// LMaterial implementation -//------------------------------------------------------- - -LMaterial::LMaterial() -: LObject() -{ - m_id = 0; - m_texMap1 = emptyMap; - m_texMap2 = emptyMap; - m_opacMap = emptyMap; - m_bumpMap = emptyMap; - m_reflMap = emptyMap; - m_specMap = emptyMap; - m_ambient = black; - m_diffuse = black; - m_specular = black; - m_shading = sGouraud; - m_shininess = 0; - m_transparency = 0; -} - -LMaterial::~LMaterial() -{ - -} - -uint LMaterial::GetID() -{ - return m_id; -} - -LMap& LMaterial::GetTextureMap1() -{ - return m_texMap1; -} - -LMap& LMaterial::GetTextureMap2() -{ - return m_texMap2; -} - -LMap& LMaterial::GetOpacityMap() -{ - return m_opacMap; -} - -LMap& LMaterial::GetSpecularMap() -{ - return m_specMap; -} - -LMap& LMaterial::GetBumpMap() -{ - return m_bumpMap; -} - -LMap& LMaterial::GetReflectionMap() -{ - return m_reflMap; -} - -LColor3 LMaterial::GetAmbientColor() -{ - return m_ambient; -} - -LColor3 LMaterial::GetDiffuseColor() -{ - return m_diffuse; -} - -LColor3 LMaterial::GetSpecularColor() -{ - return m_specular; -} - -float LMaterial::GetShininess() -{ - return m_shininess; -} - -float LMaterial::GetTransparency() -{ - return m_transparency; -} - -LShading LMaterial::GetShadingType() -{ - return m_shading; -} - -void LMaterial::SetID(uint value) -{ - m_id = value; -} - -void LMaterial::SetAmbientColor(const LColor3 &color) -{ - m_ambient = color; -} - -void LMaterial::SetDiffuseColor(const LColor3 &color) -{ - m_diffuse = color; -} - -void LMaterial::SetSpecularColor(const LColor3 &color) -{ - m_specular = color; -} - -void LMaterial::SetShininess(float value) -{ - m_shininess = value; - if (m_shininess < 0) - m_shininess = 0; - if (m_shininess > 1) - m_shininess = 1; -} - -void LMaterial::SetTransparency(float value) -{ - m_transparency = value; - if (m_transparency < 0) - m_transparency = 0; - if (m_transparency > 1) - m_transparency = 1; -} - -void LMaterial::SetShadingType(LShading shading) -{ - m_shading = shading; -} - -//------------------------------------------------------- -// LMesh implementation -//------------------------------------------------------- - -LMesh::LMesh() -: LObject() -{ - Clear(); -} - -LMesh::~LMesh() -{ - Clear(); -} - -void LMesh::Clear() -{ - m_vertices.clear(); - m_normals.clear(); - m_uv.clear(); - m_tangents.clear(); - m_binormals.clear(); - m_triangles.clear(); - m_tris.clear(); - m_materials.clear(); - LoadIdentityMatrix(m_matrix); -} - -uint LMesh::GetVertexCount() -{ - return m_vertices.size(); -} - -void LMesh::SetVertexArraySize(uint value) -{ - m_vertices.resize(value); - m_normals.resize(value); - m_uv.resize(value); - m_tangents.resize(value); - m_binormals.resize(value); -} - -uint LMesh::GetTriangleCount() -{ - return m_triangles.size(); -} - -void LMesh::SetTriangleArraySize(uint value) -{ - m_triangles.resize(value); - m_tris.resize(value); -} - -const LVector4& LMesh::GetVertex(uint index) -{ - return m_vertices[index]; -} - -const LVector3& LMesh::GetNormal(uint index) -{ - return m_normals[index]; -} - -const LVector2& LMesh::GetUV(uint index) -{ - return m_uv[index]; -} - -const LVector3& LMesh::GetTangent(uint index) -{ - return m_tangents[index]; -} - -const LVector3& LMesh::GetBinormal(uint index) -{ - return m_binormals[index]; -} - -void LMesh::SetVertex(const LVector4 &vec, uint index) -{ - if (index >= m_vertices.size()) - return; - m_vertices[index] = vec; -} - -void LMesh::SetNormal(const LVector3 &vec, uint index) -{ - if (index >= m_vertices.size()) - return; - m_normals[index] = vec; -} - -void LMesh::SetUV(const LVector2 &vec, uint index) -{ - if (index >= m_vertices.size()) - return; - m_uv[index] = vec; -} - -void LMesh::SetTangent(const LVector3 &vec, uint index) -{ - if (index >= m_vertices.size()) - return; - m_tangents[index] = vec; -} - -void LMesh::SetBinormal(const LVector3 &vec, uint index) -{ - if (index >= m_vertices.size()) - return; - m_binormals[index] = vec; -} - -const LTriangle& LMesh::GetTriangle(uint index) -{ - return m_triangles[index]; -} - -LTriangle2 LMesh::GetTriangle2(uint index) -{ - LTriangle2 f; - LTriangle t = GetTriangle(index); - f.vertices[0] = GetVertex(t.a); - f.vertices[1] = GetVertex(t.b); - f.vertices[2] = GetVertex(t.c); - - f.vertexNormals[0] = GetNormal(t.a); - f.vertexNormals[1] = GetNormal(t.b); - f.vertexNormals[2] = GetNormal(t.c); - - f.textureCoords[0] = GetUV(t.a); - f.textureCoords[1] = GetUV(t.b); - f.textureCoords[2] = GetUV(t.c); - - LVector3 a, b; - - a = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[0])); - b = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[2])); - - f.faceNormal = CrossProduct(b, a); - - f.faceNormal = NormalizeVector(f.faceNormal); - - f.materialId = m_tris[index].materialId; - - return f; -} - -LMatrix4 LMesh::GetMatrix() -{ - return m_matrix; -} - -void LMesh::SetMatrix(LMatrix4 m) -{ - m_matrix = m; -} - -void LMesh::TransformVertices() -{ - for (uint i=0; i > array; - array.resize(m_vertices.size()); - for (i=0; i smGroups; - std::vector< std::vector > smList; - - uint loop_size = m_vertices.size(); - - for (i=0; i 1) - for (uint j=1; j< smGroups.size(); j++) - { - m_vertices.push_back(m_vertices[i]); - m_normals.push_back(m_normals[i]); - m_uv.push_back(m_uv[i]); - m_tangents.push_back(m_tangents[i]); - m_binormals.push_back(m_binormals[i]); - - uint t = m_vertices.size()-1; - for (uint h=0; h > array; - array.resize(m_vertices.size()); - for (int i=0; i<(int)m_triangles.size(); i++) - { - uint k = m_tris[i].a; - array[k].push_back(i); - - k = m_tris[i].b; - array[k].push_back(i); - - k = m_tris[i].c; - array[k].push_back(i); - } - - // now average the tangents and compute the binormals as (tangent X normal) - for (int i=0; i<(int)m_vertices.size(); i++) - { - v1 = zero3; - v2 = zero3; - int t = array[i].size(); - - for (int k=0; k= m_triangles.size()) - return; - m_tris[index] = tri; -} - -LTri& LMesh::GetTri(uint index) -{ - return m_tris[index]; -} - -uint LMesh::GetMaterial(uint index) -{ - return m_materials[index]; -} - -uint LMesh::AddMaterial(uint id) -{ - m_materials.push_back(id); - return m_materials.size()-1; -} - -uint LMesh::GetMaterialCount() -{ - return m_materials.size(); -} - -//------------------------------------------------------- -// LLight implementation -//------------------------------------------------------- - -LLight::LLight() -: LObject() -{ - Clear(); -} - -LLight::~LLight() -{ - -} - -void LLight::Clear() -{ - m_pos.x = m_pos.y = m_pos.z = 0.0f; - m_color.r = m_color.g = m_color.b = 0.0f; - m_spotlight = false; -} - -void LLight::SetPosition(LVector3 vec) -{ - m_pos = vec; -} - -LVector3 LLight::GetPosition() -{ - return m_pos; -} - -void LLight::SetColor(LColor3 color) -{ - m_color = color; -} - -LColor3 LLight::GetColor() -{ - return m_color; -} - -void LLight::SetSpotlight(bool value) -{ - m_spotlight = value; -} - -bool LLight::GetSpotlight() -{ - return m_spotlight; -} - -void LLight::SetTarget(LVector3 target) -{ - m_target = target; -} - -LVector3 LLight::GetTarget() -{ - return m_target; -} - -void LLight::SetHotspot(float value) -{ - m_hotspot = value; -} - -float LLight::GetHotspot() -{ - return m_hotspot; -} - -void LLight::SetFalloff(float value) -{ - m_falloff = value; -} - -float LLight::GetFalloff() -{ - return m_falloff; -} - -//------------------------------------------------------- -// LImporter implementation -//------------------------------------------------------- - -LImporter::LImporter() -{ - Clear(); -} - -LImporter::~LImporter() -{ - Clear(); -} - -uint LImporter::GetMeshCount() -{ - return m_meshes.size(); -} - -uint LImporter::GetLightCount() -{ - return m_lights.size(); -} - -uint LImporter::GetMaterialCount() -{ - return m_materials.size(); -} - -LMesh& LImporter::GetMesh(uint index) -{ - return m_meshes[index]; -} - -LLight& LImporter::GetLight(uint index) -{ - return m_lights[index]; -} - -LMaterial& LImporter::GetMaterial(uint index) -{ - return m_materials[index]; -} - -LMaterial* LImporter::FindMaterial(const std::string& name) -{ - for (uint i=0; i 0) - free(m_buffer); -} - -bool L3DS::LoadFile(const char *filename) -{ - FILE *f; - f = fopen(filename, "rb"); - if (f == 0) - { - ErrorMsg("L3DS::LoadFile - cannot open file"); - return false; - } - fseek(f, 0, SEEK_END); - m_bufferSize = ftell(f); - fseek(f, 0, SEEK_SET); - m_buffer = (unsigned char*) calloc(m_bufferSize, 1); - if (m_buffer == 0) - { - ErrorMsg("L3DS::LoadFile - not enough memory (malloc failed)"); - return false; - } - if (fread(m_buffer, m_bufferSize, 1, f) != 1) - { - fclose(f); - free(m_buffer); - m_bufferSize = 0; - ErrorMsg("L3DS::LoadFile - error reading from file"); - return false; - } - fclose(f); - Clear(); - bool res = Read3DS(); - free(m_buffer); - m_buffer = 0; - m_bufferSize = 0; - return res; -} - -short L3DS::ReadShort() -{ - if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+2)=m_bufferSize)) - { - count = 0; - m_eof = true; - return count; - } - count = 0; - char c = ReadChar(); - while ((c!=0) && (count= m_bufferSize) - m_pos = m_bufferSize-1; - m_eof = false; -} - -uint L3DS::Pos() -{ - return m_pos; -} - -LChunk L3DS::ReadChunk() -{ - LChunk chunk; - chunk.id = ReadShort(); - int a = ReadInt(); - chunk.start = Pos(); - chunk.end = chunk.start+a-6; - return chunk; -} - -bool L3DS::FindChunk(LChunk &target, const LChunk &parent) -{ - if (Pos() >= parent.end) - return false; - LChunk chunk; - chunk = ReadChunk(); - while (( chunk.id != target.id) && (chunk.end <= parent.end)) - { - SkipChunk(chunk); - if (chunk.end >= parent.end) - break; - chunk = ReadChunk(); - } - if (chunk.id == target.id) - { - target.start = chunk.start; - target.end = chunk.end; - return true; - } - return false; -} - -void L3DS::SkipChunk(const LChunk &chunk) -{ - Seek(chunk.end, SEEK_START); -} - -void L3DS::GotoChunk(const LChunk &chunk) -{ - Seek(chunk.start, SEEK_START); -} - -LColor3 L3DS::ReadColor(const LChunk &chunk) -{ - LColor3 col = black; - GotoChunk(chunk); - switch (chunk.id) - { - case COLOR_F: - col.r = ReadFloat(); - col.g = ReadFloat(); - col.b = ReadFloat(); - break; - case COLOR_24: - col.r = ReadByte()/255.0f; - col.g = ReadByte()/255.0f; - col.b = ReadByte()/255.0f; - break; - case LIN_COLOR_F: - col.r = ReadFloat(); - col.g = ReadFloat(); - col.b = ReadFloat(); - break; - case LIN_COLOR_24: - col.r = ReadByte()/255.0f; - col.g = ReadByte()/255.0f; - col.b = ReadByte()/255.0f; - break; - default: - ErrorMsg("L3DS::ReadColor - error this is not a color chunk"); - } - return col; -} - -float L3DS::ReadPercentage(const LChunk &chunk) -{ - GotoChunk(chunk); - switch (chunk.id) - { - case INT_PERCENTAGE: - return (ReadShort()/100.0f); - case FLOAT_PERCENTAGE: - return ReadFloat(); - } - ErrorMsg("L3DS::ReadPercentage - error, the chunk is not a percentage chunk"); - return 0; -} - -bool L3DS::Read3DS() -{ - LChunk mainchunk; - LChunk edit; - edit.id = EDIT3DS; - mainchunk = ReadChunk(); - if (mainchunk.id != MAIN3DS) - { - ErrorMsg("L3DS::Read3DS - wrong file format"); - return false; - } - if (!FindChunk(edit, mainchunk)) - return false; - LChunk obj; - LChunk ml; - - GotoChunk(edit); - obj.id = MAT_ENTRY; - while (FindChunk(obj, edit)) - { - ReadMaterial(obj); - SkipChunk(obj); - } - GotoChunk(edit); - - obj.id = EDIT_OBJECT; - { - while (FindChunk(obj, edit)) - { - ReadASCIIZ(m_objName, 99); - ml = ReadChunk(); - if (ml.id == OBJ_TRIMESH) - ReadMesh(ml); - if (ml.id == OBJ_LIGHT) - ReadLight(ml); - SkipChunk(obj); - } - } - - // read the keyframer data here to find out correct object orientation - - LChunk keyframer; - keyframer.id = KFDATA; - - LChunk objtrack; - objtrack.id = OBJECT_NODE_TAG; - - GotoChunk(mainchunk); - if (FindChunk(keyframer, mainchunk)) - { // keyframer chunk is present - GotoChunk(keyframer); - while (FindChunk(objtrack, keyframer)) - { - ReadKeyframeData(objtrack); - SkipChunk(objtrack); - } - } - - for (uint i=0; i= parent.end) - break; - chunk = ReadChunk(); - - } - } - m_lights.push_back(light); -} - -void L3DS::ReadMesh(const LChunk &parent) -{ - unsigned short count, i; - LVector4 p; - LMatrix4 m; - LVector2 t; - p.w = 1.0f; - LMesh mesh; - mesh.SetName(m_objName); - GotoChunk(parent); - LChunk chunk = ReadChunk(); - while (chunk.end <= parent.end) - { - switch (chunk.id) - { - case TRI_VERTEXLIST: - count = ReadShort(); - mesh.SetVertexArraySize(count); - for (i=0; i < count; i++) - { - p.x = ReadFloat(); - p.y = ReadFloat(); - p.z = ReadFloat(); - mesh.SetVertex(p, i); - } - break; - case TRI_FACEMAPPING: - count = ReadShort(); - if (mesh.GetVertexCount() == 0) - mesh.SetVertexArraySize(count); - for (i=0; i < count; i++) - { - t.x = ReadFloat(); - t.y = ReadFloat(); - mesh.SetUV(t, i); - } - break; - case TRI_FACELIST: - ReadFaceList(chunk, mesh); - break; - case TRI_MATRIX: - { - for (int i = 0; i < 4; i++) - for (int j = 0; j < 3; j++) - m.m[i][j] = ReadFloat(); - - m.m[0][3] = 0.0f; - m.m[1][3] = 0.0f; - m.m[2][3] = 0.0f; - m.m[3][3] = 1.0f; - - mesh.SetMatrix(m); - } - break; - default: - break; - } - SkipChunk(chunk); - if (chunk.end >= parent.end) - break; - chunk = ReadChunk(); - } - m_meshes.push_back(mesh); -} - -void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh) -{ - // variables - unsigned short count, t; - uint i; - LTri tri; - LChunk ch; - char str[20]; - //uint mat; - - // consistency checks - if (chunk.id != TRI_FACELIST) - { - ErrorMsg("L3DS::ReadFaceList - internal error: wrong chunk passed as parameter"); - return; - } - GotoChunk(chunk); - tri.smoothingGroups = 1; - // read the number of faces - count = ReadShort(); - mesh.SetTriangleArraySize(count); - for (i=0; iGetID(); - mesh.AddMaterial(mat_id); - count = ReadShort(); - for (i=0; i 0) - { - ReadKeyheader(); - pos.x = ReadFloat(); - pos.y = ReadFloat(); - pos.z = ReadFloat(); - } - } - GotoChunk(parent); - - // now read the rotation track - LVector4 rot = zero4; - - LChunk rotchunk; - rotchunk.id = ROT_TRACK_TAG; - - frames = 0; - if (FindChunk(rotchunk, parent)) - { - GotoChunk(rotchunk); - // read the trackheader structure - ReadShort(); - ReadInt(); - ReadInt(); - frames = ReadInt(); - if (frames > 0) - { - ReadKeyheader(); - rot.x = ReadFloat(); - rot.y = ReadFloat(); - rot.z = ReadFloat(); - rot.w = ReadFloat(); - } - } - GotoChunk(parent); - - // now read the scaling chunk - LVector3 scale; - scale.x = 1; - scale.y = 1; - scale.z = 1; - - LChunk scalechunk; - scalechunk.id = SCL_TRACK_TAG; - - frames = 0; - - if (FindChunk(scalechunk, parent)) - { - GotoChunk(scalechunk); - // read the trackheader structure - ReadShort(); - ReadInt(); - ReadInt(); - frames = ReadInt(); - if (frames > 0) - { - ReadKeyheader(); - scale.x = ReadFloat(); - scale.y = ReadFloat(); - scale.z = ReadFloat(); - } - } - GotoChunk(parent); - - -} - -long L3DS::ReadKeyheader() -{ - long frame; - frame = ReadInt(); - short opts = ReadShort(); - if (opts & 32768) // 32768 is 1000000000000000 binary - { // tension is present - ReadFloat(); - } - if (opts & 16384) // 16384 is 0100000000000000 binary - { // continuity is present - ReadFloat(); - } - if (opts & 8192) - { // bias info present - ReadFloat(); - } - if (opts & 4096) - { // "ease to" present - ReadFloat(); - } - if (opts & 2048) - { // "ease from" present - ReadFloat(); - } - return frame; +// copyright (c) 2001 Lev Povalahev + + +#include "stdafx.h" + +#include "l3ds.h" + +#include +#include +#include +#include + +//using namespace std; + +//------------------------------------------------------- +// generic stuff +//------------------------------------------------------- + +typedef unsigned long ulong; + +#define SEEK_START 1900 +#define SEEK_CURSOR 1901 + +// common chunks +// colors +#define COLOR_F 0x0010 +#define COLOR_24 0x0011 +#define LIN_COLOR_24 0x0012 +#define LIN_COLOR_F 0x0013 +// percentage +#define INT_PERCENTAGE 0x0030 +#define FLOAT_PERCENTAGE 0x0031 +// ambient light +#define AMBIENT_LIGHT 0x2100 + + +#define MAIN3DS 0x4D4D +#define EDIT3DS 0x3D3D // this is the start of the editor config + +// keyframer chunk ids +#define KFDATA 0xB000 // the keyframer section +#define KFHDR 0xB00A +#define OBJECT_NODE_TAG 0xB002 +#define NODE_HDR 0xB010 +#define PIVOT 0xB013 +#define POS_TRACK_TAG 0xB020 +#define ROT_TRACK_TAG 0xB021 +#define SCL_TRACK_TAG 0xB022 + +// material entries +#define MAT_ENTRY 0xAFFF +#define MAT_NAME 0xA000 +#define MAT_AMBIENT 0xA010 +#define MAT_DIFFUSE 0xA020 +#define MAT_SPECULAR 0xA030 +#define MAT_SHININESS 0xA040 +#define MAT_SHIN2PCT 0xA041 +#define MAT_TRANSPARENCY 0xA050 +#define MAT_SHADING 0xA100 +#define MAT_TWO_SIDE 0xA081 +#define MAT_ADDITIVE 0xA083 +#define MAT_WIRE 0xA085 +#define MAT_FACEMAP 0xA088 +#define MAT_WIRESIZE 0xA087 +#define MAT_DECAL 0xA082 +#define MAT_TEXMAP 0xA200 +#define MAT_MAPNAME 0xA300 +#define MAT_MAP_TILING 0xA351 +#define MAT_MAP_USCALE 0xA354 +#define MAT_MAP_VSCALE 0xA356 +#define MAT_MAP_UOFFSET 0xA358 +#define MAT_MAP_VOFFSET 0xA35A +#define MAT_MAP_ANG 0xA35C +#define MAT_TEX2MAP 0xA33A +#define MAT_OPACMAP 0xA210 +#define MAT_BUMPMAP 0xA230 +#define MAT_SPECMAP 0xA204 +#define MAT_SHINMAP 0xA33C +#define MAT_REFLMAP 0xA220 +#define MAT_ACUBIC 0xA310 + +#define EDIT_OBJECT 0x4000 +#define OBJ_TRIMESH 0x4100 +#define OBJ_LIGHT 0x4600 +#define OBJ_CAMERA 0x4700 +#define LIT_OFF 0x4620 +#define LIT_SPOT 0x4610 +#define TRI_VERTEXLIST 0x4110 +#define TRI_VERTEXOPTIONS 0x4111 + +#define TRI_FACELIST 0x4120 + #define TRI_MAT_GROUP 0x4130 + #define TRI_SMOOTH_GROUP 0x4150 + +#define TRI_FACEMAPPING 0x4140 +#define TRI_MATRIX 0x4160 + +#define SPOTLIGHT 0x4610 + +//---------------------------------- + +#define MAX_SHARED_TRIS 100 + +// the error reporting routine + +void ErrorMsg(const char *msg) +{ + +} + +struct LChunk +{ + unsigned short id; + uint start; + uint end; +}; + +struct LTri +{ + unsigned short a; + unsigned short b; + unsigned short c; + ulong smoothingGroups; + LVector3 normal; + LVector3 tangent; + LVector3 binormal; + uint materialId; +}; + +// globals + +LColor3 black = {0, 0, 0}; + +LVector3 zero3 = {0, 0, 0}; + +LVector4 zero4 = {0, 0, 0, 0}; + +LMap emptyMap = {0, "", 1, 1, 0, 0, 0}; + +LVector3 _4to3(const LVector4 &vec) +{ + LVector3 t; + t.x = vec.x; + t.y = vec.y; + t.z = vec.z; + return t; +} + +LVector3 AddVectors(const LVector3 &a, const LVector3 &b) +{ + LVector3 t; + t.x = a.x+b.x; + t.y = a.y+b.y; + t.z = a.z+b.z; + return t; +} + +LVector3 SubtractVectors(const LVector3 &a, const LVector3 &b) +{ + LVector3 t; + t.x = a.x-b.x; + t.y = a.y-b.y; + t.z = a.z-b.z; + return t; +} + +float VectorLength(const LVector3 &vec) +{ + return (float)sqrt(vec.x*vec.x + vec.y*vec.y+vec.z*vec.z); +} + +LVector3 NormalizeVector(const LVector3 &vec) +{ + float a = VectorLength(vec); + if (a == 0) + return vec; + float b = 1/a; + LVector3 v; + v.x = vec.x*b; + v.y = vec.y*b; + v.z = vec.z*b; + return v; +} + +LVector3 CrossProduct(const LVector3 &a, const LVector3 &b) +{ + LVector3 v; + v.x = a.y*b.z - a.z*b.y; + v.y = a.z*b.x - a.x*b.z; + v.z = a.x*b.y - a.y*b.x; + return v; +} + +void LoadIdentityMatrix(LMatrix4 &m) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + m.m[i][j] = (i==j) ? 1.0f : 0.0f; +} + +LVector4 VectorByMatrix(const LMatrix4 &m, const LVector4 &vec) +{ + LVector4 res; + + res.x = m.m[0][0]*vec.x + m.m[1][0]*vec.y + m.m[2][0]*vec.z + m.m[3][0]*vec.w; + res.y = m.m[0][1]*vec.x + m.m[1][1]*vec.y + m.m[2][1]*vec.z + m.m[3][1]*vec.w; + res.z = m.m[0][2]*vec.x + m.m[1][2]*vec.y + m.m[2][2]*vec.z + m.m[3][2]*vec.w; + res.w = m.m[0][3]*vec.x + m.m[1][3]*vec.y + m.m[2][3]*vec.z + m.m[3][3]*vec.w; + + if (res.w != 0) { + float b = 1/res.w; + res.x *= b; + res.y *= b; + res.z *= b; + res.w = 1; + } + else { + res.w = 1; + } + + return res; +} + +void QuatToMatrix(const LVector4 &quat, LMatrix4 &m) +{ + +} + +//------------------------------------------------------- +// LObject implementation +//------------------------------------------------------- + +LObject::LObject() +{ + m_name = "";//.clear(); +} + +LObject::~LObject() +{ + // nothing here +} + +void LObject::SetName(const std::string& value) +{ + m_name = value; +} + +const std::string& LObject::GetName() +{ + return m_name; +} + +bool LObject::IsObject(const std::string &name) +{ + return (m_name == name); +} + + +//------------------------------------------------------- +// LMaterial implementation +//------------------------------------------------------- + +LMaterial::LMaterial() +: LObject() +{ + m_id = 0; + m_texMap1 = emptyMap; + m_texMap2 = emptyMap; + m_opacMap = emptyMap; + m_bumpMap = emptyMap; + m_reflMap = emptyMap; + m_specMap = emptyMap; + m_ambient = black; + m_diffuse = black; + m_specular = black; + m_shading = sGouraud; + m_shininess = 0; + m_transparency = 0; +} + +LMaterial::~LMaterial() +{ + +} + +uint LMaterial::GetID() +{ + return m_id; +} + +LMap& LMaterial::GetTextureMap1() +{ + return m_texMap1; +} + +LMap& LMaterial::GetTextureMap2() +{ + return m_texMap2; +} + +LMap& LMaterial::GetOpacityMap() +{ + return m_opacMap; +} + +LMap& LMaterial::GetSpecularMap() +{ + return m_specMap; +} + +LMap& LMaterial::GetBumpMap() +{ + return m_bumpMap; +} + +LMap& LMaterial::GetReflectionMap() +{ + return m_reflMap; +} + +LColor3 LMaterial::GetAmbientColor() +{ + return m_ambient; +} + +LColor3 LMaterial::GetDiffuseColor() +{ + return m_diffuse; +} + +LColor3 LMaterial::GetSpecularColor() +{ + return m_specular; +} + +float LMaterial::GetShininess() +{ + return m_shininess; +} + +float LMaterial::GetTransparency() +{ + return m_transparency; +} + +LShading LMaterial::GetShadingType() +{ + return m_shading; +} + +void LMaterial::SetID(uint value) +{ + m_id = value; +} + +void LMaterial::SetAmbientColor(const LColor3 &color) +{ + m_ambient = color; +} + +void LMaterial::SetDiffuseColor(const LColor3 &color) +{ + m_diffuse = color; +} + +void LMaterial::SetSpecularColor(const LColor3 &color) +{ + m_specular = color; +} + +void LMaterial::SetShininess(float value) +{ + m_shininess = value; + if (m_shininess < 0) + m_shininess = 0; + if (m_shininess > 1) + m_shininess = 1; +} + +void LMaterial::SetTransparency(float value) +{ + m_transparency = value; + if (m_transparency < 0) + m_transparency = 0; + if (m_transparency > 1) + m_transparency = 1; +} + +void LMaterial::SetShadingType(LShading shading) +{ + m_shading = shading; +} + +//------------------------------------------------------- +// LMesh implementation +//------------------------------------------------------- + +LMesh::LMesh() +: LObject() +{ + Clear(); +} + +LMesh::~LMesh() +{ + Clear(); +} + +void LMesh::Clear() +{ + m_vertices.clear(); + m_normals.clear(); + m_uv.clear(); + m_tangents.clear(); + m_binormals.clear(); + m_triangles.clear(); + m_tris.clear(); + m_materials.clear(); + LoadIdentityMatrix(m_matrix); +} + +uint LMesh::GetVertexCount() +{ + return m_vertices.size(); +} + +void LMesh::SetVertexArraySize(uint value) +{ + m_vertices.resize(value); + m_normals.resize(value); + m_uv.resize(value); + m_tangents.resize(value); + m_binormals.resize(value); +} + +uint LMesh::GetTriangleCount() +{ + return m_triangles.size(); +} + +void LMesh::SetTriangleArraySize(uint value) +{ + m_triangles.resize(value); + m_tris.resize(value); +} + +const LVector4& LMesh::GetVertex(uint index) +{ + return m_vertices[index]; +} + +const LVector3& LMesh::GetNormal(uint index) +{ + return m_normals[index]; +} + +const LVector2& LMesh::GetUV(uint index) +{ + return m_uv[index]; +} + +const LVector3& LMesh::GetTangent(uint index) +{ + return m_tangents[index]; +} + +const LVector3& LMesh::GetBinormal(uint index) +{ + return m_binormals[index]; +} + +void LMesh::SetVertex(const LVector4 &vec, uint index) +{ + if (index >= m_vertices.size()) + return; + m_vertices[index] = vec; +} + +void LMesh::SetNormal(const LVector3 &vec, uint index) +{ + if (index >= m_vertices.size()) + return; + m_normals[index] = vec; +} + +void LMesh::SetUV(const LVector2 &vec, uint index) +{ + if (index >= m_vertices.size()) + return; + m_uv[index] = vec; +} + +void LMesh::SetTangent(const LVector3 &vec, uint index) +{ + if (index >= m_vertices.size()) + return; + m_tangents[index] = vec; +} + +void LMesh::SetBinormal(const LVector3 &vec, uint index) +{ + if (index >= m_vertices.size()) + return; + m_binormals[index] = vec; +} + +const LTriangle& LMesh::GetTriangle(uint index) +{ + return m_triangles[index]; +} + +LTriangle2 LMesh::GetTriangle2(uint index) +{ + LTriangle2 f; + LTriangle t = GetTriangle(index); + f.vertices[0] = GetVertex(t.a); + f.vertices[1] = GetVertex(t.b); + f.vertices[2] = GetVertex(t.c); + + f.vertexNormals[0] = GetNormal(t.a); + f.vertexNormals[1] = GetNormal(t.b); + f.vertexNormals[2] = GetNormal(t.c); + + f.textureCoords[0] = GetUV(t.a); + f.textureCoords[1] = GetUV(t.b); + f.textureCoords[2] = GetUV(t.c); + + LVector3 a, b; + + a = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[0])); + b = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[2])); + + f.faceNormal = CrossProduct(b, a); + + f.faceNormal = NormalizeVector(f.faceNormal); + + f.materialId = m_tris[index].materialId; + + return f; +} + +LMatrix4 LMesh::GetMatrix() +{ + return m_matrix; +} + +void LMesh::SetMatrix(LMatrix4 m) +{ + m_matrix = m; +} + +void LMesh::TransformVertices() +{ + for (uint i=0; i > array; + array.resize(m_vertices.size()); + for (i=0; i smGroups; + std::vector< std::vector > smList; + + uint loop_size = m_vertices.size(); + + for (i=0; i 1) + for (uint j=1; j< smGroups.size(); j++) + { + m_vertices.push_back(m_vertices[i]); + m_normals.push_back(m_normals[i]); + m_uv.push_back(m_uv[i]); + m_tangents.push_back(m_tangents[i]); + m_binormals.push_back(m_binormals[i]); + + uint t = m_vertices.size()-1; + for (uint h=0; h > array; + array.resize(m_vertices.size()); + for (int i=0; i<(int)m_triangles.size(); i++) + { + uint k = m_tris[i].a; + array[k].push_back(i); + + k = m_tris[i].b; + array[k].push_back(i); + + k = m_tris[i].c; + array[k].push_back(i); + } + + // now average the tangents and compute the binormals as (tangent X normal) + for (int i=0; i<(int)m_vertices.size(); i++) + { + v1 = zero3; + v2 = zero3; + int t = array[i].size(); + + for (int k=0; k= m_triangles.size()) + return; + m_tris[index] = tri; +} + +LTri& LMesh::GetTri(uint index) +{ + return m_tris[index]; +} + +uint LMesh::GetMaterial(uint index) +{ + return m_materials[index]; +} + +uint LMesh::AddMaterial(uint id) +{ + m_materials.push_back(id); + return m_materials.size()-1; +} + +uint LMesh::GetMaterialCount() +{ + return m_materials.size(); +} + +//------------------------------------------------------- +// LLight implementation +//------------------------------------------------------- + +LLight::LLight() +: LObject() +{ + Clear(); +} + +LLight::~LLight() +{ + +} + +void LLight::Clear() +{ + m_pos.x = m_pos.y = m_pos.z = 0.0f; + m_color.r = m_color.g = m_color.b = 0.0f; + m_spotlight = false; +} + +void LLight::SetPosition(LVector3 vec) +{ + m_pos = vec; +} + +LVector3 LLight::GetPosition() +{ + return m_pos; +} + +void LLight::SetColor(LColor3 color) +{ + m_color = color; +} + +LColor3 LLight::GetColor() +{ + return m_color; +} + +void LLight::SetSpotlight(bool value) +{ + m_spotlight = value; +} + +bool LLight::GetSpotlight() +{ + return m_spotlight; +} + +void LLight::SetTarget(LVector3 target) +{ + m_target = target; +} + +LVector3 LLight::GetTarget() +{ + return m_target; +} + +void LLight::SetHotspot(float value) +{ + m_hotspot = value; +} + +float LLight::GetHotspot() +{ + return m_hotspot; +} + +void LLight::SetFalloff(float value) +{ + m_falloff = value; +} + +float LLight::GetFalloff() +{ + return m_falloff; +} + +//------------------------------------------------------- +// LImporter implementation +//------------------------------------------------------- + +LImporter::LImporter() +{ + Clear(); +} + +LImporter::~LImporter() +{ + Clear(); +} + +uint LImporter::GetMeshCount() +{ + return m_meshes.size(); +} + +uint LImporter::GetLightCount() +{ + return m_lights.size(); +} + +uint LImporter::GetMaterialCount() +{ + return m_materials.size(); +} + +LMesh& LImporter::GetMesh(uint index) +{ + return m_meshes[index]; +} + +LLight& LImporter::GetLight(uint index) +{ + return m_lights[index]; +} + +LMaterial& LImporter::GetMaterial(uint index) +{ + return m_materials[index]; +} + +LMaterial* LImporter::FindMaterial(const std::string& name) +{ + for (uint i=0; i 0) + free(m_buffer); +} + +bool L3DS::LoadFile(const char *filename) +{ + FILE *f; + f = fopen(filename, "rb"); + if (f == 0) + { + ErrorMsg("L3DS::LoadFile - cannot open file"); + return false; + } + fseek(f, 0, SEEK_END); + m_bufferSize = ftell(f); + fseek(f, 0, SEEK_SET); + m_buffer = (unsigned char*) calloc(m_bufferSize, 1); + if (m_buffer == 0) + { + ErrorMsg("L3DS::LoadFile - not enough memory (malloc failed)"); + return false; + } + if (fread(m_buffer, m_bufferSize, 1, f) != 1) + { + fclose(f); + free(m_buffer); + m_bufferSize = 0; + ErrorMsg("L3DS::LoadFile - error reading from file"); + return false; + } + fclose(f); + Clear(); + bool res = Read3DS(); + free(m_buffer); + m_buffer = 0; + m_bufferSize = 0; + return res; +} + +short L3DS::ReadShort() +{ + if ((m_buffer!=0) && (m_bufferSize != 0) && ((m_pos+2)=m_bufferSize)) + { + count = 0; + m_eof = true; + return count; + } + count = 0; + char c = ReadChar(); + while ((c!=0) && (count= m_bufferSize) + m_pos = m_bufferSize-1; + m_eof = false; +} + +uint L3DS::Pos() +{ + return m_pos; +} + +LChunk L3DS::ReadChunk() +{ + LChunk chunk; + chunk.id = ReadShort(); + int a = ReadInt(); + chunk.start = Pos(); + chunk.end = chunk.start+a-6; + return chunk; +} + +bool L3DS::FindChunk(LChunk &target, const LChunk &parent) +{ + if (Pos() >= parent.end) + return false; + LChunk chunk; + chunk = ReadChunk(); + while (( chunk.id != target.id) && (chunk.end <= parent.end)) + { + SkipChunk(chunk); + if (chunk.end >= parent.end) + break; + chunk = ReadChunk(); + } + if (chunk.id == target.id) + { + target.start = chunk.start; + target.end = chunk.end; + return true; + } + return false; +} + +void L3DS::SkipChunk(const LChunk &chunk) +{ + Seek(chunk.end, SEEK_START); +} + +void L3DS::GotoChunk(const LChunk &chunk) +{ + Seek(chunk.start, SEEK_START); +} + +LColor3 L3DS::ReadColor(const LChunk &chunk) +{ + LColor3 col = black; + GotoChunk(chunk); + switch (chunk.id) + { + case COLOR_F: + col.r = ReadFloat(); + col.g = ReadFloat(); + col.b = ReadFloat(); + break; + case COLOR_24: + col.r = ReadByte()/255.0f; + col.g = ReadByte()/255.0f; + col.b = ReadByte()/255.0f; + break; + case LIN_COLOR_F: + col.r = ReadFloat(); + col.g = ReadFloat(); + col.b = ReadFloat(); + break; + case LIN_COLOR_24: + col.r = ReadByte()/255.0f; + col.g = ReadByte()/255.0f; + col.b = ReadByte()/255.0f; + break; + default: + ErrorMsg("L3DS::ReadColor - error this is not a color chunk"); + } + return col; +} + +float L3DS::ReadPercentage(const LChunk &chunk) +{ + GotoChunk(chunk); + switch (chunk.id) + { + case INT_PERCENTAGE: + return (ReadShort()/100.0f); + case FLOAT_PERCENTAGE: + return ReadFloat(); + } + ErrorMsg("L3DS::ReadPercentage - error, the chunk is not a percentage chunk"); + return 0; +} + +bool L3DS::Read3DS() +{ + LChunk mainchunk; + LChunk edit; + edit.id = EDIT3DS; + mainchunk = ReadChunk(); + if (mainchunk.id != MAIN3DS) + { + ErrorMsg("L3DS::Read3DS - wrong file format"); + return false; + } + if (!FindChunk(edit, mainchunk)) + return false; + LChunk obj; + LChunk ml; + + GotoChunk(edit); + obj.id = MAT_ENTRY; + while (FindChunk(obj, edit)) + { + ReadMaterial(obj); + SkipChunk(obj); + } + GotoChunk(edit); + + obj.id = EDIT_OBJECT; + { + while (FindChunk(obj, edit)) + { + ReadASCIIZ(m_objName, 99); + ml = ReadChunk(); + if (ml.id == OBJ_TRIMESH) + ReadMesh(ml); + if (ml.id == OBJ_LIGHT) + ReadLight(ml); + SkipChunk(obj); + } + } + + // read the keyframer data here to find out correct object orientation + + LChunk keyframer; + keyframer.id = KFDATA; + + LChunk objtrack; + objtrack.id = OBJECT_NODE_TAG; + + GotoChunk(mainchunk); + if (FindChunk(keyframer, mainchunk)) + { // keyframer chunk is present + GotoChunk(keyframer); + while (FindChunk(objtrack, keyframer)) + { + ReadKeyframeData(objtrack); + SkipChunk(objtrack); + } + } + + for (uint i=0; i= parent.end) + break; + chunk = ReadChunk(); + + } + } + m_lights.push_back(light); +} + +void L3DS::ReadMesh(const LChunk &parent) +{ + unsigned short count, i; + LVector4 p; + LMatrix4 m; + LVector2 t; + p.w = 1.0f; + LMesh mesh; + mesh.SetName(m_objName); + GotoChunk(parent); + LChunk chunk = ReadChunk(); + while (chunk.end <= parent.end) + { + switch (chunk.id) + { + case TRI_VERTEXLIST: + count = ReadShort(); + mesh.SetVertexArraySize(count); + for (i=0; i < count; i++) + { + p.x = ReadFloat(); + p.y = ReadFloat(); + p.z = ReadFloat(); + mesh.SetVertex(p, i); + } + break; + case TRI_FACEMAPPING: + count = ReadShort(); + if (mesh.GetVertexCount() == 0) + mesh.SetVertexArraySize(count); + for (i=0; i < count; i++) + { + t.x = ReadFloat(); + t.y = ReadFloat(); + mesh.SetUV(t, i); + } + break; + case TRI_FACELIST: + ReadFaceList(chunk, mesh); + break; + case TRI_MATRIX: + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 3; j++) + m.m[i][j] = ReadFloat(); + + m.m[0][3] = 0.0f; + m.m[1][3] = 0.0f; + m.m[2][3] = 0.0f; + m.m[3][3] = 1.0f; + + mesh.SetMatrix(m); + } + break; + default: + break; + } + SkipChunk(chunk); + if (chunk.end >= parent.end) + break; + chunk = ReadChunk(); + } + m_meshes.push_back(mesh); +} + +void L3DS::ReadFaceList(const LChunk &chunk, LMesh &mesh) +{ + // variables + unsigned short count, t; + uint i; + LTri tri; + LChunk ch; + char str[20]; + //uint mat; + + // consistency checks + if (chunk.id != TRI_FACELIST) + { + ErrorMsg("L3DS::ReadFaceList - internal error: wrong chunk passed as parameter"); + return; + } + GotoChunk(chunk); + tri.smoothingGroups = 1; + // read the number of faces + count = ReadShort(); + mesh.SetTriangleArraySize(count); + for (i=0; iGetID(); + mesh.AddMaterial(mat_id); + count = ReadShort(); + for (i=0; i 0) + { + ReadKeyheader(); + pos.x = ReadFloat(); + pos.y = ReadFloat(); + pos.z = ReadFloat(); + } + } + GotoChunk(parent); + + // now read the rotation track + LVector4 rot = zero4; + + LChunk rotchunk; + rotchunk.id = ROT_TRACK_TAG; + + frames = 0; + if (FindChunk(rotchunk, parent)) + { + GotoChunk(rotchunk); + // read the trackheader structure + ReadShort(); + ReadInt(); + ReadInt(); + frames = ReadInt(); + if (frames > 0) + { + ReadKeyheader(); + rot.x = ReadFloat(); + rot.y = ReadFloat(); + rot.z = ReadFloat(); + rot.w = ReadFloat(); + } + } + GotoChunk(parent); + + // now read the scaling chunk + LVector3 scale; + scale.x = 1; + scale.y = 1; + scale.z = 1; + + LChunk scalechunk; + scalechunk.id = SCL_TRACK_TAG; + + frames = 0; + + if (FindChunk(scalechunk, parent)) + { + GotoChunk(scalechunk); + // read the trackheader structure + ReadShort(); + ReadInt(); + ReadInt(); + frames = ReadInt(); + if (frames > 0) + { + ReadKeyheader(); + scale.x = ReadFloat(); + scale.y = ReadFloat(); + scale.z = ReadFloat(); + } + } + GotoChunk(parent); + + +} + +long L3DS::ReadKeyheader() +{ + long frame; + frame = ReadInt(); + short opts = ReadShort(); + if (opts & 32768) // 32768 is 1000000000000000 binary + { // tension is present + ReadFloat(); + } + if (opts & 16384) // 16384 is 0100000000000000 binary + { // continuity is present + ReadFloat(); + } + if (opts & 8192) + { // bias info present + ReadFloat(); + } + if (opts & 4096) + { // "ease to" present + ReadFloat(); + } + if (opts & 2048) + { // "ease from" present + ReadFloat(); + } + return frame; } \ No newline at end of file diff --git a/Magic2/l3ds.h b/Magic2/l3ds.h index b38e1e8..16204b5 100644 --- a/Magic2/l3ds.h +++ b/Magic2/l3ds.h @@ -1,457 +1,457 @@ -// copyright (c) 2001-2002 Lev Povalahev -// this is a 3ds importer version 2 - -#ifndef L3DS_H -#define L3DS_H - -// includes -#include -#include - -//--------------------------------------------------------- - -typedef unsigned int uint; -typedef unsigned char byte; - -enum LShading {sWireframe, sFlat, sGouraud, sPhong, sMetal}; - -enum LOptimizationLevel {oNone, oSimple, oFull}; - -// for internal use -struct LChunk; -struct LTri; - -//------------------------------------------------ - -struct LVector4 -{ - float x; - float y; - float z; - float w; - - int operator==(const LVector4& v) const { return x==v.x && y==v.y && z==v.z && w==v.w; } -}; - -struct LVector3 -{ - float x; - float y; - float z; - - int operator==(const LVector3& v) const { return x==v.x && y==v.y && z==v.z; } -}; - -struct LVector2 -{ - float x; - float y; - - int operator==(const LVector2& v) const { return x==v.x && y==v.y; } -}; - -struct LColor3 -{ - float r; - float g; - float b; - - int operator==(const LColor3& v) const { return r==v.r && g==v.g && b==v.b; } -}; - -//------------------------------------------------ - -struct LTriangle -{ - unsigned short a; - unsigned short b; - unsigned short c; -}; - -struct LMatrix4 -{ - float m[4][4]; -}; - -struct LTriangle2 -{ - LVector4 vertices[3]; - LVector3 vertexNormals[3]; - LVector2 textureCoords[3]; - LVector3 faceNormal; - uint materialId; -}; - -// a structure for a texture map -struct LMap -{ - // the strength of the texture map - float strength; - // the file name of the map. only 8.3 format in 3ds files :( - char mapName[255]; - float uScale; - float vScale; - float uOffset; - float vOffset; - float angle; -}; - -//------------------------------------------------ - -class LObject -{ -public: - // the default constructor, initilializes the m_name here - LObject(); - // the destructor frees memory (m_name) - virtual ~LObject(); - // call this to get the name of the object - virtual const std::string& GetName(); - - // this methods should not be used by the "user", they're used internally to fill the class - // with valid data when reading from file. If you're about to add an importer for another format you'LL - // have to use these methods - // call this to set the name of the object - virtual void SetName(const std::string& value); - // returns true if the object's name is the name passed as parameter - bool IsObject(const std::string &name); -protected: - // the name of the object - std::string m_name; -}; - -//------------------------------------------------ - -class LMaterial : public LObject -{ -public: - // the default constructor, does the initialization - LMaterial(); - // the destructor - virtual ~LMaterial(); - // returns the material ID - uint GetID(); - // returns the pointer to teh texture map 1 - LMap& GetTextureMap1(); - // returns the pointer to the texture map 2 - LMap& GetTextureMap2(); - // returns the pointer to teh opacity map - LMap& GetOpacityMap(); - // returns the pointer to the specular (gloss) map - LMap& GetSpecularMap(); - // returns the pointer to the bump map - LMap& GetBumpMap(); - // returns the pointer to the reflection map - LMap& GetReflectionMap(); - // returns the ambient color of the material - LColor3 GetAmbientColor(); - // returns the diffuse color of the material - LColor3 GetDiffuseColor(); - // returns the specular color of the material - LColor3 GetSpecularColor(); - // returns the shininess of the material, ranging from 0(matte) to 1(shiny) - float GetShininess(); - // returns the transparency of the material, ranging from 1(fully transparent) to 0(opaque) - float GetTransparency(); - // returns the type of shading, see LShading type - LShading GetShadingType(); - - // this methods should not be used by the "user", they're used internally to fill the class - // with valid data when reading from file. If you're about to add an importer for another format you'LL - // have to use these methods - // sets the material ID to "value" - void SetID(uint value); - // call this to set the ambient color of the material - void SetAmbientColor(const LColor3 &color); - // sets the diffuse color of the material - void SetDiffuseColor(const LColor3 &color); - // sets the specular color of the material - void SetSpecularColor(const LColor3 &color); - // sets the shininess of the material - void SetShininess(float value); - // sets the transparency of the material - void SetTransparency(float value); - // sets the shading type - void SetShadingType(LShading shading); -protected: - // the unique material ID - int m_id; - // the first texture map - LMap m_texMap1; - // the second texture map - LMap m_texMap2; - // the opacity map - LMap m_opacMap; - // the reflection map - LMap m_reflMap; - // the bump map - LMap m_bumpMap; - // specular map - LMap m_specMap; - // material ambient color - LColor3 m_ambient; - // material diffuse color - LColor3 m_diffuse; - // material specular color - LColor3 m_specular; - // shininess - float m_shininess; - // transparency - float m_transparency; - // the shading type for the material - LShading m_shading; -}; - -//------------------------------------------------ - -class LMesh : public LObject -{ -public: - // the default constructor - LMesh(); - // the destructor - virtual ~LMesh(); - // clears the mesh, deleteing all data - void Clear(); - // returns the number of vertices in the mesh - uint GetVertexCount(); - // sets the the size fo the vertex array - for internal use - void SetVertexArraySize(uint value); - // returns the number of triangles in the mesh - uint GetTriangleCount(); - // sets the size of the triangle array - for internal use - void SetTriangleArraySize(uint value); - // returns given vertex - const LVector4& GetVertex(uint index); - // returns the given normal - const LVector3& GetNormal(uint index); - // returns the given texture coordinates vector - const LVector2& GetUV(uint index); - // returns the pointer to the array of tangents - const LVector3& GetTangent(uint index); - // returns the pointer to the array of binormals - const LVector3& GetBinormal(uint index); - // sets the vertex at a given index to "vec" - for internal use - void SetVertex(const LVector4 &vec, uint index); - // sets the normal at a given index to "vec" - for internal use - void SetNormal(const LVector3 &vec, uint index); - // sets the texture coordinates vector at a given index to "vec" - for internal use - void SetUV(const LVector2 &vec, uint index); - // sets the tangent at a given index to "vec" - for internal use - void SetTangent(const LVector3 &vec, uint index); - // sets the binormal at a given index to "vec" - for internal use - void SetBinormal(const LVector3 &vec, uint index); - // returns the triangle with a given index - const LTriangle& GetTriangle(uint index); - // returns the triangle with a given index, see LTriangle2 structure description - LTriangle2 GetTriangle2(uint index); - // returns the mesh matrix, should be identity matrix after loading - LMatrix4 GetMatrix(); - // sets the mesh matrix to a given matrix - for internal use - void SetMatrix(LMatrix4 m); - // optimizises the mesh using a given optimization level - void Optimize(LOptimizationLevel value); - // sets an internal triangle structure with index "index" - for internal use only - void SetTri(const LTri &tri, uint index); - // returns the pointer to the internal triangle structure - for internal use only - LTri& GetTri(uint index); - // returns the material id with a given index for the mesh - uint GetMaterial(uint index); - // adds a material to the mesh and returns its index - for internal use - uint AddMaterial(uint id); - // returns the number of materials used in the mesh - uint GetMaterialCount(); -protected: - // the vertices, normals, etc. - std::vector m_vertices; - std::vector m_normals; - std::vector m_binormals; - std::vector m_tangents; - std::vector m_uv; - - // triangles - std::vector m_triangles; - - //used internally - std::vector m_tris; - - // the transformation matrix. - LMatrix4 m_matrix; - - // the material ID array - std::vector m_materials; - - // calculates the normals, either using the smoothing groups information or not - void CalcNormals(bool useSmoothingGroups); - // calculates the texture(tangent) space for each vertex - void CalcTextureSpace(); - // transforms the vertices by the mesh matrix - void TransformVertices(); -}; - -//------------------------------------------------ - -class LLight : public LObject -{ -public: - // the default constructor - LLight(); - // the destructor - virtual ~LLight(); - // clears the data the class holds - void Clear(); - // sets the position of the light source - for internal use - void SetPosition(LVector3 vec); - // returns the position of the light source - LVector3 GetPosition(); - // sets the color of the light - for internal use - void SetColor(LColor3 color); - // returns the color of the light - LColor3 GetColor(); - // sets whether the light is a spotlight or not - internal use - void SetSpotlight(bool value); - // returns true if the light is a spotlight - bool GetSpotlight(); - // sets the target of the light - internal use - void SetTarget(LVector3 target); - // returns the target of the spotlight - LVector3 GetTarget(); - // sets the hotspot - internal use - void SetHotspot(float value); - // returns the hotspot - float GetHotspot(); - // sets falloff - internal use - void SetFalloff(float value); - // returns falloff - float GetFalloff(); -protected: - LVector3 m_pos; - LColor3 m_color; - bool m_spotlight; - LVector3 m_target; - float m_hotspot; - float m_falloff; -}; - -//------------------------------------------------ - -class LImporter -{ -public: - // the default constructor - LImporter(); - // the destructor - virtual ~LImporter(); - // reads the model from a file, must be overriden by the child classes - virtual bool LoadFile(const char *filename) = 0; - // returns the number of meshes in the scene - uint GetMeshCount(); - // returns the number of lights in the scene - uint GetLightCount(); - // returns the number of materials in the scene - uint GetMaterialCount(); - // returns a pointer to a mesh - LMesh& GetMesh(uint index); - // returns a pointer to a light at a given index - LLight& GetLight(uint index); - // returns the pointer to the material - LMaterial& GetMaterial(uint index); - // returns the pointer to the material with a given name, or NULL if the material was not found - LMaterial* FindMaterial(const std::string &name); - // returns the pointer to the mesh with a given name, or NULL if the mesh with such name - // is not present in the scene - LMesh* FindMesh(const std::string &name); - // returns the pointer to the light with a given name, or NULL if not found - LLight* FindLight(const std::string &name); - // sets the optimization level to a given value - void SetOptimizationLevel(LOptimizationLevel value); - // returns the current optimization level - LOptimizationLevel GetOptimizationLevel(); -protected: - // the lights found in the scene - std::vector m_lights; - // triangular meshes - std::vector m_meshes; - // the materials in the scene - std::vector m_materials; - // level of optimization to perform on the meshes - LOptimizationLevel m_optLevel; - // clears all data. - virtual void Clear(); -}; -//------------------------------------------------ - -class L3DS : public LImporter -{ -public: - // the default contructor - L3DS(); - // constructs the object and loads the file - L3DS(const char *filename); - // destructor - virtual ~L3DS(); - // load 3ds file - virtual bool LoadFile(const char *filename); -protected: - // used internally for reading - char m_objName[100]; - // true if end of file is reached - bool m_eof; - // buffer for loading, used for speedup - unsigned char *m_buffer; - // the size of the buffer - uint m_bufferSize; - // the current cursor position in the buffer - uint m_pos; - - // reads a short value from the buffer - short ReadShort(); - // reads an int value from the buffer - int ReadInt(); - // reads a char from the buffer - char ReadChar(); - //reada a floatvalue from the buffer - float ReadFloat(); - //reads an unsigned byte from the buffer - byte ReadByte(); - //reads an asciiz string - int ReadASCIIZ(char *buf, int max_count); - // seek wihtin the buffer - void Seek(int offset, int origin); - // returns the position of the cursor - uint Pos(); - - // read the chunk and return it. - LChunk ReadChunk(); - // read until given chunk is found - bool FindChunk(LChunk &target, const LChunk &parent); - // skip to the end of chunk "chunk" - void SkipChunk(const LChunk &chunk); - // goes to the beginning of the data in teh given chunk - void GotoChunk(const LChunk &chunk); - - // the function read the color chunk (any of the color chunks) - LColor3 ReadColor(const LChunk &chunk); - // the function that read the percentage chunk and returns a float from 0 to 1 - float ReadPercentage(const LChunk &chunk); - // this is where 3ds file is being read - bool Read3DS(); - // read a light chunk - void ReadLight(const LChunk &parent); - // read a trimesh chunk - void ReadMesh(const LChunk &parent); - // reads the face list, face materials, smoothing groups... and fill rthe information into the mesh - void ReadFaceList(const LChunk &chunk, LMesh &mesh); - // reads the material - void ReadMaterial(const LChunk &parent); - // reads the map info and fills the given map with this information - void ReadMap(const LChunk &chunk, LMap& map); - // reads keyframer data of the OBJECT_NODE_TAG chunk - void ReadKeyframeData(const LChunk &parent); - // reads the keyheader structure from the current offset and returns the frame number - long ReadKeyheader(); -}; - -//--------------------------------------------------------- - +// copyright (c) 2001-2002 Lev Povalahev +// this is a 3ds importer version 2 + +#ifndef L3DS_H +#define L3DS_H + +// includes +#include +#include + +//--------------------------------------------------------- + +typedef unsigned int uint; +typedef unsigned char byte; + +enum LShading {sWireframe, sFlat, sGouraud, sPhong, sMetal}; + +enum LOptimizationLevel {oNone, oSimple, oFull}; + +// for internal use +struct LChunk; +struct LTri; + +//------------------------------------------------ + +struct LVector4 +{ + float x; + float y; + float z; + float w; + + int operator==(const LVector4& v) const { return x==v.x && y==v.y && z==v.z && w==v.w; } +}; + +struct LVector3 +{ + float x; + float y; + float z; + + int operator==(const LVector3& v) const { return x==v.x && y==v.y && z==v.z; } +}; + +struct LVector2 +{ + float x; + float y; + + int operator==(const LVector2& v) const { return x==v.x && y==v.y; } +}; + +struct LColor3 +{ + float r; + float g; + float b; + + int operator==(const LColor3& v) const { return r==v.r && g==v.g && b==v.b; } +}; + +//------------------------------------------------ + +struct LTriangle +{ + unsigned short a; + unsigned short b; + unsigned short c; +}; + +struct LMatrix4 +{ + float m[4][4]; +}; + +struct LTriangle2 +{ + LVector4 vertices[3]; + LVector3 vertexNormals[3]; + LVector2 textureCoords[3]; + LVector3 faceNormal; + uint materialId; +}; + +// a structure for a texture map +struct LMap +{ + // the strength of the texture map + float strength; + // the file name of the map. only 8.3 format in 3ds files :( + char mapName[255]; + float uScale; + float vScale; + float uOffset; + float vOffset; + float angle; +}; + +//------------------------------------------------ + +class LObject +{ +public: + // the default constructor, initilializes the m_name here + LObject(); + // the destructor frees memory (m_name) + virtual ~LObject(); + // call this to get the name of the object + virtual const std::string& GetName(); + + // this methods should not be used by the "user", they're used internally to fill the class + // with valid data when reading from file. If you're about to add an importer for another format you'LL + // have to use these methods + // call this to set the name of the object + virtual void SetName(const std::string& value); + // returns true if the object's name is the name passed as parameter + bool IsObject(const std::string &name); +protected: + // the name of the object + std::string m_name; +}; + +//------------------------------------------------ + +class LMaterial : public LObject +{ +public: + // the default constructor, does the initialization + LMaterial(); + // the destructor + virtual ~LMaterial(); + // returns the material ID + uint GetID(); + // returns the pointer to teh texture map 1 + LMap& GetTextureMap1(); + // returns the pointer to the texture map 2 + LMap& GetTextureMap2(); + // returns the pointer to teh opacity map + LMap& GetOpacityMap(); + // returns the pointer to the specular (gloss) map + LMap& GetSpecularMap(); + // returns the pointer to the bump map + LMap& GetBumpMap(); + // returns the pointer to the reflection map + LMap& GetReflectionMap(); + // returns the ambient color of the material + LColor3 GetAmbientColor(); + // returns the diffuse color of the material + LColor3 GetDiffuseColor(); + // returns the specular color of the material + LColor3 GetSpecularColor(); + // returns the shininess of the material, ranging from 0(matte) to 1(shiny) + float GetShininess(); + // returns the transparency of the material, ranging from 1(fully transparent) to 0(opaque) + float GetTransparency(); + // returns the type of shading, see LShading type + LShading GetShadingType(); + + // this methods should not be used by the "user", they're used internally to fill the class + // with valid data when reading from file. If you're about to add an importer for another format you'LL + // have to use these methods + // sets the material ID to "value" + void SetID(uint value); + // call this to set the ambient color of the material + void SetAmbientColor(const LColor3 &color); + // sets the diffuse color of the material + void SetDiffuseColor(const LColor3 &color); + // sets the specular color of the material + void SetSpecularColor(const LColor3 &color); + // sets the shininess of the material + void SetShininess(float value); + // sets the transparency of the material + void SetTransparency(float value); + // sets the shading type + void SetShadingType(LShading shading); +protected: + // the unique material ID + int m_id; + // the first texture map + LMap m_texMap1; + // the second texture map + LMap m_texMap2; + // the opacity map + LMap m_opacMap; + // the reflection map + LMap m_reflMap; + // the bump map + LMap m_bumpMap; + // specular map + LMap m_specMap; + // material ambient color + LColor3 m_ambient; + // material diffuse color + LColor3 m_diffuse; + // material specular color + LColor3 m_specular; + // shininess + float m_shininess; + // transparency + float m_transparency; + // the shading type for the material + LShading m_shading; +}; + +//------------------------------------------------ + +class LMesh : public LObject +{ +public: + // the default constructor + LMesh(); + // the destructor + virtual ~LMesh(); + // clears the mesh, deleteing all data + void Clear(); + // returns the number of vertices in the mesh + uint GetVertexCount(); + // sets the the size fo the vertex array - for internal use + void SetVertexArraySize(uint value); + // returns the number of triangles in the mesh + uint GetTriangleCount(); + // sets the size of the triangle array - for internal use + void SetTriangleArraySize(uint value); + // returns given vertex + const LVector4& GetVertex(uint index); + // returns the given normal + const LVector3& GetNormal(uint index); + // returns the given texture coordinates vector + const LVector2& GetUV(uint index); + // returns the pointer to the array of tangents + const LVector3& GetTangent(uint index); + // returns the pointer to the array of binormals + const LVector3& GetBinormal(uint index); + // sets the vertex at a given index to "vec" - for internal use + void SetVertex(const LVector4 &vec, uint index); + // sets the normal at a given index to "vec" - for internal use + void SetNormal(const LVector3 &vec, uint index); + // sets the texture coordinates vector at a given index to "vec" - for internal use + void SetUV(const LVector2 &vec, uint index); + // sets the tangent at a given index to "vec" - for internal use + void SetTangent(const LVector3 &vec, uint index); + // sets the binormal at a given index to "vec" - for internal use + void SetBinormal(const LVector3 &vec, uint index); + // returns the triangle with a given index + const LTriangle& GetTriangle(uint index); + // returns the triangle with a given index, see LTriangle2 structure description + LTriangle2 GetTriangle2(uint index); + // returns the mesh matrix, should be identity matrix after loading + LMatrix4 GetMatrix(); + // sets the mesh matrix to a given matrix - for internal use + void SetMatrix(LMatrix4 m); + // optimizises the mesh using a given optimization level + void Optimize(LOptimizationLevel value); + // sets an internal triangle structure with index "index" - for internal use only + void SetTri(const LTri &tri, uint index); + // returns the pointer to the internal triangle structure - for internal use only + LTri& GetTri(uint index); + // returns the material id with a given index for the mesh + uint GetMaterial(uint index); + // adds a material to the mesh and returns its index - for internal use + uint AddMaterial(uint id); + // returns the number of materials used in the mesh + uint GetMaterialCount(); +protected: + // the vertices, normals, etc. + std::vector m_vertices; + std::vector m_normals; + std::vector m_binormals; + std::vector m_tangents; + std::vector m_uv; + + // triangles + std::vector m_triangles; + + //used internally + std::vector m_tris; + + // the transformation matrix. + LMatrix4 m_matrix; + + // the material ID array + std::vector m_materials; + + // calculates the normals, either using the smoothing groups information or not + void CalcNormals(bool useSmoothingGroups); + // calculates the texture(tangent) space for each vertex + void CalcTextureSpace(); + // transforms the vertices by the mesh matrix + void TransformVertices(); +}; + +//------------------------------------------------ + +class LLight : public LObject +{ +public: + // the default constructor + LLight(); + // the destructor + virtual ~LLight(); + // clears the data the class holds + void Clear(); + // sets the position of the light source - for internal use + void SetPosition(LVector3 vec); + // returns the position of the light source + LVector3 GetPosition(); + // sets the color of the light - for internal use + void SetColor(LColor3 color); + // returns the color of the light + LColor3 GetColor(); + // sets whether the light is a spotlight or not - internal use + void SetSpotlight(bool value); + // returns true if the light is a spotlight + bool GetSpotlight(); + // sets the target of the light - internal use + void SetTarget(LVector3 target); + // returns the target of the spotlight + LVector3 GetTarget(); + // sets the hotspot - internal use + void SetHotspot(float value); + // returns the hotspot + float GetHotspot(); + // sets falloff - internal use + void SetFalloff(float value); + // returns falloff + float GetFalloff(); +protected: + LVector3 m_pos; + LColor3 m_color; + bool m_spotlight; + LVector3 m_target; + float m_hotspot; + float m_falloff; +}; + +//------------------------------------------------ + +class LImporter +{ +public: + // the default constructor + LImporter(); + // the destructor + virtual ~LImporter(); + // reads the model from a file, must be overriden by the child classes + virtual bool LoadFile(const char *filename) = 0; + // returns the number of meshes in the scene + uint GetMeshCount(); + // returns the number of lights in the scene + uint GetLightCount(); + // returns the number of materials in the scene + uint GetMaterialCount(); + // returns a pointer to a mesh + LMesh& GetMesh(uint index); + // returns a pointer to a light at a given index + LLight& GetLight(uint index); + // returns the pointer to the material + LMaterial& GetMaterial(uint index); + // returns the pointer to the material with a given name, or NULL if the material was not found + LMaterial* FindMaterial(const std::string &name); + // returns the pointer to the mesh with a given name, or NULL if the mesh with such name + // is not present in the scene + LMesh* FindMesh(const std::string &name); + // returns the pointer to the light with a given name, or NULL if not found + LLight* FindLight(const std::string &name); + // sets the optimization level to a given value + void SetOptimizationLevel(LOptimizationLevel value); + // returns the current optimization level + LOptimizationLevel GetOptimizationLevel(); +protected: + // the lights found in the scene + std::vector m_lights; + // triangular meshes + std::vector m_meshes; + // the materials in the scene + std::vector m_materials; + // level of optimization to perform on the meshes + LOptimizationLevel m_optLevel; + // clears all data. + virtual void Clear(); +}; +//------------------------------------------------ + +class L3DS : public LImporter +{ +public: + // the default contructor + L3DS(); + // constructs the object and loads the file + L3DS(const char *filename); + // destructor + virtual ~L3DS(); + // load 3ds file + virtual bool LoadFile(const char *filename); +protected: + // used internally for reading + char m_objName[100]; + // true if end of file is reached + bool m_eof; + // buffer for loading, used for speedup + unsigned char *m_buffer; + // the size of the buffer + uint m_bufferSize; + // the current cursor position in the buffer + uint m_pos; + + // reads a short value from the buffer + short ReadShort(); + // reads an int value from the buffer + int ReadInt(); + // reads a char from the buffer + char ReadChar(); + //reada a floatvalue from the buffer + float ReadFloat(); + //reads an unsigned byte from the buffer + byte ReadByte(); + //reads an asciiz string + int ReadASCIIZ(char *buf, int max_count); + // seek wihtin the buffer + void Seek(int offset, int origin); + // returns the position of the cursor + uint Pos(); + + // read the chunk and return it. + LChunk ReadChunk(); + // read until given chunk is found + bool FindChunk(LChunk &target, const LChunk &parent); + // skip to the end of chunk "chunk" + void SkipChunk(const LChunk &chunk); + // goes to the beginning of the data in teh given chunk + void GotoChunk(const LChunk &chunk); + + // the function read the color chunk (any of the color chunks) + LColor3 ReadColor(const LChunk &chunk); + // the function that read the percentage chunk and returns a float from 0 to 1 + float ReadPercentage(const LChunk &chunk); + // this is where 3ds file is being read + bool Read3DS(); + // read a light chunk + void ReadLight(const LChunk &parent); + // read a trimesh chunk + void ReadMesh(const LChunk &parent); + // reads the face list, face materials, smoothing groups... and fill rthe information into the mesh + void ReadFaceList(const LChunk &chunk, LMesh &mesh); + // reads the material + void ReadMaterial(const LChunk &parent); + // reads the map info and fills the given map with this information + void ReadMap(const LChunk &chunk, LMap& map); + // reads keyframer data of the OBJECT_NODE_TAG chunk + void ReadKeyframeData(const LChunk &parent); + // reads the keyheader structure from the current offset and returns the frame number + long ReadKeyheader(); +}; + +//--------------------------------------------------------- + #endif \ No newline at end of file diff --git a/Magic2/resource.h b/Magic2/resource.h index f183426..84d4573 100644 --- a/Magic2/resource.h +++ b/Magic2/resource.h @@ -1,233 +1,233 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by Magic.rc -// -#define ID_RESET 3 -#define IDC_NEW_MATERIAL 3 -#define ID_BACK_COLOR 4 -#define IDC_DEL_MATERIAL 4 -#define IDC_SELECT_POLYS 5 -#define IDD_ABOUTBOX 100 -#define IDR_MAINFRAME 128 -#define IDR_MAGICTYPE 129 -#define IDD_SURFACE_PROPS 130 -#define IDD_CAMERA_PROPS 131 -#define IDD_MODIFY_SURFACE 135 -#define IDD_VERTS_REDUCE 136 -#define IDD_MODIFY_POLY 137 -#define IDD_CREATE_CUBE 138 -#define IDD_CREATE_CYLINDER 139 -#define IDD_CREATE_SPHERE 140 -#define IDD_MODIFY_TEXTURE 141 -#define IDD_GRIDPROPS 142 -#define IDD_MODIFY_POLYS 143 -#define IDD_CREATE_POLY 144 -#define IDD_EXTRUSION_PROPS 146 -#define IDD_MODIFY_MATERIAL 147 -#define IDC_SURFACE_NAME 1000 -#define IDC_SURFACE_NVERTS 1001 -#define IDC_SURFACE_NPOLYS 1002 -#define IDC_SURFACE_COLOR 1003 -#define IDC_SURFACE_RADIUS 1003 -#define IDC_SURFACE_LENGTH 1004 -#define IDC_SURFACE_WIDTH 1005 -#define IDC_CAMERA_DISTANCE 1006 -#define IDC_SURFACE_HEIGHT 1006 -#define IDC_CAMERA_FOV 1007 -#define IDC_CAMERA_MODE 1008 -#define IDC_SURFACE_LIST 1009 -#define IDC_SURF_NAME 1010 -#define IDC_SURF_POLYS 1011 -#define IDC_SURF_COLOR 1012 -#define IDC_SURF_HIDDEN 1013 -#define IDC_SURF_LOCKED 1014 -#define IDC_SURF_CREATE 1015 -#define IDC_SURF_DISCARD 1016 -#define IDC_SURF_CLONE 1017 -#define IDC_SURF_DELETE 1018 -#define IDC_SURF_ADD_POLYS 1019 -#define IDC_THRESHOLD 1020 -#define IDC_SURF_ID 1020 -#define IDC_FLATTEN 1021 -#define IDC_FLIP_NORM 1022 -#define IDC_DOUBLE_SIDE 1023 -#define IDC_TRIANGULATE 1024 -#define IDC_REMOVE 1025 -#define IDC_POLY_VERTS 1026 -#define IDC_POLY_X 1027 -#define IDC_POLY_Y 1028 -#define IDC_POLY_Z 1029 -#define IDC_POLY_CURVE 1030 -#define IDC_POLY_SURF 1031 -#define IDC_POLY_TEX 1032 -#define IDC_LOC_X 1033 -#define IDC_LOC_Y 1034 -#define IDC_LOC_Z 1035 -#define IDC_SIZE_X 1036 -#define IDC_SIZE_Y 1037 -#define IDC_SIZE_Z 1038 -#define IDC_SECTORS 1039 -#define IDC_RINGS 1040 -#define IDC_GRID_SNAP 1041 -#define IDC_TEXTURE 1041 -#define IDC_MATERIAL 1041 -#define IDC_GRID_SIZE 1042 -#define IDC_MAPPING 1042 -#define IDC_GRID_SHOW 1043 -#define IDC_ALIGN_X 1043 -#define IDC_GRID_LINES 1044 -#define IDC_ALIGN_Y 1044 -#define IDC_GRID_DOTS 1045 -#define IDC_ALIGN_Z 1045 -#define IDC_SCALE_U 1046 -#define IDC_SCALE_V 1047 -#define IDC_TEXTURE_ADD 1048 -#define IDC_TEXTURE_DELETE 1049 -#define IDC_ALIGN_FLIP 1050 -#define IDC_ALIGN_MIRROR 1051 -#define IDC_ALIGN_ROTATE 1052 -#define IDC_TEXTURE_RELOAD 1053 -#define IDC_TEXTURE_PREVIEW 1054 -#define IDC_TEMPLATE 1055 -#define IDC_AMBIENT_COLOR 1055 -#define IDC_FLAG_FLAT 1056 -#define IDC_DIFFUSE_COLOR 1056 -#define IDC_FLAG_LUMINOUS 1057 -#define IDC_NSIDES 1057 -#define IDC_SPECULAR_COLOR 1057 -#define IDC_FLAG_TRANSLUCENT 1058 -#define IDC_EMISSIVE_COLOR 1058 -#define IDC_FLAG_TRANSPARENT 1059 -#define IDC_SECONDARY 1059 -#define IDC_FLAG_SPECULAR 1060 -#define IDC_FLAG_FLAT2 1061 -#define IDC_FLAG_LUMINOUS2 1062 -#define IDC_POLY_INDEX 1062 -#define IDC_FLAG_TRANSLUCENT2 1063 -#define IDC_FLAG_TRANSPARENT2 1064 -#define IDC_FLAG_SPECULAR2 1065 -#define IDC_FLAG_TEXCLAMP 1066 -#define IDC_DISTANCE 1067 -#define IDC_FLAG_SPECULAR22 1067 -#define IDC_FLAG_SPECULAR1 1068 -#define IDC_FLAG_SPECULAR12 1069 -#define IDC_FLAG_TEXCLAMP2 1070 -#define IDC_MATERIAL_LIST 1070 -#define IDC_MATERIAL_NAME 1071 -#define IDC_DIFFUSE_TEXTURE 1072 -#define IDC_SPECULAR_TEXTURE 1073 -#define IDC_EMISSIVE_TEXTURE 1074 -#define IDC_BUMP_TEXTURE 1075 -#define IDC_AMBIENT_VALUE 1076 -#define IDC_DIFFUSE_VALUE 1077 -#define IDC_SPECULAR_VALUE 1078 -#define IDC_EMISSIVE_VALUE 1079 -#define IDC_BUMP_VALUE 1080 -#define IDC_POWER_VALUE 1081 -#define IDC_BRILLIANCE_VALUE 1082 -#define IDC_BLEND_MODE 1083 -#define IDC_MATERIAL_PREVIEW 1084 -#define IDC_FILE_DIFFUSE 1085 -#define IDC_FILE_SPECULAR 1086 -#define IDC_REFERENCE_PLAN 1086 -#define IDC_FILE_EMISSIVE 1087 -#define IDC_REFERENCE_SIDE 1087 -#define IDC_FILE_BUMP 1088 -#define IDC_REFERENCE_FRONT 1088 -#define IDC_SHADOW 1089 -#define IDC_FILE_PLAN 1090 -#define IDC_MATERIAL_SHADER 1090 -#define IDC_FILE_SIDE 1091 -#define IDC_FILE_FRONT 1092 -#define ID_GRID_PROPS 32771 -#define ID_VIEW_ZOOM_IN 32771 -#define ID_VIEW_ZOOM_OUT 32772 -#define ID_VIEW_ZOOM_NORMAL 32773 -#define ID_VIEW_CENTER 32774 -#define ID_SURFACE_CREATE 32779 -#define ID_MODIFY_DRAG_VERTS 32780 -#define ID_CREATE_CUBE 32781 -#define ID_CREATE_TETRA 32782 -#define ID_MODIFY_EXTRUDE 32784 -#define ID_MODIFY_BEVEL 32785 -#define ID_MODIFY_STUD 32786 -#define ID_MODIFY_SUBDIVIDE 32787 -#define ID_PROP_SURFACE 32788 -#define ID_PROP_CAMERA 32789 -#define ID_EDIT_FLIP_NORMAL 32790 -#define ID_EDIT_REMOVE_POLY 32791 -#define ID_EDIT_MERGE_POLY 32792 -#define ID_MODIFY_TEXTURE 32795 -#define ID_OPTIONS_VERTEX_NORMALS 32798 -#define ID_PROP_GRID 32800 -#define ID_EDIT_DELETE 32801 -#define ID_CREATE_POLY 32802 -#define ID_CREATE_VERT 32803 -#define ID_CREATE_CYLINDER 32804 -#define ID_CREATE_SPHERE 32805 -#define ID_FILE_IMPORT 32806 -#define ID_FILE_EXPORT 32807 -#define ID_MODIFY_POLY 32808 -#define ID_MODIFY_VERTS 32809 -#define ID_VERTS_REDUCE 32810 -#define ID_VERTS_SNAP 32811 -#define ID_MODIFY_SCALE_VERTS 32812 -#define ID_MODIFY_ROTATE 32813 -#define ID_CREATE_CONE 32814 -#define ID_FINAL_RENDER 32815 -#define ID_MODIFY_SCALE_X 32817 -#define ID_MODIFY_SCALE_Z 32819 -#define ID_MODIFY_SCALE_Y 32822 -#define ID_MODIFY_SPLIT1 32824 -#define ID_MODIFY_SPLIT2 32825 -#define ID_EDIT_MIRROR 32826 -#define ID_EDIT_SEAL 32827 -#define ID_EDIT_CLONE 32828 -#define ID_GRID_SNAP 32829 -#define ID_MODIFY_FLATTEN_X 32830 -#define ID_MODIFY_FLATTEN_Y 32831 -#define ID_MODIFY_FLATTEN_Z 32832 -#define ID_EDIT_SELECT_NONE 32833 -#define ID_NUDGE_RIGHT 32834 -#define ID_NUDGE_LEFT 32835 -#define ID_NUDGE_UP 32836 -#define ID_NUDGE_DOWN 32837 -#define ID_STEP_LEFT 32838 -#define ID_STEP_RIGHT 32839 -#define ID_STEP_UP 32840 -#define ID_STEP_DOWN 32841 -#define ID_VIEW_RENDER 32842 -#define ID_VIEW_ALL 32843 -#define ID_VIEW_FRONT 32844 -#define ID_VIEW_SIDE 32845 -#define ID_VIEW_TOP 32846 -#define ID_VIEW_PERSPECTIVE 32847 -#define ID_MODIFY_TEXTURE_MAP 32848 -#define ID_MODIFY_MATERIAL 32849 -#define ID_VIEW_MODE_WIREFRAME 32850 -#define ID_VIEW_MODE_SOLID 32851 -#define ID_VIEW_MODE_TEXTURED 32852 -#define ID_GRID_SHOW 32853 -#define ID_VIEW_BACK_COLOR 32854 -#define ID_EDIT_SELECT_INVERSE 32855 -#define ID_MODIFY_UV_MAP 32856 -#define ID_VIEW_SHADOWS 32857 -#define ID_VIEW_ANIMATELIGHT 32858 -#define ID_VIEW_BUMPMAPS 32859 -#define ID_VIEW_VERTEXSHADER 32860 -#define ID_VIEW_PIXELSHADER 32861 -#define ID_VIEW_VISIBLESHADOWS 32862 -#define ID_SURFACE_OPTIMIZE 32863 -#define ID_SURFACE_EXPLODE 32864 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 148 -#define _APS_NEXT_COMMAND_VALUE 32865 -#define _APS_NEXT_CONTROL_VALUE 1091 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Magic.rc +// +#define ID_RESET 3 +#define IDC_NEW_MATERIAL 3 +#define ID_BACK_COLOR 4 +#define IDC_DEL_MATERIAL 4 +#define IDC_SELECT_POLYS 5 +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_MAGICTYPE 129 +#define IDD_SURFACE_PROPS 130 +#define IDD_CAMERA_PROPS 131 +#define IDD_MODIFY_SURFACE 135 +#define IDD_VERTS_REDUCE 136 +#define IDD_MODIFY_POLY 137 +#define IDD_CREATE_CUBE 138 +#define IDD_CREATE_CYLINDER 139 +#define IDD_CREATE_SPHERE 140 +#define IDD_MODIFY_TEXTURE 141 +#define IDD_GRIDPROPS 142 +#define IDD_MODIFY_POLYS 143 +#define IDD_CREATE_POLY 144 +#define IDD_EXTRUSION_PROPS 146 +#define IDD_MODIFY_MATERIAL 147 +#define IDC_SURFACE_NAME 1000 +#define IDC_SURFACE_NVERTS 1001 +#define IDC_SURFACE_NPOLYS 1002 +#define IDC_SURFACE_COLOR 1003 +#define IDC_SURFACE_RADIUS 1003 +#define IDC_SURFACE_LENGTH 1004 +#define IDC_SURFACE_WIDTH 1005 +#define IDC_CAMERA_DISTANCE 1006 +#define IDC_SURFACE_HEIGHT 1006 +#define IDC_CAMERA_FOV 1007 +#define IDC_CAMERA_MODE 1008 +#define IDC_SURFACE_LIST 1009 +#define IDC_SURF_NAME 1010 +#define IDC_SURF_POLYS 1011 +#define IDC_SURF_COLOR 1012 +#define IDC_SURF_HIDDEN 1013 +#define IDC_SURF_LOCKED 1014 +#define IDC_SURF_CREATE 1015 +#define IDC_SURF_DISCARD 1016 +#define IDC_SURF_CLONE 1017 +#define IDC_SURF_DELETE 1018 +#define IDC_SURF_ADD_POLYS 1019 +#define IDC_THRESHOLD 1020 +#define IDC_SURF_ID 1020 +#define IDC_FLATTEN 1021 +#define IDC_FLIP_NORM 1022 +#define IDC_DOUBLE_SIDE 1023 +#define IDC_TRIANGULATE 1024 +#define IDC_REMOVE 1025 +#define IDC_POLY_VERTS 1026 +#define IDC_POLY_X 1027 +#define IDC_POLY_Y 1028 +#define IDC_POLY_Z 1029 +#define IDC_POLY_CURVE 1030 +#define IDC_POLY_SURF 1031 +#define IDC_POLY_TEX 1032 +#define IDC_LOC_X 1033 +#define IDC_LOC_Y 1034 +#define IDC_LOC_Z 1035 +#define IDC_SIZE_X 1036 +#define IDC_SIZE_Y 1037 +#define IDC_SIZE_Z 1038 +#define IDC_SECTORS 1039 +#define IDC_RINGS 1040 +#define IDC_GRID_SNAP 1041 +#define IDC_TEXTURE 1041 +#define IDC_MATERIAL 1041 +#define IDC_GRID_SIZE 1042 +#define IDC_MAPPING 1042 +#define IDC_GRID_SHOW 1043 +#define IDC_ALIGN_X 1043 +#define IDC_GRID_LINES 1044 +#define IDC_ALIGN_Y 1044 +#define IDC_GRID_DOTS 1045 +#define IDC_ALIGN_Z 1045 +#define IDC_SCALE_U 1046 +#define IDC_SCALE_V 1047 +#define IDC_TEXTURE_ADD 1048 +#define IDC_TEXTURE_DELETE 1049 +#define IDC_ALIGN_FLIP 1050 +#define IDC_ALIGN_MIRROR 1051 +#define IDC_ALIGN_ROTATE 1052 +#define IDC_TEXTURE_RELOAD 1053 +#define IDC_TEXTURE_PREVIEW 1054 +#define IDC_TEMPLATE 1055 +#define IDC_AMBIENT_COLOR 1055 +#define IDC_FLAG_FLAT 1056 +#define IDC_DIFFUSE_COLOR 1056 +#define IDC_FLAG_LUMINOUS 1057 +#define IDC_NSIDES 1057 +#define IDC_SPECULAR_COLOR 1057 +#define IDC_FLAG_TRANSLUCENT 1058 +#define IDC_EMISSIVE_COLOR 1058 +#define IDC_FLAG_TRANSPARENT 1059 +#define IDC_SECONDARY 1059 +#define IDC_FLAG_SPECULAR 1060 +#define IDC_FLAG_FLAT2 1061 +#define IDC_FLAG_LUMINOUS2 1062 +#define IDC_POLY_INDEX 1062 +#define IDC_FLAG_TRANSLUCENT2 1063 +#define IDC_FLAG_TRANSPARENT2 1064 +#define IDC_FLAG_SPECULAR2 1065 +#define IDC_FLAG_TEXCLAMP 1066 +#define IDC_DISTANCE 1067 +#define IDC_FLAG_SPECULAR22 1067 +#define IDC_FLAG_SPECULAR1 1068 +#define IDC_FLAG_SPECULAR12 1069 +#define IDC_FLAG_TEXCLAMP2 1070 +#define IDC_MATERIAL_LIST 1070 +#define IDC_MATERIAL_NAME 1071 +#define IDC_DIFFUSE_TEXTURE 1072 +#define IDC_SPECULAR_TEXTURE 1073 +#define IDC_EMISSIVE_TEXTURE 1074 +#define IDC_BUMP_TEXTURE 1075 +#define IDC_AMBIENT_VALUE 1076 +#define IDC_DIFFUSE_VALUE 1077 +#define IDC_SPECULAR_VALUE 1078 +#define IDC_EMISSIVE_VALUE 1079 +#define IDC_BUMP_VALUE 1080 +#define IDC_POWER_VALUE 1081 +#define IDC_BRILLIANCE_VALUE 1082 +#define IDC_BLEND_MODE 1083 +#define IDC_MATERIAL_PREVIEW 1084 +#define IDC_FILE_DIFFUSE 1085 +#define IDC_FILE_SPECULAR 1086 +#define IDC_REFERENCE_PLAN 1086 +#define IDC_FILE_EMISSIVE 1087 +#define IDC_REFERENCE_SIDE 1087 +#define IDC_FILE_BUMP 1088 +#define IDC_REFERENCE_FRONT 1088 +#define IDC_SHADOW 1089 +#define IDC_FILE_PLAN 1090 +#define IDC_MATERIAL_SHADER 1090 +#define IDC_FILE_SIDE 1091 +#define IDC_FILE_FRONT 1092 +#define ID_GRID_PROPS 32771 +#define ID_VIEW_ZOOM_IN 32771 +#define ID_VIEW_ZOOM_OUT 32772 +#define ID_VIEW_ZOOM_NORMAL 32773 +#define ID_VIEW_CENTER 32774 +#define ID_SURFACE_CREATE 32779 +#define ID_MODIFY_DRAG_VERTS 32780 +#define ID_CREATE_CUBE 32781 +#define ID_CREATE_TETRA 32782 +#define ID_MODIFY_EXTRUDE 32784 +#define ID_MODIFY_BEVEL 32785 +#define ID_MODIFY_STUD 32786 +#define ID_MODIFY_SUBDIVIDE 32787 +#define ID_PROP_SURFACE 32788 +#define ID_PROP_CAMERA 32789 +#define ID_EDIT_FLIP_NORMAL 32790 +#define ID_EDIT_REMOVE_POLY 32791 +#define ID_EDIT_MERGE_POLY 32792 +#define ID_MODIFY_TEXTURE 32795 +#define ID_OPTIONS_VERTEX_NORMALS 32798 +#define ID_PROP_GRID 32800 +#define ID_EDIT_DELETE 32801 +#define ID_CREATE_POLY 32802 +#define ID_CREATE_VERT 32803 +#define ID_CREATE_CYLINDER 32804 +#define ID_CREATE_SPHERE 32805 +#define ID_FILE_IMPORT 32806 +#define ID_FILE_EXPORT 32807 +#define ID_MODIFY_POLY 32808 +#define ID_MODIFY_VERTS 32809 +#define ID_VERTS_REDUCE 32810 +#define ID_VERTS_SNAP 32811 +#define ID_MODIFY_SCALE_VERTS 32812 +#define ID_MODIFY_ROTATE 32813 +#define ID_CREATE_CONE 32814 +#define ID_FINAL_RENDER 32815 +#define ID_MODIFY_SCALE_X 32817 +#define ID_MODIFY_SCALE_Z 32819 +#define ID_MODIFY_SCALE_Y 32822 +#define ID_MODIFY_SPLIT1 32824 +#define ID_MODIFY_SPLIT2 32825 +#define ID_EDIT_MIRROR 32826 +#define ID_EDIT_SEAL 32827 +#define ID_EDIT_CLONE 32828 +#define ID_GRID_SNAP 32829 +#define ID_MODIFY_FLATTEN_X 32830 +#define ID_MODIFY_FLATTEN_Y 32831 +#define ID_MODIFY_FLATTEN_Z 32832 +#define ID_EDIT_SELECT_NONE 32833 +#define ID_NUDGE_RIGHT 32834 +#define ID_NUDGE_LEFT 32835 +#define ID_NUDGE_UP 32836 +#define ID_NUDGE_DOWN 32837 +#define ID_STEP_LEFT 32838 +#define ID_STEP_RIGHT 32839 +#define ID_STEP_UP 32840 +#define ID_STEP_DOWN 32841 +#define ID_VIEW_RENDER 32842 +#define ID_VIEW_ALL 32843 +#define ID_VIEW_FRONT 32844 +#define ID_VIEW_SIDE 32845 +#define ID_VIEW_TOP 32846 +#define ID_VIEW_PERSPECTIVE 32847 +#define ID_MODIFY_TEXTURE_MAP 32848 +#define ID_MODIFY_MATERIAL 32849 +#define ID_VIEW_MODE_WIREFRAME 32850 +#define ID_VIEW_MODE_SOLID 32851 +#define ID_VIEW_MODE_TEXTURED 32852 +#define ID_GRID_SHOW 32853 +#define ID_VIEW_BACK_COLOR 32854 +#define ID_EDIT_SELECT_INVERSE 32855 +#define ID_MODIFY_UV_MAP 32856 +#define ID_VIEW_SHADOWS 32857 +#define ID_VIEW_ANIMATELIGHT 32858 +#define ID_VIEW_BUMPMAPS 32859 +#define ID_VIEW_VERTEXSHADER 32860 +#define ID_VIEW_PIXELSHADER 32861 +#define ID_VIEW_VISIBLESHADOWS 32862 +#define ID_SURFACE_OPTIMIZE 32863 +#define ID_SURFACE_EXPLODE 32864 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 148 +#define _APS_NEXT_COMMAND_VALUE 32865 +#define _APS_NEXT_CONTROL_VALUE 1091 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- cgit v1.1