|  | 
|  | 1 | +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. | 
|  | 2 | +
 | 
|  | 3 | +Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | +you may not use this file except in compliance with the License. | 
|  | 5 | +You may obtain a copy of the License at | 
|  | 6 | +
 | 
|  | 7 | +    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | +
 | 
|  | 9 | +Unless required by applicable law or agreed to in writing, software | 
|  | 10 | +distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | +See the License for the specific language governing permissions and | 
|  | 13 | +limitations under the License. | 
|  | 14 | +==============================================================================*/ | 
|  | 15 | + | 
|  | 16 | +#include "tensorflow/core/framework/op_kernel.h" | 
|  | 17 | +#include "tensorflow/core/platform/logging.h" | 
|  | 18 | +#include "tiny_obj_loader.h" | 
|  | 19 | + | 
|  | 20 | +namespace tensorflow { | 
|  | 21 | +namespace io { | 
|  | 22 | +namespace { | 
|  | 23 | + | 
|  | 24 | +class DecodeObjVertexOp : public OpKernel { | 
|  | 25 | + public: | 
|  | 26 | +  explicit DecodeObjVertexOp(OpKernelConstruction* context) | 
|  | 27 | +      : OpKernel(context) {} | 
|  | 28 | + | 
|  | 29 | +  void Compute(OpKernelContext* context) override { | 
|  | 30 | +    const Tensor* input_tensor; | 
|  | 31 | +    OP_REQUIRES_OK(context, context->input("input", &input_tensor)); | 
|  | 32 | +    OP_REQUIRES(context, TensorShapeUtils::IsScalar(input_tensor->shape()), | 
|  | 33 | +                errors::InvalidArgument("input must be scalar, got shape ", | 
|  | 34 | +                                        input_tensor->shape().DebugString())); | 
|  | 35 | +    const tstring& input = input_tensor->scalar<tstring>()(); | 
|  | 36 | + | 
|  | 37 | +    tinyobj::ObjReader reader; | 
|  | 38 | + | 
|  | 39 | +    if (!reader.ParseFromString(input.c_str(), "")) { | 
|  | 40 | +      OP_REQUIRES( | 
|  | 41 | +          context, false, | 
|  | 42 | +          errors::Internal("Unable to read obj file: ", reader.Error())); | 
|  | 43 | +    } | 
|  | 44 | + | 
|  | 45 | +    if (!reader.Warning().empty()) { | 
|  | 46 | +      LOG(WARNING) << "TinyObjReader: " << reader.Warning(); | 
|  | 47 | +    } | 
|  | 48 | + | 
|  | 49 | +    auto& attrib = reader.GetAttrib(); | 
|  | 50 | + | 
|  | 51 | +    int64 count = attrib.vertices.size() / 3; | 
|  | 52 | + | 
|  | 53 | +    Tensor* output_tensor = nullptr; | 
|  | 54 | +    OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape({count, 3}), | 
|  | 55 | +                                                     &output_tensor)); | 
|  | 56 | +    // Loop over attrib.vertices: | 
|  | 57 | +    for (int64 i = 0; i < count; i++) { | 
|  | 58 | +      tinyobj::real_t x = attrib.vertices[i * 3 + 0]; | 
|  | 59 | +      tinyobj::real_t y = attrib.vertices[i * 3 + 1]; | 
|  | 60 | +      tinyobj::real_t z = attrib.vertices[i * 3 + 2]; | 
|  | 61 | +      output_tensor->tensor<float, 2>()(i, 0) = x; | 
|  | 62 | +      output_tensor->tensor<float, 2>()(i, 1) = y; | 
|  | 63 | +      output_tensor->tensor<float, 2>()(i, 2) = z; | 
|  | 64 | +    } | 
|  | 65 | +  } | 
|  | 66 | +}; | 
|  | 67 | +REGISTER_KERNEL_BUILDER(Name("IO>DecodeObjVertex").Device(DEVICE_CPU), | 
|  | 68 | +                        DecodeObjVertexOp); | 
|  | 69 | + | 
|  | 70 | +}  // namespace | 
|  | 71 | +}  // namespace io | 
|  | 72 | +}  // namespace tensorflow | 
0 commit comments