[Artoolkit] Marker of nftSimple
重点看:markers.dat 的解析原理
1.
int main(int argc, char** argv)
{
char glutGamemode[32];
const char *cparam_name = "Data2/camera_para.dat";
char vconf[] = "";
const char markerConfigDataFilename[] = "Data2/markers.dat";
2.
// Load marker(s).
newMarkers(markerConfigDataFilename, &markersNFT, &markersNFTCount);
if (!markersNFTCount) {
ARLOGe("Error loading markers from config. file '%s'.\n", markerConfigDataFilename);
cleanup();
exit(-1);
}
ARLOGi("Marker count = %d\n", markersNFTCount); //等于1
3.
// Marker data has been loaded, so now load NFT data. if (!loadNFTData()) { ARLOGe("Error loading NFT data.\n"); cleanup(); exit(-1); }
newMarkers 到底是如何工作的呢?
# Number of markers
1
# Entries for each marker. Format is:
#
# Name of pattern file (relative to this file)
# Marker type (SINGLE)
# Marker width in millimetres (floating point number)
# Optional tokens:
# FILTER [x] Enable pose estimate filtering for the preceding marker
# x (optional) specifies the cutoff frequency. Default
# value is AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT, which
# at time of writing, equals 5.0.
# A blank line
../DataNFT/pinball
NFT
FILTER 15.0
1 void newMarkers(const char *markersConfigDataFilePathC, ARMarkerNFT **markersNFT_out, int *markersNFTCount_out)
2 {
3 FILE *fp;
4 char buf[MAXPATHLEN], buf1[MAXPATHLEN];
5 int tempI;
6 ARMarkerNFT *markersNFT;
7 int markersNFTCount;
8 ARdouble tempF;
9 int i;
10 char markersConfigDataDirC[MAXPATHLEN];
11 size_t markersConfigDataDirCLen;
12
13 if (!markersConfigDataFilePathC || markersConfigDataFilePathC[0] == '\0' || !markersNFT_out || !markersNFTCount_out) return;
14
15 // Load the marker data file.
16 ARLOGd("Opening marker config. data file from path '%s'.\n", markersConfigDataFilePathC);
17 arUtilGetDirectoryNameFromPath(markersConfigDataDirC, markersConfigDataFilePathC, MAXPATHLEN, 1); // 1 = add '/' at end.
18 markersConfigDataDirCLen = strlen(markersConfigDataDirC);
19 if ((fp = fopen(markersConfigDataFilePathC, "r")) == NULL) {
20 ARLOGe("Error: unable to locate marker config data file '%s'.\n", markersConfigDataFilePathC);
21 return;
22 }
23
24 // First line is number of markers to read.
25 get_buff(buf, MAXPATHLEN, fp, 1);
26 if (sscanf(buf, "%d", &tempI) != 1 ) {
27 ARLOGe("Error in marker configuration data file; expected marker count.\n");
28 fclose(fp);
29 return;
30 }
31
32 arMallocClear(markersNFT, ARMarkerNFT, tempI);
33 markersNFTCount = tempI;
34
35 ARLOGd("Reading %d marker configuration(s).\n", markersNFTCount);
36
37 for (i = 0; i < markersNFTCount; i++) {
38
39 // Read marker file name.
40 if (!get_buff(buf, MAXPATHLEN, fp, 1)) {
41 ARLOGe("Error in marker configuration data file; expected marker name.\n");
42 break;
43 }
44
45 // Read marker type.
46 if (!get_buff(buf1, MAXPATHLEN, fp, 1)) {
47 ARLOGe("Error in marker configuration data file; expected marker type.\n");
48 break;
49 }
50
51 // Interpret marker type, and read more data.
52 if (strcmp(buf1, "SINGLE") == 0) {
53 ARLOGe("Error in marker configuration data file; SINGLE markers not supported in this build.\n");
54 } else if (strcmp(buf1, "MULTI") == 0) {
55 ARLOGe("Error in marker configuration data file; MULTI markers not supported in this build.\n");
56 } else if (strcmp(buf1, "NFT") == 0) {
57 markersNFT[i].valid = markersNFT[i].validPrev = FALSE;
58 arMalloc(markersNFT[i].datasetPathname, char, markersConfigDataDirCLen + strlen(buf) + 1);
59 strcpy(markersNFT[i].datasetPathname, markersConfigDataDirC);
60 strcpy(markersNFT[i].datasetPathname + markersConfigDataDirCLen, buf);
61 markersNFT[i].pageNo = -1;
62 } else {
63 ARLOGe("Error in marker configuration data file; unsupported marker type %s.\n", buf1);
64 }
65
66 // Look for optional tokens. A blank line marks end of options.
67 while (get_buff(buf, MAXPATHLEN, fp, 0) && (buf[0] != '\0')) {
68 if (strncmp(buf, "FILTER", 6) == 0) {
69 markersNFT[i].filterCutoffFrequency = AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT;
70 markersNFT[i].filterSampleRate = AR_FILTER_TRANS_MAT_SAMPLE_RATE_DEFAULT;
71 if (strlen(buf) != 6) {
72 if (sscanf(&buf[6],
73 #ifdef ARDOUBLE_IS_FLOAT
74 "%f"
75 #else
76 "%lf"
77 #endif
78 , &tempF) == 1) markersNFT[i].filterCutoffFrequency = tempF;
79 }
80 markersNFT[i].ftmi = arFilterTransMatInit(markersNFT[i].filterSampleRate, markersNFT[i].filterCutoffFrequency);
81 }
82 // Unknown tokens are ignored.
83 }
84 }
85 fclose(fp);
86
87 // If not all markers were read, an error occurred.
88 if (i < markersNFTCount) {
89
90 // Clean up.
91 for (; i >= 0; i--) {
92 if (markersNFT[i].datasetPathname) free(markersNFT[i].datasetPathname);
93 if (markersNFT[i].ftmi) arFilterTransMatFinal(markersNFT[i].ftmi);
94 }
95 free(markersNFT);
96
97 *markersNFTCount_out = 0;
98 *markersNFT_out = NULL;
99 return;
100 }
101
102 *markersNFTCount_out = markersNFTCount;
103 *markersNFT_out = markersNFT;
104 }
typedef struct _ARMarkerNFT {
// ARMarker protected
bool valid;
bool validPrev;
ARdouble trans[3][4];
ARPose pose;
ARdouble marker_width;
ARdouble marker_height;
// ARMarker private
ARFilterTransMatInfo *ftmi; // 变换矩阵,为何使用链表的形式?
ARdouble filterCutoffFrequency;
ARdouble filterSampleRate;
// ARMarkerNFT
int pageNo;
char *datasetPathname;
} ARMarkerNFT;
loadNFTData 开始分析。
1 // References globals: markersNFTCount
2 // Modifies globals: threadHandle, surfaceSet[], surfaceSetCount, markersNFT[]
3 static int loadNFTData(void)
4 {
5 int i;
6 KpmRefDataSet *refDataSet;
7
8 // If data was already loaded, stop KPM tracking thread and unload previously loaded data.
9 if (threadHandle) {
10 ARLOGi("Reloading NFT data.\n");
11 unloadNFTData();
12 } else {
13 ARLOGi("Loading NFT data.\n");
14 }
15
16 refDataSet = NULL;
17
18 for (i = 0; i < markersNFTCount; i++) { // 重点在这里!
19 // (1) Load KPM data.
20 KpmRefDataSet *refDataSet2;
21 ARLOGi("Reading %s.fset3\n", markersNFT[i].datasetPathname);
22 if (kpmLoadRefDataSet(markersNFT[i].datasetPathname, "fset3", &refDataSet2) < 0 ) {
23 ARLOGe("Error reading KPM data from %s.fset3\n", markersNFT[i].datasetPathname);
24 markersNFT[i].pageNo = -1;
25 continue;
26 }
27 markersNFT[i].pageNo = surfaceSetCount;
28 ARLOGi(" Assigned page no. %d.\n", surfaceSetCount);
29 if (kpmChangePageNoOfRefDataSet(refDataSet2, KpmChangePageNoAllPages, surfaceSetCount) < 0) {
30 ARLOGe("Error: kpmChangePageNoOfRefDataSet\n");
31 exit(-1);
32 }
33 if (kpmMergeRefDataSet(&refDataSet, &refDataSet2) < 0) {
34 ARLOGe("Error: kpmMergeRefDataSet\n");
35 exit(-1);
36 }
37 ARLOGi(" Done.\n");
38
39 // (2) Load AR2 data.
40 ARLOGi("Reading %s.fset\n", markersNFT[i].datasetPathname);
41
42 if ((surfaceSet[surfaceSetCount] = ar2ReadSurfaceSet(markersNFT[i].datasetPathname, "fset", NULL)) == NULL ) {
43 ARLOGe("Error reading data from %s.fset\n", markersNFT[i].datasetPathname);
44 }
45 ARLOGi(" Done.\n");
46
47 surfaceSetCount++;
48 if (surfaceSetCount == PAGES_MAX) break;
49 }
50 if (kpmSetRefDataSet(kpmHandle, refDataSet) < 0) {
51 ARLOGe("Error: kpmSetRefDataSet\n");
52 exit(-1);
53 }
54 kpmDeleteRefDataSet(&refDataSet);
55
56 // Start the KPM tracking thread.
57 threadHandle = trackingInitInit(kpmHandle);
58 if (!threadHandle) exit(-1);
59
60 ARLOGi("Loading of NFT data complete.\n");
61 return (TRUE);
62 }
需要找个multi marker的例子再继续分析。