1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "MtlReader.h"
18 
19 #include <android-base/logging.h>
20 #include <cstdio>
21 
22 namespace android {
23 namespace hardware {
24 namespace automotive {
25 namespace sv {
26 namespace V1_0 {
27 namespace implementation {
28 
29 namespace {
30 
31 constexpr int kCharBufferSize = 128;
32 
ReadFloat3(FILE * file,float * value)33 void ReadFloat3(FILE* file, float* value) {
34     float temp[3];
35     int res = fscanf(file, "%f %f %f", &temp[0], &temp[1], &temp[2]);
36     3 == res ? std::memcpy(value, temp, 3 * sizeof(float)) : nullptr;
37 }
38 
ReadFloat(FILE * file,float * value)39 void ReadFloat(FILE* file, float* value) {
40     float temp;
41     int res = fscanf(file, "%f", &temp);
42     *value = res > 0 ? temp : -1;
43 }
44 
ReadInt(FILE * file,int * value)45 void ReadInt(FILE* file, int* value) {
46     int temp;
47     int res = fscanf(file, "%d", &temp);
48     *value = res > 0 ? temp : -1;
49 }
50 
ReadString(FILE * file,std::string * value)51 void ReadString(FILE* file, std::string* value) {
52     char temp[kCharBufferSize];
53     fscanf(file, "%s", temp);
54     *value = temp;
55 }
56 }  // namespace
57 
ReadMtlFromFile(const std::string & mtlFilename,std::map<std::string,MtlConfigParams> * params)58 bool ReadMtlFromFile(const std::string& mtlFilename,
59                      std::map<std::string, MtlConfigParams>* params) {
60     FILE* file = fopen(mtlFilename.c_str(), "r");
61     if (!file) {
62         LOG(ERROR) << "Failed to open mtl file: " << mtlFilename;
63         return false;
64     }
65 
66     std::string currentConfig;
67     while (true) {
68         char lineHeader[kCharBufferSize];
69         // read the first word of the line
70         int res = fscanf(file, "%s", lineHeader);
71 
72         if (res == EOF) {
73             break;  // EOF = End Of File. Quit the loop.
74         }
75 
76         if (strcmp(lineHeader, "#") == 0) {
77             fgets(lineHeader, sizeof(lineHeader), file);
78             continue;
79         }
80         if (strcmp(lineHeader, "newmtl") == 0) {
81             res = fscanf(file, "%s", lineHeader);
82             if (params->find(lineHeader) != params->end()) {
83                 fclose(file);
84                 LOG(ERROR) << "Duplicated params of : " << lineHeader[0];
85                 return false;
86             }
87             currentConfig = lineHeader;
88             continue;
89         }
90 
91         if (strcmp(lineHeader, "Ns") == 0) {
92             ReadFloat(file, &((*params)[currentConfig].ns));
93             continue;
94         }
95         if (strcmp(lineHeader, "Ni") == 0) {
96             ReadFloat(file, &((*params)[currentConfig].ni));
97             continue;
98         }
99         if (strcmp(lineHeader, "d") == 0) {
100             ReadFloat(file, &((*params)[currentConfig].d));
101             continue;
102         }
103         if (strcmp(lineHeader, "Tr") == 0) {
104             ReadFloat(file, &((*params)[currentConfig].tr));
105             continue;
106         }
107         if (strcmp(lineHeader, "Tf") == 0) {
108             ReadFloat3(file, (*params)[currentConfig].tf);
109             continue;
110         }
111         if (strcmp(lineHeader, "illum") == 0) {
112             ReadInt(file, &((*params)[currentConfig].illum));
113             continue;
114         }
115         if (strcmp(lineHeader, "Ka") == 0) {
116             ReadFloat3(file, (*params)[currentConfig].ka);
117             continue;
118         }
119         if (strcmp(lineHeader, "Kd") == 0) {
120             ReadFloat3(file, (*params)[currentConfig].kd);
121             continue;
122         }
123         if (strcmp(lineHeader, "Ks") == 0) {
124             ReadFloat3(file, (*params)[currentConfig].ks);
125             continue;
126         }
127         if (strcmp(lineHeader, "Ke") == 0) {
128             ReadFloat3(file, (*params)[currentConfig].ke);
129             continue;
130         }
131         if (strcmp(lineHeader, "map_bump") == 0) {
132             ReadString(file, &((*params)[currentConfig].mapBump));
133             continue;
134         }
135         if (strcmp(lineHeader, "bump") == 0) {
136             ReadString(file, &((*params)[currentConfig].bump));
137             continue;
138         }
139         if (strcmp(lineHeader, "map_Ka") == 0) {
140             ReadString(file, &((*params)[currentConfig].mapKa));
141             continue;
142         }
143         if (strcmp(lineHeader, "map_Kd") == 0) {
144             ReadString(file, &((*params)[currentConfig].mapKd));
145             continue;
146         }
147         if (strcmp(lineHeader, "map_Ks") == 0) {
148             ReadString(file, &((*params)[currentConfig].mapKs));
149             continue;
150         } else {
151             LOG(WARNING) << "Unknown tag " << lineHeader << ". Skipped";
152             fgets(lineHeader, sizeof(lineHeader), file);
153             continue;
154         }
155     }
156 
157     fclose(file);
158     return true;
159 }
160 
161 }  // namespace implementation
162 }  // namespace V1_0
163 }  // namespace sv
164 }  // namespace automotive
165 }  // namespace hardware
166 }  // namespace android
167