{"id":875,"date":"2012-10-24T10:08:52","date_gmt":"2012-10-24T10:08:52","guid":{"rendered":"http:\/\/coherent-labs.com\/?p=875"},"modified":"2017-11-13T12:28:08","modified_gmt":"2017-11-13T12:28:08","slug":"cryengine-3-integration","status":"publish","type":"post","link":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/","title":{"rendered":"CryEngine 3 Integration"},"content":{"rendered":"<p>This week we&#8217;re on a multimedia frenzy and we&#8217;re presenting another video of\u00a0<strong>Coherent UI<\/strong>\u00a0:).<\/p>\n<p>This one is about our experimental integration in\u00a0<a href=\"http:\/\/mycryengine.com\/\" target=\"_blank\"><strong>CryEngine 3<\/strong><\/a>. It&#8217;s experimental because our integration is with the free SDK, which doesn&#8217;t expose enough resources for maximal performance (e.g. the DirectX device is not easily accessible). We wanted to have it as clean as possible (no hacky stuff!) to understand the problems one might have when trying to integrate\u00a0<strong>Coherent UI<\/strong>\u00a0in an existing engine. While this led to having sub-optimal performance (technical details below the video), it was still very good and we believe it&#8217;s worth showing.<\/p>\n<p>The video demonstrates some exciting features of\u00a0<strong>Coherent UI<\/strong>:<\/p>\n<ul>\n<li>Displaying any website on any surface<\/li>\n<li>Support for HTML5\/CSS3, SSL<\/li>\n<li>Social integration with Facebook, Twitter, Google+ (well, this isn&#8217;t exactly demonstrated, but we have it :))<\/li>\n<li>JavaScript binding (for engine variables and methods)<\/li>\n<li>Live editing\/debugging the interface<\/li>\n<\/ul>\n<div>Without further ado (and I realize it&#8217;s been quite an ado :)) I present you\u00a0<strong>Coherent UI<\/strong>\u00a0in CryEngine3!<\/div>\n<p>&nbsp;<br \/>\n&nbsp;<\/p>\n<div class=\"alignCenterImg_blog\"><iframe loading=\"lazy\" width=\"640\" height=\"360\" src=\"\/\/www.youtube.com\/embed\/tMv1PsXVRS4?wmode=transparent\" frameborder=\"0\" allowfullscreen><\/iframe><\/div>\n<p>&nbsp;<\/p>\n<div class=\"alignCenterImg_blog\"><strong>Coherent UI<\/strong>\u00a0in CryEngine 3<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<div>\n<div class=\"alignCenterImg_blog\"><iframe loading=\"lazy\" width=\"640\" height=\"360\" src=\"\/\/www.youtube.com\/embed\/Rai7vxH_gs8?wmode=transparent\" frameborder=\"0\" allowfullscreen><\/iframe><\/div>\n<p>&nbsp;<\/p>\n<div class=\"alignCenterImg_blog\"><strong>Coherent UI<\/strong>\u00a0in CryEngine 3 (short version of the above)<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<p class=\"title\">Developer tidbits<\/p>\n<div>Here&#8217;s the story of the hurdles we had to overcome.\u00a0Let me start with this first, the lack of access to the DirectX device was extremely annoying. So, now that we&#8217;ve got that clear, we just started our integration&#8230; and immediately ran into a problem.<\/p>\n<div>There was no easy way to create an empty texture with specified size. Let alone create a shared texture for Windows Vista\/7. This presented the first small inefficiency in the integration, since we had to use shared memory as image transport mechanism from\u00a0<strong>Coherent UI<\/strong>\u00a0to CryEngine 3, which involves some memory copying (and using shared textures doesn&#8217;t). Even access to the device wouldn&#8217;t help that much here since we&#8217;d like to have a valid engine handle for the texture, which means that we can&#8217;t bypass it. After some experimenting, we settled on creating a dummy material with the editor, assigning a placeholder diffuse texture and getting its ID with the following code:<\/div>\n<p>&nbsp;<br \/>\n<script src=\"https:\/\/gist.github.com\/3946392.js\"> <\/script><\/p>\n<div>Having the ID, we can update the texture at runtime using\u00a0<span class=\"blog_post_fontStyleSnippet\">IRenderer::UpdateTextureInVideoMemory<\/span>. This approach comes with its own set of problems, however. An obvious one is that you need unique dummy material and diffuse texture for each\u00a0<strong>Coherent UI\u00a0<\/strong><span class=\"blog_post_fontStyleSnippet\">View<\/span>, which is annoying. Another problem is that this texture is not resizable, so we had an array of textures with common sizes that were the only ones allowed when resizing a\u00a0View. The least obvious problem was that if the material&#8217;s texture had a mip-chain,\u00a0<span class=\"blog_post_fontStyleSnippet\">IRenderer::UpdateTextureInVideoMemory<\/span>\u00a0did\u00a0<strong>not\u00a0<\/strong>automatically generate the lower mip levels which resulted in some strange results, because of the trilinear filtering. It didn&#8217;t perform any kind of stretching either, and that&#8217;s why we only allowed preset\u00a0<span class=\"blog_post_fontStyleSnippet\">View<\/span>\u00a0resolutions. You can see the mips problem here:<\/div>\n<p>&nbsp;<\/p>\n<div  class=\"alignCenterImg_blog\"><a href=\"\/wp-content\/themes\/post_img\/blog\/cryengine-3-integration_img1.jpg\" target=\"_blank\"><img decoding=\"async\" alt=\"CryEngine 3 Integration\" src=\"\/wp-content\/themes\/post_img\/blog\/cryengine-3-integration_img1.jpg\" width=\"640\" height=\"auto\" border=\"0\" \/><\/a><\/div>\n<p>&nbsp;<\/p>\n<div class=\"alignCenterImg_blog\">Problematic trilinear texture filtering<\/div>\n<p>&nbsp;<\/p>\n<div  class=\"alignCenterImg_blog\"><a href=\"\/wp-content\/themes\/post_img\/blog\/cryengine-3-integration_img2.jpg\" target=\"_blank\"><img decoding=\"async\" alt=\"CryEngine 3 Integration\" src=\"\/wp-content\/themes\/post_img\/blog\/cryengine-3-integration_img2.jpg\" width=\"640\" height=\"auto\" border=\"0\" \/><\/a><\/div>\n<p>&nbsp;<\/p>\n<div class=\"alignCenterImg_blog\">The placeholder texture<\/div>\n<p>&nbsp;<\/p>\n<div>It took some time for figuring out since, at first, we didn&#8217;t have fancy placeholder textures, but only solid color ones. The solution was to simply assign a texture that had only one surface (i.e. no mips). This presented another small inefficiency.<\/div>\n<div><\/div>\n<div>Ok, we have a texture now, we can update it and all, but how do we draw it on top of everything so it acts as a UI? After some digging in the SDK, we found that the\u00a0<span class=\"blog_post_fontStyleSnippet\">CBitmapUI<\/span>(and more precisely,\u00a0<span class=\"blog_post_fontStyleSnippet\">IGameFramwork&#8217;s\u00a0IUIDraw<\/span>) class should be able to solve this, having various methods for drawing full-screen quads. The color and alpha channel weights were messed up, however, so we had to <span class=\"blog_post_fontStyleSnippet\">callIUIDraw::DrawImage<\/span>\u00a0beforehand, which had the weights as parameters, so we could reset them to 1.0. We just drew a dummy image outside the viewport to reset these values, having yet another small inefficiency.<\/div>\n<p>&nbsp;<\/p>\n<div>Moving on, to the biggest inefficiency of all &#8211;\u00a0<strong>Coherent UI<\/strong>\u00a0provides color values with premultiplied alpha. This means that transparency is already taken into account. When drawing the fullscreen quad, the blending modes in CryEngine are set to\u00a0<i>SourceAlpha<\/i>\/<i>1-SourceAlpha<\/i>\u00a0for the source and destination colors, respectively, meaning that the source alpha will be taken into account\u00a0<i>again<\/i>. What we had to is &#8220;post-divide&#8221; the alpha value, so when DirectX multiplies is we get the correct result. We had to do this for each pixel, involving both bitwise and floating point operations &#8211; imagine the slowdown for doing that on a 1280&#215;720 or even 1920&#215;1080 image. If we had device access, all that would be fixed with a single call for the blend mode but, alas, we don&#8217;t.\u00a0Also, if we used DirectX11 renderer, we&#8217;d have to do another pass on the pixels to swap their\u00a0<i>red<\/i>\u00a0and\u00a0<i>blue\u00a0<\/i>channels, because the component ordering has been changed since DirectX 10!<\/div>\n<p>&nbsp;<\/p>\n<div>Next on the list was input forwarding &#8211; we wanted to add means for stopping player input(so we don&#8217;t walk or lean or anything while typing) and redirecting it to\u00a0<strong>Coherent UI<\/strong>, so we could interact with the\u00a0View<i>s<\/i>. This wasn&#8217;t really a problem but it was rather tedious &#8211; we had to register our own\u00a0<span class=\"blog_post_fontStyleSnippet\">IInputEventListener<\/span>\u00a0that forwards input events to the focused View, if any.\u00a0The tedious part was creating gigantic mappings for CryEngine 3 to\u00a0<strong>Coherent UI<\/strong>\u00a0event conversion. Stopping player input when interacting with a\u00a0<span class=\"blog_post_fontStyleSnippet\">View<\/span>\u00a0was easy, too &#8211; we just had to disable the &#8220;<i>player<\/i>&#8221; action map using the\u00a0<span class=\"blog_post_fontStyleSnippet\">IActionMapManage<\/span>. We also needed a free cursor while ingame, so you can move your mouse when browsing, which was just a matter of calling the Windows API\u00a0<span class=\"blog_post_fontStyleSnippet\">ShowCursor<\/span>.<\/div>\n<p>&nbsp;<\/p>\n<div>The final problem was actually getting the texture coordinates of the projected mouse position onto the surface below. I tried using the physics system which provided some sort of raycasts that I got working, but i couldn&#8217;t do a refined trace on the actual geometry nor obtain it to do the tracing myself. And even if I managed to do that, I couldn&#8217;t find any way to get the texture coordinates using the free CryEngine 3 SDK. That&#8217;s why I just exported the\u00a0<i>interesting<\/i>\u00a0objects to .obj files using the CryEngine Editor, put the geometry into a KD-Tree and did the raycasting myself after all. For correct results, first we&#8217;d have to trace using the physics system so we know that no object is obstructing the\u00a0<span class=\"blog_post_fontStyleSnippet\">View<\/span>. Then, we trace in the KD-Tree and get the texture coordinates, which can be translated to\u00a0<span class=\"blog_post_fontStyleSnippet\">View<\/span>\u00a0coordinates.<\/div>\n<p>&nbsp;<\/p>\n<div>On the upside, there are some things that\u00a0<i>just worked\u00a0<\/i>&#8211; the JavaScript binding, debug highlights&#8230; pretty much anything that \u00a0didn&#8217;t rely on the CryEngine 3 renderer :).<\/div>\n<div>In conclusion, it worked pretty well, although if Crytek gave us access to the rendering device we could have been much more efficient in the integration, but then again, we used the free version so that&#8217;s what we get. I was thinking of ways to get the device, like scanning the memory around\u00a0<span class=\"blog_post_fontStyleSnippet\">gEnv-&gt;pRenderer<\/span>\u00a0for\u00a0<span class=\"blog_post_fontStyleSnippet\">IUnknowns<\/span> (by\u00a0<span class=\"blog_post_fontStyleSnippet\">memcmp<\/span>ing the first 3 virtual table entries) and then querying the interface for a D3D device, or just making a proxy DLL that exports the same functions as\u00a0<i>d3d9\/11.dll<\/i>\u00a0and installing hooks on the relevant calls, but I don&#8217;t have time for such fun now.<br \/>\n&nbsp;<br \/>\nNow that we&#8217;ve seen how far can we go using the free CryEngine 3 SDK, next on the agenda is full\u00a0<a href=\"http:\/\/blog.coherent-labs.com\/2012\/11\/coherent-ui-in-unity3d-first-look.html\" target=\"_blank\"><strong>Unity 3D<\/strong><\/a>\u00a0integration (we have device access there!). Be on the lookout for it next month!<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This week we&#8217;re on a multimedia frenzy and we&#8217;re presenting another video of\u00a0Coherent UI\u00a0:). This one is about our experimental integration in\u00a0CryEngine 3. It&#8217;s experimental because our integration is with the free SDK, which doesn&#8217;t expose enough resources for maximal performance (e.g. the DirectX device is not easily accessible). We wanted to have it as [&hellip;]<\/p>\n","protected":false},"author":10,"featured_media":9884,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[32],"tags":[157,161,168],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>CryEngine 3 Integration - Coherent Labs<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"CryEngine 3 Integration - Coherent Labs\" \/>\n<meta property=\"og:description\" content=\"This week we&#8217;re on a multimedia frenzy and we&#8217;re presenting another video of\u00a0Coherent UI\u00a0:). This one is about our experimental integration in\u00a0CryEngine 3. It&#8217;s experimental because our integration is with the free SDK, which doesn&#8217;t expose enough resources for maximal performance (e.g. the DirectX device is not easily accessible). We wanted to have it as [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/\" \/>\n<meta property=\"og:site_name\" content=\"Coherent Labs\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/CoherentLabs\/\" \/>\n<meta property=\"article:published_time\" content=\"2012-10-24T10:08:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-11-13T12:28:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/coherent-labs.com\/posts\/wp-content\/uploads\/2012\/10\/stencil.blog-post-feature-23.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Nick\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@CoherentLabs\" \/>\n<meta name=\"twitter:site\" content=\"@CoherentLabs\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nick\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/\",\"url\":\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/\",\"name\":\"CryEngine 3 Integration - Coherent Labs\",\"isPartOf\":{\"@id\":\"https:\/\/coherent-labs.com\/posts\/#website\"},\"datePublished\":\"2012-10-24T10:08:52+00:00\",\"dateModified\":\"2017-11-13T12:28:08+00:00\",\"author\":{\"@id\":\"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/0f7e122b7a2587b2ccaf7fe8f9964f94\"},\"breadcrumb\":{\"@id\":\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/coherent-labs.com\/posts\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"CryEngine 3 Integration\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/coherent-labs.com\/posts\/#website\",\"url\":\"https:\/\/coherent-labs.com\/posts\/\",\"name\":\"Coherent Labs\",\"description\":\"Cross-Platform Game UI Middleware\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/coherent-labs.com\/posts\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/0f7e122b7a2587b2ccaf7fe8f9964f94\",\"name\":\"Nick\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cf9bc3aa3b82bb10f4cc082fad0faa59?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cf9bc3aa3b82bb10f4cc082fad0faa59?s=96&d=mm&r=g\",\"caption\":\"Nick\"},\"url\":\"https:\/\/coherent-labs.com\/posts\/author\/nick\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"CryEngine 3 Integration - Coherent Labs","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/","og_locale":"en_US","og_type":"article","og_title":"CryEngine 3 Integration - Coherent Labs","og_description":"This week we&#8217;re on a multimedia frenzy and we&#8217;re presenting another video of\u00a0Coherent UI\u00a0:). This one is about our experimental integration in\u00a0CryEngine 3. It&#8217;s experimental because our integration is with the free SDK, which doesn&#8217;t expose enough resources for maximal performance (e.g. the DirectX device is not easily accessible). We wanted to have it as [&hellip;]","og_url":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/","og_site_name":"Coherent Labs","article_publisher":"https:\/\/www.facebook.com\/CoherentLabs\/","article_published_time":"2012-10-24T10:08:52+00:00","article_modified_time":"2017-11-13T12:28:08+00:00","og_image":[{"width":1200,"height":600,"url":"https:\/\/coherent-labs.com\/posts\/wp-content\/uploads\/2012\/10\/stencil.blog-post-feature-23.jpg","type":"image\/jpeg"}],"author":"Nick","twitter_card":"summary_large_image","twitter_creator":"@CoherentLabs","twitter_site":"@CoherentLabs","twitter_misc":{"Written by":"Nick","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/","url":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/","name":"CryEngine 3 Integration - Coherent Labs","isPartOf":{"@id":"https:\/\/coherent-labs.com\/posts\/#website"},"datePublished":"2012-10-24T10:08:52+00:00","dateModified":"2017-11-13T12:28:08+00:00","author":{"@id":"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/0f7e122b7a2587b2ccaf7fe8f9964f94"},"breadcrumb":{"@id":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/coherent-labs.com\/posts\/cryengine-3-integration\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/coherent-labs.com\/posts\/"},{"@type":"ListItem","position":2,"name":"CryEngine 3 Integration"}]},{"@type":"WebSite","@id":"https:\/\/coherent-labs.com\/posts\/#website","url":"https:\/\/coherent-labs.com\/posts\/","name":"Coherent Labs","description":"Cross-Platform Game UI Middleware","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/coherent-labs.com\/posts\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/0f7e122b7a2587b2ccaf7fe8f9964f94","name":"Nick","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/coherent-labs.com\/posts\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/cf9bc3aa3b82bb10f4cc082fad0faa59?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cf9bc3aa3b82bb10f4cc082fad0faa59?s=96&d=mm&r=g","caption":"Nick"},"url":"https:\/\/coherent-labs.com\/posts\/author\/nick\/"}]}},"_links":{"self":[{"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/posts\/875"}],"collection":[{"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/comments?post=875"}],"version-history":[{"count":1,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/posts\/875\/revisions"}],"predecessor-version":[{"id":9492,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/posts\/875\/revisions\/9492"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/media\/9884"}],"wp:attachment":[{"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/media?parent=875"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/categories?post=875"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coherent-labs.com\/posts\/wp-json\/wp\/v2\/tags?post=875"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}