3D VR Headset
Blitz3D Forums/Blitz3D Programming/3D VR Headset
| ||
Hi, i try to use a Cybermaxx VR HMD with BB3D. But my C++ is so Poor that i need your HELP. I have the help of the LIB and the DLL Here is what i have: int AutoDetectComPort(void); Auto-Detects CyberMaxx on COM1 though COM4 returns COM0_ID if not found else COM1_ID though COM4_ID; Parameters: NONE BOOL OpenCom(const char*); Opens selected comm port and looks for CyberMaxx. Auto-Detect calls OpenCom for each port. If port opened successfully and CyberMaxx found, function returns TRUE else comm port is closed and return value is FALSE; Parameters: COM1,...,COM4; BOOL ReadFromPort(void); Reads data from port. Use Get_PYR(...) to access the data. Returns TRUE if successful. Void Get_PYR(int*, int*, int*); Get Pitch, Yaw, Roll respectively +45<->-45, 359<->0, +45<->-45 char* Get_Version(void) Returns firmware version, else NULL if device not found BOOL HardReset(void); HardReset sets CyberMaxx to power up default state BOOL Set9600(void); Sets port and CyberMaxx to 9600 bps (default) BOOL Set19200(void); Sets port and CyberMaxx to 19200 bps BOOL SetHysteresisOn(void); Sets hysteresis on (prefered) BOOL SetHysteresisOff(void); Sets hysteresis off (default) BOOL CheckSumOn(void); Enables checksum on. If error occured, then last valid packet will be used. BOOL CheckSumOff(void); Enables checksum off (default) char GetDataMode(void) Returns data transmission mode. BINARY_MODE - faster (default) ASCII_MODE - slower, used for debug void SetDataMode(char) Sets data transmission mode. Same as above char GetTransMode(void) Returns SAMPLE_UPON_REQUEST (default) or CONTINOUS_SAMPLE_MODE void SetTransMode(char) Sets transmission Mode. Same as above void SetSamplingRate(int rate); Sets CyberMaxx packet sampling rate. MINPACK <-> MAXPACK increments of 5 default rate is 40 pps int GetSamplingRate(void) Returns current sampling rate that CyberMaxx is set to. int GetCurrentSpeed(void) Returns current comm port speed. 9600 or 19200 int GetPortId(void) Returns port number to which CyberMaxx is attached. COM1_ID,...,COM4_ID if found, else COM0_ID Sample code: // CyberMaxx 2.0 Win95 & NT SDK // Copyright (©) 1996 VictorMaxx Technologies, Inc // Author: Robert J. Gebis // Date: 6 March 96 Ver 1.0 #include <conio.h> #include <iostream.h> #include "CyberMaxx.h" // This has to be linked with MaxxCom.lib // to use MaxxCom.dll void main(void) { MaxxCom CyberHMD; int Pitch, Yaw, Roll; // Start by connecting to the CyberMaxx if( !CyberHMD.AutoDetectComPort()) { // ERROR CyberMaxx not Found exit(-1); } // These are optional CyberHMD.SetHysteresisOn(); // turn on the hysteresis filter to minimize jittering char version[10]; strcpy( version, CyberHMD.Get_Version()); CyberHMD.SetSamplingRate(50); // Used only in continous mode // defailt is 40 packets/s // This is how you read while( !_kbhit()) { // if the CyberMaxx has supplied data, this returns true if( CyberHMD.ReadFromPort()) { CyberHMD.Get_PYR(&Pitch, &Yaw, &Roll); // Read data cout << "Pitch -> " << Pitch << endl; cout << "Yaw -> " << Yaw << endl; cout << "Roll -> " << Roll << endl << endl; } else { cout << "Error" << endl; } } // go until a key is hit } // end of main I need help to write my decls, here is my try: .lib "maxxcom.dll" AutoDetectComPort() Get_PYR(pit%,yaw%,roll%) OpenCom$() ReadFromPort$() Get_Version$() HardReset$() Set9600$() Set19200$() SetHysteresisOn$() SetHysteresisOff$() CheckSumOn$() CheckSumOff$() GetDataMode$() SetDataMode($) GetTransMode%() SetTransMode($) SetSamplingRate(%) GetSamplingRate() GetCurrentSpeed() GetPortId() Please Help me. Greet's MErren |
| ||
one thing: it seems to me: void Get_PYR(int*, int*, int*); wants some pointers to write the results to. So you need to use 3 blitz bank handles, each bank of 4 bytes size. Once executed the banks should contains pitch yaw and roll. so in the decls you also need to use the pointer sign:Get_PYR%(pit*,yaw*,roll*) Additionaly: SetTransMode($) SetSamplingRate(%) AFAIK you need to use some kind of variable names here, at least: SetTransMode(a$) SetSamplingRate(b%) And: you need to define what type of return value will be used, so when it's gonna return a string (char) then you need to declare it as: GetTransMode$() the same for GetDataMode etc. |
| ||
WOW , thank you very much. I ll try my be a long night!! I show results!!! |
| ||
Don't you just love the people on this fourm? Nice one JFK IPete2. |
| ||
No, sorry i am to stupid. it won't return anything. I can't read out PYR cause i don't know how to. That's to high for me BB and C++ |
| ||
Hi I think I can help you. Your VR system requires a lot more than the detection routines and when turned on - will display in mono (2D) same image in both eyes. What you will need toi do is create a quad buffer system and use the system pointer to pointers to the sepretly rendered views in blitz 3D, In this way, and only this way will you get true 3D. Good luck. Dr, Wildrick Creator of the TruDimension 3D shutter glasses, 3D monitor and VR Headset add-on for Blitz 3D, Intel C++, Java and Add-on Bryce. |
| ||
Oh, One final worrd. You may wish to consider how much time you put into the developmet of the srivers as the image quality is BAD with a capital B - worse - its fiels sequential - meaning that you havlve the already very bad resolution rigt from the gate - if your intrested in a "Hey neat!" sort of thing - go for it - If toyr trying to develop a game - any text will be un=readable and forget someting like a HUD, We suppored them becase of popular request - but thety arebt even made any more as far as I know. Let me know how your quest turns out. Best of luck to you. Regards Dr. WIldrick |
| ||
You are Right, Dr. Wildrick. But the Way is the Target. I want to learn more about Decls and DLL and my Projekt is to make my 3d Architekturprojekts viewable and get a better Feeling for the Dimentions. The Way is the Target. Do you know how to translate the C++ Part into BB? And do you have a Demo of the Interlace DLL u use in your 3dVU? |
| ||
it won't return anything. I can't read out PYR cause i don't know how to. Of course you first need to execute the commands to initialise the device. Then the PYR should work like this (assuming you have declared it in the decls) my_pitch=createbank(4) my_yaw=createbank(4) my_roll=createbank(4) Get_PYR(my_pitch, my_yaw, my_roll) print peekint(my_pitch,0) print peekint(my_yaw,0) print peekint(my_roll,0) as for the C++ code, it looks like everything is pretty simple to convert to blitz: my_pitch=createbank(4) my_yaw=createbank(4) my_roll=createbank(4) ;// Start by connecting to the CyberMaxx if AutoDetectComPort()=0 ;// ERROR CyberMaxx not Found runtimeerror "ERROR CyberMaxx not Found" endif ;// These are optional ;CyberHMD.SetHysteresisOn(); // turn on the hysteresis filter to minimize jittering (try this later) my_version_adr=Get_Version%() ; returns a pointer to a string SetSamplingRate(50); // Used only in continous mode ;// default is 40 packets/s ;// This is how you read while keyhit(1)=0 ;// if the CyberMaxx has supplied data, this returns true if ReadFromPort()<>0 Get_PYR(my_pitch, my_yaw, my_roll) print peekint(my_pitch,0) print peekint(my_yaw,0) print peekint(my_roll,0) else print "Error" endif wend Of course I doubt it will work right away, but probably it gives you the direction. Again, make sure your decls are using the right function name return types, I see you have a lot of string return types, doublecheck if everything is right void dothis() means it won't return anything char dothis() means it will return a string. declare: dothis$() char* dothis() means it will return a (32bit int) pointer to a string, use dothis%() (see below how to use a pointer) int dothis() means it will return an int, use dothis%() BOOL dothis() means it will return true or false, I think you can use an int here. The function Get_Version is a bit special, it will return an adress (=Pointer) of a 10 Bytes string. You need to use RTLMemoryMove2 to copy the 10 bytes to a blitz bank. See code archives, userlibs, Avifil32 Frame grabber example on how to declare and use RTLMemoryMove. |
| ||
while I'm at it: in a "kernel32.decls" the following lines are required: .lib "kernel32.dll" RtlMoveMemory2%(Destination*,Source,Length) : "RtlMoveMemory" In the app you will have to make a 10 bytes bank ready to retrieve data from the returned adress: my_buffer=createbank(10) In blitz you would then: adr=Get_Version() rtlMoveMemory2(my_buffer,adr,10) version$="" for i=0 to 9 version$=version$+chr$(peekbyte(my_buffer,i)) next Print version$ |
| ||
Wow, hey JFK EO-11110 you must come form the c++ Planet. Thank you so far. But i think i must recompile the DLL cause the BB-Mainprogram say's "Function in Lib not found.". then i have downloded a Tool to check DLL's and the Function's are there. The DLLs are in the correct Folder, its a Cross to wear. But I will do. Thank's to JFK.. again. |
| ||
I think the functions of the dll must be declared for shared use in the dll. |
| ||
JFK comes from MARS ! |
| ||
yeah, just escaped from area 51, btw. |
| ||
OK OK, i must call again. I've downloaded "PE Explorer" and try to declare my dll as an "shared" one. but noting the Gr#*%$%& Blitzbasic says " User lib function not found" and i have no Idea of how to handle. Greet M.Erren |
| ||
It's many years ago since I stopped using C++, so my advice is far from competence. In Purebasic one needs to declare a procedure in a special way to allow other apps to access it in a dll, there you have to say ProcedureDLL() or ProcedureCDLL(), compared to the ordinary Procedure(), the function declaration. So maybe the functions have to be declared in a special way too. Sorry, I have no better advice. at least the Windows Api DLLs (kernel32.dll, user32.dll etc) can be accessed by blitz. Please post your userlib and your blitz sourcecode. |
| ||
At First I think its clever to give the Link to the DLL http://www.geocities.com/mellott124/CyberDrivers.htm Here the User lib dir 09.03.2006 22:02 <DIR> .. 25.07.2002 21:36 1.069.056 3d2.exe 20.07.2003 04:45 1.666 blitz_extend.decls 20.07.2003 13:53 15.360 blitz_extend.dll 20.07.2003 13:53 4.741 blitz_extend.dpr 24.02.2003 07:42 564 dlportio.decls 27.09.1996 10:29 34.816 DLPORTIO.DLL 10.01.1999 11:00 3.584 DLPORTIO.SYS 13.10.2004 06:06 54 INPOUT.decl 03.12.1996 14:01 27.648 INPOUT32.DLL 13.10.2004 12:23 54 K8055d.decl 27.04.2004 21:35 46.592 K8055D.dll 13.10.2004 06:35 1.047 kernel32.dec 09.03.2006 23:09 848 kernel32.decls 09.11.2002 17:10 24.576 pbca3d2.dll 22.02.2005 06:58 26.998 User32.decls 11.02.2003 02:11 4.425 UserLibs.txt 09.03.2006 22:56 63 InpOut32.decls 28.03.1996 14:43 9.216 MaxxCom.dll 28.03.1996 14:43 32.658 MaxxCom.lib 26.04.1996 15:01 3.535 MaxxCom.txt 28.03.1996 11:30 4.174 MaxxCom.h 10.03.2006 08:46 364 MaxxCom.dec.txt 10.03.2006 20:44 4.903 newton.decls 10.03.2005 13:16 405.504 Newton.dll 29.11.2005 21:40 65.024 PEview.exe 19.03.2006 17:45 158 trak.decls 11.03.2006 22:46 2.352 trak.H 11.03.2006 20:08 141 MaxxCom.decls- 19.10.1995 15:26 32.256 TRAK-org.DLL 19.03.2006 17:44 32.256 TRAK.DLL 21.03.2006 16:35 0 dir.txt 39 Datei(en) 4.490.747 Bytes And one BB sourcecode. my_pitch=CreateBank(4) my_yaw=CreateBank(4) my_roll=CreateBank(4) ;// Start by connecting to the CyberMaxx If AutoDetectComPort()=0 ;// ERROR CyberMaxx not Found RuntimeError "ERROR CyberMaxx not Found" EndIf ;OpenCom(com1) ;// These are optional ;CyberHMD.SetHysteresisOn(); // turn on the hysteresis filter to minimize jittering (try this later) ;my_version_adr=Get_Version() ; returns a pointer to a string SetSamplingRate(50); // Used only in continous mode ;// default is 40 packets/s ;// This is how you read While KeyHit(1)=0 ;// if the CyberMaxx has supplied data, this returns true If ReadFromPort()<>0 Get_PYR(my_pitch, my_yaw, my_roll) Print PeekInt(my_pitch,0) Print PeekInt(my_yaw,0) Print PeekInt(my_roll,0) Else Print "Error" EndIf Wend And i found no way to use it. GreetS Micha |
| ||
I assume the DLL in question is "MaxxCom.dll" ? MaxxCom.lib and MaxxCom.h are not required there, they are sourcecode (as far as I see). Now tell me why is the decls named: "MaxxCom.decls-" ? what's that minus at the end of the name? If it's really named like this then it's no surprise the functions are not found. Please post the content of MaxxCom.decls. Could you upload the MaxxCom.dll somewhere, So I don't have to download the entire SDK thingy. However, for debugging purposes first try to make the very first command work: print AutoDetectComPort() print "success" waitkey() end if this is once working, you'll know the dll can be accessed. |
| ||
Hi, it was my false with the "MaxxCom.decls-" cause the maxxcom.dll contains then same functions like trak.dll so i rename the Maxxcom.decls. I tryed the same like your little testprogi, but it's always the same error message. The trak.dll is smaller and contains nearly the same functions. under www.erren3d.de/dll/trak.dll or www.erren3d.de/dll/maxxcom.dll you can download the DLLs. I hope i can help you, to help me. It's very cool that you immolate your time and know how. Greet's Micha |
| ||
I tried it with the maxxcom dll, but it didn't work. As I said, I don't know much about C++, but I think it has something to do with the way the example makes use of object oriented parenting. As far as I see in cybermaxx.h a custom structure is declared, and an instance named CyberHMD is then created and used as the parent object of any further command calls. Maybe this structure is required, I'm not sure. A little help of one of our C++ gurus may b helpful here (hey!). But somehow I also think there must be a way to use it without the object structure. However, could you post the content of cybermaxx.h ? |
| ||
I don't have any cybermaxx.h here are the *.h that i have // MaxxCom.h -- header definitions for CyberMaxx Tracker // Copyright (C) 1995 VictorMaxx Technologies, Inc. // Author: Robert J. Gebis // Date: 2 Oct 95 Ver 1.0 // Date: 19 Jan 96 1.0.1 // Date: 23 Jan 96 1.0.2 // Date: 24 Jan 96 1.0.4 #ifndef __MAXXCOM_H__ #define __MAXXCOM_H__ #define ABSOLUTE_MODE "C" #define RAW_DATA_MODE "B" #define ASCII_MODE "E" #define BINARY_MODE "F" #define SAMPLE_UPON_REQUEST "G" #define CONTINOUS_SAMPLE_MODE "H" #define TRANSITION_9600_19200 "K" #define TRANSITION_19200_9600 "L" #define CHECKSUM_ON "M" #define CHECKSUM_OFF "N" #define AVERAGE_FILTER_ON "T" #define AVERAGE_FILTER_OFF "W" #define HYSTERESIS_FILTER_ON "P" #define HYSTERESIS_FILTER_OFF "O" #define HARD_RESET "R" #define REQUEST_HANDSHAKE "X" #define REQUEST_VERSION_NUM "V" #define SEND_CURRENT_COORDINATE "S" #define SEND_CURRENT_SENSOR_DATA "S" #define MAXPACK 75 // higher sampling mode #define MINPACK 5 // lower sampling mode #define DEFSAMPLE "40" // starting sampling speed #define COM0_ID 0 #define COM1_ID 1 #define COM2_ID 2 #define COM3_ID 3 #define COM4_ID 4 // Number To Read IN Check Sum Mode #define N2R_INCSM_ON 7 #define N2R_INCSM_OFF 6 const char COM1[5] = "COM1"; const char COM2[5] = "COM2"; const char COM3[5] = "COM3"; const char COM4[5] = "COM4"; #define DllExport __declspec( dllexport ) class DllExport MaxxCom { public: MaxxCom(); ~MaxxCom(); int AutoDetectComPort(void); BOOL OpenCom(const char*); BOOL checkForCyberMaxx(void); BOOL Set9600(void); BOOL Set19200(void); BOOL SetHysteresisOn(void); BOOL SetHysteresisOff(void); BOOL HardReset(void); BOOL CheckSumOff(void); BOOL CheckSumOn(void); BOOL ReadFromPort(void); char* Get_Version(void); // if not NULL then returns pointer to version void Get_PYR(int*, int*, int*); // Get Pitch,Yaw,Roll inline char GetTransMode(void){ return m_TransMode;} inline void SetTransMode(char tp){ m_TransMode = tp;} inline char GetDataMode(void){ return m_dataType;} inline void SetDataMode(char tp){ m_dataType = tp;} void CloseCom(void); void SetSamplingRate(int rate); // MINPACK <-> MAXPACK increments of 5 inline int GetSamplingRate(void){return m_SamplingRate;} inline int GetCurrentSpeed(void){return m_iPortSpeed;} inline int GetPortId(void){return m_port_ID;} // For internal use only BOOL GetDCB(void); BOOL DoCheckSum(void); BOOL SendToPort(char*); inline unsigned char* GetDataBuffer(void){return m_inBuffer;} inline HANDLE GetTempComHandle(void){return m_hConTemp;} inline BOOL CheckIfBusy(void){ return m_bPortInUse;} inline BOOL GetCheckStatus(void){ return m_bChecksum;} inline void SetPortId(int id){m_port_ID = id;} inline void SetTempComHandle( void){m_hConTemp = m_hCom;} inline void SetNewComHandle( void){m_hCom = m_hConTemp;} inline void SetSpeedFlag(int speed){ m_iPortSpeed = speed;} inline int GetBytesRead(void){return m_numOfBytesRead;} inline HANDLE GetComHandle(void){return m_hCom;} BOOL CloseCom(const HANDLE); void errMsgBox(const char*); void ResetFIFO(void); private: int m_port_ID, // COM1_ID, COM2_ID, ..... m_SamplingRate, // default 40 packet/s m_iCheckSum, // contains actual checksum data m_iPortSpeed, // 9600 | 19200, 9600 default m_pitch, m_yaw, m_roll; // -45<->+45 , 0<->359, -45<->+45 char m_dataType; // used to flag binary or ascii mode (BINARY_MODE,ASCII_MODE) char m_TransMode; // used to flag Transfer type (CONTINOUS_SAMPLE_MODE, SAMPLE_UPON_REQUEST) char m_version[30]; // HMD version number unsigned char m_inBuffer[30]; // Data read from HMD BOOL m_bPortInUse, // True if Port is used m_bChecksum; // True if chack sum enabled DCB m_dcb; HANDLE m_hCom, m_hConTemp; DWORD m_numOfBytesRead; // number of bytes read from HMD }; #endif // nothing else after this line -----AND the // CyberTrak.h : main header file for the CYBERTRAK application // #include "MaxxCom.h" #ifndef __AFXWIN_H__ #error include 'stdafx.h' before including this file for PCH #endif #include "resource.h" // main symbols ///////////////////////////////////////////////////////////////////////////// // CCyberTrakApp: // See CyberTrak.cpp for the implementation of this class // class CCyberTrakApp : public CWinApp { private: MaxxCom maxxcom; public: CCyberTrakApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCyberTrakApp) public: virtual BOOL InitInstance(); virtual int ExitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CCyberTrakApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// But there is no part to declare. |
| ||
I'd really like to help you here but it seems I don't really understand C++ (shame on me). All the functions are declared within a class, the MaxxCom Class. They are declared as public, which is good. But I don't know how to create an instance of MaxxCom() to be able to use the commands in blitz, and if this is required at all. #define DllExport __declspec( dllexport ) class DllExport MaxxCom { public: MaxxCom(); ~MaxxCom(); int AutoDetectComPort(void); ... I also still don't see what MaxxCom() actually is, all I see is it's declared. It's not looking like a function declaration since there is not return type definition (even no void). I also wonder what's that ~ in "~MaxxCom();" Sorry, cannot help you here. Somebody who's more familar with C++ is required. Maybe you need to ask in an other thread, eg. in "userlibs". |
| ||
Ok, of course it is highly recommended to use a userlib instead of the old CallDLL command, but could you test this:b=CreateBank(1000) c=CreateBank(1000) CallDLL("maxxcom.dll","AutoDetectComPort",b,c) Print PeekInt(c,0) (save it as test_calldll.bb, maxxcom.dll must be in the same directory). I was able to run it without an error, whatever that means. Of course it returned zero because I ain't got the device. If it returns something other than zero on your machine, then there may be hope :) |
| ||
Hi JFK, i ve tested it, but there is allways a 0 returned. then i have changed the Dll to trak.dll and the same. i have made some tests but that calldll won't return anything. |
| ||
OK, i cancel the way over DLL. It's to hard to get data from a extern DLL. Special thanx to JFK The next Way is ro handel it over RS232, here is a system on start and i try to use it. I found in the Net the definition of the pack's and try now to read them out. Just for Fun here ist the definition: The CyberMaxx tracker interface, and a proposed extension The CyberMaxx runs at 9600, 8 bit, no parity, 1 stop. To reset the unit, send it an ascii 'R'; it should respond with a copyright string. By default the tracker sends data in ascii, so send it an 'F' to go into binary mode. By default it sends data continuously; if you want to poll it, send it a 'G', then send an 'S' whenever you want to request a packet. In binary, the packets consist of 8 bytes. The first two are 0xFF (to mark the start of the packet). These are followed by 3 16-bit words (sent high-byte first) giving the yaw, pitch and roll. The top bit of each 16-bit word is zero, so they're really 15-bit words; the fact that the top bit is zero means that you don't have to worry about two consecutive 0xFF's occurring in the data and looking like the start of a new packet. The yaw is 0-360 degrees (i.e. 0 is zero, and 0x7FFF is 359.959 degrees). The pitch and roll are from -45 degrees to +45 degrees (i.e. 0 is -45, and 0x7FFF is +45). That's it. Pretty simple. To summarize, the packet is: 1111 1111 1111 1111 (16 bits of 1's) 0yyy yyyy yyyy yyyy (15-bit yaw) 0ppp pppp pppp pppp (15-bit pitch) 0rrr rrrr rrrr rrrr (15-bit roll) Software-wise, you send an 'R' followed by an 'F' to initialize the tracker and put it into binary mode. Your serial interrupt routine should check for two consecutive 0xFF's; when it sees them, it should reset its buffer pointer to zero. After the number of bytes in the buffer hits 6, just pick up the yaw/pitch/roll and convert. *Really* simple stuff. Here's what I propose to do to extend the packet format: Add additional 16-bit words (with the top bit clear, for backwards compatability). In other words, after the "roll" value, just add more data; old parsers will ignore everything up to the next double 0xFF, and new parsers can use the additional data. New parsers should probably check the copyright message, to see if they've got an old-format device (like the current CyberMaxx), in which case they read only the yaw/pitch/roll. The first additional word (after the roll value) would be: 0knn nnnn cccc cccc where the 6-bit 'n' value is the number of 16-bit values that follow, and the 8-bit 'c' value is a channel id (in case the serial devices are daisy-chained). The data for the additional channels would follow, 15 bits for each channel. The first three should be reserved for position information, the rest will be device-specific (e.g. finger flexion). If the 'k' bit is set, the software should expect a 16-bit (really 15-bit) checksum to follow the data; the checksum would be the unsigned sum of all the data values (not including the 0xFF's). |