@Klunk-1 (…and others) – in just looking at my “CollectNotes” method… do you see any flaws in the code???
I don’t need to look…
penny to a pound it’s a NULL pointer
Access violation writing location 0x00000000.
You are attempting to write or access to the memory address zero. Either setting an array variable which is a NULL(zero) pointer or accessing an object member variable/member function where the object is a NULL pointer...
That is why c/c++ proliferates with code like
DefNoteTrack* nt = (DefNoteTrack*)node->GetNoteTrack(i);
if(nt)
{
.....
which is why you need to run under the debugger so you can spot the error should be pretty easy to find once you get the hang of it, it's pretty simple to learn and (damn useful) no thats wrong it's essential !, having a proper debugger is one of the big advantages developing with the SDK has over mxs.
some quirks of running max under the debugger. Get into the habit of stepping through a couple of lines of code after a break point with (f10) if you go straight back into a run (f5) it has a habit of dropping into some dissembled code then you need to keep pressing f5 to get out of it (though sometimes you have to kill max and start the session again). It will drop into this mode at random time usually after executing your code and going back to max again keep pressing (f5) until it returns.
you should also read up on assert() and assert macros defined in
assert1.h of the sdk.
DbgAssert(myPointer);
will throw an error if myPointer == 0 showing the line, file & function the error occurred in. But only in a debug build it will evaluate to nop in a release build so you can leave it in at all times.
Thanks… I will endeavor to dive deeper into the debugger…
On another possible source… I searched the SDK (3dsMax6) samples for “DefNoteTrack” and in the VRML exporter… it was interesting to discover that in their code they had to include a custom header for the class definition for all the NoteTrack classes. In their custom header they stated:
// FIXME this should be exported from the SDK!
#include "notetrck.h"
class NoteKey {...blah...};
class NoteKeyTab : public Tab<NoteKey*> {...blah...};
class DefNoteTrack : public NoteTrack {...blah...};
should have used
// TODO: this should be exported from the SDK!
then it would have appearing in the visual studio task list and would have been fixed ! I don’t think that’s your error as It probably wouldn’t have compiled and linked without the header files
@Klunk-1 – found this information in the 3dsMax6 SDK (…which seems to include old Sparks forum discussions):
I thought I’d share with everyone a problem and solution I found over the past day and a half. This solution may not be the best, and if someone has a faster solution I’d love to hear it.
For one reason or another we decided we wanted to export the note information from Track View. When I started the extraction code I began to run into a few problems.
Problem #1: The wizard doesn’t add support for notetracks with export plug-ins. Help file does not mention where the correct .h file is with Note track information
Solution #1: Add Notetrck.hProblem #2: Animatable->GetNoteTrack(i) returns NoteTrack *. NoteTrack itself has no useful functions.
Soultion #2: Typecast it as a DefNoteTrack *
which the help file touches on.Problem #3: DefNoteTrack->keys.Addr(i) returns a pointer to what is tabbed, which is a pointer.
Solution #3: Simple C++ pointer conversion but I was unsure I would get any actual data from a NoteKey **.My solution:
DefNoteTrack * notetrack = (DefNoteTrack *)n->GetNoteTrack(i); if(notetrack) { for(int k = 0; k < notetrack->keys.Count();k++) { NoteKey * notekey = *(notetrack->keys.Addr(k)); if(notekey->time); //tests if(notekey->note); //tests } }
// Please excuse my formatting
So perhaps the error in my code is that I am not accessing the key data properly… since I am not using:
->keys.Addr(k);
:shrug:
i would think your error lies here
NoteKey* nk = nt->keys[t];
keys would be an index array access so should read
NoteKey* nk = nt->keys[j];
and also change
for (int j = 0; j < nt->keys.Count(); j++)
to
for (int j = 0; j < nt->NumKeys(); j++)
Oops… yeah that (t) was a holdover when I was trying to use ->GetKeyIndex(TimeValue)…
…went home for lunch and quickly tried these changes:
I tried using .Addr() but it failed… also, I made those changes you suggested, but it still failed.
If I uncheck “Export NoteTracks” then it gets thru the for loop down to a temporary MessageBox ( <– my debugger… hah!) I use to tell me it was successful.
I will have to dig deeper… :hmm:
the following ran with out issue in my exporter
#if 1
NoteKeyTab noteList;
INode* maxnode = child->GetMaxNode();
if(maxnode)
{
int numNoteTracks = maxnode->NumNoteTracks();
for(int i = 0; i < numNoteTracks; ++i)
{
DefNoteTrack* nt = dynamic_cast<DefNoteTrack*>(maxnode->GetNoteTrack(i));
if(nt)
{
int numkeys = nt->NumKeys();
for(int j = 0; j < numkeys; ++j)
{
NoteKey* key = nt->keys[j];
noteList.Append(1,&key);
}
}
}
}
#endif
the
INode* maxnode = child->GetMaxNode();
is to convert from an IGameNode*
I’m very grateful for your help …so forgive me for asking– so you added NoteTracks and NoteKeys to your node to exercise your code snippet and populate noteList? Again, meaning no offense.
also, thanks for the hybrid directives… I made those changes in the Hybrid properties (and ran debugger at lunch time) but it told me no source code was available for my exporter and I had to use disassembly… which made no sense to me… I never got yellow arrows inside my open visual studio code. I will have to find some tutorials for using the Debug feature.
yep I added a notetrack with 6 notekeys and they were successfully collected in the notelist tab.
also what version of max are you compiling for ?
Would you modify your code and try doing it as pass-by-reference on the NoteKeyTab like I was trying to do???
I’m using Visual Studio .NET 2003 to compile against 3dsMax 6 SDK (which will work in Max 7, 8)… once I get this exporter and output verified in the game engine, then I will compile for Max 9 to Max 2014 (both 32/64-bit).
i doubt that’s the issue here, if you can’t get the debugger working correctly then you’ll have to use assert to trace the error.
The CollectNotes method gets passed in a private class member variable which is declared as:
private:
.
.
.
NoteKeyTab m_noteList;
std::vector<Point3> m_posList;
std::vector<Point3> m_rotList;
std::vector<IPoint2> m_noteCatalog;
IPoint2 m_noNotes;
.
.
.
In the body of the “DoExport” method m_noteCatalog is never initialized to anything… just passed into the CollectNotes method as:
.
.
.
if ( g_ExportOptions.bNoteTracks && pNode->HasNoteTracks() )
{
CollectNotes(pNode, m_noteCatalog, m_noteList);
}
else
{
//set to default
m_noteCatalog.resize(( m_nAnimEnd - m_nAnimStart + 1 ), m_noNotes);
}
.
.
.
.