tag:blogger.com,1999:blog-82139339550314299792024-03-06T01:47:28.841+01:00The Aav dev blgAnonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-8213933955031429979.post-18705187825421985102010-11-17T23:40:00.005+01:002010-11-18T00:09:13.906+01:00Skylight shadow and stuff.<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtvoZCINCxoNay2O0pWYOZIcWsqI2vlnOmokSuxNgRIw_YE4v5P2jkdQKo8cDpn1kvNsdgj7-8of34hyphenhyphenrnLOJx3xdgkvrr1gmPGZDVkEKThZySl5F_G0q-luCbl8zRMkNYZO1BVIdNB8w5/s1600/mchammer31.jpg"></a><div style="text-align: left;">Been working on the ambient/sky shadowing. Since the sky shadowing is block based, I had to blur it to avoid artefacts (currently a simple averaging filter). It is quite fuzzy, but better than anticipated. Also by adding another filter tap directly above a block, this provided a nice and simple way to simulate light "bleeding" into columns of blocks that lie in shadow, so the shadows are softened in the downward direction (provided that they neighbor some bright ones). I think I'm approaching a look that I like... still lots of tweaking remains.</div><div>
<br /></div><div>For OpenGL 3 capable cards, I added support for EXT_texture_arrays. This helps to solve the texture atlas issue, so now there is full mipmapping and anisotropic filtering in there with zero tiling problems. Just wish it was available on older hw too. </div><div>
<br /></div><div>1) Using a favorite 32x32 mid-res texture pack (John Smith Textures v4), this shot shows some light patterns on the floor projected by the ceiling window. This is before the blurring was added, so if you walked up close you'd be annoyed by the vertex interpolation. </div><div>
<br /></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIKfc58zMyNMJdE5n_gVhG0-z0xcS_kpsrMdF9BtmfNyCqCgiJBBkNnYuAKlQ2cBkPV_YbMWS0isDldJ5K1h4R2HknPZbOFQknDjUifTU661XLjoxRM7xDUBHpRu6zMMzy90llzSpBATVF/s1600/mchammer27.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIKfc58zMyNMJdE5n_gVhG0-z0xcS_kpsrMdF9BtmfNyCqCgiJBBkNnYuAKlQ2cBkPV_YbMWS0isDldJ5K1h4R2HknPZbOFQknDjUifTU661XLjoxRM7xDUBHpRu6zMMzy90llzSpBATVF/s400/mchammer27.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5540653142447714002" /></a>2) Same set of textures, and still point filtered in this one.<div>
<br /><div><span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicGI3qV610rVNcWBCGHbaESMbhbHF6T4M9VJ8Bs3AVISLGWtI5tMx-sL7oRxsAQBNOoYdK3ACH2iBtc59m93eME8xdl5Ugvycv1y7TK11av20n0YlWmegCd12zVhidZPQTQiFdt2XbAUDa/s400/mchammer29.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5540655109263225874" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 299px; " /></span></div><div>3) My coplayers modified the train station while I was coding, as this new TCP dump shows, ithas even more corners, ledges and interesting light patterns to test with now. This also shows the skylight bleeding in from the cross shaped "window", and some of the new 128 x 128 texture set. Torches are missing, that's why it's quite dark.</div><div><span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; ">
<br /></div><div><span class="Apple-style-span"><span class="Apple-style-span" style="color: rgb(0, 0, 0); "><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtvoZCINCxoNay2O0pWYOZIcWsqI2vlnOmokSuxNgRIw_YE4v5P2jkdQKo8cDpn1kvNsdgj7-8of34hyphenhyphenrnLOJx3xdgkvrr1gmPGZDVkEKThZySl5F_G0q-luCbl8zRMkNYZO1BVIdNB8w5/s1600/mchammer31.jpg"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtvoZCINCxoNay2O0pWYOZIcWsqI2vlnOmokSuxNgRIw_YE4v5P2jkdQKo8cDpn1kvNsdgj7-8of34hyphenhyphenrnLOJx3xdgkvrr1gmPGZDVkEKThZySl5F_G0q-luCbl8zRMkNYZO1BVIdNB8w5/s400/mchammer31.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5540656010244059826" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 299px; " /></a>
<br /></span></span></div></div><div>Next up either torch lighting or some player controls. I want to jump around in there, and not have to use the official client to connect me anymore.</div><div></div><div>Eventually I will port over my sky system from the old game. That'll be quite dramatic. </div>Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com1tag:blogger.com,1999:blog-8213933955031429979.post-84622838357330203522010-11-12T09:18:00.009+01:002010-11-12T09:55:27.042+01:00MC Hammer<div style="text-align: left;">Well, in my limited spare time I found a new obsession. Again of questionable use... but I'll be dumping some progress here. Eventually this will become MC Hammer, an alternate Minecraft client.</div><div><br /></div><div style="text-align: center;">First steps. Ran Minecraft and dumped the TCP stream via Wireshark. Thanks to #mcc on irc.esper.net and <a href="http://mc.kev009.com/wiki/Protocol">this excellent wiki</a> documenting the protocol, I managed to parse some wireframe geometry out of it!</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzYVud37GbSE9oNCDhfTR_cI8Hgl2ZfmbGUEBcPQ119_1VbIT1VEP3qOQypecg14XZPiZ9ZZg0i-qJiMgBIiscu1zBXg3Ow7xxOj59m48dq-u1hIi1jOKxXA0VBtPRE_6EjNnCAOREukft/s400/mchammer1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5538577064987190050" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 250px; " /></div><div style="text-align: center;"><br /></div><div style="text-align: center;">Some time later. I have texturing working etc, but it's Minecraft-style so not very pretty. I focused on working out the protocol and now render all world geometry. Next up, implementing my ambient occlusion scheme. Here are some first results, showing AO and some basic ambient shadow. The latter is done per block, and you can clearly see the squares. It's going to be blurred and interpolated.</div><br /><div style="text-align: center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAVhqY0Wj7nPTUoSl0a6iZhc-P66aNJFPQKQxyaWFMsmwgPhKFOitkXPY-QNH5E-MIRvsPbTVN9PqPqOpjWCf-r67ezr3By1fKIBpk6VBH7lLz6EKFv3P6LKwgisZPOUaoOieeeGNVJlv_/s400/mchammer14.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5538578081212759170" /><br /></div><div style="text-align: center;">Ambient shadow is filtered and interpolated... starting to look nice now I think. A little bland though. I need a good texture set.</div><div style="text-align: center;"><br /></div><div style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhruIRMB_f7z1Vk01RcxzxCPh8J9dE9QCHlMZJO4Gxmmn8MPDYPsBzdSZFP_8cgBZjBdN_qUAmIN_kfzF3avLF1QuNAj9Uc9-dQUqSFsNWFDVsenxXMeOv4RGJXQlyMFD1F6xaceMB1Fpc0/s1600/mchammer17.jpg"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhruIRMB_f7z1Vk01RcxzxCPh8J9dE9QCHlMZJO4Gxmmn8MPDYPsBzdSZFP_8cgBZjBdN_qUAmIN_kfzF3avLF1QuNAj9Uc9-dQUqSFsNWFDVsenxXMeOv4RGJXQlyMFD1F6xaceMB1Fpc0/s400/mchammer17.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5538579000255965026" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 295px; " /></a></div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH-t9diMSEdDcadKBQd0357POL9qmXU84-a6s4N2nkL2_ybks08awOr5VlvNxjxTzZh2iZr1aN9W4IWx6fvuM3WDuKI-fYHe_gk0VihR78I1wzx8hp3tGxAvo2UqN8L4NuilQ_8Nr9DOuV/s1600/mchammer19.jpg"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH-t9diMSEdDcadKBQd0357POL9qmXU84-a6s4N2nkL2_ybks08awOr5VlvNxjxTzZh2iZr1aN9W4IWx6fvuM3WDuKI-fYHe_gk0VihR78I1wzx8hp3tGxAvo2UqN8L4NuilQ_8Nr9DOuV/s400/mchammer19.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5538582472170815106" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 250px; " /></a></div><div><br /></div>Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-23414400507417601762009-06-21T00:11:00.004+02:002009-06-21T00:19:58.885+02:00Fixed cost gaussian blur (or: what no-one else will tell you)Well the title's a bit of an exaggeration. But this piece of code is used in ColorLab for calculating the gaussian blur kernel. You get an almost arbitrary blur strength (sigma) for an almost fixed cost (in fact it's faster the stronger the blur). It does this by approximating a little:<br /><br />- Assumes you first scale down the image using a box filter N times (the algorithm gives you the N).<br />- You then run the shader pass, using M bilinear texture samples. Most of those samples actually pick up two pixels, for a near 2x speedup.<br /><br />I haven't actually seen correct calculations of the bilinear sample points online so I worked it out myself. Turned out to be trivial, I wonder why I couldn't find it.<br /><br />Since this kind of set-up code is hard to come by (for some reason) I'm posting it here:<br /><br /><a href="http://code-bin.homedns.org/307">Click to get the code<br /></a><br />I rather like how it turned out. With contrast rich images you can sometimes get "popping" due to the decimations, but by setting MAX_WEIGHTS arbitrarily high you can pretty much bypass the decimation step and still use the generator (and in particular OptimizeBilinear).Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-54967758696052299182009-05-19T16:34:00.003+02:002009-05-19T16:38:56.545+02:00Windows InstallerWindows Installer/MSI files are such a nightmare to work with. I think <a href="http://msdn.microsoft.com/en-us/library/aa371865.aspx">this MSDN page</a> speaks for itself. And that was just one detail of what I just went through.Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com1tag:blogger.com,1999:blog-8213933955031429979.post-751665311638322792009-05-13T20:08:00.004+02:002009-05-13T20:45:13.596+02:0064-bit Win!I got ColorLab running natively in the public Windows 7 RC today, under Vegas Pro 9 64-bit (yes indeed), and the experience was painless. My ColorLab code is 64-bit safe already, thanks to the Visual C++ compiler checks. There were just a few hiccups (and even one blatant bug) in the DXMedia SDK files.<br /><br />So the thing is, Sony Vegas as of 2009 still uses smoking hot DirectX Transform plugin technology. It's <span style="font-weight: bold;">at least </span>ten years old, DirectX Media saw its last release in the age of DirectX 6 (!), and that's really quite depressing. Why Sony, why? But despite this, ColorLab seems to be working and I'm impressed with Microsoft again. It could have been a nightmare but just... wasn't.<br /><br />Now I just have to make a 64-bit installer and 1.0 RC2 is nearly at yer doorstep.Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-11719393763430463362009-02-13T14:03:00.002+01:002009-02-13T14:24:03.392+01:00DLL headachesMy <a href="http://aav6cc.blogspot.com">ColorLab</a> project has an ATL DLL which exposes a couple of COM objects. These COM objects are plugins that are spawned from the host application (Sony Vegas/Movie Studio), and there may be any number of instances. However, there is only meant to be one back-end "engine" in this DLL running for a Sony Vegas process, independent of how many COM objects are created.<br /><br />In managing this per-process "engine", proper cleanup was the most problematic. When is it no longer needed? Any DLL "unloading" hooks would be too late. DLL_PROCESS_DETACH is also too late. So I was listening for DLL_THREAD_DETACH in my DllMain, and looking at _Module.GetLockCount() for a kind of "reference count". If this got down to zero, I assumed Vegas was no longer using my DLL and destroyed the engine. How naïve I was. It worked fine for a while, but after other revisions to my code GetModuleCount() didn't seem to reach zero any more.<br /><br /><a href="http://blogs.msdn.com/larryosterman/archive/2004/04/23/118979.aspx">Turns out</a>, it's quite forbidden to do heavy cleanup involving threads and COM from within DllMain. In fact, <span style="font-weight:bold;">don't do anything in DllMain unless it's explicitly allowed.</span><br /><br />The solution for me was to explicitly reference count my back-end engine, and let the COM objects created from Vegas do an AddRef() in their constructor, and a Release() in their destructor. So when no more COM objects are active, the back-end is no longer needed and is destroyed. The shortcut I had taken turned out to be a slippery mountain road.<br /><br />Moral of the story: be very very careful with DLL:s.Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-47941769656453546412009-02-07T14:58:00.007+01:002009-02-07T16:30:04.777+01:00White balance and highlight protectionWhen you fix the white balance of an image, you typically shift the colors using some linear or nonlinear transform. In the case of ColorLab, it's a chromatic adaptation transform based on the CIECAT02 matrix, and it shifts the image colors between two illuminants. The source illuminant is one that the user has helped to define by clicking a pixel in the image that is meant to be white. If this is an orange-tinted color, a light source with these characteristics is found by the algorithm. The destination illuminant is always based on the standard D65 one, which is what modern PAL/NTSC/HDTV as well as computer video assumes.<br /><br />Anyway, when you shift colors in this way, and some colors are clipped to pure white or nearly pure white in the original image (which has a bad color cast overall), those <span style="font-weight: bold;">highlights</span> of the image might look pretty ugly afterwards. See this clock for an example:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJJgqq2PdkFZIPTs1ShKrmtZWiWhMrjO7mIGA4Bh0czRe7b5S6tbK-yn8lmB0_9xBWNoKqv1elu0HmfiG1pfX8if2CcRfoBEyXTQ1mIy24TyHYgtrRfd3Du7uT5sVCxr6xSQxtIiTyPQzY/s1600-h/original_vegas.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 170px; height: 159px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJJgqq2PdkFZIPTs1ShKrmtZWiWhMrjO7mIGA4Bh0czRe7b5S6tbK-yn8lmB0_9xBWNoKqv1elu0HmfiG1pfX8if2CcRfoBEyXTQ1mIy24TyHYgtrRfd3Du7uT5sVCxr6xSQxtIiTyPQzY/s400/original_vegas.JPG" alt="" id="BLOGGER_PHOTO_ID_5300057069334127762" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi80fPvLg3sEACq65R-1vg6qnHoglcHwwg5zzAoky3_VqQfWooQehNzSiqKzDPdQrtcMr_TbNjpK7UJbcw3SyzORqO-9CPaOWZW_ScoAuNd2KjvcfkDZxeQ3lNIWjbXmkN1k1gCHtphJ35s/s1600-h/wb_vegas.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 170px; height: 171px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi80fPvLg3sEACq65R-1vg6qnHoglcHwwg5zzAoky3_VqQfWooQehNzSiqKzDPdQrtcMr_TbNjpK7UJbcw3SyzORqO-9CPaOWZW_ScoAuNd2KjvcfkDZxeQ3lNIWjbXmkN1k1gCHtphJ35s/s400/wb_vegas.JPG" alt="" id="BLOGGER_PHOTO_ID_5300057340350148258" border="0" /></a>As you can see, overall the image has been improved but the clock face is now a dull cyan shade. The linear white balance transform didn't take into account that this was meant to be a highlight. Trying to white balance this image in Adobe Lightroom will give a result that isn't cyan-tinted. However, it seems that Lightroom does this by raising the brightness of the <span style="font-weight: bold;">entire</span> image. This causes the clock face to again clip at white. I don't like that, since it might compromise the rest of the image.<br /><br />So I had to find my own way. After a little experimentation, and discussion with John O., I found a solution that seems to work at least most of the time. I added an option called "Protect highlights" to ColorLab, and made the strength of the effect configurable.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJU77ZBOx850QB2V6MzDBkn7hFEPXVcHRmMfnrY9RlW5GkSlsR-FUelnUmDmBsie4jyXchUh-NDCAnOr45fLvSxw6m-cj-m_VnXDZvTVRkJwXzCNyYzM09SPuKqnFoDHg0lWiu54gOb3BC/s1600-h/great_or_what.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 268px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJU77ZBOx850QB2V6MzDBkn7hFEPXVcHRmMfnrY9RlW5GkSlsR-FUelnUmDmBsie4jyXchUh-NDCAnOr45fLvSxw6m-cj-m_VnXDZvTVRkJwXzCNyYzM09SPuKqnFoDHg0lWiu54gOb3BC/s400/great_or_what.JPG" alt="" id="BLOGGER_PHOTO_ID_5300057647180167666" border="0" /></a><br />This looks a lot better. :) What the algorithm does is examine the R/G/B value of the original pixel, and depending on how close it is to the maximum (255 for each channel), it shifts the WB-corrected pixel towards a desaturated version of the original. Therefore the luma of the original is retained, while removing the original color cast.<br /><br />I still have to test this technique on more images, but it looks promising.Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-63404348489644975422009-02-07T13:25:00.004+01:002009-02-07T21:56:19.543+01:00Fast and easy float-to-int conversion with SSEIf you’ve ever found float-to-integer conversion to be a hotspot in your application, you’ve probably run into using <span style="font-family:courier new;">fistp</span> in inline assembly as an alternative. <a href="http://www.stereopsis.com/sree/fpu2006.html">This article</a> is a great writeup of why conversion is slow, and benchmarks various ways to do float-to-integer on the x86 platform. However, it omits a nice alternative if you’re not into inline assembly (and on the x64 platform you might not even be allowed to use it by the compiler!), and it’s right in the SSE instruction set (which happens to be guaranteed on x64).<br /><br />If your compiler has the <span style="font-family:courier new;">“xmmintrin.h”</span> header, you can probably use the SSE “intrinsics”, a set of functions replaced pretty much 1:1 with real instructions by the compiler. It will also do automatic register housekeeping for you, so it’s a vastly simplified way of getting access to SIMD instructions from C/C++.<br /><br />For our conversion, the interesting instruction is <span style="font-family:courier new;">_mm_cvtss_si32</span>. It performs conversion of a single precision scalar with rounding, and should behave similarly to <span style="font-family:courier new;">fistp</span>. It’s not <span style="font-weight: bold;">the</span> fastest way to convert, but it’s a lot better than the standard <span style="font-family:courier new;">(int)</span>. Going back to <a href="http://www.stereopsis.com/sree/fpu2006.html">the article referenced above</a>, <span style="font-family:courier new;">_mm_cvtss_si32</span> does nearly as well as <span style="font-family:courier new;">BitConvert23</span>, yet passes the correctness test!<br /><br />If you do want truncation, there is <span style="font-family:courier new;">_mm_cvttss_si32</span> which does so, although without performance benefit. There are also actual SIMD versions of the instruction, converting two values at once. This may well be the overall winner, but for a drop-in replacement to <span style="font-family:courier new;">(int)</span>, here’s a snippet that helped speed up my model data load times:<br /><br /><blockquote><span style=";font-family:courier new;font-size:85%;" >__forceinline int FastToInt( float f )</span><span style="font-size:85%;"><br /></span><span style=";font-family:courier new;font-size:85%;" >{</span><span style="font-size:85%;"><br /></span><span style=";font-family:courier new;font-size:85%;" >return _mm_cvtss_si32( _mm_load_ss( &f ) );</span><span style="font-size:85%;"><br /></span><span style=";font-family:courier new;font-size:85%;" >}</span><br /><br /></blockquote>Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-43662420070482972462009-02-07T13:14:00.000+01:002009-02-07T13:16:00.688+01:00Dev blg!Decided to set up another blog where I'll post development diary entries etc. Welcome!Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0tag:blogger.com,1999:blog-8213933955031429979.post-12087682036294078202008-05-03T21:57:00.001+02:002009-02-07T22:17:41.976+01:00Compressing normals (and other unit vectors)<p>A while ago I was thinking about compact GPU-friendly vertex data formats to use for normals and other unit vectors (tangents, bitangents etc).</p> <p>Among the most interesting are <span style="font-family:courier new;">DEC3N</span>, which is 10 bit per component (-511..511), and the simple method of just quantizing to (-127..127) range and stuffing the vector in <span style="font-family:courier new;">UBYTE4</span> or <span style="font-family:courier new;">UBYTE4N</span>. These all let you store a unit vector in a <span style="font-family:courier new;">DWORD</span>, but the precision is rather bad. The quantization can make the normals visibly different from the original floating point versions.</p> <p>So it occurred to me that just using this “shell” of integers for unit vectors isn’t making good use of the representable values. You already know your unit vector is, well, unit length, so all you care about is the direction. And there are far more directions expressable as<strong> n-length </strong>vectors than there are ones expressable as <strong>unit</strong> vectors in a 3 byte tuple. Assuming adding a <span style="font-family:courier new;">normalize()</span> to your decoding step is cheap, we can exploit this!</p><p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmBMpbDtTTF-fPauvYq7fjYFK8D2YhyALBFLnuoGJ16lQ7N4eZXY-v8Ls715VRSMGFz57Vi86RitGVMxSwlsEocohH0C8I9SOQwOwjNh4U8JbgiESVSN8nmqaqK0yVFZ6R9aNWJkg8JfI1/s1600-h/normal_compress.gif"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 212px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmBMpbDtTTF-fPauvYq7fjYFK8D2YhyALBFLnuoGJ16lQ7N4eZXY-v8Ls715VRSMGFz57Vi86RitGVMxSwlsEocohH0C8I9SOQwOwjNh4U8JbgiESVSN8nmqaqK0yVFZ6R9aNWJkg8JfI1/s400/normal_compress.gif" alt="" id="BLOGGER_PHOTO_ID_5300162928309102178" border="0" /></a></p><p style="text-align: center;">(Click the image to magnify.)</p><p>I hacked up some code and made a compressor that takes a 3 float vector, uses 3D DDA to scan the “3-byte space” for useful candidates, finds the best of these, and spits out a 3 byte vector for you. The code is downright horrible, and I think I lifted the DDA code from the Interweb, but the idea should be clear enough to run with. Also, the compressor seems to work well for any game data I’ve thrown at it, and gives very low error compared to the original normal.</p> <p>I intend to make a follow-up post with some error numbers, and improved code later. If anyone can find ways to improve it, please comment!</p><br /><br /><p><a href="http://code-bin.homedns.org/221">Grab the code here.</a></p>Anonymoushttp://www.blogger.com/profile/11940847780535802514noreply@blogger.com0