| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /// Settings
- String cubeMapGen_Name;
- String cubeMapGen_Path;
- int cubeMapGen_Size;
- Array<EditorCubeCapture@> activeCubeCapture; // Editor capture tasks in progress, Stop() method of EditorCubeCapture moves forward through the queue as captures are finished
- Array<Zone@> cloneZones; // Duplicate zones constructed to prevent IBL doubling
- Array<Zone@> disabledZones; // Zones that were disabled to prevent IBL doubling
- const String cubemapDefaultOutputPath = "Textures/Cubemaps";
- void PrepareZonesForCubeRendering()
- {
- // Only clone zones when we aren't actively processing
- if (cloneZones.length > 0)
- return;
-
- Array<Component@>@ zones = editorScene.GetComponents("Zone", true);
- for (uint i = 0; i < zones.length; ++i)
- {
- Zone@ srcZone = cast<Zone>(zones[i]);
- if (zones[i].enabled)
- {
- Zone@ cloneZone = srcZone.node.CreateComponent("Zone");
- cloneZone.zoneMask = srcZone.zoneMask;
- cloneZone.priority = srcZone.priority;
- cloneZone.boundingBox = srcZone.boundingBox;
-
- cloneZone.ambientColor = srcZone.ambientColor;
- cloneZone.ambientGradient = srcZone.ambientGradient;
-
- cloneZone.fogColor = srcZone.fogColor;
- cloneZone.fogStart = srcZone.fogStart;
- cloneZone.fogEnd = srcZone.fogEnd;
- cloneZone.fogHeight = srcZone.fogHeight;
- cloneZone.fogHeightScale = srcZone.fogHeightScale;
- cloneZone.heightFog = srcZone.heightFog;
-
- srcZone.enabled = false;
-
- // Add the zones to our temporary lists
- cloneZones.Push(cloneZone);
- disabledZones.Push(srcZone);
- }
- }
-
- // Hide grid and debugIcons until bake
- if (grid !is null)
- grid.viewMask = 0;
- if (debugIconsNode !is null)
- debugIconsNode.enabled = false;
- debugRenderDisabled = true;
- }
- void UnprepareZonesForCubeRendering()
- {
- // Clean up the clones
- for (uint i = 0; i < cloneZones.length; ++i)
- cloneZones[i].Remove();
- cloneZones.Clear();
-
- // Reenable anyone we disabled
- for (uint i = 0; i < disabledZones.length; ++i)
- disabledZones[i].enabled = true;
- disabledZones.Clear();
-
- // Show grid and debug icons
- if (grid !is null)
- grid.viewMask = 0x80000000;
- if (debugIconsNode !is null)
- debugIconsNode.enabled = true;
- debugRenderDisabled = false;
- }
- class EditorCubeCapture : ScriptObject // script object in order to get events
- {
- private String name_;
- private String path_;
- private Node@ camNode_;
- private Camera@ camera_;
- private Zone@ target_;
- private Viewport@ viewport_;
- private Texture2D@ renderImage_;
- private RenderSurface@ renderSurface_;
- int updateCycle_;
- String imagePath_;
-
- EditorCubeCapture(Zone@ forZone)
- {
- PrepareZonesForCubeRendering();
-
- // Store name and path because if we have a lot of zones it could take long enough to queue another go, and it may have different settings
- name_ = cubeMapGen_Name;
- path_ = sceneResourcePath + cubeMapGen_Path;
- updateCycle_ = 0;
-
- target_ = forZone;
-
- camNode_ = scene.CreateChild("RenderCamera");
- camera_ = camNode_.GetOrCreateComponent("Camera");
- camera_.fov = 90.0f;
- camera_.nearClip = 0.0001f;
- camera_.aspectRatio = 1.0f;
- camNode_.worldPosition = forZone.node.worldPosition;
-
- viewport_ = Viewport(scene, camera_);
- viewport_.renderPath = renderer.viewports[0].renderPath;
-
- updateCycle_ = 0;
- }
-
- ~EditorCubeCapture()
- {
- camNode_.Remove();
- }
-
- void Start()
- {
- // Construct render surface
- renderImage_ = Texture2D();
- renderImage_.SetSize(cubeMapGen_Size, cubeMapGen_Size, Graphics::GetRGBAFormat(), TEXTURE_RENDERTARGET);
-
- renderSurface_ = renderImage_.renderSurface;
- renderSurface_.viewports[0] = viewport_;
- renderSurface_.updateMode = SURFACE_UPDATEALWAYS;
-
- SubscribeToEvent("BeginFrame", "HandlePreRender");
- SubscribeToEvent("EndFrame", "HandlePostRender");
- }
-
- private void Stop()
- {
- camNode_.Remove();
- camNode_ = null;
- viewport_ = null;
- renderSurface_ = null;
-
- UnsubscribeFromEvent("BeginFrame");
- UnsubscribeFromEvent("EndFrame");
-
- WriteXML();
-
- // Remove ourselves from the processing list and if necessary clean things up
- // If others are pending in the queue then start the next one
- activeCubeCapture.Erase(activeCubeCapture.FindByRef(this));
- if (activeCubeCapture.length == 0)
- UnprepareZonesForCubeRendering();
- else
- activeCubeCapture[0].Start();
- }
-
- // Position camera accordingly
- void HandlePreRender(StringHash eventType, VariantMap& eventData)
- {
- if (camNode_ !is null)
- {
- ++updateCycle_;
-
- if (updateCycle_ < 7)
- camNode_.worldRotation = RotationOf(GetFaceForCycle(updateCycle_));
- else
- Stop();
- }
- }
-
- // Save our image
- void HandlePostRender(StringHash eventType, VariantMap& eventData)
- {
- Image@ img = renderImage_.GetImage();
- String sceneName = editorScene.name.length > 0 ? editorScene.name + "/" : "";
- String path = path_ + "/" + sceneName;
- fileSystem.CreateDir(path);
- path = path + "/" + String(target_.id) + "_" + GetFaceName(GetFaceForCycle(updateCycle_)) + ".png";
- img.SavePNG(path);
- }
-
- private void WriteXML()
- {
- String sceneName = editorScene.name.length > 0 ? "/" + editorScene.name + "/" : "";
- String basePath = AddTrailingSlash(path_ + sceneName);
- String cubeName = name_.length > 0 ? (name_ + "_") : "";
- String xmlPath = basePath + "/" + name_ + String(target_.id) + ".xml";
- XMLFile@ file = XMLFile();
- XMLElement rootElem = file.CreateRoot("cubemap");
-
- for (int i = 0; i < 6; ++i)
- {
- XMLElement faceElem = rootElem.CreateChild("face");
- faceElem.SetAttribute("name", GetResourceNameFromFullName(basePath + cubeName + String(target_.id) + "_" + GetFaceName(CubeMapFace(i)) + ".png"));
- }
- file.Save(File(xmlPath, FILE_WRITE), " ");
- ResourceRef ref;
- ref.type = StringHash("TextureCube");
- ref.name = GetResourceNameFromFullName(xmlPath);
- target_.SetAttribute("Zone Texture", Variant(ref));
- }
-
- private CubeMapFace GetFaceForCycle(int cycle)
- {
- switch (updateCycle_)
- {
- case 1:
- return FACE_POSITIVE_X;
- case 2:
- return FACE_POSITIVE_Y;
- case 3:
- return FACE_POSITIVE_Z;
- case 4:
- return FACE_NEGATIVE_X;
- case 5:
- return FACE_NEGATIVE_Y;
- case 6:
- return FACE_NEGATIVE_Z;
- }
- return FACE_POSITIVE_X;
- }
-
- private String GetFaceName(CubeMapFace face)
- {
- switch (face)
- {
- case FACE_POSITIVE_X:
- return "PosX";
- case FACE_POSITIVE_Y:
- return "PosY";
- case FACE_POSITIVE_Z:
- return "PosZ";
- case FACE_NEGATIVE_X:
- return "NegX";
- case FACE_NEGATIVE_Y:
- return "NegY";
- case FACE_NEGATIVE_Z:
- return "NegZ";
- }
- return "PosX";
- }
-
- private Quaternion RotationOf(CubeMapFace face)
- {
- Quaternion result;
- switch (face)
- {
- // Rotate camera according to probe rotation
- case FACE_POSITIVE_X:
- result = Quaternion(0, 90, 0);
- break;
- case FACE_NEGATIVE_X:
- result = Quaternion(0, -90, 0);
- break;
- case FACE_POSITIVE_Y:
- result = Quaternion(-90, 0, 0);
- break;
- case FACE_NEGATIVE_Y:
- result = Quaternion(90, 0, 0);
- break;
- case FACE_POSITIVE_Z:
- result = Quaternion(0, 0, 0);
- break;
- case FACE_NEGATIVE_Z:
- result = Quaternion(0, 180, 0);
- break;
- }
- return result;
- }
- }
|