00001
00013 #include <cmath>
00014 #include <iostream>
00015 #include <string>
00016 #include <sstream>
00017 #include <vector>
00018
00019 #include "popassert.h"
00020 #include "CVector3f.h"
00021 #include "CColor.h"
00022 #include "CImage.h"
00023 #include "CVectBase.h"
00024 #include "compute.h"
00025 #include "CMathExpression.h"
00026 #include "CRenderObj.h"
00027 #include "CCommand.h"
00028 #include "CCommandParser.h"
00029 #include "CCommandExecutor.h"
00030
00031
00032
00033 const std::string HelpMessages[CCommand::PARAMETER_END+1] =
00034 {
00035
00036 "The implicit equation of the surface to render.",
00037
00038 "The step taken at each iteration in the signed mode.\n"
00039 "Lowering that value causes the rendering to be slower\n"
00040 "but more precise.\n"
00041 "\"help Sign\" for more info on the signed mode.",
00042
00043 "The step taken at each iteration in the no signed mode.\n"
00044 "Lowering that value cause the rendering to be slower\n"
00045 "but more precise.\n"
00046 "\"help Sign\" for more info on the no signed mode.",
00047
00048 "The limit under which a floating point value is considered\n"
00049 "to be equal to zero. It is used as the criterium to know\n"
00050 "if a point is on the surface in the no signed mode.\n"
00051 "\"help Sign\" for more info on the no signed mode.",
00052
00053 "The zoom factor of the camera. If that value is set to 0,\n"
00054 "the camera is left in its position. If the zoom is set to 1,\n"
00055 "the camera is placed so that all the viewing volume is seen.",
00056
00057 "The vector holding the minimum x, y and z value of the\n"
00058 "bouding box of the surface to be rendered.",
00059
00060 "The vector holding the maximum x, y and z value of the\n"
00061 "bouding box of the surface to be rendered.",
00062
00063 "The vector holding the position of the camera viewing\n"
00064 "the surface to be rendered.",
00065
00066 "The vector holding the direction of the directional light\n"
00067 "that is lightening the surface.",
00068
00069 "The ambient color component of the surface.\n"
00070 "The color is in RGB with each component between 0 and 1.",
00071
00072 "The diffuse color component of the surface.\n"
00073 "The color is in RGB with each component between 0 and 1.",
00074
00075 "The specular color component of the surface.\n"
00076 "The color is in RGB with each component between 0 and 1.",
00077
00078 "The specular color exponent of the surface.\n"
00079 "It influences the specular highlights.",
00080
00081 "The ambient color component of the bounding box.\n"
00082 "The color is in RGB with each component between 0 and 1.",
00083
00084 "The diffuse color component of the bounding box.\n"
00085 "The color is in RGB with each component between 0 and 1.",
00086
00087 "The specular color component of the bounding box.\n"
00088 "The color is in RGB with each component between 0 and 1.",
00089
00090 "The specular color exponent of the box.\n"
00091 "It influences the specular highlights.",
00092
00093 "The background color of the scene.\n"
00094 "The color is in RGB with each component between 0 and 1.",
00095
00096 "The width of the picture that will be rendering, in pixels.",
00097
00098 "The height of the picture that will be rendering, in pixels.",
00099
00100 "Option to choose to use perspective or orthonormal projection.\n"
00101 "usage: set Perspective {on,off}",
00102
00103 "Option to choose to draw the bounding box or not.\n"
00104 "usage: set BoundingBox {on,off}",
00105
00106 "Option to choose between the signed mode and the no signed mode.\n"
00107 "The signed mode uses the signed of the expression f(x,y,z )to\n"
00108 "know if the ray hit the surface. When the sign changes, there\n"
00109 "is a hit. The no signed mode uses a threshold under which\n"
00110 "f(x,y,z) is considered to be equal to zero, so that the ray hit\n"
00111 "the surface.\n"
00112 "usage: set Sign {on,off}",
00113
00114 "Option to choose between OpenGL specular lighting calculation\n"
00115 "and normal ray-tracing specular lighting."
00116 "usage: set OpenGLSpecular {on,off}",
00117
00118 "Commands: help : help on a topic\n"
00119 " run : launches the tracing\n"
00120 " set : sets a parameter\n"
00121 " print : prints the value of a parameter\n"
00122 " quit : exit the program\n"
00123 "\n"
00124 "Parameters: FormulaString\n"
00125 " SignIncrement\n"
00126 " NoSignIncrement\n"
00127 " NoSignPrecision\n"
00128 " Zoom\n"
00129 " MinVector\n"
00130 " MaxVector\n"
00131 " ViewerPos\n"
00132 " LightDirection\n"
00133 " SurfaceAmbientColor\n"
00134 " SurfaceDiffuseColor\n"
00135 " SurfaceSpecularColor\n"
00136 " SurfaceSpecularExponent\n"
00137 " BoxAmbientColor\n"
00138 " BoxDiffuseColor\n"
00139 " BoxSpecularColor\n"
00140 " SurfaceSpecularExponent\n"
00141 " BackgroundColor\n"
00142 " Width\n"
00143 " Height\n"
00144 "\n"
00145 " Perspective\n"
00146 " BoundingBox\n"
00147 " Sign\n"
00148 " OpenGLSpecular"
00149 };
00150
00151
00152 CCommandExecutor* CCommandExecutor::s_pInstance = NULL;
00153
00158 #ifdef WIN32
00159
00160 #include <fstream>
00161
00162 bool CCommandExecutor::FileExist(const std::string& FileName)
00163 {
00164 std::ifstream File;
00165 bool Exist;
00166
00167 File.open(FileName.c_str());
00168 Exist = !(File.fail());
00169 File.close();
00170
00171 return(Exist);
00172 }
00173
00174 #elif defined(LINUX)
00175
00176 #include <sys/types.h>
00177 #include <sys/stat.h>
00178
00179 bool CCommandExecutor::FileExist(const std::string& FileName)
00180 {
00181 struct stat TempStruct;
00182 return (!stat(FileName.c_str(), &TempStruct));
00183 }
00184
00185 #else
00186 #error "OS not supported"
00187 #endif
00188
00189
00190
00191
00196 void CCommandExecutor::Execute(const CCommand& command,
00197 CRenderObj& surfaceobj) const
00198 {
00199 switch (command.m_CommandID)
00200 {
00202
00203
00204
00206 case CCommand::COMMAND_HELP:
00207 {
00208 std::cout << HelpMessages[command.m_ParameterID] << std::endl;
00209 break;
00210 }
00211
00213
00214
00215
00217 case CCommand::COMMAND_RUN:
00218 {
00219 std::string strParameterCheck = surfaceobj.Validate();
00220
00221 if (strParameterCheck != "")
00222 {
00223 std::cout << "Ray tracing not started." << std::endl
00224 << strParameterCheck << std::endl;
00225 break;
00226 }
00227
00228 bool ReadyToGo = false;
00229 std::string Answer_1, Answer_2;
00230
00231 while(!ReadyToGo)
00232 {
00233 std::cout << "Enter the name of the BMP file to create."
00234 << std::endl;
00235 GetLine(std::cin, Answer_1);
00236
00237 if (Answer_1 == "")
00238 {
00239 std::cout << "Please write a non empty name." << std::endl;
00240 continue;
00241 }
00242 else
00243 {
00244 if (FileExist(Answer_1))
00245 {
00246 std::cout << "This file exists. Overwrite? (yes, no, cancel)"
00247 << std::endl;
00248 GetLine(std::cin, Answer_2);
00249
00250 if ( Answer_2 == "y" ||
00251 Answer_2 == "ye" ||
00252 Answer_2 == "yes" )
00253 {
00254 ReadyToGo = true;
00255 }
00256 else if ( Answer_2 == "n" ||
00257 Answer_2 == "no" )
00258 {
00259 continue;
00260 }
00261 else
00262 {
00263 std::cout << "Canceled" << std::endl;
00264 break;
00265 }
00266 }
00267 else
00268 {
00269 ReadyToGo = true;
00270 }
00271 }
00272 }
00273
00274 if (ReadyToGo)
00275 {
00276 surfaceobj.Update();
00277 CColor TempColor;
00278 CImage image(surfaceobj.m_Width, surfaceobj.m_Height);
00279
00280 std::cout << "Ray tracing started" << std::endl;
00281 for (int j = surfaceobj.m_Height - 1; j >= 0; --j)
00282 for (int i = surfaceobj.m_Width - 1; i >= 0; --i)
00283 {
00284 TempColor = surfaceobj.GetPixelColor(i, j);
00285 TempColor.Clamp();
00286
00287 image(i,j,0) = TempColor[0];
00288 image(i,j,1) = TempColor[1];
00289 image(i,j,2) = TempColor[2];
00290 }
00291 std::cout << "Ray tracing completed" << std::endl;
00292
00293 std::cout << "File writing started" << std::endl;
00294
00295 switch( image.WriteBmpFile(Answer_1) )
00296 {
00297 case 0:
00298 {
00299 std::cout << "File writing completed" << std::endl
00300 << "Job done" << std::endl;
00301 break;
00302 }
00303 case -1:
00304 {
00305 std::cout << "Error: unable to open file '"
00306 << Answer_1 << "'" << std::endl;
00307 break;
00308 }
00309 default:
00310 {
00311 std::cout << "Error occured while writing to file"
00312 << std::endl;
00313 break;
00314 }
00315 }
00316 }
00317
00318 break;
00319 }
00320
00322
00323
00324
00326 case CCommand::COMMAND_SET:
00327 {
00328 switch (command.m_ParameterID)
00329 {
00330 case CCommand::PARAMETER_FORMULASTRING:
00331 {
00332 surfaceobj.m_FormulaString = *command.m_pData.String;
00333 delete command.m_pData.String;
00334 break;
00335 }
00336 case CCommand::PARAMETER_SIGNINCREMENT:
00337 {
00338 surfaceobj.m_SignIncrement = *command.m_pData.Float;
00339 delete command.m_pData.Float;
00340 break;
00341 }
00342 case CCommand::PARAMETER_NOSIGNINCREMENT:
00343 {
00344 surfaceobj.m_NoSignIncrement = *command.m_pData.Float;
00345 delete command.m_pData.Float;
00346 break;
00347 }
00348 case CCommand::PARAMETER_NOSIGNPRECISION:
00349 {
00350 surfaceobj.m_NoSignPrecision = *command.m_pData.Float;
00351 delete command.m_pData.Float;
00352 break;
00353 }
00354 case CCommand::PARAMETER_ZOOM:
00355 {
00356 surfaceobj.m_Zoom = *command.m_pData.Float;
00357 delete command.m_pData.Float;
00358 break;
00359 }
00360 case CCommand::PARAMETER_MINVECTOR:
00361 {
00362 surfaceobj.m_MinVector = *command.m_pData.Vector;
00363 delete command.m_pData.Vector;
00364 break;
00365 }
00366 case CCommand::PARAMETER_MAXVECTOR:
00367 {
00368 surfaceobj.m_MaxVector = *command.m_pData.Vector;
00369 delete command.m_pData.Vector;
00370 break;
00371 }
00372 case CCommand::PARAMETER_VIEWERPOS:
00373 {
00374 surfaceobj.m_ViewerPos = *command.m_pData.Vector;
00375 delete command.m_pData.Vector;
00376 break;
00377 }
00378 case CCommand::PARAMETER_LIGHTDIRECTION:
00379 {
00380 surfaceobj.m_LightDirection = *command.m_pData.Vector;
00381 delete command.m_pData.Vector;
00382 break;
00383 }
00384 case CCommand::PARAMETER_SURFACEAMBIENTCOLOR:
00385 {
00386 surfaceobj.m_SurfaceAmbientColor = *command.m_pData.Color;
00387 delete command.m_pData.Color;
00388 break;
00389 }
00390 case CCommand::PARAMETER_SURFACEDIFFUSECOLOR:
00391 {
00392 surfaceobj.m_SurfaceDiffuseColor = *command.m_pData.Color;
00393 delete command.m_pData.Color;
00394 break;
00395 }
00396 case CCommand::PARAMETER_SURFACESPECULARCOLOR:
00397 {
00398 surfaceobj.m_SurfaceSpecularColor = *command.m_pData.Color;
00399 delete command.m_pData.Color;
00400 break;
00401 }
00402 case CCommand::PARAMETER_SURFACESPECULAREXPONENT:
00403 {
00404 surfaceobj.m_SurfaceSpecularExponent = *command.m_pData.Float;
00405 delete command.m_pData.Float;
00406 break;
00407 }
00408 case CCommand::PARAMETER_BOXAMBIENTCOLOR:
00409 {
00410 surfaceobj.m_BoxAmbientColor = *command.m_pData.Color;
00411 delete command.m_pData.Color;
00412 break;
00413 }
00414 case CCommand::PARAMETER_BOXDIFFUSECOLOR:
00415 {
00416 surfaceobj.m_BoxDiffuseColor = *command.m_pData.Color;
00417 delete command.m_pData.Color;
00418 break;
00419 }
00420 case CCommand::PARAMETER_BOXSPECULARCOLOR:
00421 {
00422 surfaceobj.m_BoxSpecularColor = *command.m_pData.Color;
00423 delete command.m_pData.Color;
00424 break;
00425 }
00426 case CCommand::PARAMETER_BOXSPECULAREXPONENT:
00427 {
00428 surfaceobj.m_BoxSpecularExponent = *command.m_pData.Float;
00429 delete command.m_pData.Float;
00430 break;
00431 }
00432 case CCommand::PARAMETER_BACKGROUNDCOLOR:
00433 {
00434 surfaceobj.m_BackgroundColor = *command.m_pData.Color;
00435 delete command.m_pData.Color;
00436 break;
00437 }
00438 case CCommand::PARAMETER_WIDTH:
00439 {
00440 surfaceobj.m_Width = *command.m_pData.Int;
00441 delete command.m_pData.Int;
00442 break;
00443 }
00444 case CCommand::PARAMETER_HEIGHT:
00445 {
00446 surfaceobj.m_Height = *command.m_pData.Int;
00447 delete command.m_pData.Int;
00448 break;
00449 }
00450 case CCommand::PARAMETER_PERSPECTIVE:
00451 {
00452 if (*command.m_pData.String == "on")
00453 {
00454 surfaceobj.m_Options = surfaceobj.m_Options | OPTION_PERSPECTIVE;
00455 }
00456 else if (*command.m_pData.String == "off")
00457 {
00458 surfaceobj.m_Options = surfaceobj.m_Options & ~OPTION_PERSPECTIVE;
00459 }
00460 else
00461 {
00462 std::cout << "Parameter error: usage: set Perspective {on,off}"
00463 << std::endl;
00464 }
00465
00466 delete command.m_pData.String;
00467 break;
00468 }
00469 case CCommand::PARAMETER_BOUNDINGBOX:
00470 {
00471 if (*command.m_pData.String == "on")
00472 {
00473 surfaceobj.m_Options = surfaceobj.m_Options | OPTION_BOUNDINGBOX;
00474 }
00475 else if (*command.m_pData.String == "off")
00476 {
00477 surfaceobj.m_Options = surfaceobj.m_Options & ~OPTION_BOUNDINGBOX;
00478 }
00479 else
00480 {
00481 std::cout << "Parameter error: usage: set BoundingBox {on,off}"
00482 << std::endl;
00483 }
00484
00485 delete command.m_pData.String;
00486 break;
00487 }
00488 case CCommand::PARAMETER_SIGN:
00489 {
00490 if (*command.m_pData.String == "on")
00491 {
00492 surfaceobj.m_Options = surfaceobj.m_Options | OPTION_SIGN;
00493 }
00494 else if (*command.m_pData.String == "off")
00495 {
00496 surfaceobj.m_Options = surfaceobj.m_Options & ~OPTION_SIGN;
00497 }
00498 else
00499 {
00500 std::cout << "Parameter error: usage: set Sign {on,off}"
00501 << std::endl;
00502 }
00503
00504 delete command.m_pData.String;
00505 break;
00506 }
00507 case CCommand::PARAMETER_OPENGLSPECULAR:
00508 {
00509 if (*command.m_pData.String == "on")
00510 {
00511 surfaceobj.m_Options = surfaceobj.m_Options | OPTION_OPENGLSPECULAR;
00512 }
00513 else if (*command.m_pData.String == "off")
00514 {
00515 surfaceobj.m_Options = surfaceobj.m_Options & ~OPTION_OPENGLSPECULAR;
00516 }
00517 else
00518 {
00519 std::cout << "Parameter error: usage: set OpenGLSpecular {on,off}"
00520 << std::endl;
00521 }
00522
00523 delete command.m_pData.String;
00524 break;
00525 }
00526 default:
00527 {
00528 POP_ILLEGAL("Not supposed to get here");
00529 }
00530 }
00531
00532 break;
00533 }
00534
00536
00537
00538
00540 case CCommand::COMMAND_PRINT:
00541 {
00542 switch (command.m_ParameterID)
00543 {
00544 case CCommand::PARAMETER_FORMULASTRING:
00545 {
00546 std::cout << surfaceobj.m_FormulaString << std::endl;
00547 break;
00548 }
00549 case CCommand::PARAMETER_SIGNINCREMENT:
00550 {
00551 std::cout << surfaceobj.m_SignIncrement << std::endl;
00552 break;
00553 }
00554 case CCommand::PARAMETER_NOSIGNINCREMENT:
00555 {
00556 std::cout << surfaceobj.m_NoSignIncrement << std::endl;
00557 break;
00558 }
00559 case CCommand::PARAMETER_NOSIGNPRECISION:
00560 {
00561 std::cout << surfaceobj.m_NoSignPrecision << std::endl;
00562 break;
00563 }
00564 case CCommand::PARAMETER_ZOOM:
00565 {
00566 std::cout << surfaceobj.m_Zoom << std::endl;
00567 break;
00568 }
00569 case CCommand::PARAMETER_MINVECTOR:
00570 {
00571 std::cout << surfaceobj.m_MinVector << std::endl;
00572 break;
00573 }
00574 case CCommand::PARAMETER_MAXVECTOR:
00575 {
00576 std::cout << surfaceobj.m_MaxVector << std::endl;
00577 break;
00578 }
00579 case CCommand::PARAMETER_VIEWERPOS:
00580 {
00581 std::cout << surfaceobj.m_ViewerPos << std::endl;
00582 break;
00583 }
00584 case CCommand::PARAMETER_LIGHTDIRECTION:
00585 {
00586 std::cout << surfaceobj.m_LightDirection << std::endl;
00587 break;
00588 }
00589 case CCommand::PARAMETER_SURFACEAMBIENTCOLOR:
00590 {
00591 std::cout << surfaceobj.m_SurfaceAmbientColor << std::endl;
00592 break;
00593 }
00594 case CCommand::PARAMETER_SURFACEDIFFUSECOLOR:
00595 {
00596 std::cout << surfaceobj.m_SurfaceDiffuseColor << std::endl;
00597 break;
00598 }
00599 case CCommand::PARAMETER_SURFACESPECULARCOLOR:
00600 {
00601 std::cout << surfaceobj.m_SurfaceSpecularColor << std::endl;
00602 break;
00603 }
00604 case CCommand::PARAMETER_SURFACESPECULAREXPONENT:
00605 {
00606 std::cout << surfaceobj.m_SurfaceSpecularExponent << std::endl;
00607 break;
00608 }
00609 case CCommand::PARAMETER_BOXAMBIENTCOLOR:
00610 {
00611 std::cout << surfaceobj.m_BoxAmbientColor << std::endl;
00612 break;
00613 }
00614 case CCommand::PARAMETER_BOXDIFFUSECOLOR:
00615 {
00616 std::cout << surfaceobj.m_BoxDiffuseColor << std::endl;
00617 break;
00618 }
00619 case CCommand::PARAMETER_BOXSPECULARCOLOR:
00620 {
00621 std::cout << surfaceobj.m_BoxSpecularColor << std::endl;
00622 break;
00623 }
00624 case CCommand::PARAMETER_BOXSPECULAREXPONENT:
00625 {
00626 std::cout << surfaceobj.m_BoxSpecularExponent << std::endl;
00627 break;
00628 }
00629 case CCommand::PARAMETER_BACKGROUNDCOLOR:
00630 {
00631 std::cout << surfaceobj.m_BackgroundColor << std::endl;
00632 break;
00633 }
00634 case CCommand::PARAMETER_WIDTH:
00635 {
00636 std::cout << surfaceobj.m_Width << std::endl;
00637 break;
00638 }
00639 case CCommand::PARAMETER_HEIGHT:
00640 {
00641 std::cout << surfaceobj.m_Height << std::endl;
00642 break;
00643 }
00644 case CCommand::PARAMETER_PERSPECTIVE:
00645 {
00646 std::cout << ((surfaceobj.m_Options & OPTION_PERSPECTIVE) ? "on" : "off")
00647 << std::endl;
00648 break;
00649 }
00650 case CCommand::PARAMETER_BOUNDINGBOX:
00651 {
00652 std::cout << ((surfaceobj.m_Options & OPTION_BOUNDINGBOX) ? "on" : "off")
00653 << std::endl;
00654 break;
00655 }
00656 case CCommand::PARAMETER_SIGN:
00657 {
00658 std::cout << ((surfaceobj.m_Options & OPTION_SIGN) ? "on" : "off")
00659 << std::endl;
00660 break;
00661 }
00662 case CCommand::PARAMETER_OPENGLSPECULAR:
00663 {
00664 std::cout << ((surfaceobj.m_Options & OPTION_OPENGLSPECULAR) ? "on" : "off")
00665 << std::endl;
00666 break;
00667 }
00668 case CCommand::PARAMETER_END:
00669 {
00670
00671 CCommand FakeCommand;
00672 FakeCommand.m_CommandID = CCommand::COMMAND_PRINT;
00673
00674 for (int i = 0; i < CCommand::PARAMETER_END; ++i)
00675 {
00676 std::cout << CCommand::s_ParameterString[i] << ": ";
00677 FakeCommand.m_ParameterID = (CCommand::TYPE_PARAMETER) i;
00678 Execute(FakeCommand, surfaceobj);
00679 }
00680
00681 break;
00682 }
00683 default:
00684 {
00685 POP_ILLEGAL("Not supposed to get here");
00686 }
00687 }
00688
00689 break;
00690 }
00691
00693
00694
00695
00697 case CCommand::COMMAND_QUIT:
00698 {
00699 std::cout << "Thanks for using MathRay." << std::endl;
00700 exit(0);
00701 break;
00702 }
00703
00704 case CCommand::COMMAND_END:
00705 {
00706 std::cout << "type 'help' for more info" << std::endl;
00707 break;
00708 }
00709
00710 default:
00711 {
00712 POP_ILLEGAL("Not supposed to get here");
00713 }
00714 }
00715 }
00716
00717