Monday, September 20, 2010

Integrating DIGuy into a project

EDIT: This still works in some cases.But due to some craziness that I've run across lately, I'm going to write another post that you might find more helpful that more carefully outlines the project settings. They seem to be the make-or-break factor for some things and to cause problems in unexpected places.

What this covers:
Adding in the DIGuy class into a Visual Studio project

What you'll need:
Visual Studio 2005 (yes, it has to be 2005)
DIGuy installed on your computer
If you want text to speech support:
SAPI 5.1 Speech SDK installed on your computer
Optional: the DIGuy class I wrote. This post mostly focuses on the project settings so you could just call DIGuy functions straight from your project, but I made the class as a wrapper to make things easier.

How to do it:

The hardest part to get right is project settings. There are a bunch of them! I will explain and put screenshots in.

1) Go to Project Settings>General. For Character Set, choose "Use Multi-Byte Character Set".
2) Go to C/C++ and add the following additional include directories:
$(DIGUY)\3rdparty\haptek\haptek_19991020\NT\Include
$(DIGUY)\include
$(DIGUY)\3rdparty\sgi\glut-3.6\include
C:\Program Files\Microsoft Speech SDK 5.1\Include


The $(DIGUY) means it's looking for an environment variable set on your computer. You can set that through right-clicking on My Computer, then clicking Properties. Go to the Advanced Tab, click Environment Variables, then under the System Variables section, click New. Let the variable name be DIGUY and the path be the path to where DIGuy is installed on your system. You might have to restart your computer for it to take effect.

Alternatively, you can replace the $(DIGUY) above with the path to DIGuy on your computer.

3) Go to Linker>General. Under Additional Library Directories, add:
"$(DIGUY)\3rdparty\haptek\haptek_19991020\NT\Include";"C:\Program Files\Microsoft Speech SDK 5.1\Lib\i386";"$(DIGUY)\lib\win32\vc8_md";"$(DIGUY)\3rdparty\sgi\glut-3.6\lib\win32\vc8_md";"$(DIGUY)\3rdparty\cygnus\pthreads-win32-20050103\lib\win32\i586_md_dll";"$(DIGUY)\3rdparty\trolltech\qt-3.3.8-win32\lib\win32\vc8_md_dll";"$(DIGUY)\3rdparty\activestate\AP822\lib\"

You should be able to just copy and paste that string; it'll make your life easier. You can see that each library directory is separated by a semicolon in case you'd want to type them in or add them individually.

4) Under Linker > Input, in the Additional Dependencies, add the following:

libdiguy_module_exface_ogl.lib hapapi.lib winmm.lib wsock32.lib netapi32.lib comctl32.lib opengl32.lib glu32.lib libdiguy.lib libdiguy_graphics_ogl.lib libdiguy_module_script_perl.lib libbdiglut.lib pthreadvc1.lib perl58_vc8_mdd.lib qt338_vc8_md.lib

Again, you should be able to copy and paste. These are separated by spaces, not semicolons, in case you'd want to type in individually.

5) If you compile now, you will see a LNK4098 warning:

1>LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library


If you try to fix it by ignoring the msvcrt library, you just get a bunch of linker errors. My research shows that it has something to do with mixing debug and release code libraries (probably somewhere deep in DIGuy) so I'd just leave the linker warning, since it compiles and works fine.

5) Now include your DIGuy code where you need it and you should be good to go!

Friday, September 17, 2010

Integrating OpenGL into a MFC project

What this covers:
- Adding in OpenGL support to a MFC project

What you'll need:
- Visual Studio 2005--yes, you have to have 2005 for this one because of restrictions on DIGuy
- OpenGL installed on your machine
- Optional: The classes I wrote for OpenGLMFC. If you don't have them you'll have to figure out how to call functions by themselves. This tutorial is focused on getting the project settings right.

How to do it:

1) If you don't have my class for OpenGL, I'd recommend following this tutorial:

http://www.codeguru.com/cpp/g-m/opengl/openfaq/article.php/c10975__1/Setting-Up-OpenGL-in-an-MFC-Control.htm

It is clear and does a good job of explaining step by step what to do.

2) If you do have my class, go ahead and add it to your solution.

3) Go to Project Settings>Linker>Input. Under "Addtional Dependencies," add "opengl32.lib" (and "glut32.lib" won't hurt either).
You should now get a clean compile.

4) Now to make a place for it to render and link in the correct events. I rely heavily on the tutorial listed above for this.

Go to Resource View and open up your program's dialog.
5) Open up the Toolbox (it's probably in a tab to the left side of the screen and select an Image control. Drag that onto your dialog.


6) Make sure your picture control is selected, then go to the Properties tab. Change its ID to something useful, like IDC_OPENGL.Also, set its visibility to FALSE. (Weird, I know.)
7) Now we're going to link that image control to the OpenGL class that I've written. Open up the header code for your dialog box (in my case, it is VPDialog.h). Include your OpenGL header. Declare an object of that class type. Mine is called openGL, so the code I added is:

#include "OpenGLMFC.h"
...
(inside class declaration)
OpenGLMFC openGL;

8) Now, open up the cpp file corresponding to that header. Find the InitInstance() function.
Insert code to link up your image control with the OpenGL rendering:

    //get the rectangle of the image control that we want to render the OpenGL into it
    CRect rect;
    GetDlgItem(IDC_OPENGL)->GetWindowRect(rect);
    ScreenToClient(rect);
    //create the OpenGL renderer
    openGL.oglCreate(rect, this);
    //set the timer for rerendering
    openGL.m_unpTimer = openGL.SetTimer(1,1,0);

8) You're all done integrating! Now you just need to set up your callback function for rendering, which you can either do within the OpenGL class or assign a function to the callback member of that OpenGL class.

Thursday, September 16, 2010

Setting Up an Application for MySql NET Connector

We started out this project working with the C++ connector but due to some character set issues I've switched to the .NET connector. Here's how to do it.

What this covers:
Getting the project settings in an existing MFC project right to allow for .NET Connector to work


You will need:
Visual Studio (I'm working from 2005)
MySQL Connector/Net: my computer has the latest version, but you should probably try versions back if yours has problems installing
Optional: the NETDatabase class that I wrote. Otherwise you can add the appropriate headers and call the Connector functions as you wish.

How to do it:

1) Open up a project in Visual Studio. I'm going to open up a MFC project that already exists so that I don't have to go through the steps of setting that up again.

2) Go to Project Properties > Configuration Properties. Look for "Common Language Runtime support", and change that option to "Common Language Runtime Support (/clr)".
3) Click OK or Apply. Your project might look like it's frozen. Don't worry, it's just updating Intellisense and other things to accommodate for the new setting.

2) Go to Project Properties> Common Properties. Click "Add New Reference..."

It might take a while for the next dialog box to come up. Be patient.

3) There are three references you will need to add. All of them are under the .NET tab, which should be what comes up automatically.:

System
System.Data
MySQL.Data

It doesn't matter which order you pick them. Just add them one by one.

Now you're good to go! When you make your function calls to the Connector you'll just have to tell it what namespace it is in.

All the examples are for C# or Visual Basic but the function calls have the same names and namespaces so you should be able to figure it out. Alternatively, you can use the class I wrote, which is a wrapper for the most common functions that we use.

Because this is a .NET component, it has to be written in managed C++, which is kind of a pain when you're mixing with unmanaged code. I've been using trial and error to figure it out and so far it's worked okay. There are books and articles you can read about that online.

Monday, September 13, 2010

Setting Up an Application for Dragon Naturally Speaking

What this covers:
 Setting up a new project with all the correct settings to integrate Dragon Naturally Speaking into it 

You will need:
- Dragon Naturally Speaking SDK installed on your computer
- Visual Studio (I'll be working from Visual Studio 2005)
- optional: the DragonTools class I wrote. You can also just do Dragon SDK calls but it helps me to have things separated out into a class so that I can reuse things easily and not have to go digging through the SDK documentation to figure things out.

 How it's done:

1) Open up Visual Studio. Begin a new project. Start a project of type "MFC Application".



2) A wizard will come up. Follow the wizard as shown in the images below, and I'll explain what we're doing:
 In this step we're telling it that we're making a "Dialog Based" application, which basically means we're not loading documents into it or anything. We just want a project that's going to be based on a Windows Form so that we can have controls like buttons and text fields. We're also saying to not use Unicode libraries because in a lot of the libraries we use for other things, Unicode character sets will cause problems that are infuriating and impossible to debug.



In the next box you can choose whatever you want. If you want it to be possible to have the traditional drop down style menus and for a person to be able to minimize and maximize your applications, you need to set that up now. I've highlighted the options that make those things possible.
Next we need to make sure that ActiveX components are enabled since Dragon is an ActiveX component.
You can then finish out that wizard however you like.

3) When you're finished, you get a new shiny project. If you go to your Solution Explorer, you'll see something like this. I've labeled the diagram to explain.

You'll be working mostly in the Dialog source file (in this case VirtualPatientDialog.cpp).

4) Optional step. I really hate precompiled headers. To me they don't make compiling any quicker and they only get in my way when I'm trying to add in other classes. I'm going to outline how to disable them because I always do.

Go ahead and open up stdafx.h. The only crucial things that we need for this project are these three lines:

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxdisp.h>        // MFC Automation classes

Copy them. Paste them in the overall application header file (for me, that's Virtual Patient.h). Now, comment out all of stdafx.h and compile. It should compile clean. It might not if you did settings different than I did, so in that case you'll have to figure it out yourself.

Now, go to your Project Settings>Configuration Properties>C/C++>Precompiled Headers and change the first option to "Not using precompiled headers".
Go to your Solution Explorer, highlight stdafx.h and stdafx.cpp, and press the Delete button. It will ask you if you want to remove or delete them. Go ahead and delete.

Compile. Your compiler will tell you anywhere that #includes stdafx, since we just deleted it. Go to those lines and delete them.

5) Now we need to tell the project where to find the Dragon include files. Go to Project Settings> Configuration Properties>C/C++>General. On the top setting, add the path to the Dragon include files. For my computer, it is: C:\Program Files\Nuance\Dragon SDK Client Edition10\SDK\include

Now. This is where it gets confusing, and I don't fully understand what is going on. I am going to guide you through things step by step but I won't be able to explain all of it because I don't understand all of it.

The complexity comes because the Dragon engine is really an ActiveX control. In order to use it in our project, we have to connect through COM, which stands for Component Object Model. It's a standard, not an implementation, but Microsoft has implemented it and that's what we're using. Dragon has already generated "wrapper classes", which translate between our C++ code and the internal ActiveX that Dragon uses, and that's what we're calling in the Dragon include files. But, to make this work we have to do a bunch of weird function calls to start "listening" for those kinds of messages. A lot of that I've already implemented in my DragonTools class, so I won't go into it here. If you have questions, e-mail me.

6) I will assume here that you are going to use my DragonTools class. Go ahead and bring it into your project. It should compile clean if you compile it at this point. Its header contains all the necessary headers.

7) Go to your dialog header file (in my case, Virtual PatientDialog.h). Include the DragonTools header. Make an object of type DragonTools inside of that class. I'm going to call mine Dragon, so in my class variables, I will add:

DragonTools dragon;

8)Go to your main program's .cpp file (in my case, Virtual Patient.h). This is the part I can't quite explain to you, but it has to do with initializing the COM stuff your program needs. At the top right under the includes, declare an object of type CComModule. MSDN tells me that this type is obsolete, but I will keep using it because I'm not sure what to replace it with. I have named my object _Module, so my declaration line is:

CComModule _Module;

9) Scroll down to your InitInstance() function. Under the SetRegistryKey call, paste the following two lines:

::CoInitialize(NULL);
_Module.Init(NULL,m_hInstance);

This somehow associates the COM model to your program. m_hInstance is kind of like a pointer to your application so you're initializing a COM module to your application.

10) Scroll past the modal dialog stuff. There should be a call to dlg.doModal(); and then an if statement to handle responses. Right after that if-statement, paste these two lines:

_Module.Term();
::CoUninitialize();

This will unassociate the COM module and uninitialize it from your program after you close it.

After all this, you should be good to go! You should be able to call Dragon functionality from the DragonTools class from anywhere in your dialog box source file.

Wednesday, January 20, 2010

So I figured out yesterday that I am able to get the process to work with all quads as well. Yesterday, I tried to get the head to work, but that didn't work so well, but yesterday I was able to get the entire right leg to work, with textures and all. I am stepping my way through the body and trying to figure out which body part Haptek doesn't like. I am trucking away and want to give this idea a full try before i resort to using a Haptek model and morphing it. Still trying to figure out some stuff with Maya!!

Toni

Friday, January 15, 2010

Poser Child into Haptek [ Trial 1.1]

Tip 1: Haptek does not like an .obj file exported from Maya. Maya does something funny with their .obj files, they do not enter after every line, which is what I think Haptek doesn't like.
Tip 2: Haptek does like .obj files exported from Poser. Poser .obj files are in the correct format.
Tip 3: Haptek only likes to work with Triangles and Quadrilaterals and for some reason it likes when you only use triangles or quads, not both at the same time.

I tried exporting the entire child model from Poser and dragging it into HapDeltaSetMaker and this does not work. I believe that this is because the Poser child is roughly 76000 polygons and because Poser uses triangles and quadrilaterals together. Since, I can not reduce polygons or triangulate in Poser, I exported the Poser child as an obj file and then I imported it into Maya. In Maya, I am able to reduce polygons and triangulate them. There is a triangulate button and a reduce button. Easy trick Lauren showed me was to set the properties of the reduce option to triangulate before reduction, therefore it is done all in one step.
After finished reducing, I export the child back into an obj file. I then have to import that new obj file back into Poser. Once in Poser I must export it back into an obj file. This will put the file into the proper obj format that Haptek like.
Then I dragged the new obj file into HapDeltaSetMaker and Haptek recognizes it. The obj file will come up white, since there isn't a texture map given to it. All you have to do then is drag the texture map into the same window and it will apply it to the obj.

I tried to start off with the whole body at first and I could not get this to work, so I decided to start smaller and see if I could just get all the steps to work. So far I have been able to go through all the steps with the left eyeball of the Poser child. The eyeball was originally almost 1200 polygons and I was able to get it down to about 300 polygons. I was able to get it into Haptek and the appropriate texture. Here is a picture of just the eyeball in Haptek.

Now, I am going to try to start a little bigger and see if I can get the head to work and then work down.

Tuesday, January 12, 2010

the vr_walking project

The code base for our current prototype for the virtual patient project is from an old project called vr_walking. I've retitled it "VirtualPatient" and taken out some things we won't need for that project and uploaded it to our svn repository at:

https://free2.projectlocker.com/ClemsonVEGroup/VirtualPatient/svn
 (password protected, e-mail me if you have problems)

Today I'm working on getting the project into a slightly more manageable structure and on reading through the code so that I understand it before we go poking around making changes in it.

From what I can tell, the only two code files we need to go poking around in are the script.cpp and VR_walking.cpp files. The rest have to do with image and .obj reading, writing, and manipulation, joystick controls, and that kind of thing. Hopefully I'll be able to rearrange the project in order to make it easier to understand what should and shouldn't be modified.