//============================== // FontInfoType::LoadFromBuffer bool FontInfoType::LoadFromBuffer( void const * buffer, size_t const bufferSize ) { char const * errorMsg = NULL; OVR::JSON * jsonRoot = OVR::JSON::Parse( reinterpret_cast< char const * >( buffer ), &errorMsg ); if ( jsonRoot == NULL ) { LOG( "JSON Error: %s", ( errorMsg != NULL ) ? errorMsg : "<NULL>" ); return false; } int32_t maxCharCode = -1; // currently we're only supporting the first unicode plane up to 65k. If we were to support other planes // we could conceivably end up with a very sparse 1,114,111 byte type for mapping character codes to // glyphs and if that's the case we may just want to use a hash, or use a combination of tables for // the first 65K and hashes for the other, less-frequently-used characters. static const int MAX_GLYPHS = 0xffff; // load the glyphs const JsonReader jsonGlyphs( jsonRoot ); if ( !jsonGlyphs.IsObject() ) { jsonRoot->Release(); return false; } int Version = jsonGlyphs.GetChildFloatByName( "Version" ); if ( Version != FNT_FILE_VERSION ) { jsonRoot->Release(); return false; } FontName = jsonGlyphs.GetChildStringByName( "FontName" ); CommandLine = jsonGlyphs.GetChildStringByName( "CommandLine" ); ImageFileName = jsonGlyphs.GetChildStringByName( "ImageFileName" ); const int numGlyphs = jsonGlyphs.GetChildInt32ByName( "NumGlyphs" ); if ( numGlyphs < 0 || numGlyphs > MAX_GLYPHS ) { OVR_ASSERT( numGlyphs > 0 && numGlyphs <= MAX_GLYPHS ); jsonRoot->Release(); return false; } NaturalWidth = jsonGlyphs.GetChildFloatByName( "NaturalWidth" ); NaturalHeight = jsonGlyphs.GetChildFloatByName( "NaturalHeight" ); // we scale everything after loading integer values from the JSON file because the OVR JSON writer loses precision on floats double nwScale = 1.0f / NaturalWidth; double nhScale = 1.0f / NaturalHeight; HorizontalPad = jsonGlyphs.GetChildFloatByName( "HorizontalPad" ) * nwScale; VerticalPad = jsonGlyphs.GetChildFloatByName( "VerticalPad" ) * nhScale; FontHeight = jsonGlyphs.GetChildFloatByName( "FontHeight" ) * nhScale; CenterOffset = jsonGlyphs.GetChildFloatByName( "CenterOffset" ); TweakScale = jsonGlyphs.GetChildFloatByName( "TweakScale", 1.0f ); LOG( "FontName = %s", FontName.ToCStr() ); LOG( "CommandLine = %s", CommandLine.ToCStr() ); LOG( "HorizontalPad = %.4f", HorizontalPad ); LOG( "VerticalPad = %.4f", VerticalPad ); LOG( "FontHeight = %.4f", FontHeight ); LOG( "CenterOffset = %.4f", CenterOffset ); LOG( "TweakScale = %.4f", TweakScale ); LOG( "ImageFileName = %s", ImageFileName.ToCStr() ); LOG( "Loading %i glyphs.", numGlyphs ); /// HACK: this is hard-coded until we do not have a dependcy on reading the font from Home if ( OVR_stricmp( FontName.ToCStr(), "korean.fnt" ) == 0 ) { TweakScale = 1.4f; CenterOffset = -0.02f; } /// HACK: end hack Glyphs.Resize( numGlyphs ); const JsonReader jsonGlyphArray( jsonGlyphs.GetChildByName( "Glyphs" ) ); double totalWidth = 0.0; if ( jsonGlyphArray.IsArray() ) { for ( int i = 0; i < Glyphs.GetSizeI() && !jsonGlyphArray.IsEndOfArray(); i++ ) { const JsonReader jsonGlyph( jsonGlyphArray.GetNextArrayElement() ); if ( jsonGlyph.IsObject() ) { FontGlyphType & g = Glyphs[i]; g.CharCode = jsonGlyph.GetChildInt32ByName( "CharCode" ); g.X = jsonGlyph.GetChildFloatByName( "X" ); g.Y = jsonGlyph.GetChildFloatByName( "Y" ); g.Width = jsonGlyph.GetChildFloatByName( "Width" ); g.Height = jsonGlyph.GetChildFloatByName( "Height" ); g.AdvanceX = jsonGlyph.GetChildFloatByName( "AdvanceX" ); g.AdvanceY = jsonGlyph.GetChildFloatByName( "AdvanceY" ); g.BearingX = jsonGlyph.GetChildFloatByName( "BearingX" ); g.BearingY = jsonGlyph.GetChildFloatByName( "BearingY" ); g.X *= nwScale; g.Y *= nhScale; g.Width *= nwScale; g.Height *= nhScale; g.AdvanceX *= nwScale; g.AdvanceY *= nhScale; g.BearingX *= nwScale; g.BearingY *= nhScale; totalWidth += g.Width; maxCharCode = Alg::Max( maxCharCode, g.CharCode ); } } } double averageGlyphWidth = totalWidth / numGlyphs; // this is the average width in uv space of characters in the ClearSans font. This is used to // compute a scaling factor for other fonts. double const DEFAULT_GLYPH_UV_WIDTH = 0.047458650262793022; float const DEFAULT_TEXT_SCALE = 0.0025f; float const widthScaleFactor = static_cast< float >( DEFAULT_GLYPH_UV_WIDTH / averageGlyphWidth ); ScaleFactor = DEFAULT_SCALE_FACTOR * DEFAULT_TEXT_SCALE * widthScaleFactor * TweakScale; // This is not intended for wide or ucf character sets -- depending on the size range of // character codes lookups may need to be changed to use a hash. if ( maxCharCode >= MAX_GLYPHS ) { OVR_ASSERT( maxCharCode <= MAX_GLYPHS ); maxCharCode = MAX_GLYPHS; } // resize the array to the maximum glyph value CharCodeMap.Resize( maxCharCode + 1 ); for ( int i = 0; i < Glyphs.GetSizeI(); ++i ) { FontGlyphType const & g = Glyphs[i]; CharCodeMap[g.CharCode] = i; } jsonRoot->Release(); return true; }
void ParseModelsJsonTest( const char * jsonFileName, const char * binFileName ) { const BinaryReader bin( binFileName, NULL ); if ( bin.ReadUInt32() != 0x6272766F ) { return; } JSON * json = JSON::Load( jsonFileName ); if ( json == NULL ) { return; } const JsonReader models( json ); if ( models.IsObject() ) { // // Render Model // const JsonReader render_model( models.GetChildByName( "render_model" ) ); if ( render_model.IsObject() ) { const JsonReader texture_array( render_model.GetChildByName( "textures" ) ); if ( texture_array.IsArray() ) { while ( !texture_array.IsEndOfArray() ) { const JsonReader texture( texture_array.GetNextArrayElement() ); if ( texture.IsObject() ) { const String name = texture.GetChildStringByName( "name" ); const String usage = texture.GetChildStringByName( "usage" ); const String occlusion = texture.GetChildStringByName( "occlusion" ); } } } const JsonReader joint_array( render_model.GetChildByName( "joints" ) ); if ( joint_array.IsArray() ) { while ( !joint_array.IsEndOfArray() ) { const JsonReader joint( joint_array.GetNextArrayElement() ); if ( joint.IsObject() ) { struct Joint { String name; Matrix4f transform; String animation; Vector3f parameters; float timeOffset; float timeScale; } newJoint; newJoint.name = joint.GetChildStringByName( "name" ); newJoint.animation = joint.GetChildStringByName( "animation" ); StringUtils::StringTo( newJoint.transform, joint.GetChildStringByName( "transform" ) ); newJoint.parameters.x = joint.GetChildFloatByName( "parmX" ); newJoint.parameters.y = joint.GetChildFloatByName( "parmY" ); newJoint.parameters.z = joint.GetChildFloatByName( "parmZ" ); newJoint.timeScale = joint.GetChildFloatByName( "timeScale" ); newJoint.timeOffset = joint.GetChildFloatByName( "timeOffset" ); } } } const JsonReader tag_array( render_model.GetChildByName( "tags" ) ); if ( tag_array.IsArray() ) { while ( !tag_array.IsEndOfArray() ) { const JsonReader tag( tag_array.GetNextArrayElement() ); if ( tag.IsObject() ) { struct Tag { String name; Matrix4f matrix; Vector4i jointIndices; Vector4f jointWeights; } newTag; const String name = tag.GetChildStringByName( "name" ); StringUtils::StringTo( newTag.matrix, tag.GetChildStringByName( "matrix" ) ); StringUtils::StringTo( newTag.jointIndices, tag.GetChildStringByName( "jointIndices" ) ); StringUtils::StringTo( newTag.jointWeights, tag.GetChildStringByName( "jointWeights" ) ); } } } const JsonReader surface_array( render_model.GetChildByName( "surfaces" ) ); if ( surface_array.IsArray() ) { while ( !surface_array.IsEndOfArray() ) { struct Surface { String name; String materialType; int diffuseTexture; int normalTexture; int specularTexture; int emissiveTexture; Bounds3f bounds; Array< Vector3f > position; Array< Vector3f > normal; Array< Vector3f > tangent; Array< Vector3f > binormal; Array< Vector4f > color; Array< Vector2f > uv0; Array< Vector2f > uv1; Array< Vector4f > jointWeights; Array< Vector4i > jointIndices; Array< uint16_t > indices; } newSurface; const JsonReader surface( surface_array.GetNextArrayElement() ); if ( surface.IsObject() ) { const JsonReader source( surface.GetChildByName( "source" ) ); if ( source.IsArray() ) { while ( !source.IsEndOfArray() ) { if ( newSurface.name.GetLength() ) { newSurface.name += ";"; } newSurface.name += source.GetNextArrayString(); } } const JsonReader material( surface.GetChildByName( "material" ) ); if ( material.IsObject() ) { newSurface.materialType = material.GetChildStringByName( "type" ); newSurface.diffuseTexture = material.GetChildInt32ByName( "diffuse", -1 ); newSurface.normalTexture = material.GetChildInt32ByName( "normal", -1 ); newSurface.specularTexture = material.GetChildInt32ByName( "specular", -1 ); newSurface.emissiveTexture = material.GetChildInt32ByName( "emissive", -1 ); } StringUtils::StringTo( newSurface.bounds, surface.GetChildStringByName( "bounds" ) ); // // Vertices // const JsonReader vertices( surface.GetChildByName( "vertices" ) ); if ( vertices.IsObject() ) { const int vertexCount = vertices.GetChildInt32ByName( "vertexCount" ); ReadModelArray( newSurface.position, vertices.GetChildStringByName( "position" ), bin, vertexCount ); ReadModelArray( newSurface.normal, vertices.GetChildStringByName( "normal" ), bin, vertexCount ); ReadModelArray( newSurface.tangent, vertices.GetChildStringByName( "tangent" ), bin, vertexCount ); ReadModelArray( newSurface.binormal, vertices.GetChildStringByName( "binormal" ), bin, vertexCount ); ReadModelArray( newSurface.color, vertices.GetChildStringByName( "color" ), bin, vertexCount ); ReadModelArray( newSurface.uv0, vertices.GetChildStringByName( "uv0" ), bin, vertexCount ); ReadModelArray( newSurface.uv1, vertices.GetChildStringByName( "uv1" ), bin, vertexCount ); ReadModelArray( newSurface.jointIndices, vertices.GetChildStringByName( "jointIndices" ), bin, vertexCount ); ReadModelArray( newSurface.jointWeights, vertices.GetChildStringByName( "jointWeights" ), bin, vertexCount ); } // // Triangles // const JsonReader triangles( surface.GetChildByName( "triangles" ) ); if ( triangles.IsObject() ) { const int indexCount = triangles.GetChildInt32ByName( "indexCount" ); ReadModelArray( newSurface.indices, triangles.GetChildStringByName( "indices" ), bin, indexCount ); } } } } } // // Collision Model // const JsonReader collision_model( models.GetChildByName( "collision_model" ) ); if ( collision_model.IsArray() ) { while ( !collision_model.IsEndOfArray() ) { Array< Planef > planes; const JsonReader polytope( collision_model.GetNextArrayElement() ); if ( polytope.IsObject() ) { const String name = polytope.GetChildStringByName( "name" ); StringUtils::StringTo( planes, polytope.GetChildStringByName( "planes" ) ); } } } // // Ground Collision Model // const JsonReader ground_collision_model( models.GetChildByName( "ground_collision_model" ) ); if ( ground_collision_model.IsArray() ) { while ( !ground_collision_model.IsEndOfArray() ) { Array< Planef > planes; const JsonReader polytope( ground_collision_model.GetNextArrayElement() ); if ( polytope.IsObject() ) { const String name = polytope.GetChildStringByName( "name" ); StringUtils::StringTo( planes, polytope.GetChildStringByName( "planes" ) ); } } } // // Ray-Trace Model // const JsonReader raytrace_model( models.GetChildByName( "raytrace_model" ) ); if ( raytrace_model.IsObject() ) { ModelTrace traceModel; traceModel.header.numVertices = raytrace_model.GetChildInt32ByName( "numVertices" ); traceModel.header.numUvs = raytrace_model.GetChildInt32ByName( "numUvs" ); traceModel.header.numIndices = raytrace_model.GetChildInt32ByName( "numIndices" ); traceModel.header.numNodes = raytrace_model.GetChildInt32ByName( "numNodes" ); traceModel.header.numLeafs = raytrace_model.GetChildInt32ByName( "numLeafs" ); traceModel.header.numOverflow = raytrace_model.GetChildInt32ByName( "numOverflow" ); StringUtils::StringTo( traceModel.header.bounds, raytrace_model.GetChildStringByName( "bounds" ) ); ReadModelArray( traceModel.vertices, raytrace_model.GetChildStringByName( "vertices" ), bin, traceModel.header.numVertices ); ReadModelArray( traceModel.uvs, raytrace_model.GetChildStringByName( "uvs" ), bin, traceModel.header.numUvs ); ReadModelArray( traceModel.indices, raytrace_model.GetChildStringByName( "indices" ), bin, traceModel.header.numIndices ); if ( !bin.ReadArray( traceModel.nodes, traceModel.header.numNodes ) ) { const JsonReader nodes_array( raytrace_model.GetChildByName( "nodes" ) ); if ( nodes_array.IsArray() ) { while ( !nodes_array.IsEndOfArray() ) { const UPInt index = traceModel.nodes.AllocBack(); const JsonReader node( nodes_array.GetNextArrayElement() ); if ( node.IsObject() ) { traceModel.nodes[index].data = (UInt32) node.GetChildInt64ByName( "data" ); traceModel.nodes[index].dist = node.GetChildFloatByName( "dist" ); } } } } if ( !bin.ReadArray( traceModel.leafs, traceModel.header.numLeafs ) ) { const JsonReader leafs_array( raytrace_model.GetChildByName( "leafs" ) ); if ( leafs_array.IsArray() ) { while ( !leafs_array.IsEndOfArray() ) { const UPInt index = traceModel.leafs.AllocBack(); const JsonReader leaf( leafs_array.GetNextArrayElement() ); if ( leaf.IsObject() ) { StringUtils::StringTo( traceModel.leafs[index].triangles, RT_KDTREE_MAX_LEAF_TRIANGLES, leaf.GetChildStringByName( "triangles" ) ); StringUtils::StringTo( traceModel.leafs[index].ropes, 6, leaf.GetChildStringByName( "ropes" ) ); StringUtils::StringTo( traceModel.leafs[index].bounds, leaf.GetChildStringByName( "bounds" ) ); } } } } ReadModelArray( traceModel.overflow, raytrace_model.GetChildStringByName( "overflow" ), bin, traceModel.header.numOverflow ); } } json->Release(); assert( bin.IsAtEnd() ); }