PageRenderTime 65ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/src/slg/telnet/telnet.cpp

https://bitbucket.org/luxrender/luxrays
C++ | 917 lines | 789 code | 52 blank | 76 comment | 316 complexity | b293ecde7363adcb2832f9a460d52c9c MD5 | raw file
Possible License(s): GPL-3.0
  1. /***************************************************************************
  2. * Copyright (C) 1998-2013 by authors (see AUTHORS.txt) *
  3. * *
  4. * This file is part of LuxRays. *
  5. * *
  6. * LuxRays is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * LuxRays is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * You should have received a copy of the GNU General Public License *
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  18. * *
  19. * LuxRays website: http://www.luxrender.net *
  20. ***************************************************************************/
  21. #include <iostream>
  22. #include <string>
  23. #include <boost/asio.hpp>
  24. #include <boost/thread/thread.hpp>
  25. #include <boost/algorithm/string/split.hpp>
  26. #include <boost/algorithm/string/classification.hpp>
  27. #include <boost/algorithm/string/trim.hpp>
  28. #include "slg/telnet/telnet.h"
  29. #include "slg/renderconfig.h"
  30. #include "luxrays/utils/properties.h"
  31. using namespace std;
  32. using namespace luxrays;
  33. using namespace slg;
  34. using boost::asio::ip::tcp;
  35. TelnetServer::TelnetServer(const unsigned int serverPort, RenderSession *renderSession) : port(serverPort) {
  36. session = renderSession;
  37. serverThread = new boost::thread(boost::bind(TelnetServer::ServerThreadImpl, this));
  38. }
  39. TelnetServer::~TelnetServer() {
  40. serverThread->interrupt();
  41. serverThread->join();
  42. }
  43. void TelnetServer::ServerThreadImpl(TelnetServer *telnetServer) {
  44. SLG_LOG("[Telnet server] Thread started");
  45. try {
  46. ServerState state = RUN;
  47. boost::asio::io_service ioService;
  48. tcp::acceptor acceptor(ioService, tcp::endpoint(tcp::v4(), telnetServer->port));
  49. SLG_LOG("[Telnet server] Server started on port: " << telnetServer->port);
  50. for (;;) {
  51. tcp::socket socket(ioService);
  52. acceptor.accept(socket);
  53. // Handle the connection
  54. try {
  55. boost::asio::streambuf response;
  56. std::ostream respStream(&response);
  57. respStream << "SmallLuxGPU Telnet Server Interface\n";
  58. boost::asio::write(socket, response);
  59. bool echoCommandOn = true;
  60. for (bool exit = false; !exit;) {
  61. // Print prompt
  62. boost::asio::write(socket, boost::asio::buffer("> ", 2));
  63. // Read the command
  64. boost::asio::streambuf commandBuf;
  65. boost::asio::read_until(socket, commandBuf, "\n");
  66. std::istream commandStream(&commandBuf);
  67. string command;
  68. commandStream >> command;
  69. if (echoCommandOn)
  70. SLG_LOG("[Telnet server] Received command: " << command);
  71. RenderSession *session = telnetServer->session;
  72. Scene *scene = session->renderConfig->scene;
  73. Film *film = session->film;
  74. if (command == "exit")
  75. exit = true;
  76. else if (command == "help") {
  77. boost::asio::streambuf response;
  78. std::ostream respStream(&response);
  79. respStream << "exit - close the connection\n";
  80. respStream << "get <property name> - return the value of a (supported) property\n";
  81. respStream << "echocmd.off\n";
  82. respStream << "echocmd.on\n";
  83. respStream << "edit.start - start an editing session (alias render.start for SLG 1.x compatibility)\n";
  84. respStream << "edit.stop - stop an editing session (alias render.stop for SLG 1.x compatibility)\n";
  85. respStream << "help - this help\n";
  86. respStream << "help.get - print the list of get supported properties\n";
  87. respStream << "help.set - print the list of set supported properties\n";
  88. respStream << "image.reset - reset the rendering image (requires edit.start)\n";
  89. respStream << "image.save - save the rendering image\n";
  90. respStream << "material.list - print the list of materials\n";
  91. respStream << "object.list - print the list of objects\n";
  92. respStream << "set <property name> = <values> - set the value of a (supported) property\n";
  93. respStream << "set scene.materials.<name>.* = <values>, ... - update a material definition\n";
  94. respStream << "transmit.framebuffer.rgb_float - transmit the current framebuffer (RGB float format)\n";
  95. respStream << "transmit.framebuffer.rgb_byte - transmit the current framebuffer (RGB byte format)\n";
  96. respStream << "OK\n";
  97. boost::asio::write(socket, response);
  98. } else if (command == "echocmd.off") {
  99. echoCommandOn = false;
  100. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  101. } else if (command == "echocmd.on") {
  102. echoCommandOn = true;
  103. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  104. } else if (command == "get") {
  105. //------------------------------------------------------
  106. // Get property
  107. //------------------------------------------------------
  108. // Get the name of the property to recover
  109. string property;
  110. commandStream >> property;
  111. // Check if is one of the supported properties
  112. if (property == "film.tonemap.linear.scale") {
  113. if (film->GetToneMapParams()->GetType() == TONEMAP_LINEAR) {
  114. boost::asio::streambuf response;
  115. std::ostream respStream(&response);
  116. LinearToneMapParams *params = (LinearToneMapParams *)film->GetToneMapParams();
  117. respStream << params->scale << "\n";
  118. respStream << "OK\n";
  119. boost::asio::write(socket, response);
  120. } else {
  121. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  122. SLG_LOG("[Telnet server] Not using TONEMAP_LINEAR");
  123. }
  124. } else if (property == "film.tonemap.reinhard02.burn") {
  125. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  126. boost::asio::streambuf response;
  127. std::ostream respStream(&response);
  128. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams();
  129. respStream << params->burn << "\n";
  130. respStream << "OK\n";
  131. boost::asio::write(socket, response);
  132. } else {
  133. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  134. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  135. }
  136. } else if (property == "film.tonemap.reinhard02.postscale") {
  137. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  138. boost::asio::streambuf response;
  139. std::ostream respStream(&response);
  140. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams();
  141. respStream << params->postScale << "\n";
  142. respStream << "OK\n";
  143. boost::asio::write(socket, response);
  144. } else {
  145. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  146. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  147. }
  148. } else if (property == "film.tonemap.reinhard02.prescale") {
  149. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  150. boost::asio::streambuf response;
  151. std::ostream respStream(&response);
  152. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams();
  153. respStream << params->preScale << "\n";
  154. respStream << "OK\n";
  155. boost::asio::write(socket, response);
  156. } else {
  157. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  158. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  159. }
  160. } else if (property == "film.tonemap.type") {
  161. boost::asio::streambuf response;
  162. std::ostream respStream(&response);
  163. respStream << film->GetToneMapParams()->GetType() << "\n";
  164. respStream << "OK\n";
  165. boost::asio::write(socket, response);
  166. } else if (property == "scene.camera.lookat") {
  167. boost::asio::streambuf response;
  168. std::ostream respStream(&response);
  169. const Point &o = scene->camera->orig;
  170. const Point &t = scene->camera->target;
  171. respStream << o.x << " " << o.y << " " << o.z << " "
  172. << t.x << " " << t.y << " " << t.z << "\n";
  173. respStream << "OK\n";
  174. boost::asio::write(socket, response);
  175. } else if (property == "scene.camera.up") {
  176. boost::asio::streambuf response;
  177. std::ostream respStream(&response);
  178. const Vector &up = scene->camera->up;
  179. respStream << up.x << " " << up.y << " " << up.z << "\n";
  180. respStream << "OK\n";
  181. boost::asio::write(socket, response);
  182. } else if (property == "scene.camera.lensradius") {
  183. boost::asio::streambuf response;
  184. std::ostream respStream(&response);
  185. respStream << scene->camera->lensRadius << "\n";
  186. respStream << "OK\n";
  187. boost::asio::write(socket, response);
  188. } else if (property == "scene.camera.fieldofview") {
  189. boost::asio::streambuf response;
  190. std::ostream respStream(&response);
  191. respStream << scene->camera->fieldOfView << "\n";
  192. respStream << "OK\n";
  193. boost::asio::write(socket, response);
  194. } else if (property == "scene.camera.focaldistance") {
  195. boost::asio::streambuf response;
  196. std::ostream respStream(&response);
  197. respStream << scene->camera->focalDistance << "\n";
  198. respStream << "OK\n";
  199. boost::asio::write(socket, response);
  200. } else if (property == "image.filename") {
  201. boost::asio::streambuf response;
  202. std::ostream respStream(&response);
  203. respStream << session->renderConfig->cfg.GetString("image.filename", "image.png") << "\n";
  204. respStream << "OK\n";
  205. boost::asio::write(socket, response);
  206. } else if (property == "scene.infinitelight.gain") {
  207. InfiniteLight *il = (InfiniteLight *)scene->GetLightByType(TYPE_IL);
  208. if (il) {
  209. std::ostream respStream(&response);
  210. const Spectrum gain = il->GetGain();
  211. respStream << gain.r << " " << gain.g << " " << gain.b << "\n";
  212. respStream << "OK\n";
  213. boost::asio::write(socket, response);
  214. } else {
  215. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  216. SLG_LOG("[Telnet server] No InfiniteLight defined: " << property);
  217. }
  218. } else if (property == "scene.infinitelight.shift") {
  219. InfiniteLight *il = (InfiniteLight *)scene->GetLightByType(TYPE_IL);
  220. if (il) {
  221. std::ostream respStream(&response);
  222. respStream << il->GetUVMapping()->uDelta << " " <<
  223. il->GetUVMapping()->vDelta << "\n";
  224. respStream << "OK\n";
  225. boost::asio::write(socket, response);
  226. } else {
  227. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  228. SLG_LOG("[Telnet server] No InfiniteLight defined: " << property);
  229. }
  230. } else if (property == "scene.skylight.dir") {
  231. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  232. if (sl) {
  233. std::ostream respStream(&response);
  234. const Vector &dir = sl->GetSunDir();
  235. respStream << dir.x << " " << dir.y << " " << dir.x << "\n";
  236. respStream << "OK\n";
  237. boost::asio::write(socket, response);
  238. } else {
  239. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  240. SLG_LOG("[Telnet server] No SkyLight defined: " << property);
  241. }
  242. } else if (property == "scene.skylight.gain") {
  243. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  244. if (sl) {
  245. std::ostream respStream(&response);
  246. const Spectrum gain = sl->GetGain();
  247. respStream << gain.r << " " << gain.g << " " << gain.b << "\n";
  248. respStream << "OK\n";
  249. boost::asio::write(socket, response);
  250. } else {
  251. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  252. SLG_LOG("[Telnet server] No SkyLight defined: " << property);
  253. }
  254. } else if (property == "scene.skylight.turbidity") {
  255. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  256. if (sl) {
  257. std::ostream respStream(&response);
  258. respStream << sl->GetTubidity() << "\n";
  259. respStream << "OK\n";
  260. boost::asio::write(socket, response);
  261. } else {
  262. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  263. SLG_LOG("[Telnet server] No SkyLight defined: " << property);
  264. }
  265. } else if (property == "scene.sunlight.turbidity") {
  266. // Look for the SunLight
  267. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  268. if (sl) {
  269. std::ostream respStream(&response);
  270. respStream << sl->GetTubidity() << "\n";
  271. respStream << "OK\n";
  272. boost::asio::write(socket, response);
  273. } else {
  274. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  275. SLG_LOG("[Telnet server] No SunLight defined: " << property);
  276. }
  277. } else if (property == "scene.sunlight.relsize") {
  278. // Look for the SunLight
  279. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  280. if (sl) {
  281. std::ostream respStream(&response);
  282. respStream << sl->GetRelSize() << "\n";
  283. respStream << "OK\n";
  284. boost::asio::write(socket, response);
  285. } else {
  286. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  287. SLG_LOG("[Telnet server] No SunLight defined: " << property);
  288. }
  289. } else if (property == "scene.sunlight.dir") {
  290. // Look for the SunLight
  291. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  292. if (sl) {
  293. std::ostream respStream(&response);
  294. const Vector &dir = sl->GetDir();
  295. respStream << dir.x << " " << dir.y << " " << dir.x << "\n";
  296. respStream << "OK\n";
  297. boost::asio::write(socket, response);
  298. } else {
  299. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  300. SLG_LOG("[Telnet server] No SunLight defined: " << property);
  301. }
  302. } else if (property == "scene.sunlight.gain") {
  303. // Look for the SunLight
  304. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  305. if (sl) {
  306. std::ostream respStream(&response);
  307. const Spectrum &gain = sl->GetGain();
  308. respStream << gain.r << " " << gain.g << " " << gain.b << "\n";
  309. respStream << "OK\n";
  310. boost::asio::write(socket, response);
  311. } else {
  312. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  313. SLG_LOG("[Telnet server] No SunLight defined: " << property);
  314. }
  315. } else {
  316. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  317. SLG_LOG("[Telnet server] Unknown property: " << property);
  318. }
  319. } else if (command == "help.get") {
  320. boost::asio::streambuf response;
  321. std::ostream respStream(&response);
  322. respStream << "film.tonemap.linear.scale\n";
  323. respStream << "film.tonemap.reinhard02.burn\n";
  324. respStream << "film.tonemap.reinhard02.postscale\n";
  325. respStream << "film.tonemap.reinhard02.prescale\n";
  326. respStream << "film.tonemap.type\n";
  327. respStream << "image.filename\n";
  328. respStream << "scene.camera.fieldofview\n";
  329. respStream << "scene.camera.focaldistance\n";
  330. respStream << "scene.camera.lensradius\n";
  331. respStream << "scene.camera.lookat\n";
  332. respStream << "scene.camera.up\n";
  333. respStream << "scene.infinitelight.gain\n";
  334. respStream << "scene.infinitelight.shift\n";
  335. respStream << "scene.skylight.dir\n";
  336. respStream << "scene.skylight.gain\n";
  337. respStream << "scene.skylight.turbidity\n";
  338. respStream << "scene.sunlight.dir\n";
  339. respStream << "scene.sunlight.gain\n";
  340. respStream << "scene.sunlight.relsize\n";
  341. respStream << "scene.sunlight.turbidity\n";
  342. respStream << "OK\n";
  343. boost::asio::write(socket, response);
  344. } else if (command == "help.set") {
  345. boost::asio::streambuf response;
  346. std::ostream respStream(&response);
  347. respStream << "film.tonemap.linear.scale\n";
  348. respStream << "film.tonemap.reinhard02.burn\n";
  349. respStream << "film.tonemap.reinhard02.postscale\n";
  350. respStream << "film.tonemap.reinhard02.prescale\n";
  351. respStream << "film.tonemap.type\n";
  352. respStream << "image.filename\n";
  353. respStream << "scene.camera.fieldofview (requires edit.start)\n";
  354. respStream << "scene.camera.focaldistance (requires edit.start)\n";
  355. respStream << "scene.camera.lensradius (requires edit.start)\n";
  356. respStream << "scene.camera.lookat (requires edit.start)\n";
  357. respStream << "scene.camera.up (requires edit.start)\n";
  358. respStream << "scene.materials.* (requires edit.start, comma separated list of properties)\n";
  359. respStream << "scene.infinitelight.gain (requires edit.start)\n";
  360. respStream << "scene.infinitelight.shift (requires edit.start)\n";
  361. respStream << "scene.objects.*.transformation (requires edit.start)\n";
  362. respStream << "scene.skylight.dir (requires edit.start)\n";
  363. respStream << "scene.skylight.gain (requires edit.start)\n";
  364. respStream << "scene.skylight.turbidity (requires edit.start)\n";
  365. respStream << "scene.sunlight.dir (requires edit.start)\n";
  366. respStream << "scene.sunlight.gain (requires edit.start)\n";
  367. respStream << "scene.sunlight.relsize (requires edit.start)\n";
  368. respStream << "scene.sunlight.turbidity (requires edit.start)\n";
  369. respStream << "OK\n";
  370. boost::asio::write(socket, response);
  371. } else if (command == "image.reset") {
  372. if (state == EDIT) {
  373. session->film->Reset();
  374. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  375. } else {
  376. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  377. SLG_LOG("[Telnet server] Wrong state");
  378. }
  379. } else if (command == "material.list") {
  380. boost::asio::streambuf response;
  381. std::ostream respStream(&response);
  382. std::vector<std::string> names = scene->matDefs.GetMaterialNames();
  383. for (std::vector<std::string>::const_iterator iter = names.begin(); iter < names.end(); ++iter)
  384. respStream << (*iter) << "\n";
  385. respStream << "OK\n";
  386. boost::asio::write(socket, response);
  387. } else if (command == "object.list") {
  388. boost::asio::streambuf response;
  389. std::ostream respStream(&response);
  390. std::vector<std::string> names = scene->meshDefs.GetExtMeshNames();
  391. for (std::vector<std::string>::const_iterator iter = names.begin(); iter < names.end(); ++iter)
  392. respStream << (*iter) << "\n";
  393. respStream << "OK\n";
  394. boost::asio::write(socket, response);
  395. } else if (command == "image.save") {
  396. session->SaveFilmImage();
  397. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  398. } else if ((command == "edit.stop") || (command == "render.start")) {
  399. if (state == EDIT) {
  400. if (session->editActions.Has(MATERIALS_EDIT)) {
  401. session->renderConfig->scene->RemoveUnusedMaterials();
  402. session->renderConfig->scene->RemoveUnusedTextures();
  403. }
  404. session->EndEdit();
  405. }
  406. state = RUN;
  407. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  408. } else if ((command == "edit.start") || (command == "render.stop")) {
  409. if (state == RUN)
  410. session->BeginEdit();
  411. state = EDIT;
  412. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  413. } else if (command == "set") {
  414. //------------------------------------------------------
  415. // Set property
  416. //------------------------------------------------------
  417. try {
  418. // Get the name of the property to set
  419. string properties;
  420. getline(commandStream, properties, '\n');
  421. if (echoCommandOn)
  422. SLG_LOG("[Telnet server] Set: " << properties);
  423. // Split the line by comma
  424. std::vector<std::string> splitProperties;
  425. boost::split(splitProperties, properties, boost::is_any_of(","));
  426. for (std::vector<std::string>::iterator it = splitProperties.begin(); it < splitProperties.end(); ++it)
  427. boost::trim(*it);
  428. // Build the Properties
  429. Properties props;
  430. const string propertyName = props.SetString(splitProperties[0]);
  431. for (std::vector<std::string>::const_iterator it = splitProperties.begin() + 1; it < splitProperties.end(); ++it)
  432. props.SetString(*it);
  433. // Check if is one of the supported properties
  434. if (propertyName == "film.tonemap.linear.scale") {
  435. const float k = props.GetFloat(propertyName, 1.f);
  436. if (film->GetToneMapParams()->GetType() == TONEMAP_LINEAR) {
  437. boost::asio::streambuf response;
  438. std::ostream respStream(&response);
  439. LinearToneMapParams *params = (LinearToneMapParams *)film->GetToneMapParams()->Copy();
  440. params->scale = k;
  441. film->SetToneMapParams(*params);
  442. delete params;
  443. respStream << "OK\n";
  444. boost::asio::write(socket, response);
  445. } else {
  446. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  447. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  448. }
  449. } else if (propertyName == "film.tonemap.reinhard02.burn") {
  450. const float k = props.GetFloat(propertyName, 3.75f);
  451. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  452. boost::asio::streambuf response;
  453. std::ostream respStream(&response);
  454. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams()->Copy();
  455. params->burn = k;
  456. film->SetToneMapParams(*params);
  457. delete params;
  458. respStream << "OK\n";
  459. boost::asio::write(socket, response);
  460. } else {
  461. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  462. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  463. }
  464. } else if (propertyName == "film.tonemap.reinhard02.postscale") {
  465. const float k = props.GetFloat(propertyName, 1.2f);
  466. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  467. boost::asio::streambuf response;
  468. std::ostream respStream(&response);
  469. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams()->Copy();
  470. params->postScale = k;
  471. film->SetToneMapParams(*params);
  472. delete params;
  473. respStream << "OK\n";
  474. boost::asio::write(socket, response);
  475. } else {
  476. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  477. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  478. }
  479. } else if (propertyName == "film.tonemap.reinhard02.prescale") {
  480. const float k = props.GetFloat(propertyName, 1.f);
  481. if (film->GetToneMapParams()->GetType() == TONEMAP_REINHARD02) {
  482. boost::asio::streambuf response;
  483. std::ostream respStream(&response);
  484. Reinhard02ToneMapParams *params = (Reinhard02ToneMapParams *)film->GetToneMapParams()->Copy();
  485. params->preScale = k;
  486. film->SetToneMapParams(*params);
  487. delete params;
  488. respStream << "OK\n";
  489. boost::asio::write(socket, response);
  490. } else {
  491. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  492. SLG_LOG("[Telnet server] Not using TONEMAP_REINHARD02");
  493. }
  494. } else if (propertyName == "film.tonemap.type") {
  495. const int type = props.GetInt(propertyName, 0);
  496. if (type == 0) {
  497. LinearToneMapParams params;
  498. film->SetToneMapParams(params);
  499. } else {
  500. Reinhard02ToneMapParams params;
  501. film->SetToneMapParams(params);
  502. }
  503. respStream << "OK\n";
  504. boost::asio::write(socket, response);
  505. } else if (propertyName == "image.filename") {
  506. // Get the image file name
  507. const string fileName = props.GetString(propertyName, "image.png");
  508. session->renderConfig->cfg.SetString("image.filename", fileName);
  509. respStream << "OK\n";
  510. boost::asio::write(socket, response);
  511. } else if (propertyName == "scene.infinitelight.gain") {
  512. // Check if we are in the right state
  513. if (state == EDIT) {
  514. InfiniteLight *il = (InfiniteLight *)scene->GetLightByType(TYPE_IL);
  515. if (il) {
  516. const std::vector<float> vf = props.GetFloatVector(propertyName, "1.0 1.0 1.0");
  517. Spectrum gain(vf.at(0), vf.at(1), vf.at(2));
  518. il->SetGain(gain);
  519. session->editActions.AddAction(INFINITELIGHT_EDIT);
  520. respStream << "OK\n";
  521. boost::asio::write(socket, response);
  522. } else {
  523. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  524. SLG_LOG("[Telnet server] No InifinteLight defined: " << properties);
  525. }
  526. } else {
  527. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  528. SLG_LOG("[Telnet server] Wrong state: " << properties);
  529. }
  530. } else if (propertyName == "scene.infinitelight.shift") {
  531. // Check if we are in the right state
  532. if (state == EDIT) {
  533. InfiniteLight *il = (InfiniteLight *)scene->GetLightByType(TYPE_IL);
  534. if (il) {
  535. const std::vector<float> vf = props.GetFloatVector(propertyName, "0.0 0.0");
  536. il->GetUVMapping()->uDelta = vf.at(0);
  537. il->GetUVMapping()->vDelta = vf.at(1);
  538. session->editActions.AddAction(INFINITELIGHT_EDIT);
  539. respStream << "OK\n";
  540. boost::asio::write(socket, response);
  541. } else {
  542. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  543. SLG_LOG("[Telnet server] No InifinteLight defined: " << properties);
  544. }
  545. } else {
  546. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  547. SLG_LOG("[Telnet server] Wrong state: " << properties);
  548. }
  549. } else if (propertyName == "scene.skylight.dir") {
  550. // Check if we are in the right state
  551. if (state == EDIT) {
  552. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  553. if (sl) {
  554. const std::vector<float> vf = props.GetFloatVector(propertyName, "0.0 0.0 1.0");
  555. Vector dir(vf.at(0), vf.at(1), vf.at(2));
  556. sl->SetSunDir(dir);
  557. sl->Preprocess();
  558. session->editActions.AddAction(SKYLIGHT_EDIT);
  559. respStream << "OK\n";
  560. boost::asio::write(socket, response);
  561. } else {
  562. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  563. SLG_LOG("[Telnet server] No SkyLight defined: " << properties);
  564. }
  565. } else {
  566. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  567. SLG_LOG("[Telnet server] Wrong state: " << properties);
  568. }
  569. } else if (propertyName == "scene.skylight.gain") {
  570. // Check if we are in the right state
  571. if (state == EDIT) {
  572. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  573. if (sl) {
  574. const std::vector<float> vf = props.GetFloatVector(propertyName, "1.0 1.0 1.0");
  575. Spectrum gain(vf.at(0), vf.at(1), vf.at(2));
  576. sl->SetGain(gain);
  577. session->editActions.AddAction(SKYLIGHT_EDIT);
  578. respStream << "OK\n";
  579. boost::asio::write(socket, response);
  580. } else {
  581. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  582. SLG_LOG("[Telnet server] No SkyLight defined: " << properties);
  583. }
  584. } else {
  585. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  586. SLG_LOG("[Telnet server] Wrong state: " << properties);
  587. }
  588. } else if (propertyName == "scene.skylight.turbidity") {
  589. // Check if we are in the right state
  590. if (state == EDIT) {
  591. SkyLight *sl = (SkyLight *)scene->GetLightByType(TYPE_IL_SKY);
  592. if (sl) {
  593. sl->SetTurbidity(props.GetFloat(propertyName, 2.2f));
  594. sl->Preprocess();
  595. session->editActions.AddAction(SKYLIGHT_EDIT);
  596. respStream << "OK\n";
  597. boost::asio::write(socket, response);
  598. } else {
  599. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  600. SLG_LOG("[Telnet server] No SkyLight defined: " << properties);
  601. }
  602. } else {
  603. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  604. SLG_LOG("[Telnet server] Wrong state: " << properties);
  605. }
  606. } else if (propertyName == "scene.sunlight.turbidity") {
  607. if (state == EDIT) {
  608. // Look for the SunLight
  609. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  610. if (sl) {
  611. sl->SetTurbidity(props.GetFloat(propertyName, 2.2f));
  612. sl->Preprocess();
  613. session->editActions.AddAction(SUNLIGHT_EDIT);
  614. respStream << "OK\n";
  615. boost::asio::write(socket, response);
  616. } else {
  617. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  618. SLG_LOG("[Telnet server] No SunLight defined: " << properties);
  619. }
  620. } else {
  621. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  622. SLG_LOG("[Telnet server] Wrong state: " << properties);
  623. }
  624. } else if (propertyName == "scene.sunlight.relsize") {
  625. if (state == EDIT) {
  626. // Look for the SunLight
  627. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  628. if (sl) {
  629. sl->SetRelSize(props.GetFloat(propertyName, 1.f));
  630. sl->Preprocess();
  631. session->editActions.AddAction(SUNLIGHT_EDIT);
  632. respStream << "OK\n";
  633. boost::asio::write(socket, response);
  634. } else {
  635. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  636. SLG_LOG("[Telnet server] No SunLight defined: " << properties);
  637. }
  638. } else {
  639. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  640. SLG_LOG("[Telnet server] Wrong state: " << properties);
  641. }
  642. } else if (propertyName == "scene.sunlight.dir") {
  643. if (state == EDIT) {
  644. // Look for the SunLight
  645. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  646. if (sl) {
  647. const std::vector<float> vf = props.GetFloatVector(propertyName, "0.0 0.0 1.0");
  648. Vector dir(vf.at(0), vf.at(1), vf.at(2));
  649. sl->SetDir(dir);
  650. sl->Preprocess();
  651. session->editActions.AddAction(SUNLIGHT_EDIT);
  652. respStream << "OK\n";
  653. boost::asio::write(socket, response);
  654. } else {
  655. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  656. SLG_LOG("[Telnet server] No SunLight defined: " << properties);
  657. }
  658. } else {
  659. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  660. SLG_LOG("[Telnet server] Wrong state: " << properties);
  661. }
  662. } else if (propertyName == "scene.sunlight.gain") {
  663. if (state == EDIT) {
  664. // Look for the SunLight
  665. SunLight *sl = (SunLight *)scene->GetLightByType(TYPE_SUN);
  666. if (sl) {
  667. const std::vector<float> vf = props.GetFloatVector(propertyName, "1.0 1.0 1.0");
  668. Spectrum gain(vf.at(0), vf.at(1), vf.at(2));
  669. sl->SetGain(gain);
  670. sl->Preprocess();
  671. session->editActions.AddAction(SUNLIGHT_EDIT);
  672. respStream << "OK\n";
  673. boost::asio::write(socket, response);
  674. } else {
  675. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  676. SLG_LOG("[Telnet server] No SunLight defined: " << properties);
  677. }
  678. } else {
  679. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  680. SLG_LOG("[Telnet server] Wrong state: " << properties);
  681. }
  682. } else if (propertyName.find("scene.materials.") == 0) {
  683. if (state == EDIT) {
  684. // Check if it is the name of a known material
  685. const std::string matName = Properties::ExtractField(propertyName, 2);
  686. if (matName == "")
  687. throw std::runtime_error("Syntax error in " + propertyName);
  688. // Update material definition
  689. scene->UpdateMaterial(matName, props);
  690. const Material *newMat = scene->matDefs.GetMaterial(matName);
  691. // To enable this optimization, I should check not only all
  692. // referenced materials (i.e. Mix) but also all referenced textures.
  693. // Doesn't seem worth the work.
  694. //// Check if the material type is one of the already enabled
  695. //if (!session->renderEngine->IsMaterialCompiled(newMat->GetType()))
  696. session->editActions.AddAction(MATERIAL_TYPES_EDIT);
  697. // Check if both are light sources
  698. if (newMat->IsLightSource())
  699. session->editActions.AddAction(AREALIGHTS_EDIT);
  700. session->editActions.AddAction(MATERIALS_EDIT);
  701. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  702. } else {
  703. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  704. SLG_LOG("[Telnet server] Wrong state: " << properties);
  705. }
  706. } else if ((propertyName.find("scene.objects.") == 0) && (propertyName.find(".transformation") == propertyName.size() - 15)) {
  707. if (state == EDIT) {
  708. // Check if it is the name of a known objects
  709. const std::string objName = Properties::ExtractField(propertyName, 2);
  710. if (objName == "")
  711. throw std::runtime_error("Syntax error in " + propertyName);
  712. // Read the new transformation
  713. const std::vector<float> vf = props.GetFloatVector(propertyName,
  714. "1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0");
  715. const Matrix4x4 mat(
  716. vf.at(0), vf.at(4), vf.at(8), vf.at(12),
  717. vf.at(1), vf.at(5), vf.at(9), vf.at(13),
  718. vf.at(2), vf.at(6), vf.at(10), vf.at(14),
  719. vf.at(3), vf.at(7), vf.at(11), vf.at(15));
  720. const Transform trans(mat);
  721. // Update object transformation
  722. scene->UpdateObjectTransformation(objName, trans);
  723. // Check if it is a light source
  724. const u_int meshIndex = scene->meshDefs.GetExtMeshIndex(objName);
  725. if (scene->objectMaterials[meshIndex]->IsLightSource()) {
  726. // Some render engine requires a complete update when
  727. // modifying a light source
  728. session->editActions.AddAction(AREALIGHTS_EDIT);
  729. }
  730. // Set the flag to Update the DataSet
  731. ExtMesh *mesh = scene->meshDefs.GetExtMesh(objName);
  732. if (mesh->GetType() == TYPE_EXT_TRIANGLE_INSTANCE)
  733. session->editActions.AddAction(INSTANCE_TRANS_EDIT);
  734. else
  735. session->editActions.AddAction(GEOMETRY_EDIT);
  736. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  737. } else {
  738. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  739. SLG_LOG("[Telnet server] Wrong state: " << properties);
  740. }
  741. } else if (propertyName == "scene.camera.lookat") {
  742. // Check if we are in the right state
  743. if (state == EDIT) {
  744. const std::vector<float> vf = props.GetFloatVector(propertyName, "10.0 0.0 0.0 0.0 0.0 0.0");
  745. Point o(vf.at(0), vf.at(1), vf.at(2));
  746. Point t(vf.at(3), vf.at(4), vf.at(5));
  747. scene->camera->orig = o;
  748. scene->camera->target = t;
  749. scene->camera->Update(film->GetWidth(),
  750. film->GetHeight());
  751. session->editActions.AddAction(CAMERA_EDIT);
  752. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  753. } else {
  754. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  755. SLG_LOG("[Telnet server] Wrong state: " << properties);
  756. }
  757. } else if (propertyName == "scene.camera.up") {
  758. // Check if we are in the right state
  759. if (state == EDIT) {
  760. const std::vector<float> vf = props.GetFloatVector(propertyName, "0.0 0.0 0.1");
  761. Vector up(vf.at(0), vf.at(1), vf.at(2));
  762. scene->camera->up = Normalize(up);
  763. scene->camera->Update(film->GetWidth(),
  764. film->GetHeight());
  765. session->editActions.AddAction(CAMERA_EDIT);
  766. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  767. } else {
  768. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  769. SLG_LOG("[Telnet server] Wrong state: " << properties);
  770. }
  771. } else if (propertyName == "scene.camera.lensradius") {
  772. // Check if we are in the right state
  773. if (state == EDIT) {
  774. scene->camera->lensRadius = props.GetFloat(propertyName, 0.f);
  775. scene->camera->Update(film->GetWidth(),
  776. film->GetHeight());
  777. session->editActions.AddAction(CAMERA_EDIT);
  778. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  779. } else {
  780. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  781. SLG_LOG("[Telnet server] Wrong state: " << properties);
  782. }
  783. } else if (propertyName == "scene.camera.fieldofview") {
  784. // Check if we are in the right state
  785. if (state == EDIT) {
  786. scene->camera->fieldOfView = props.GetFloat(propertyName, 0.f);
  787. scene->camera->Update(film->GetWidth(),
  788. film->GetHeight());
  789. session->editActions.AddAction(CAMERA_EDIT);
  790. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  791. } else {
  792. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  793. SLG_LOG("[Telnet server] Wrong state: " << properties);
  794. }
  795. } else if (propertyName == "scene.camera.focaldistance") {
  796. // Check if we are in the right state
  797. if (state == EDIT) {
  798. scene->camera->focalDistance = props.GetFloat(propertyName, 0.f);
  799. scene->camera->Update(film->GetWidth(),
  800. film->GetHeight());
  801. session->editActions.AddAction(CAMERA_EDIT);
  802. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  803. } else {
  804. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  805. SLG_LOG("[Telnet server] Wrong state: " << properties);
  806. }
  807. } else {
  808. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  809. SLG_LOG("[Telnet server] Unknown property: " << properties);
  810. }
  811. } catch (std::exception& e) {
  812. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  813. SLG_LOG("[Telnet server] Error while setting a property: " << e.what());
  814. }
  815. } else if ((command == "transmit.framebuffer.rgb_float")) {
  816. // Lock the film
  817. {
  818. boost::unique_lock<boost::mutex> lock(session->filmMutex);
  819. // Transmit the image size
  820. const unsigned int w = film->GetWidth();
  821. const unsigned int h = film->GetHeight();
  822. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(&w, sizeof(unsigned int))));
  823. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(&h, sizeof(unsigned int))));
  824. // Transmit the framebuffer (RGB float)
  825. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(session->film->GetScreenBuffer(),
  826. sizeof(float) * w * h * 3)));
  827. }
  828. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  829. } else if ((command == "transmit.framebuffer.rgb_byte")) {
  830. // Lock the film
  831. {
  832. boost::unique_lock<boost::mutex> lock(session->filmMutex);
  833. // Transmit the image size
  834. const unsigned int w = film->GetWidth();
  835. const unsigned int h = film->GetHeight();
  836. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(&w, sizeof(unsigned int))));
  837. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(&h, sizeof(unsigned int))));
  838. // Translate the framebuffer
  839. unsigned char *fb = new unsigned char[w * h * 3];
  840. unsigned char *dst = fb;
  841. const float *src = session->film->GetScreenBuffer();
  842. for (unsigned int i = 0; i < w * h; ++i) {
  843. *dst++ = (*src++) * 255.f + .5f;
  844. *dst++ = (*src++) * 255.f + .5f;
  845. *dst++ = (*src++) * 255.f + .5f;
  846. }
  847. // Transmit the framebuffer (RGB byte)
  848. boost::asio::write(socket, boost::asio::buffer(boost::asio::const_buffer(fb,
  849. sizeof(unsigned char) * w * h * 3)));
  850. delete fb;
  851. }
  852. boost::asio::write(socket, boost::asio::buffer("OK\n", 3));
  853. } else {
  854. boost::asio::write(socket, boost::asio::buffer("ERROR\n", 6));
  855. SLG_LOG("[Telnet server] Unknown command");
  856. }
  857. }
  858. } catch (std::exception& e) {
  859. SLG_LOG("[Telnet server] Connection error: " << e.what());
  860. }
  861. }
  862. } catch (std::exception& e) {
  863. SLG_LOG("Telnet server error: " << e.what());
  864. }
  865. }