Thursday, May 10, 2007

Converting OpenDX VRML to Texture-mapped VRML

OpenDX typically writes VRML files with vertex colors, so that every vertex has an associated RGB value. Many modeling programs cannot read VRML with vertex colors, so it is useful to convert them. If you are converting a single object or a relatively simple object, there are applications to do the conversion, such as Ultimate Unwrap3D. This program examines the given Shape and figures out how to dice it evenly onto a two-dimensional texture map.

VRML from OpenDX is typically special, though, in that all of the color comes from a colormap applied to a scalar value. That means you probably started with every vertex being associated with a number between some min and max and assigned RGB values to the range of numbers. Because of this, we can use a one-dimensional texture to color a VRML from OpenDX. The process is a lot faster than unwrapping the texture, and it doesn't leave any seams.

Here's how we did it.
  1. Save the VRML as grayscale.
  2. Save the colormap as a jpeg or tiff (depending on what colormaps your VRML viewer can read).
  3. Use a custom python script to translate each grayscale value into a u-v index into the saved colormap.
Because I didn't want to write code to read VRML, I used a shortcut. There is a program called X3D-Edit which translates VRML to X3D, which is essentially VRML in XML form. Then I used Python's ElementTree to process the XML and write a new X3D file. Then X3D-Edit or the standard XSLT will translate X3D back to VRML. It sounds complicated, but the translation from VRML to X3D and back is quite sure, and X3D is a lot easier to parse than VRML.

Labels: , , ,

Powershell XML Handling for Empty nodes

Windows Powershell handles xml objects a little inconsistently. If a node is empty, then Powershell treats it as a string. If the node is non-empty, then it treats the node as an XmlNode. You can circumvent this behavior by using the Item() interface.

PS>$x=[xml]"<root/>"
PS>$x.root.GetType()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object

PS>$x.Item("root").GetType()

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False XmlElement System.Xml.XmlLinkedNode

Labels: ,

Wednesday, April 25, 2007

Vista Update KB930178 Fails

An update failed on my new Vista installation with error 0xc015001a. "c015" seems to refer to Component Based Servicing (CBS), which is the tool that applied the update. 001a generally means it couldn't create or delete something. C:\Windows\WindowsUpdate.log shows more detail about the error, including the directory where it unpacked the distribution. Running Process Monitor from Sysinternals shows that TrustedInstaller.exe failed to create a file in the unpacking directory, C:\Windows\SoftwareDistribution\Download\\inst.

I tried turning off Symantec Antivirus. I tried turning off User Access Control (UAC) in the Users and Groups control panel.

When it finally worked, the system state was the following:
- Logged on as THE administrator.
- UAC was off
- Changed properties on the SoftwareDistribution\Download\ directory so that it, and its children, were no longer read only.
- applied the patch during shutdown

Drew

Labels: ,

Monday, October 09, 2006

Fortran Memory Error

My buddy Steve just tracked down a Fortran memory error on Windows. I like recording these debugging sessions and thought to share one.

This Fortran90 application couples fluid dynamics and chemistry to do combustion. It uses the MKL version of LAPACK. It failed with a page fault, which means that there was a memory problem. How do you find it?

Fortran90 is unlikely to cause memory errors of its own accord. The language doesn't use C-style pointers, although it does add allocatable arrays to the Fortran77 standard. These arrays shouldn't be capable of corruption under normal circumstances.

The first step for Steve was to use the PageHeap tool. The old-fashioned way to use this is to use gflags.exe to turn on the PageHeap switch in the operating system. I read there is a fancier way to use it in Visual Studio 2005, but gflags.exe will suffice.

Turning on PageHeap made the program crash much sooner than before. It crashed in a particular function during exit from that function. Pseudocode for the function follows.

Sub DoWork(array,size)
If size>N
array = Allocate(4000)
end if
End Sub

This function only failed when allocate was not called. We knew that this subroutine implicitly calls deallocate when it exits, so it seemed like there might be an invalid array pointer in the heap. That means that the heap corruption discovered during the implicit deallocation was caused by stack corruption which claimed that the array had been allocated.

Steve's friend had the bright idea to use this function as a test to find where the corruption first occurred. He moved it higher and higher in the code until he found a function call to LAPACK. Looking closely at that function call, he realized that he had called LAPACK to process a matrix but had given it the wrong size for the matrix. LAPACK was overwriting past the matrix boundary. Why was it able to do this? The LAPACK libraries are Fortran77, therefore without a header file. Fortran90 was unable to check that the arguments were correct.

- Drew

Labels: , ,

Thursday, July 13, 2006

Finally Fixed VTK .NET Widget Bug

I thought there was a subtle interaction between .NET and VTK that caused threading problems during user interaction. The result was that widgets did not always work. Picking would fail. The problem turned out to be that I had defined an enum for EventIds that was a copy of the VTK enum. VTK, itself, changed these values from version 5.0 to the development version, 5.x, and I was using the 5.x enum for the 5.0 code.

The fix for what I thought was a subtle bug is just to use integers instead of the EventId enum. For instance, replace EventIds.EndPickEvent with the number 9. You can look up these values in VTK\Common\vtkCommand.h.

There are no other real bugs in VTK .NET, that I know of. I could do a few things to make debugging easier and wrap HWND values, but that's about it.

That means I can release a version of VTK .NET for VTK 5.0.1. I've already integrated the new release into the patch code, tested the code for the new version, and will package it as soon as I can.

Labels: ,

Sunday, June 04, 2006

Compilation of Debugging Tools

Debugging Applications for Microsoft .NET and Microsoft Windows by Robbins has been a great, great help to me. Tonight, I used Visual Studio 2005 to compile several of the utilities supplied with the book and had to make a few changes to upgrade from Visual Studio .NET.

For CrashFinder, change the return value of OnNcHitTest to LRESULT in About.{h,cpp} and Statlink.{h,cpp}. The tricky bit is to add #define _USE_32BIT_TIME_T to stdafx.h. Then you can either modify all of the string handling routines or unselect Treat Warnings as Errors to complete the compilation.

Robbins recommends creating map files with the linker options /MAPINFO:EXPORTS and /MAPINFO:LINES. The LINES option in Visual Studio 2005's linker has been removed, but you can resurrect that information using pdb2map from the book's CD. That's the only way I know to get this information.

Thursday, May 11, 2006

VTK .NET to Sourceforge

I posted VTK .NET on 23 March and have had about one hundred people come to the site each week. I can see that people download examples, so it seems to run well. I have submitted a request for a Sourceforge site, using the BSD license, which is the same that VTK uses. That should take another week or two to process.


Bugs Discovered


  • I did not modify CMakeLists.txt for vtkMy or vtkLocal, which are the standard ways to wrap your own VTK C++ code for wrapper languages.

  • There seems to be a problem with vtk3DWidgets. They mostly work, but a few things do not work. For example, annotatePick.cs from the examples does not notify you of new picks.

What People Want Next


  • I saw a comment that the previous version of VTK .NET needed to wrap HWND types so that you could build a Windows Forms Control in C#. I've built one in managed C++, but I see the logic in the request, and I think I can add that translation to the wrapper code.

  • Two people who emailed me have commented that they are working on using VTK .NET within ASP.NET. One wanted to use it to generate images on the server side. The other is interested in the more ambitious project of providing manipulable 3D graphics, something that interests me, too. There are a number of challenges to making this happen, but it would clearly be a great thing to implement.

Friday, April 28, 2006

SciPy distribution for P3 fails - what illegal instruction means

I have been trying to help someone install SciPy on our clusters. The site provides a package for P4 which works fine and one for PIII which works on my laptop but fails on our test login node. I downloaded CPU-Z to check things out, and it turns out that my Pentium M (Dothan) laptop supports MMX, SSE, and SSE2 while the dual Pentium III-S ancient server for testing supports only MMX and SSE.

As a result the provided installer for Python 2.4 and Pentium III fails for older P3 machines.
scipy-0.4.8.win32-py2.4-pentium3.exe

The test code from that provided distribution, scipy.test() will fail on older P3 chips (such as PIII-S, Tualatin) in several of the package tests with a Dr. Watson error of
Unhandled exception at 0x6988d3f7 in python.exe:
0xC000001D: Illegal instruction

The supplied binaries for ATLAS on a Windows P3 box do not have this problem. I built a running package using online instructions for a MinGW build using the precompiled ATLAS binaries. It is a quick process because you don't have to rebuild ATLAS.

I'm pretty sure we didn't just accidentally install the P4 version because I checked the show_config at the time, and we did it twice. I can't prove it because I didn't save the output. Also, the P4 version fails quickly on the P3, but the fewer tests fail when using an SSE2 P3 version on an older P3.

On the PIII-S where the install failed, the CPU information is
has_mmx has_sse is_32bit is_Intel is_PentiumIII is686
The ATLAS archdef for both the supplied package and my working build was PIII/gcc/misc and mmdef was PIII/gcc/gemm.

We run on Python 2.4.2, Windows XP Service Pack 2

The instructions that failed included cvtsi2sd, movsd, and ucomisd. I found them listed in the MMX section of the Intel assembly specification, but they are included listed only for SSE2 support. For a sense of what the code looks like, the following shows the assembly snippet.
684C5825  mov         dword ptr [esp+68h],0 
684C582D mov eax,dword ptr [edx]
684C582F mov edx,dword ptr [esi]
684C5831 cmp eax,edx
684C5833 cmovg eax,edx
684C5836 cvtsi2sd xmm0,eax
684C583A movsd mmword ptr [esp+14h],xmm0
684C5840 fld qword ptr [esp+14h]
684C5844 mov dword ptr [esp+5Ch],0
684C584C fmul qword ptr ds:[684C5538h]

EAX = 0000000F EBX = 684C550E ECX = 00902DD0 EDX = 0000000F
ESI = 0021EB6C EDI = 0021EB60 EIP = 684C5836 ESP = 0021E8A4
EBP = 00000001 EFL = 00010216

The instruction pointer is at the cvtsi2sd instruction. Normally, exceptions are thrown by the instruction before the instruction pointer, but here the exception happened just before the instruction pointer would be incremented.

Drew Dolgert