Initial commit.
This commit is contained in:
parent
41a2582ff6
commit
088196decf
|
@ -0,0 +1,385 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
022C25F6239ADF4400E2D35D /* Source.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 022C25F4239ADF4400E2D35D /* Source.cpp */; };
|
||||
026842D323D727A70023E614 /* ObjetDiffusant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 026842D123D727A70023E614 /* ObjetDiffusant.cpp */; };
|
||||
02862264240ED9750000A6ED /* Scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02F319B423DA713B0059D3AF /* Scene.cpp */; };
|
||||
02AEC71D23F2CB8900816C72 /* ObjetsOptiques.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02AEC71B23F2CB8900816C72 /* ObjetsOptiques.cpp */; };
|
||||
02B2BEE923FF44B8009FDF7F /* SceneTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02B2BEE723FF44B8009FDF7F /* SceneTest.cpp */; };
|
||||
02C0BBF923F99485006F99C7 /* Brouillard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02C0BBF723F99485006F99C7 /* Brouillard.cpp */; };
|
||||
02D1B5942376E96400B7FC13 /* ObjetsCourbes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02D1B5922376E96400B7FC13 /* ObjetsCourbes.cpp */; };
|
||||
02D1B5972376EC0E00B7FC13 /* Rayon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02D1B5952376EC0E00B7FC13 /* Rayon.cpp */; };
|
||||
02D1B59A2377242B00B7FC13 /* Util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02D1B5982377242B00B7FC13 /* Util.cpp */; };
|
||||
02D1B59D237744EC00B7FC13 /* ObjetMilieux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02D1B59B237744EC00B7FC13 /* ObjetMilieux.cpp */; };
|
||||
02D1B5A02379ED3B00B7FC13 /* Ecran.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02D1B59E2379ED3B00B7FC13 /* Ecran.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
020AFBD8240006F6009C70B1 /* main_brouillard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main_brouillard.cpp; sourceTree = "<group>"; };
|
||||
022C25F4239ADF4400E2D35D /* Source.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Source.cpp; sourceTree = "<group>"; };
|
||||
022C25F5239ADF4400E2D35D /* Source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Source.h; sourceTree = "<group>"; };
|
||||
0231D0D223FF5743009E26E3 /* main_milieux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main_milieux.cpp; sourceTree = "<group>"; };
|
||||
0266D47823A9A64D00A89D08 /* sfml_c01.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = sfml_c01.hpp; path = ../../Libs/sfml_c01.hpp; sourceTree = "<group>"; };
|
||||
026842D123D727A70023E614 /* ObjetDiffusant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjetDiffusant.cpp; sourceTree = "<group>"; };
|
||||
026842D223D727A70023E614 /* ObjetDiffusant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjetDiffusant.h; sourceTree = "<group>"; };
|
||||
0273457B240C0E6B00C35E09 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = "<none>"; };
|
||||
02AEC71B23F2CB8900816C72 /* ObjetsOptiques.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjetsOptiques.cpp; sourceTree = "<group>"; };
|
||||
02AEC71C23F2CB8900816C72 /* ObjetsOptiques.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjetsOptiques.h; sourceTree = "<group>"; };
|
||||
02AEC71F23F33ACF00816C72 /* ObjetsCourbes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjetsCourbes.h; sourceTree = "<group>"; };
|
||||
02AEC72123F3619600816C72 /* main_debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main_debug.cpp; sourceTree = "<group>"; };
|
||||
02B2BEE523FEAF75009FDF7F /* main_diffus_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main_diffus_test.cpp; sourceTree = "<group>"; };
|
||||
02B2BEE723FF44B8009FDF7F /* SceneTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneTest.cpp; sourceTree = "<group>"; };
|
||||
02B2BEE823FF44B8009FDF7F /* SceneTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneTest.h; sourceTree = "<group>"; };
|
||||
02C0BBF723F99485006F99C7 /* Brouillard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Brouillard.cpp; sourceTree = "<group>"; };
|
||||
02C0BBF823F99485006F99C7 /* Brouillard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Brouillard.h; sourceTree = "<group>"; };
|
||||
02D1B57A23762C8200B7FC13 /* LightRays.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LightRays.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
02D1B57E23762C8300B7FC13 /* LightRays-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LightRays-Info.plist"; sourceTree = "<group>"; };
|
||||
02D1B58223762C8300B7FC13 /* main_store.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main_store.cpp; sourceTree = "<group>"; };
|
||||
02D1B5922376E96400B7FC13 /* ObjetsCourbes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjetsCourbes.cpp; sourceTree = "<group>"; };
|
||||
02D1B5932376E96400B7FC13 /* Objet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Objet.h; sourceTree = "<group>"; };
|
||||
02D1B5952376EC0E00B7FC13 /* Rayon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Rayon.cpp; sourceTree = "<group>"; };
|
||||
02D1B5962376EC0E00B7FC13 /* Rayon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Rayon.h; sourceTree = "<group>"; };
|
||||
02D1B5982377242B00B7FC13 /* Util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Util.cpp; sourceTree = "<group>"; };
|
||||
02D1B5992377242B00B7FC13 /* Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Util.h; sourceTree = "<group>"; };
|
||||
02D1B59B237744EC00B7FC13 /* ObjetMilieux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjetMilieux.cpp; sourceTree = "<group>"; };
|
||||
02D1B59C237744EC00B7FC13 /* ObjetMilieux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjetMilieux.h; sourceTree = "<group>"; };
|
||||
02D1B59E2379ED3B00B7FC13 /* Ecran.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Ecran.cpp; sourceTree = "<group>"; };
|
||||
02D1B59F2379ED3B00B7FC13 /* Ecran.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Ecran.h; sourceTree = "<group>"; };
|
||||
02F319B423DA713B0059D3AF /* Scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scene.cpp; sourceTree = "<group>"; };
|
||||
02F319B523DA713B0059D3AF /* Scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scene.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
02D1B57623762C8200B7FC13 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
02D1B57023762C8200B7FC13 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
02D1B57C23762C8200B7FC13 /* LightRays */,
|
||||
02D1B57B23762C8200B7FC13 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
02D1B57B23762C8200B7FC13 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
02D1B57A23762C8200B7FC13 /* LightRays.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
02D1B57C23762C8200B7FC13 /* LightRays */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
02D1B5992377242B00B7FC13 /* Util.h */,
|
||||
02D1B5982377242B00B7FC13 /* Util.cpp */,
|
||||
02D1B5962376EC0E00B7FC13 /* Rayon.h */,
|
||||
02D1B5952376EC0E00B7FC13 /* Rayon.cpp */,
|
||||
02D1B5932376E96400B7FC13 /* Objet.h */,
|
||||
02AEC71F23F33ACF00816C72 /* ObjetsCourbes.h */,
|
||||
02D1B5922376E96400B7FC13 /* ObjetsCourbes.cpp */,
|
||||
02D1B59C237744EC00B7FC13 /* ObjetMilieux.h */,
|
||||
02D1B59B237744EC00B7FC13 /* ObjetMilieux.cpp */,
|
||||
026842D223D727A70023E614 /* ObjetDiffusant.h */,
|
||||
026842D123D727A70023E614 /* ObjetDiffusant.cpp */,
|
||||
02AEC71C23F2CB8900816C72 /* ObjetsOptiques.h */,
|
||||
02AEC71B23F2CB8900816C72 /* ObjetsOptiques.cpp */,
|
||||
02C0BBF823F99485006F99C7 /* Brouillard.h */,
|
||||
02C0BBF723F99485006F99C7 /* Brouillard.cpp */,
|
||||
022C25F5239ADF4400E2D35D /* Source.h */,
|
||||
022C25F4239ADF4400E2D35D /* Source.cpp */,
|
||||
02D1B59F2379ED3B00B7FC13 /* Ecran.h */,
|
||||
02D1B59E2379ED3B00B7FC13 /* Ecran.cpp */,
|
||||
02F319B523DA713B0059D3AF /* Scene.h */,
|
||||
02F319B423DA713B0059D3AF /* Scene.cpp */,
|
||||
02B2BEE823FF44B8009FDF7F /* SceneTest.h */,
|
||||
02B2BEE723FF44B8009FDF7F /* SceneTest.cpp */,
|
||||
02B2BEE523FEAF75009FDF7F /* main_diffus_test.cpp */,
|
||||
02D1B58223762C8300B7FC13 /* main_store.cpp */,
|
||||
020AFBD8240006F6009C70B1 /* main_brouillard.cpp */,
|
||||
0231D0D223FF5743009E26E3 /* main_milieux.cpp */,
|
||||
02AEC72123F3619600816C72 /* main_debug.cpp */,
|
||||
0266D47823A9A64D00A89D08 /* sfml_c01.hpp */,
|
||||
0273457B240C0E6B00C35E09 /* Makefile */,
|
||||
02D1B57D23762C8200B7FC13 /* Supporting Files */,
|
||||
);
|
||||
path = LightRays;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
02D1B57D23762C8200B7FC13 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
02D1B57E23762C8300B7FC13 /* LightRays-Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
02D1B57923762C8200B7FC13 /* LightRays */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 02D1B58F23762C8300B7FC13 /* Build configuration list for PBXNativeTarget "LightRays" */;
|
||||
buildPhases = (
|
||||
02D1B57523762C8200B7FC13 /* Sources */,
|
||||
02D1B57623762C8200B7FC13 /* Frameworks */,
|
||||
02D1B57723762C8200B7FC13 /* Resources */,
|
||||
02D1B57823762C8200B7FC13 /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = LightRays;
|
||||
productName = LightRays;
|
||||
productReference = 02D1B57A23762C8200B7FC13 /* LightRays.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
02D1B57123762C8200B7FC13 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0620;
|
||||
ORGANIZATIONNAME = xif;
|
||||
TargetAttributes = {
|
||||
02D1B57923762C8200B7FC13 = {
|
||||
CreatedOnToolsVersion = 6.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 02D1B57423762C8200B7FC13 /* Build configuration list for PBXProject "LightRays" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 02D1B57023762C8200B7FC13;
|
||||
productRefGroup = 02D1B57B23762C8200B7FC13 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
02D1B57923762C8200B7FC13 /* LightRays */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
02D1B57723762C8200B7FC13 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
02D1B57823762C8200B7FC13 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# This shell script simply copies required SFML dylibs/frameworks into the application bundle frameworks folder.\n# If you're using static libraries (which is not recommended) you should remove this script from your project.\n\n# SETTINGS\nCMAKE_INSTALL_FRAMEWORK_PREFIX=\"/Library/Frameworks\"\nCMAKE_INSTALL_LIB_PREFIX=\"/usr/local/lib\"\nFRAMEWORKS_FULL_PATH=\"$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/\"\n\n# Are we building a project that uses frameworks or dylibs?\ncase \"$SFML_BINARY_TYPE\" in\n DYLIBS)\n frameworks=\"false\"\n ;;\n *)\n frameworks=\"true\"\n ;;\nesac\n\n# Echoes to stderr\nerror () # $* message to display\n{\n echo $* 1>&2\n exit 2\n}\n\nassert () # $1 is a boolean, $2...N is an error message\n{\n if [ $# -lt 2 ]\n then\n error \"Internal error in assert: not enough args\"\n fi\n\n if [ $1 -ne 0 ]\n then\n shift\n error \"$*\"\n fi\n}\n\nforce_remove () # $@ is some paths\n{\n test $# -ge 1\n assert $? \"force_remove() requires at least one parameter\"\n rm -fr $@\n assert $? \"couldn't remove $@\"\n}\n\ncopy () # $1 is a source, $2 is a destination\n{\n test $# -eq 2\n assert $? \"copy() requires two parameters\"\n ditto \"$1\" \"$2\"\n assert $? \"couldn't copy $1 to $2\"\n}\n\nrequire () # $1 is a SFML module like 'system' or 'audio'\n{\n dest=\"$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/\"\n\n if [ -z \"$1\" ]\n then\n error \"require() requires one parameter!\"\n else\n # clean potentially old stuff\n force_remove \"$dest/libsfml-$1\"*\n force_remove \"$dest/sfml-$1.framework\"\n\n # copy SFML libraries\n if [ \"$frameworks\" = \"true\" ]\n then\n source=\"$CMAKE_INSTALL_FRAMEWORK_PREFIX/sfml-$1.framework\"\n target=\"sfml-$1.framework\"\n elif [ \"$SFML_LINK_DYLIBS_SUFFIX\" = \"-d\" ]\n then\n source=\"$CMAKE_INSTALL_LIB_PREFIX/libsfml-$1-d.dylib\"\n target=\"`readlink $source`\"\n else\n source=\"$CMAKE_INSTALL_LIB_PREFIX/libsfml-$1.dylib\"\n target=\"`readlink $source`\"\n fi\n\n copy \"$source\" \"$dest/$target\"\n\n # copy extra dependencies\n if [ \"$1\" = \"audio\" ]\n then\n # copy \"FLAC\" \"ogg\" \"vorbis\" \"vorbisenc\" \"vorbisfile\" \"OpenAL\" frameworks too\n for f in \"FLAC\" \"ogg\" \"vorbis\" \"vorbisenc\" \"vorbisfile\" \"OpenAL\"\n do\n copy \"$CMAKE_INSTALL_FRAMEWORK_PREFIX/$f.framework\" \"$dest/$f.framework\"\n done\n elif [ \"$1\" = \"graphics\" ]\n then\n copy \"$CMAKE_INSTALL_FRAMEWORK_PREFIX/freetype.framework\" \"$dest/freetype.framework\"\n fi\n fi\n}\n\nif [ -n \"$SFML_SYSTEM\" ]\nthen\n require \"system\"\nfi\n\nif [ -n \"$SFML_AUDIO\" ]\nthen\n require \"audio\"\nfi\n\nif [ -n \"$SFML_NETWORK\" ]\nthen\n require \"network\"\nfi\n\nif [ -n \"$SFML_WINDOW\" ]\nthen\n require \"window\"\nfi\n\nif [ -n \"$SFML_GRAPHICS\" ]\nthen\n require \"graphics\"\nfi\n\n ";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
02D1B57523762C8200B7FC13 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
02D1B5942376E96400B7FC13 /* ObjetsCourbes.cpp in Sources */,
|
||||
02862264240ED9750000A6ED /* Scene.cpp in Sources */,
|
||||
026842D323D727A70023E614 /* ObjetDiffusant.cpp in Sources */,
|
||||
02D1B59D237744EC00B7FC13 /* ObjetMilieux.cpp in Sources */,
|
||||
022C25F6239ADF4400E2D35D /* Source.cpp in Sources */,
|
||||
02D1B5A02379ED3B00B7FC13 /* Ecran.cpp in Sources */,
|
||||
02C0BBF923F99485006F99C7 /* Brouillard.cpp in Sources */,
|
||||
02D1B5972376EC0E00B7FC13 /* Rayon.cpp in Sources */,
|
||||
02B2BEE923FF44B8009FDF7F /* SceneTest.cpp in Sources */,
|
||||
02D1B59A2377242B00B7FC13 /* Util.cpp in Sources */,
|
||||
02AEC71D23F2CB8900816C72 /* ObjetsOptiques.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
02D1B58D23762C8300B7FC13 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
/Library/Frameworks/,
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/usr/local/include/,
|
||||
"$(inherited)",
|
||||
../../Libs/,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
/usr/local/lib/,
|
||||
"$(inherited)",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-DSFMLC01_WINDOW_UNIT=720",
|
||||
"-Dvec2_t=vec_t",
|
||||
"-Dpt2_t=point_t",
|
||||
"-DFONT_PATH=\\\"/Users/xif/Desktop/Code/LightRays/LightRays/DejaVuSansMono.ttf\\\"",
|
||||
"-DNOSTDOPTIONAL",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"$(SFML_SYSTEM)",
|
||||
"$(SFML_WINDOW)",
|
||||
"$(SFML_GRAPHICS)",
|
||||
"$(SFML_AUDIO)",
|
||||
"$(SFML_NETWORK)",
|
||||
"-lfmt",
|
||||
);
|
||||
SFML_AUDIO = "";
|
||||
SFML_BINARY_TYPE = FRAMEWORKS;
|
||||
SFML_GRAPHICS = "$(SFML_LINK_PREFIX) sfml-graphics$(SFML_LINK_SUFFIX)";
|
||||
SFML_LINK_DYLIBS_PREFIX = "-l";
|
||||
SFML_LINK_DYLIBS_SUFFIX = "";
|
||||
SFML_LINK_FRAMEWORKS_PREFIX = "-framework";
|
||||
SFML_LINK_FRAMEWORKS_SUFFIX = "";
|
||||
SFML_LINK_PREFIX = "$(SFML_LINK_$(SFML_BINARY_TYPE)_PREFIX)";
|
||||
SFML_LINK_SUFFIX = "$(SFML_LINK_$(SFML_BINARY_TYPE)_SUFFIX)";
|
||||
SFML_NETWORK = "";
|
||||
SFML_SYSTEM = "$(SFML_LINK_PREFIX) sfml-system$(SFML_LINK_SUFFIX)";
|
||||
SFML_WINDOW = "$(SFML_LINK_PREFIX) sfml-window$(SFML_LINK_SUFFIX)";
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
02D1B58E23762C8300B7FC13 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
/Library/Frameworks/,
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
/usr/local/include/,
|
||||
"$(inherited)",
|
||||
../../Libs/,
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
/usr/local/lib/,
|
||||
"$(inherited)",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-DSFMLC01_WINDOW_UNIT=720",
|
||||
"-Dvec2_t=vec_t",
|
||||
"-Dpt2_t=point_t",
|
||||
"-DFONT_PATH=\\\"/Users/xif/Desktop/Code/LightRays/LightRays/DejaVuSansMono.ttf\\\"",
|
||||
"-DNOSTDOPTIONAL",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"$(SFML_SYSTEM)",
|
||||
"$(SFML_WINDOW)",
|
||||
"$(SFML_GRAPHICS)",
|
||||
"$(SFML_AUDIO)",
|
||||
"$(SFML_NETWORK)",
|
||||
"-lfmt",
|
||||
);
|
||||
SFML_AUDIO = "";
|
||||
SFML_BINARY_TYPE = FRAMEWORKS;
|
||||
SFML_GRAPHICS = "$(SFML_LINK_PREFIX) sfml-graphics$(SFML_LINK_SUFFIX)";
|
||||
SFML_LINK_DYLIBS_PREFIX = "-l";
|
||||
SFML_LINK_DYLIBS_SUFFIX = "";
|
||||
SFML_LINK_FRAMEWORKS_PREFIX = "-framework";
|
||||
SFML_LINK_FRAMEWORKS_SUFFIX = "";
|
||||
SFML_LINK_PREFIX = "$(SFML_LINK_$(SFML_BINARY_TYPE)_PREFIX)";
|
||||
SFML_LINK_SUFFIX = "$(SFML_LINK_$(SFML_BINARY_TYPE)_SUFFIX)";
|
||||
SFML_NETWORK = "";
|
||||
SFML_SYSTEM = "$(SFML_LINK_PREFIX) sfml-system$(SFML_LINK_SUFFIX)";
|
||||
SFML_WINDOW = "$(SFML_LINK_PREFIX) sfml-window$(SFML_LINK_SUFFIX)";
|
||||
SUPPORTED_PLATFORMS = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
02D1B59023762C8300B7FC13 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = "LightRays/LightRays-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
OTHER_CFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
02D1B59123762C8300B7FC13 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = "LightRays/LightRays-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
OTHER_CFLAGS = "";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
02D1B57423762C8200B7FC13 /* Build configuration list for PBXProject "LightRays" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
02D1B58D23762C8300B7FC13 /* Debug */,
|
||||
02D1B58E23762C8300B7FC13 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
02D1B58F23762C8300B7FC13 /* Build configuration list for PBXNativeTarget "LightRays" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
02D1B59023762C8300B7FC13 /* Debug */,
|
||||
02D1B59123762C8300B7FC13 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 02D1B57123762C8200B7FC13 /* Project object */;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:LightRays.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,151 @@
|
|||
#include "Brouillard.h"
|
||||
#include "ObjetsCourbes.h"
|
||||
#include <cmath>
|
||||
|
||||
Objet::extension_t Objet_Brouillard::objet_extension () const {
|
||||
vec_t v = { lx*reso_x/2, ly*reso_y/2 };
|
||||
return {
|
||||
.pos = o + v,
|
||||
.rayon = std::max(v.x, v.y)
|
||||
};
|
||||
}
|
||||
|
||||
// Test d'interception avec le brouillard : parcours du rayon à travers les cellules
|
||||
// et décision si oui ou non on diffuserait le rayon
|
||||
//
|
||||
Objet::intercept_t Objet_Brouillard::essai_intercept (const Rayon& ray) const {
|
||||
|
||||
if (ray.spectre.intensite_tot() < intens_cutoff)
|
||||
return { .dist2 = Inf, .intercept_struct = nullptr };
|
||||
|
||||
// on test si le rayon passe sur le rectange bornant le brouillard
|
||||
std::vector<ObjetLigne::intersection_segdd_t> isects;
|
||||
auto test_isect = [&] (point_t a, point_t b) {
|
||||
auto isect = ObjetLigne::intersection_segment_demidroite(a, b, ray.orig, ray.dir_angle);
|
||||
if (isect.has_value())
|
||||
isects.push_back(isect.value());
|
||||
};
|
||||
point_t o2 = o + vec_t{lx*reso_x,0},
|
||||
o3 = o + vec_t{lx*reso_x,ly*reso_y},
|
||||
o4 = o + vec_t{0,ly*reso_y};
|
||||
test_isect(o , o2);
|
||||
test_isect(o2, o3);
|
||||
test_isect(o3, o4);
|
||||
test_isect(o4, o );
|
||||
// assert(isects.size() <= 2); // le rayon ne peut avoir que 1 (si source interne) ou 2 intersections (ou zéro) avec les bords
|
||||
|
||||
if (isects.size() != 0) {
|
||||
|
||||
float s;
|
||||
float s_fin = isects[0].t_dd;
|
||||
if (isects.size() == 1) { // rayon émis à l'intérieur du brouillard
|
||||
s = 0;
|
||||
} else { // rayon provenant de l'expérieur du brouillard
|
||||
s = isects[1].t_dd;
|
||||
if (s > s_fin)
|
||||
std::swap(s, s_fin);
|
||||
}
|
||||
float ds = std::min(reso_x,reso_y) / 2;
|
||||
vec_t u_ray = isects[0].u_dd;
|
||||
// le rayon parcourt le brouillard jusqu'à s_fin par incréments de ds
|
||||
// avec une probabilité donnée par `densit_brouillard` d'être diffusé à chaque pas, pour la méthode 1
|
||||
// et avec une probabilité de `diffus_partielle_syst_proba`
|
||||
intercept_brouillard_t p;
|
||||
float proba_acc = 0;
|
||||
|
||||
while (s < s_fin) {
|
||||
p.p_diff = ray.orig + s * u_ray;
|
||||
vec_t v = p.p_diff - this->o;
|
||||
p.x_diff = floorf( v.x / reso_x );
|
||||
p.y_diff = floorf( v.y / reso_y );
|
||||
if (0 <= p.x_diff and p.x_diff < (int)this->lx and 0 <= p.y_diff and p.y_diff < (int)this->ly) {
|
||||
|
||||
float proba = ds / diffus_partielle_syst_libreparcours;
|
||||
if (proba > 1e-5) {
|
||||
// méthode par diffusion systématique partielle
|
||||
proba_acc += proba;
|
||||
p.fraction_transmis = std::max<float>(0, 1 - ds/proba * this->densit_brouillard(p.x_diff, p.y_diff));
|
||||
} else {
|
||||
// méthode par diffusion probabiliste complète
|
||||
proba = ds * this->densit_brouillard(p.x_diff, p.y_diff);
|
||||
proba_acc += proba;
|
||||
p.fraction_transmis = 0;
|
||||
}
|
||||
bool diffuse = parcours_deterministe ? (proba_acc >= 1) : (rand01() < proba);
|
||||
if (diffuse) {
|
||||
// rayon diffusé
|
||||
s += /*rand01() */ ds;
|
||||
p.p_diff = ray.orig + s * u_ray;
|
||||
return { .dist2 = s*s,
|
||||
.intercept_struct = std::make_shared<intercept_brouillard_t>(std::move(p)) };
|
||||
}
|
||||
|
||||
}
|
||||
s += ds;
|
||||
}
|
||||
|
||||
}
|
||||
return { .dist2 = Inf, .intercept_struct = nullptr };
|
||||
};
|
||||
|
||||
// Ré-émission du rayon intercepté par le brouillard
|
||||
//
|
||||
std::vector<Rayon> Objet_Brouillard::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
|
||||
const intercept_brouillard_t& intercept = *(intercept_brouillard_t*)interception.get();
|
||||
std::vector<Rayon> rayons;
|
||||
|
||||
// Nombre de rayons secondaires
|
||||
size_t n_re_emit = std::max<size_t>(1, lroundf(
|
||||
n_re_emit_par_intens * ray.spectre.intensite_tot() * (1-intercept.fraction_transmis))
|
||||
);
|
||||
float fact_I_re_emit = 1./n_re_emit;
|
||||
|
||||
// On laisse vivre le rayon incident seulement si il a une intensité > 0.01
|
||||
if (intercept.fraction_transmis > 0.01) {
|
||||
Rayon ray_trsm = ray;
|
||||
ray_trsm.spectre.for_each([&] (float lambda, pola_t, float& I) {
|
||||
I *= intercept.fraction_transmis;
|
||||
});
|
||||
ray_trsm.orig = intercept.p_diff;
|
||||
rayons.push_back(std::move(ray_trsm));
|
||||
|
||||
fact_I_re_emit *= 1 - intercept.fraction_transmis;
|
||||
}
|
||||
|
||||
// Émission des rayons secondaires
|
||||
for (size_t k = 0; k < n_re_emit; k++) {
|
||||
|
||||
float ang_diff = 2*M_PI * rand01();
|
||||
Rayon ray_diff;
|
||||
ray_diff.orig = intercept.p_diff;
|
||||
ray_diff.dir_angle = ray.dir_angle + ang_diff;
|
||||
|
||||
ray_diff.spectre = ray.spectre;
|
||||
ray_diff.spectre.for_each([&] (float lambda, pola_t, float& I) {
|
||||
I *= this->directivite_diffus(ang_diff, lambda) * fact_I_re_emit;
|
||||
});
|
||||
|
||||
rayons.push_back(std::move(ray_diff));
|
||||
}
|
||||
return rayons;
|
||||
}
|
||||
|
||||
#include "sfml_c01.hpp"
|
||||
|
||||
void Objet_Brouillard::dessiner (sf::RenderWindow& window, bool emphasize) const {
|
||||
for (size_t x = 0; x < this->lx; x++) {
|
||||
for (size_t y = 0; y < this->ly; y++) {
|
||||
sf::RectangleShape dens;
|
||||
sf::c01::setRectShape(dens, o + vec_t{reso_x*x, reso_y*y}, {reso_x, reso_y});
|
||||
dens.setFillColor(sf::Color(255,255,255, std::min(255.f, this->densit_brouillard(x,y)) ));
|
||||
window.draw(dens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<point_t> Objet_Brouillard::point_interception (std::shared_ptr<void> interception) const {
|
||||
if (interception) {
|
||||
return ((intercept_brouillard_t*)interception.get())->p_diff;
|
||||
} else
|
||||
return std::nullopt;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* Brouillards.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIGHTRAYS_BROUILLARD_H_
|
||||
#define _LIGHTRAYS_BROUILLARD_H_
|
||||
|
||||
#include "Objet.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Brouillard à "cellules/voxels" de densité arbitraire. Implémentation naïve,
|
||||
// loin d'être performante.
|
||||
|
||||
class Objet_Brouillard : virtual public Objet {
|
||||
public:
|
||||
point_t o; // bottom-left corner (origine)
|
||||
float reso_x, reso_y; // résolutions (taille d'une cellule du brouillard) dans les directions x et y
|
||||
uint lx, ly; // taille du brouillard en nombre de cellules
|
||||
std::function< float(size_t x, size_t y) > densit_brouillard; // fonction densité(x,y) du brouillard
|
||||
std::function< float(float theta, float lambda) > directivite_diffus; // distribution angulaire des rayons diffusés, avec theta l'angle du rayon diffusé par rapport au rayon incident
|
||||
|
||||
// Il y a deux techniques de diffusion (non équivalentes en terme de résultat) :
|
||||
// - soit on diffuse totalement (en `n_re_emit_par_intens` rayons-fils, avec la directivité `directivite_diffus`)
|
||||
// le rayon avec une probabilité à chaque pas donnée par la densité du brouillard
|
||||
// ("diffusion browienne")
|
||||
// (adapté au temps réel car peu de rayons produits, mais résultat bruité)
|
||||
// - soit on diffuse partiellement (fraction donnée par la densité du brouillard, et en
|
||||
// `n_re_emit_par_intens` rayons-fils, avec la directivité `directivite_diffus`) le rayon,
|
||||
// mais systématiquement avec un libre parcours moyen `diffus_partielle_syst_libreparcours`
|
||||
// ("diffusion à la bert-lambert") (attention, la directivité effective est `directivite_diffus` + un dirac theta=0)
|
||||
// (peu bruité, mais lent car "cascade" -> nombreux rayons produits)
|
||||
// La deuxième méthode est utilisée lorsque `diffus_partielle_syst_libreparcours` est non infini
|
||||
// Lorsque la longueur `diffus_partielle_syst_libreparcours` n'est pas trop grande face à la taille du brouillard,
|
||||
// et qu'elle est supérieure à la résolution, les deux méthodes doivent donner la même intensité
|
||||
// transmise en ligne droite ("rayon non dévié") en moyenne
|
||||
float n_re_emit_par_intens;
|
||||
float diffus_partielle_syst_libreparcours;
|
||||
|
||||
// Parcours déterministe ou non du rayon passant à traver le brouillard. Typiquement, soit
|
||||
// on fait une diffusion du rayon aléatoire avec une certaine probabilité, soit on diffuse
|
||||
// régulièrement le rayon avec cette même "probabilité". Les deux méthodes convergent à
|
||||
// grande résolution.
|
||||
bool parcours_deterministe;
|
||||
|
||||
// Les rayons d'intensité < `intens_cutoff` sont ignorés (amélioration de performance)
|
||||
float intens_cutoff;
|
||||
|
||||
// Par défaut, méthode "brownienne", directivté uniforme, parcours aléatoire, pas de cutoff
|
||||
Objet_Brouillard (point_t o, float reso_x, float reso_y, uint lx, uint ly, decltype(densit_brouillard) densit_brouillard) :
|
||||
o(o), reso_x(reso_x), reso_y(reso_y), lx(lx), ly(ly), densit_brouillard(densit_brouillard),
|
||||
directivite_diffus([] (float, float) { return 1.f; }),
|
||||
n_re_emit_par_intens(5), diffus_partielle_syst_libreparcours(Inf), parcours_deterministe(false), intens_cutoff(0) {}
|
||||
|
||||
Objet_Brouillard& operator= (const Objet_Brouillard&) = default;
|
||||
Objet_Brouillard (const Objet_Brouillard&) = default;
|
||||
virtual ~Objet_Brouillard () {}
|
||||
|
||||
// Routines d'interception et de ré-émission
|
||||
struct intercept_brouillard_t {
|
||||
point_t p_diff;
|
||||
int x_diff, y_diff;
|
||||
float fraction_transmis;
|
||||
};
|
||||
virtual intercept_t essai_intercept (const Rayon&) const override;
|
||||
virtual extension_t objet_extension () const override;
|
||||
virtual std::vector<Rayon> re_emit (const Rayon&, std::shared_ptr<void>) override;
|
||||
virtual std::optional<point_t> point_interception (std::shared_ptr<void> intercept_struct) const override;
|
||||
|
||||
// Dessin
|
||||
virtual void dessiner (sf::RenderWindow& window, bool emphasize) const override;
|
||||
// Pas de dessin d'interception
|
||||
virtual void dessiner_interception (sf::RenderWindow& window, const Rayon& ray, std::shared_ptr<void> intercept) const override {};
|
||||
};
|
||||
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,142 @@
|
|||
#include "Ecran.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include "sfml_c01.hpp"
|
||||
|
||||
///------------------------ EcranLigne_Multi ------------------------///
|
||||
|
||||
EcranLigne_Multi::EcranLigne_Multi (point_t a, point_t b, float bin_dens, float lumino) :
|
||||
EcranLigne_Multi (a, b, (uint16_t)(bin_dens * !(b-a)), lumino) {}
|
||||
|
||||
EcranLigne_Multi::EcranLigne_Multi (point_t a, point_t b, uint16_t bins_n, float lumino) :
|
||||
Ecran_Base(lumino),
|
||||
ObjetLigne(a, b),
|
||||
bins_intensit( std::max<size_t>(1, bins_n) ),
|
||||
epaisseur_affich(std::nullopt)
|
||||
{ this->reset(); }
|
||||
|
||||
void EcranLigne_Multi::reset () {
|
||||
n_acc = 0;
|
||||
for (Specte& intensit : bins_intensit) {
|
||||
intensit.for_each([&] (float, pola_t, float& I) -> void {
|
||||
I = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Accumulation des rayons dans les pixels
|
||||
//
|
||||
std::vector<Rayon> EcranLigne_Multi::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
|
||||
intercept_ligne_t& intercept = *(intercept_ligne_t*)interception.get();
|
||||
size_t N = bins_intensit.size();
|
||||
ssize_t k_bin = floorf(intercept.s_incid * N);
|
||||
if (k_bin == -1) k_bin = 0;
|
||||
if (k_bin == (ssize_t)N) k_bin = N-1;
|
||||
Specte::for_each_manual([&] (size_t i, float lambda, pola_t pol) -> void {
|
||||
bins_intensit[k_bin].comps[i] += ray.spectre.comps[i];
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
// Retrourne la matrice de pixels traitée
|
||||
//
|
||||
std::vector<EcranLigne_Multi::pixel_t> EcranLigne_Multi::matrice_pixels () const {
|
||||
size_t N = this->bins_intensit.size();
|
||||
// dans chaque pixel, c'est une puissance qu'on accumule, proportionnelle
|
||||
// à la taille d'un pixel ( |b-a|/N ) pour une source omnidirectionnelle
|
||||
// -> il faut diviser par la taille d'un pixel pour avoir d'intensité
|
||||
// lumineuse (dont la luminosité RGB affichée est proportionnelle)
|
||||
float ItoL = this->luminosite / this->n_acc * (float)N / !(b-a);
|
||||
std::vector<pixel_t> mat (N);
|
||||
for (size_t k = 0; k < N; k++) {
|
||||
mat[k].s1 = k / (float)N;
|
||||
mat[k].s2 = (k+1) / (float)N;
|
||||
mat[k].s_mid = (mat[k].s1 + mat[k].s2) / 2;
|
||||
mat[k].spectre = bins_intensit[k];
|
||||
mat[k].spectre.for_each([&] (float, pola_t, float& I) -> void {
|
||||
I *= ItoL;
|
||||
});
|
||||
std::tie(mat[k].r, mat[k].g, mat[k].b, mat[k].sat) = mat[k].spectre.rgb256_noir_intensite(false);
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
// Dessin de la matrice de pixels
|
||||
//
|
||||
void EcranLigne_Multi::dessiner (sf::RenderWindow& window, bool emphasize) const {
|
||||
std::vector<pixel_t> pix =
|
||||
this->matrice_pixels();
|
||||
vec_t v = a - b;
|
||||
auto p = [&] (float s) { return b + v * s; };
|
||||
if (epaisseur_affich.has_value()) {
|
||||
vec_t perp = v.rotate_p90() / (!v) * (*epaisseur_affich);
|
||||
for (size_t k = 0; k < pix.size(); k++) {
|
||||
auto color = sf::Color(pix[k].r, pix[k].g, pix[k].b);
|
||||
vec_t lng = v * (pix[k].s2 - pix[k].s1);
|
||||
sf::ConvexShape rect = sf::c01::buildParallelogram(p(pix[k].s1), lng, perp, color);
|
||||
window.draw(rect);
|
||||
}
|
||||
} else {
|
||||
for (size_t k = 0; k < pix.size(); k++) {
|
||||
if (pix[k].sat) { // saturation
|
||||
auto c = sf::c01::buildCircleShapeCR(p(pix[k].s_mid), 0.003);
|
||||
c.setFillColor(sf::Color::Yellow);
|
||||
window.draw(c);
|
||||
}
|
||||
auto color = sf::Color(pix[k].r, pix[k].g, pix[k].b);
|
||||
auto line = sf::c01::buildLine(p(pix[k].s1), p(pix[k].s2), color, color);
|
||||
window.draw(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///------------------------ EcranLigne_Mono ------------------------///
|
||||
|
||||
EcranLigne_Mono::EcranLigne_Mono (point_t a, point_t b, float lumino) :
|
||||
Ecran_Base(lumino),
|
||||
ObjetLigne(a, b),
|
||||
intensit()
|
||||
{ this->reset(); }
|
||||
|
||||
void EcranLigne_Mono::reset () {
|
||||
n_acc = 0;
|
||||
intensit.for_each([&] (float, pola_t, float& I) -> void {
|
||||
I = 0;
|
||||
});
|
||||
}
|
||||
|
||||
// Accumulations des rayons sur l'écran
|
||||
//
|
||||
std::vector<Rayon> EcranLigne_Mono::re_emit (const Rayon& ray, std::shared_ptr<void>) {
|
||||
Specte::for_each_manual([&] (size_t i, float lambda, pola_t pol) -> void {
|
||||
intensit.comps[i] += ray.spectre.comps[i];
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
// Pixel traité
|
||||
//
|
||||
EcranLigne_Mono::pixel_t EcranLigne_Mono::pixel () const {
|
||||
float ItoL = this->luminosite / this->n_acc / !(b-a);
|
||||
pixel_t pix;
|
||||
Specte sp = intensit;
|
||||
sp.for_each([&] (float, pola_t, float& I) -> void {
|
||||
I *= ItoL;
|
||||
});
|
||||
std::tie(pix.r, pix.g, pix.b, pix.sat) = sp.rgb256_noir_intensite(false);
|
||||
return pix;
|
||||
}
|
||||
|
||||
// Dessin du pixel
|
||||
//
|
||||
void EcranLigne_Mono::dessiner (sf::RenderWindow& window, bool emphasize) const {
|
||||
pixel_t pix = this->pixel();
|
||||
if (pix.sat) {
|
||||
auto c = sf::c01::buildCircleShapeCR(milieu_2points(a,b), 0.003);
|
||||
c.setFillColor(sf::Color::Yellow);
|
||||
window.draw(c);
|
||||
}
|
||||
auto color = sf::Color(pix.r, pix.g, pix.b);
|
||||
auto line = sf::c01::buildLine(a, b, color, color);
|
||||
window.draw(line);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
* Écrans : objets absorbant les rayons et accumulant l'intensité pour
|
||||
* l'afficher ou l'enregistrer ("CCD").
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIGHTRAYS_ECRAN_H_
|
||||
#define _LIGHTRAYS_ECRAN_H_
|
||||
|
||||
#include "ObjetsCourbes.h"
|
||||
#include <vector>
|
||||
#include "Rayon.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Classe de base virtuelle des écrans. Ne fait rien.
|
||||
|
||||
class Ecran_Base : virtual public Objet {
|
||||
protected:
|
||||
size_t n_acc; // nombre de frames accumulées
|
||||
public:
|
||||
float luminosite; // coefficient de conversion intensité réelle -> intensité affichée
|
||||
|
||||
Ecran_Base (float lumino = 1.) : n_acc(0), luminosite(lumino) {}
|
||||
virtual ~Ecran_Base () {}
|
||||
|
||||
// appellé à la fin de chaque frame
|
||||
virtual void commit () { n_acc++; }
|
||||
// réinitialisation de l'écran
|
||||
virtual void reset () = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Écran en forme de segment. Matrice (1D) de pixels, affichable ou enregistrable.
|
||||
|
||||
class EcranLigne_Multi : virtual public Ecran_Base, virtual public ObjetLigne {
|
||||
protected:
|
||||
std::vector<Specte> bins_intensit; // matrice de pixels; un spectre par pixel
|
||||
public:
|
||||
std::optional<float> epaisseur_affich = std::nullopt; // épaisseur de l'écran affiché
|
||||
|
||||
// Construction à partir des points A et B et du nombre de pixels par unité de longueur
|
||||
EcranLigne_Multi (point_t pos_a, point_t pos_b, float pixel_density, float lumino = 1.);
|
||||
// Construction à partir des points A et B et du nombre de pixels
|
||||
EcranLigne_Multi (point_t pos_a, point_t pos_b, uint16_t pixels_n, float lumino = 1.);
|
||||
|
||||
virtual ~EcranLigne_Multi () {}
|
||||
|
||||
// Absorption et accumulation des rayons; pas de ré-émission
|
||||
virtual std::vector<Rayon> re_emit (const Rayon& ray, std::shared_ptr<void> intercept) override;
|
||||
// Réinitialisation de l'écran
|
||||
virtual void reset () override;
|
||||
|
||||
// Récupération de la matrice de pixels RGB ou spectres :
|
||||
struct pixel_t {
|
||||
float s1, s_mid, s2; // abscice du début, du milieu et de la fin du pixel
|
||||
uint8_t r, g, b; // valeurs RGB (les mêmes qu'affichées)
|
||||
bool sat; // saturation du pixel
|
||||
Specte spectre; // spectre accumulé sur le pixel
|
||||
};
|
||||
std::vector<pixel_t> matrice_pixels () const;
|
||||
// Dessin de cette matrice de pixels
|
||||
virtual void dessiner (sf::RenderWindow& window, bool emphasize) const override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Écran en forme de segment avec un unique pixel
|
||||
|
||||
class EcranLigne_Mono : virtual public Ecran_Base, virtual public ObjetLigne {
|
||||
protected:
|
||||
Specte intensit; // spectre accumulé
|
||||
public:
|
||||
|
||||
EcranLigne_Mono (point_t pos_a, point_t pos_b, float lumino = 1.);
|
||||
virtual ~EcranLigne_Mono () {}
|
||||
|
||||
virtual std::vector<Rayon> re_emit (const Rayon& ray, std::shared_ptr<void> intercept) override;
|
||||
virtual void reset () override;
|
||||
|
||||
struct pixel_t { uint8_t r, g, b; bool sat; };
|
||||
pixel_t pixel () const;
|
||||
virtual void dessiner (sf::RenderWindow& window, bool emphasize) const override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>xif.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,29 @@
|
|||
CPPFLAGS := -O3 -Wall -DSFMLC01_WINDOW_UNIT=720 -Dvec2_t=vec_t -Dpt2_t=point_t -DFONT_PATH=\"DejaVuSansMono.ttf\"
|
||||
LDFLAGS := -lsfml-graphics -lsfml-window -lsfml-system
|
||||
|
||||
all: brouillard diffus_test milieux store
|
||||
|
||||
COMMON := Rayon.o Util.o Scene.o SceneTest.o Ecran.o ObjetsCourbes.o Source.o ObjetsOptiques.o
|
||||
|
||||
brouillard: $(COMMON) Brouillard.o ObjetDiffusant.o main_brouillard.o
|
||||
g++ -o lightrays-brouillard -lm $^ $(LDFLAGS)
|
||||
./lightrays-brouillard
|
||||
|
||||
diffus_test: $(COMMON) ObjetDiffusant.o main_diffus_test.o
|
||||
g++ -o lightrays-diffus_test -lm $^ $(LDFLAGS)
|
||||
./lightrays-diffus_test
|
||||
|
||||
milieux: $(COMMON) ObjetMilieux.o main_milieux.o
|
||||
g++ -o lightrays-milieux -lm $^ $(LDFLAGS)
|
||||
./lightrays-milieux
|
||||
|
||||
store: $(COMMON) ObjetDiffusant.o main_store.o
|
||||
g++ -o lightrays-store -lm $^ $(LDFLAGS)
|
||||
./lightrays-store
|
||||
|
||||
%.o: %.cpp
|
||||
g++ -o $@ -c $< -std=c++17 $(CPPFLAGS)
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm lightrays-*
|
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
* Objet optique générique, capable de se dessiner, et surtout de tester
|
||||
* l'interception d'un rayon, et, le cas échéant, de ré-émettre le rayon.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIGHTRAYS_OBJET_H_
|
||||
#define _LIGHTRAYS_OBJET_H_
|
||||
|
||||
#include <memory>
|
||||
#include "Rayon.h"
|
||||
#include "Util.h"
|
||||
#include <vector>
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
// Note : tous les std::optional<std::shared_ptr<T>> pourraient être remplacés par des T* (null ou pas),
|
||||
// mais il faudrait gérer la désallocation à la main
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Classe de base des objets optiques. Déclare l'interface commune utilisée lors
|
||||
// de la propagation (interception puis ré-émission) des rayons, et l'affichage.
|
||||
// Un objet est capable de tester l'interception d'un rayon avec `essai_intercept`,
|
||||
// et, le cas échéant, de ré-émettre le rayon `re_emit` et (optionnellement) de
|
||||
// donner le point d'interception avec `point_interception`. Il est aussi capable
|
||||
// de se dessiner et de donner son extension spatiale approximative.
|
||||
|
||||
class Objet {
|
||||
public:
|
||||
|
||||
Objet () {}
|
||||
Objet& operator= (const Objet&) = default;
|
||||
Objet (const Objet&) = default;
|
||||
virtual ~Objet () {}
|
||||
|
||||
// L'objet intercepte-t-il le rayon ? Si oui, donne la distance géométrique au carré
|
||||
// `dist2` parcourue par le rayon depuis son point d'émission, et renvoie une structure
|
||||
// interne à utiliser éventuellement pour la ré-émission du même rayon.
|
||||
// Si non, `intercept_struct` est nul et `dist2 = Inf`
|
||||
// Attention, la création de std::shared_ptr<void> est délicate (https://stackoverflow.com/questions/25858939/is-there-a-way-to-cast-shared-ptrvoid-to-shared-ptrt/25858963 et voir ObjetCourbe::essai_intercept)
|
||||
struct intercept_t { float dist2; std::shared_ptr<void> intercept_struct; };
|
||||
virtual intercept_t essai_intercept (const Rayon& ray) const = 0;
|
||||
// Point d'interception. Aucune garantie, non défini par défaut.
|
||||
virtual std::optional<point_t> point_interception (std::shared_ptr<void> intercept_struct) const { return std::nullopt; }
|
||||
|
||||
// Extension spatiale approximative pessimiste de l'objet à fin d'optimisation
|
||||
// (ne pas avoir à appeller un coûteux `essai_intercept(ray)` lorsque qu'on est
|
||||
// certain que le rayon ne sera pas intercepté par l'objet)
|
||||
struct extension_t { point_t pos; float rayon; };
|
||||
virtual extension_t objet_extension () const = 0;
|
||||
|
||||
// Ré-émission du rayon, devant utiliser la structure `.intercept_struct` renvoyée par `essai_intercept(ray)`
|
||||
virtual std::vector<Rayon> re_emit (const Rayon& ray, std::shared_ptr<void> intercept) = 0;
|
||||
|
||||
// Rendu graphique de l'objet
|
||||
virtual void dessiner (sf::RenderWindow& window, bool emphasize) const = 0;
|
||||
// Rendu graphique de l'interception d'un rayon (voir re_emit)
|
||||
virtual void dessiner_interception (sf::RenderWindow& window, const Rayon& ray, std::shared_ptr<void> intercept) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
#include "ObjetDiffusant.h"
|
||||
#include <cmath>
|
||||
|
||||
decltype(ObjetCourbe_Diffusant::BRDF) ObjetCourbe_Diffusant::BRDF_Lambert = [] (float theta_i, float theta_r) -> float {
|
||||
return 1;
|
||||
};
|
||||
|
||||
// Diffusion du rayon incident
|
||||
//
|
||||
std::vector<Rayon> ObjetCourbe_Diffusant::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
|
||||
intercept_courbe_t& intercept = *(intercept_courbe_t*)interception.get();
|
||||
std::vector<Rayon> rayons;
|
||||
|
||||
// nombre de rayons ré-émis selon l'intensité du rayon incident
|
||||
size_t n_re_emit = std::max<size_t>(1, lroundf(n_re_emit_par_intens * ray.spectre.intensite_tot()));
|
||||
|
||||
for (size_t k = 0; k < n_re_emit; k++) {
|
||||
|
||||
float ang_refl = 0;
|
||||
switch (diff_met) {
|
||||
case diffus_methode_t::AleaUnif:
|
||||
ang_refl = M_PI/2 * (1-2*rand01()); break; // angles aléatoires équirépartis
|
||||
case diffus_methode_t::Equirep:
|
||||
ang_refl = M_PI/2 * (1-2*(k+1)/(float)(n_re_emit+1)); break; // angles déterministes équirépartis
|
||||
default:
|
||||
throw std::runtime_error("TODO");
|
||||
}
|
||||
|
||||
Rayon ray_refl;
|
||||
ray_refl.orig = intercept.p_incid;
|
||||
ray_refl.dir_angle = intercept.ang_normale + ang_refl;
|
||||
|
||||
// pondération de l'intensité par la BRDF en fonction de l'angle incident et réfléchi
|
||||
ray_refl.spectre = ray.spectre;
|
||||
if (not BRDF_lambda) {
|
||||
float ampl = albedo / n_re_emit * BRDF( intercept.ang_incid, ang_refl );
|
||||
ray_refl.spectre.for_each([&] (float, pola_t, float& I) {
|
||||
I *= ampl;
|
||||
});
|
||||
} else {
|
||||
ray_refl.spectre.for_each([&] (float lambda, pola_t, float& I) {
|
||||
I *= albedo / n_re_emit * BRDF_lambda( intercept.ang_incid, ang_refl, lambda );
|
||||
});
|
||||
}
|
||||
|
||||
rayons.push_back(std::move(ray_refl));
|
||||
}
|
||||
|
||||
return rayons;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*******************************************************************************
|
||||
* Surfaces diffusantes à distribution de réflectivité (BRDF) arbitraire.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _LIGHTRAYS_DIFFUS_H_
|
||||
#define _LIGHTRAYS_DIFFUS_H_
|
||||
|
||||
#include "ObjetsCourbes.h"
|
||||
|
||||
class ObjetCourbe_Diffusant : virtual public ObjetCourbe {
|
||||
public:
|
||||
|
||||
// Méthode de tirage de rayon (même résultats en moyenne, mais performances et fluctuations différentes)
|
||||
enum diffus_methode_t {
|
||||
Equirep, // Équirépartition des rayons sur tous les angles i_r avec modulation d'amplitude par la BRDF
|
||||
AleaUnif, // Émission aléatoire uniforme avec modulation d'amplitude par la BRDF
|
||||
MonteCarlo, // Tirage de rayons d'intensité constante avec une distribution respectant la BRDF (Metropolis)
|
||||
} diff_met;
|
||||
// Bidirectional reflectance distribution function, possiblement dépendante de la couleur
|
||||
std::function<float(float theta_i, float theta_r)> BRDF; // utilisée si `BRDF_lambda` nulle
|
||||
std::function<float(float theta_i, float theta_r, float lambda)> BRDF_lambda; // utilisée si non nulle
|
||||
// Albedo, entre 0 et 1 (simple facteur d'intensité)
|
||||
float albedo;
|
||||
// Nombre moyen de rayons ré-émis par rayon incident par unité d'intensité. Doit être grand si diffus_methode_t::Equirep utilisée.
|
||||
float n_re_emit_par_intens;
|
||||
|
||||
static decltype(BRDF) BRDF_Lambert; // Diffusion lambertienne (isotrope <=> loi en cos(θ) <=> BRDF = 1)
|
||||
static decltype(BRDF) BRDF_Oren_Nayar (float sigma); // Diffusion de Oren Nayar
|
||||
|
||||
ObjetCourbe_Diffusant (decltype(BRDF) BRDF) : diff_met(AleaUnif), BRDF(BRDF), BRDF_lambda(nullptr), albedo(1), n_re_emit_par_intens(1) {}
|
||||
ObjetCourbe_Diffusant& operator= (const ObjetCourbe_Diffusant&) = default;
|
||||
ObjetCourbe_Diffusant (const ObjetCourbe_Diffusant&) = default;
|
||||
virtual ~ObjetCourbe_Diffusant () {};
|
||||
|
||||
// Diffusion du rayon incident
|
||||
virtual std::vector<Rayon> re_emit (const Rayon& ray, std::shared_ptr<void> intercept) override final;
|
||||
};
|
||||
|
||||
class ObjetArc_Diffusant : virtual public ObjetCourbe_Diffusant, virtual public ObjetArc {
|
||||
public:
|
||||
// relai des arguments aux constructeurs de ObjetArc
|
||||
template<typename... Args> ObjetArc_Diffusant (decltype(BRDF) BRDF, Args&&... x) : ObjetCourbe_Diffusant(BRDF), ObjetArc(x...) {}
|
||||
virtual ~ObjetArc_Diffusant () {}
|
||||
};
|
||||
|
||||
class ObjetLigne_Diffusant : virtual public ObjetCourbe_Diffusant, virtual public ObjetLigne {
|
||||
public:
|
||||
// relai des arguments aux constructeurs de ObjetLigne
|
||||
template<typename... Args> ObjetLigne_Diffusant (decltype(BRDF) BRDF, Args&&... x) : ObjetCourbe_Diffusant(BRDF), ObjetLigne(x...) {}
|
||||
virtual ~ObjetLigne_Diffusant () {};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
#include "ObjetMilieux.h"
|
||||
#include <cmath>
|
||||
|
||||
void ObjetComposite_LignesMilieu::re_positionne (point_t o) {
|
||||
std::optional<vec_t> trsl = std::nullopt;
|
||||
for (auto& obj : this->comp) {
|
||||
ObjetLigne_Milieux& ligne = *dynamic_cast<ObjetLigne_Milieux*>(&(*obj));
|
||||
if (not trsl.has_value())
|
||||
trsl = o - ligne.a;
|
||||
ligne.a = ligne.a + *trsl;
|
||||
ligne.b = ligne.b + *trsl;
|
||||
}
|
||||
}
|
||||
|
||||
// Réflexion et réfraction sur un dioptre : lois de Snell-Descartes
|
||||
// et coefficients de Fresnel. Voir lois.pdf pour plus de détails.
|
||||
// Deux cas : indice de réfraction indep. de λ (peu cher) et dépendant
|
||||
// de λ (cher car séparation en N_COULEURS différentes)
|
||||
//
|
||||
std::vector<Rayon> ObjetCourbe_Milieux::re_emit (const Rayon& ray, std::shared_ptr<void> interception) {
|
||||
intercept_courbe_t& intercept = *(intercept_courbe_t*)interception.get();
|
||||
std::vector<Rayon> rays_emis;
|
||||
|
||||
Rayon ray_refl;
|
||||
ray_refl.orig = intercept.p_incid;
|
||||
ray_refl.dir_angle = intercept.ang_normale - intercept.ang_incid; // i_refl = i par rapport à la normale
|
||||
ray_refl.spectre = ray.spectre;
|
||||
|
||||
auto refracte = [&intercept,&rays_emis] (Rayon& ray_refl, float n_out, float n_in) {
|
||||
|
||||
float gamma = intercept.sens_reg ? n_out/n_in : n_in/n_out; // n1/n2
|
||||
|
||||
float s = gamma * sinf(intercept.ang_incid);
|
||||
|
||||
if (fabsf(s) <= 1) { // on a un rayon transmis (i <= i_critique)
|
||||
|
||||
Rayon ray_trsm;
|
||||
ray_trsm.orig = intercept.p_incid;
|
||||
ray_trsm.dir_angle = (intercept.ang_normale + M_PI) + asinf(s);
|
||||
|
||||
float b = sqrtf( 1 - s*s );
|
||||
float cosi = cosf(intercept.ang_incid);
|
||||
float a_TE = gamma * cosi, a_TM = cosi / gamma;
|
||||
float r_coeff[2];
|
||||
r_coeff [PolTE] = (a_TE - b) / (a_TE + b);
|
||||
r_coeff [PolTM] = (a_TM - b) / (a_TM + b);
|
||||
|
||||
Specte::for_each_manual([&] (uint8_t i, float lambda, pola_t pol) {
|
||||
float R = r_coeff[pol] * r_coeff[pol];
|
||||
ray_trsm.spectre.comps[i] = (1-R) * ray_refl.spectre.comps[i];
|
||||
ray_refl.spectre.comps[i] = R * ray_refl.spectre.comps[i];
|
||||
});
|
||||
|
||||
rays_emis.push_back(ray_trsm);
|
||||
}
|
||||
// sinon, pas de rayon transmis (i > i_critique), et ray_refl est déjà prêt à être envoyé
|
||||
|
||||
rays_emis.push_back(ray_refl);
|
||||
};
|
||||
|
||||
// indice de réfraction fixe
|
||||
if (not (bool)n_lambda) {
|
||||
refracte (ray_refl, /*n_out*/1., /*n_in*/this->n_fixe);
|
||||
}
|
||||
// indice de réfraction dépendant de la longueur d'onde
|
||||
// -> séparation de toutes les composantes en rayons monochromatiques, car les directions sont différentes
|
||||
else {
|
||||
for (color_id_t i = 0; i < N_COULEURS; i++) {
|
||||
Rayon ray_refl_mono = ray_refl;
|
||||
ray_refl_mono.spectre.for_each_cid([&] (color_id_t cid, pola_t pol, float& I) {
|
||||
if (cid != i)
|
||||
I = 0;
|
||||
});
|
||||
float n_in = n_lambda(lambda_color[i]); // variable
|
||||
refracte (ray_refl_mono, /*n_out*/1., n_in);
|
||||
}
|
||||
}
|
||||
|
||||
return rays_emis;
|
||||
}
|
||||
|
||||
#include "sfml_c01.hpp"
|
||||
|
||||
void ObjetLigne_Milieux::dessiner (sf::RenderWindow& window, bool emphasize) const {
|
||||
ObjetLigne::dessiner(window, emphasize);
|
||||
sf::ConvexShape rect_milieu(4);
|
||||
vec_t v_perp = vecteur_u_perp() * 0.05;
|
||||
rect_milieu.setPoint(0, sf::c01::toWin(a));
|
||||
rect_milieu.setPoint(1, sf::c01::toWin(b));
|
||||
rect_milieu.setPoint(2, sf::c01::toWin(b+v_perp));
|
||||
rect_milieu.setPoint(3, sf::c01::toWin(a+v_perp));
|
||||
rect_milieu.setFillColor(sf::Color(255,255,255,20));
|
||||
window.draw(rect_milieu);
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*******************************************************************************
|
||||
* Objets optiques définissant différents milieux : dioptres entre deux milieux
|
||||
* d'indices différents : loi de Snell-Descartes et coefficients de Fresnel
|
||||
*******************************************************************************/
|
||||
|
||||
// Notes : l'incide de réfraction `n` est réel, donc pas d'absorption, pas de comportement métalique.
|
||||
// De plus, les objets sont supposés être des dioptres entre du vide (n=1) et un milieu (n≠1).
|
||||
// Pour faire des interfaces entre milieux, ça nécessiterait pas mal de travail.
|
||||
#warning To do
|
||||
|
||||
#ifndef _LIGHTRAYS_OBJET_MILIEU_H_
|
||||
#define _LIGHTRAYS_OBJET_MILIEU_H_
|
||||
|
||||
#include "ObjetsCourbes.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Dioptres de type courbe (1D) entre le vide et un milieu d'indice n, fixe
|
||||
// (`n_fixe`) ou dépendnant de λ (`n_lambda`). Implémentation des lois de
|
||||
// Snell-Descartes et des coefficients de Fresnel en intensité.
|
||||
|
||||
class ObjetCourbe_Milieux : virtual public ObjetCourbe {
|
||||
public:
|
||||
|
||||
std::function<float(float)> n_lambda; // n(λ) /!\ coûteux -> N_COULEURS rayons réfractés à lancer
|
||||
float n_fixe; // n indépendant de λ, considéré si `indice_refr_lambda` est nul
|
||||
|
||||
ObjetCourbe_Milieux (float incide_refr_fixe) : ObjetCourbe(), n_lambda(nullptr), n_fixe(incide_refr_fixe) {}
|
||||
ObjetCourbe_Milieux (std::function<float(float)> indice_refr_lambda) : ObjetCourbe(), n_lambda(indice_refr_lambda) {}
|
||||
|
||||
ObjetCourbe_Milieux& operator= (const ObjetCourbe_Milieux&) = default;
|
||||
ObjetCourbe_Milieux (const ObjetCourbe_Milieux&) = default;
|
||||
virtual ~ObjetCourbe_Milieux () {}
|
||||
|
||||
// Ré-émission du rayons intercepté en un rayon réfléchi et un rayon réfracté
|
||||
virtual std::vector<Rayon> re_emit (const Rayon& ray, std::shared_ptr<void> intercept) override final;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Dioptre linéaire : ObjetLigne + ObjetCourbe_Milieux
|
||||
|
||||
class ObjetLigne_Milieux : virtual public ObjetCourbe_Milieux, virtual public ObjetLigne {
|
||||
public:
|
||||
// relai des arguments aux contructeurs de ObjetLigne et ObjetCourbe_Milieux
|
||||
// (toutes les combinaisons sont possibles)
|
||||
template<typename incide_refr_t, typename... Args> ObjetLigne_Milieux (incide_refr_t incide_refr, Args&&... x) :
|
||||
ObjetCourbe_Milieux(incide_refr), ObjetLigne(x...) {}
|
||||
|
||||
virtual ~ObjetLigne_Milieux () {}
|
||||
|
||||
// Dessin (intérieur coloré)
|
||||
virtual void dessiner (sf::RenderWindow& window, bool emphasize) const override;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Dioptre en forme d'arc de cercle : ObjetArc + ObjetCourbe_Milieux
|
||||
|
||||
class ObjetArc_Milieux : virtual public ObjetCourbe_Milieux, virtual public ObjetArc {
|
||||
public:
|
||||
// relai des arguments aux contructeurs de ObjetArc et ObjetCourbe_Milieux
|
||||
template<typename incide_refr_t, typename... Args> ObjetArc_Milieux (incide_refr_t incide_refr, Args&&... x) :
|
||||
ObjetCourbe_Milieux(incide_refr), ObjetArc(x...) {}
|
||||
|
||||
virtual ~ObjetArc_Milieux () {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Utilitaire : Objet composite fermé, délimité par des lignes
|
||||
// `ObjetLigne_Milieux`, à partir d'une liste de points `points`,
|
||||
// et d'indice de réfraction intérieur `incide_refr`.
|
||||
|
||||
class ObjetComposite_LignesMilieu : virtual public ObjetComposite {
|
||||
private:
|
||||
template<typename incide_refr_t>
|
||||
static std::vector< std::unique_ptr<ObjetCourbe> > construct_liste (std::vector<point_t> points, incide_refr_t n) {
|
||||
std::vector< std::unique_ptr<ObjetCourbe> > objs;
|
||||
size_t N = points.size();
|
||||
for (size_t i = 0; i < N; i++)
|
||||
objs.emplace_back(new ObjetLigne_Milieux(n, points[ i ], points[ (i+1)%N ]));
|
||||
return objs;
|
||||
}
|
||||
public:
|
||||
// construction à partir de la liste de points
|
||||
template<typename incide_refr_t> ObjetComposite_LignesMilieu (std::vector<point_t> points, incide_refr_t incide_refr) :
|
||||
ObjetComposite(construct_liste(points,incide_refr)) {}
|
||||
|
||||
virtual ~ObjetComposite_LignesMilieu () {}
|
||||
|
||||
// simple translation : positionnement du premier point de la chaine en `o`
|
||||
void re_positionne (point_t o);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,302 @@
|
|||
#include "ObjetsCourbes.h"
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
///------------------------ ObjetCourbe ------------------------///
|
||||
|
||||
#define INTERCEPTION_DIST_MINIMALE 0.0001
|
||||
|
||||
// Relai de ObjetCourbe::essai_intercept_courbe
|
||||
//
|
||||
Objet::intercept_t ObjetCourbe::essai_intercept (const Rayon& ray) const {
|
||||
auto intercept = this->essai_intercept_courbe(ray);
|
||||
if (intercept.has_value()) {
|
||||
float dist2 = (ray.orig - (*intercept)->p_incid).norm2();
|
||||
// on introduit une distance minimale qu'un rayon peut parcourit avant d'être intercepté
|
||||
// par une courbe pour éviter qu'un objet ré-intercepte immédiatement le rayon qu'il vient
|
||||
// d'émettre, ce qui arriverait souvent en simple précision
|
||||
if (dist2 < INTERCEPTION_DIST_MINIMALE*INTERCEPTION_DIST_MINIMALE)
|
||||
return { .dist2 = Inf, .intercept_struct = nullptr };
|
||||
else
|
||||
return { .dist2 = dist2,
|
||||
.intercept_struct = std::static_pointer_cast<void>(*intercept) };
|
||||
} else
|
||||
return { .dist2 = Inf, .intercept_struct = nullptr };
|
||||
}
|
||||
|
||||
std::optional<point_t> ObjetCourbe::point_interception (std::shared_ptr<void> intercept_struct) const {
|
||||
if (intercept_struct) {
|
||||
return ((intercept_courbe_t*)intercept_struct.get())->p_incid;
|
||||
} else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
///------------------------ ObjetLigne ------------------------///
|
||||
|
||||
ObjetLigne::ObjetLigne (point_t a, float l, float ang) :
|
||||
a( a ),
|
||||
b( a + l * vec_t{ cosf(ang), sinf(ang) } ) {}
|
||||
|
||||
vec_t ObjetLigne::vecteur_u_perp () const {
|
||||
vec_t v_perp = (b - a).rotate_p90();
|
||||
return v_perp / !v_perp;
|
||||
}
|
||||
|
||||
// Routine d'intersection segment avec demi-droite
|
||||
//
|
||||
std::optional<ObjetLigne::intersection_segdd_t> ObjetLigne::intersection_segment_demidroite (point_t a, point_t b, point_t dd_orig, float angle) {
|
||||
// cas particulier d'alignement non pris en compte
|
||||
vec_t u_dd = { .x = cosf(angle),
|
||||
.y = sinf(angle) };
|
||||
vec_t v_seg = a - b;
|
||||
float s, t;
|
||||
mat22_sol(v_seg.x, -u_dd.x,
|
||||
v_seg.y, -u_dd.y,
|
||||
dd_orig.x - b.x, dd_orig.y - b.y,
|
||||
s, t);
|
||||
if ((0 <= s and s <= 1) and t >= 0) {
|
||||
return intersection_segdd_t{ .v_seg = v_seg, .u_dd = u_dd, .s_seg = s, .t_dd = t };
|
||||
} else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Test d'interception du rayon sur la ligne.
|
||||
//
|
||||
std::optional<std::shared_ptr<ObjetCourbe::intercept_courbe_t>> ObjetLigne::essai_intercept_courbe (const Rayon& ray) const {
|
||||
// `intersection_segment_demidroite` n'est pas directement intégrée ici car elle sert ailleurs
|
||||
auto isect = ObjetLigne::intersection_segment_demidroite(a, b, ray.orig, ray.dir_angle);
|
||||
if (not isect.has_value())
|
||||
return std::nullopt;
|
||||
std::shared_ptr<intercept_ligne_t> intercept = std::make_shared<intercept_ligne_t>();
|
||||
// point d'incidence
|
||||
intercept->p_incid = ray.orig + isect->t_dd * isect->u_dd;
|
||||
intercept->s_incid = isect->s_seg;
|
||||
// angle d'incidence
|
||||
float seg_angle = atan2f(isect->v_seg.y, isect->v_seg.x); // pourrait être calculé une bonne fois pour toutes
|
||||
float alpha = angle_mod2pi_11(ray.dir_angle);
|
||||
float i = alpha - (seg_angle - M_PI/2);
|
||||
if (fabsf(angle_mod2pi_11(i)) < M_PI/2) {
|
||||
intercept->ang_normale = seg_angle + M_PI/2;
|
||||
intercept->ang_incid = i;
|
||||
intercept->sens_reg = true;
|
||||
} else {
|
||||
intercept->ang_incid = i - M_PI;
|
||||
if (intercept->ang_incid < -M_PI/2) intercept->ang_incid += 2*M_PI;
|
||||
intercept->ang_normale = seg_angle - M_PI/2;
|
||||
intercept->sens_reg = false;
|
||||
}
|
||||
return std::shared_ptr<intercept_courbe_t>(intercept);
|
||||
}
|
||||
|
||||
///------------------------ ObjetArc ------------------------///
|
||||
|
||||
// Construction de l'arc de cercle à partir de deux points et du rayon
|
||||
//
|
||||
ObjetArc::ObjetArc (point_t a, point_t b, float radius, bool inv_interieur) : c({0,0}), R(radius), ang(0,0), inv_int(inv_interieur) {
|
||||
// translation
|
||||
vec_t ab = b - a;
|
||||
// vérification
|
||||
float ab2 = ab.norm2();
|
||||
if (ab2 > 4*R*R)
|
||||
throw std::domain_error("ObjetArc(A,B,R) : points A et B trop éloignés");
|
||||
// rotation
|
||||
float theta0 = atan2f(ab.y, ab.x) - M_PI/2;
|
||||
// calcul dans le repère 'prime'
|
||||
vec_t c_ = { .x = -sqrtf( R*R - ab2/4 ),
|
||||
.y = sqrtf(ab2)/2 };
|
||||
float theta_ = atanf( c_.y / c_.x );
|
||||
angle_interv_t ang_ ( theta_, -theta_ );
|
||||
// dé-rotation
|
||||
ang = ang_ + theta0;
|
||||
c_ = c_.rotate(theta0);
|
||||
// dé-translation
|
||||
c = a + c_;
|
||||
}
|
||||
|
||||
std::pair<point_t,point_t> ObjetArc::objet_extremit () const {
|
||||
vec_t u_a, u_b;
|
||||
std::tie(u_a,u_b) = this->ang.vec_a_b();
|
||||
return { c + R * u_a,
|
||||
c + R * u_b };
|
||||
}
|
||||
|
||||
// Routine d'interception du rayon sur l'arc de cercle.
|
||||
//
|
||||
std::optional<std::shared_ptr<ObjetArc::intercept_courbe_t>> ObjetArc::essai_intercept_courbe (const Rayon& ray) const {
|
||||
/// intersection arc de cercle / demi-droite
|
||||
// (notations de `lois.pdf`)
|
||||
vec_t oc = c - ray.orig;
|
||||
float b = !oc / R; // d/R
|
||||
float base_ang = atan2f(oc.y, oc.x);
|
||||
// angles relatifs à l'axe OC
|
||||
float alpha = angle_mod2pi_11( ray.dir_angle - base_ang );
|
||||
angle_interv_t thetaAB = ang + -base_ang;
|
||||
// intersection avec le cecle si en dessous de l'angle critique
|
||||
float y = b * sinf(alpha);
|
||||
if ((b > 1.00001 and fabsf(alpha) >= M_PI/2) or fabsf(y) > 1)
|
||||
return std::nullopt;
|
||||
// angles repérant les points d'intersection avec le cercle
|
||||
float arcsiny = asinf(y);
|
||||
float theta1 = alpha - arcsiny + M_PI,
|
||||
theta2 = alpha + arcsiny;
|
||||
/// si on est bien sur notre arc de cercle
|
||||
std::shared_ptr<intercept_arc_t> intercept = std::make_shared<intercept_arc_t>();
|
||||
// θ1 n'est accessible que si la rayon vient de l'extérieur
|
||||
if ( b > 1.00001 and thetaAB.inclus(theta1) ) {
|
||||
intercept->sens_reg = !inv_int; // ext vers int du cerlce
|
||||
intercept->theta_incid = intercept->ang_normale = theta1 + base_ang;
|
||||
intercept->ang_incid = M_PI - theta1 + alpha; // c'est un angle relatif, pas besoin de base_ang
|
||||
}
|
||||
// test de θ1 pour b<1 ou si θ1 a échoué pour b>1
|
||||
else if ( thetaAB.inclus(theta2) ) {
|
||||
intercept->sens_reg = inv_int; // int vers ext du cercle
|
||||
intercept->theta_incid = theta2 + base_ang;
|
||||
intercept->ang_normale = intercept->theta_incid + M_PI; // normale vers l'intérieur du cercle
|
||||
intercept->ang_incid = alpha - theta2;
|
||||
}
|
||||
else
|
||||
return std::nullopt;
|
||||
// calcul du point d'incidence
|
||||
intercept->p_incid = c + R * vec_t{ .x = cosf(intercept->theta_incid),
|
||||
.y = sinf(intercept->theta_incid) };
|
||||
return std::shared_ptr<intercept_courbe_t>(intercept);
|
||||
}
|
||||
|
||||
///------------------------ ObjetComposite ------------------------///
|
||||
|
||||
// Calcul de l'extension approximative d'un objet composite :
|
||||
// • position = barycentre
|
||||
// • extension = distance (position objet - barycentre) maximale,
|
||||
// + extension (objet) maximale
|
||||
// (non-optimal, mais se comporte bien dans la plupart des cas)
|
||||
//
|
||||
Objet::extension_t ObjetComposite::objet_extension () const {
|
||||
std::vector<vec_t> pos (comp.size());
|
||||
vec_t bary = {0,0};
|
||||
float rayon_max = 0;
|
||||
for (const auto& obj : comp) {
|
||||
extension_t ext = obj->objet_extension();
|
||||
pos.push_back( (vec_t)ext.pos );
|
||||
bary += (vec_t)ext.pos;
|
||||
rayon_max = std::max(rayon_max, ext.rayon);
|
||||
}
|
||||
bary /= comp.size();
|
||||
float pos_max = 0;
|
||||
for (vec_t p : pos)
|
||||
pos_max = std::max(pos_max, !(p - bary));
|
||||
return { .pos = {bary.x,bary.y}, .rayon = rayon_max + pos_max };
|
||||
}
|
||||
|
||||
// Relai du test d'interception sur chaque sous-objet, et interception
|
||||
// par l'objet le plus proche sur le chemin du rayon.
|
||||
//
|
||||
Objet::intercept_t ObjetComposite::essai_intercept (const Rayon& ray) const {
|
||||
intercept_composite_t interception { .courbe_intercept = comp.end() };
|
||||
float dist2_min = Inf;
|
||||
// Test d'interception du rayon contre toutes les courbes composantes;
|
||||
// la première interception en terme de distance entre l'origine du rayon
|
||||
// et le point d'incidence est choisie (recherche de minimum)
|
||||
for (auto it = comp.begin(); it != comp.end(); it++) {
|
||||
std::optional<std::shared_ptr<ObjetCourbe::intercept_courbe_t>> intercept
|
||||
= (*it)->essai_intercept_courbe(ray);
|
||||
if (intercept.has_value()) {
|
||||
float dist2 = (ray.orig - (*intercept)->p_incid).norm2();
|
||||
if (dist2 < INTERCEPTION_DIST_MINIMALE*INTERCEPTION_DIST_MINIMALE)
|
||||
continue;
|
||||
if (dist2 < dist2_min) {
|
||||
interception.courbe_intercept = it;
|
||||
< |