- clean working copy for leaving SVN

This commit is contained in:
2022-06-28 19:04:46 +02:00
parent 62a2d47cb3
commit 762b8f0e7d
1966 changed files with 699872 additions and 126 deletions
@@ -0,0 +1,10 @@
/*
==============================================================================
FragmentShader.cpp
Created: 11 Nov 2014 12:17:53pm
Author: Felix Faire
==============================================================================
*/
@@ -0,0 +1,102 @@
/*
==============================================================================
This file was auto-generated by the Introjucer!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include "../JuceLibraryCode/JuceHeader.h"
Component* createMainContentComponent();
//==============================================================================
class OpenGLAppExampleApplication : public JUCEApplication
{
public:
//==============================================================================
OpenGLAppExampleApplication() {}
const String getApplicationName() override { return ProjectInfo::projectName; }
const String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
//==============================================================================
void initialise (const String& commandLine) override
{
// This method is where you should put your application's initialisation code..
mainWindow = new MainWindow (getApplicationName());
}
void shutdown() override
{
// Add your application's shutdown code here..
mainWindow = nullptr; // (deletes our window)
}
//==============================================================================
void systemRequestedQuit() override
{
// This is called when the app is being asked to quit: you can ignore this
// request and let the app carry on running, or call quit() to allow the app to close.
quit();
}
void anotherInstanceStarted (const String& commandLine) override
{
// When another instance of the app is launched while this one is running,
// this method is invoked, and the commandLine parameter tells you what
// the other instance's command-line arguments were.
}
//==============================================================================
/*
This class implements the desktop window that contains an instance of
our MainContentComponent class.
*/
class MainWindow : public DocumentWindow
{
public:
MainWindow (String name) : DocumentWindow (name,
Colours::lightgrey,
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setContentOwned (createMainContentComponent(), true);
setResizable (true, true);
centreWithSize (getWidth(), getHeight());
setVisible (true);
}
void closeButtonPressed() override
{
// This is called when the user tries to close this window. Here, we'll just
// ask the app to quit when this happens, but you can change this to do
// whatever you need.
JUCEApplication::getInstance()->systemRequestedQuit();
}
/* Note: Be careful if you override any DocumentWindow methods - the base
class uses a lot of them, so by overriding you might break its functionality.
It's best to do all your work in your content component instead, but if
you really have to override any DocumentWindow methods, make sure your
subclass also calls the superclass's method.
*/
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};
private:
ScopedPointer<MainWindow> mainWindow;
};
//==============================================================================
// This macro generates the main() routine that launches the app.
START_JUCE_APPLICATION (OpenGLAppExampleApplication)
@@ -0,0 +1,389 @@
/*
==============================================================================
This file was auto-generated!
==============================================================================
*/
#ifndef MAINCOMPONENT_H_INCLUDED
#define MAINCOMPONENT_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
#include "Resources/WavefrontObjParser.h"
//==============================================================================
/*
This component lives inside our window, and this is where you should put all
your controls and content.
*/
class MainContentComponent : public OpenGLAppComponent
{
public:
//==============================================================================
MainContentComponent()
{
setSize (800, 600);
}
~MainContentComponent()
{
shutdownOpenGL();
}
void initialise() override
{
createShaders();
}
void shutdown() override
{
shader = nullptr;
shape = nullptr;
attributes = nullptr;
uniforms = nullptr;
}
Matrix3D<float> getProjectionMatrix() const
{
float w = 1.0f / (0.5f + 0.1f);
float h = w * getLocalBounds().toFloat().getAspectRatio (false);
return Matrix3D<float>::fromFrustum (-w, w, -h, h, 4.0f, 30.0f);
}
Matrix3D<float> getViewMatrix() const
{
Matrix3D<float> viewMatrix (Vector3D<float> (0.0f, 0.0f, -10.0f));
Matrix3D<float> rotationMatrix
= viewMatrix.rotated (Vector3D<float> (-0.3f, 5.0f * std::sin (getFrameCounter() * 0.01f), 0.0f));
return viewMatrix * rotationMatrix;
}
void render() override
{
jassert (OpenGLHelpers::isContextActive());
const float desktopScale = (float) openGLContext.getRenderingScale();
OpenGLHelpers::clear (Colour::greyLevel (0.1f));
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport (0, 0, roundToInt (desktopScale * getWidth()), roundToInt (desktopScale * getHeight()));
shader->use();
if (uniforms->projectionMatrix != nullptr)
uniforms->projectionMatrix->setMatrix4 (getProjectionMatrix().mat, 1, false);
if (uniforms->viewMatrix != nullptr)
uniforms->viewMatrix->setMatrix4 (getViewMatrix().mat, 1, false);
shape->draw (openGLContext, *attributes);
// Reset the element buffers so child Components draw correctly
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, 0);
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
}
void paint (Graphics& g) override
{
// You can add your component specific drawing code here!
// This will draw over the top of the openGL background.
g.setColour(Colours::white);
g.setFont (20);
g.drawText ("OpenGL Example", 25, 20, 300, 30, Justification::left);
g.drawLine (20, 20, 170, 20);
g.drawLine (20, 50, 170, 50);
}
void resized() override
{
// This is called when the MainContentComponent is resized.
// If you add any child components, this is where you should
// update their positions.
}
void createShaders()
{
vertexShader =
"attribute vec4 position;\n"
"attribute vec4 sourceColour;\n"
"attribute vec2 texureCoordIn;\n"
"\n"
"uniform mat4 projectionMatrix;\n"
"uniform mat4 viewMatrix;\n"
"\n"
"varying vec4 destinationColour;\n"
"varying vec2 textureCoordOut;\n"
"\n"
"void main()\n"
"{\n"
" destinationColour = sourceColour;\n"
" textureCoordOut = texureCoordIn;\n"
" gl_Position = projectionMatrix * viewMatrix * position;\n"
"}\n";
fragmentShader =
#if JUCE_OPENGL_ES
"varying lowp vec4 destinationColour;\n"
"varying lowp vec2 textureCoordOut;\n"
#else
"varying vec4 destinationColour;\n"
"varying vec2 textureCoordOut;\n"
#endif
"\n"
"void main()\n"
"{\n"
" vec4 colour = vec4(0.95, 0.57, 0.03, 0.7);\n"
" gl_FragColor = colour;\n"
"}\n";
ScopedPointer<OpenGLShaderProgram> newShader (new OpenGLShaderProgram (openGLContext));
String statusText;
if (newShader->addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (vertexShader))
&& newShader->addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (fragmentShader))
&& newShader->link())
{
shape = nullptr;
attributes = nullptr;
uniforms = nullptr;
shader = newShader;
shader->use();
shape = new Shape (openGLContext);
attributes = new Attributes (openGLContext, *shader);
uniforms = new Uniforms (openGLContext, *shader);
statusText = "GLSL: v" + String (OpenGLShaderProgram::getLanguageVersion(), 2);
}
else
{
statusText = newShader->getLastError();
}
}
private:
//==============================================================================
struct Vertex
{
float position[3];
float normal[3];
float colour[4];
float texCoord[2];
};
//==============================================================================
// This class just manages the attributes that the shaders use.
struct Attributes
{
Attributes (OpenGLContext& openGLContext, OpenGLShaderProgram& shader)
{
position = createAttribute (openGLContext, shader, "position");
normal = createAttribute (openGLContext, shader, "normal");
sourceColour = createAttribute (openGLContext, shader, "sourceColour");
texureCoordIn = createAttribute (openGLContext, shader, "texureCoordIn");
}
void enable (OpenGLContext& openGLContext)
{
if (position != nullptr)
{
openGLContext.extensions.glVertexAttribPointer (position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), 0);
openGLContext.extensions.glEnableVertexAttribArray (position->attributeID);
}
if (normal != nullptr)
{
openGLContext.extensions.glVertexAttribPointer (normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3));
openGLContext.extensions.glEnableVertexAttribArray (normal->attributeID);
}
if (sourceColour != nullptr)
{
openGLContext.extensions.glVertexAttribPointer (sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6));
openGLContext.extensions.glEnableVertexAttribArray (sourceColour->attributeID);
}
if (texureCoordIn != nullptr)
{
openGLContext.extensions.glVertexAttribPointer (texureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10));
openGLContext.extensions.glEnableVertexAttribArray (texureCoordIn->attributeID);
}
}
void disable (OpenGLContext& openGLContext)
{
if (position != nullptr) openGLContext.extensions.glDisableVertexAttribArray (position->attributeID);
if (normal != nullptr) openGLContext.extensions.glDisableVertexAttribArray (normal->attributeID);
if (sourceColour != nullptr) openGLContext.extensions.glDisableVertexAttribArray (sourceColour->attributeID);
if (texureCoordIn != nullptr) openGLContext.extensions.glDisableVertexAttribArray (texureCoordIn->attributeID);
}
ScopedPointer<OpenGLShaderProgram::Attribute> position, normal, sourceColour, texureCoordIn;
private:
static OpenGLShaderProgram::Attribute* createAttribute (OpenGLContext& openGLContext,
OpenGLShaderProgram& shader,
const char* attributeName)
{
if (openGLContext.extensions.glGetAttribLocation (shader.getProgramID(), attributeName) < 0)
return nullptr;
return new OpenGLShaderProgram::Attribute (shader, attributeName);
}
};
//==============================================================================
// This class just manages the uniform values that the demo shaders use.
struct Uniforms
{
Uniforms (OpenGLContext& openGLContext, OpenGLShaderProgram& shader)
{
projectionMatrix = createUniform (openGLContext, shader, "projectionMatrix");
viewMatrix = createUniform (openGLContext, shader, "viewMatrix");
}
ScopedPointer<OpenGLShaderProgram::Uniform> projectionMatrix, viewMatrix;
private:
static OpenGLShaderProgram::Uniform* createUniform (OpenGLContext& openGLContext,
OpenGLShaderProgram& shader,
const char* uniformName)
{
if (openGLContext.extensions.glGetUniformLocation (shader.getProgramID(), uniformName) < 0)
return nullptr;
return new OpenGLShaderProgram::Uniform (shader, uniformName);
}
};
//==============================================================================
/** This loads a 3D model from an OBJ file and converts it into some vertex buffers
that we can draw.
*/
struct Shape
{
Shape (OpenGLContext& openGLContext)
{
if (shapeFile.load (BinaryData::teapot_obj).wasOk())
for (int i = 0; i < shapeFile.shapes.size(); ++i)
vertexBuffers.add (new VertexBuffer (openGLContext, *shapeFile.shapes.getUnchecked(i)));
}
void draw (OpenGLContext& openGLContext, Attributes& attributes)
{
for (int i = 0; i < vertexBuffers.size(); ++i)
{
VertexBuffer& vertexBuffer = *vertexBuffers.getUnchecked (i);
vertexBuffer.bind();
attributes.enable (openGLContext);
glDrawElements (GL_TRIANGLES, vertexBuffer.numIndices, GL_UNSIGNED_INT, 0);
attributes.disable (openGLContext);
}
}
private:
struct VertexBuffer
{
VertexBuffer (OpenGLContext& context, WavefrontObjFile::Shape& shape) : openGLContext (context)
{
numIndices = shape.mesh.indices.size();
openGLContext.extensions.glGenBuffers (1, &vertexBuffer);
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
Array<Vertex> vertices;
createVertexListFromMesh (shape.mesh, vertices, Colours::green);
openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER, vertices.size() * sizeof (Vertex),
vertices.getRawDataPointer(), GL_STATIC_DRAW);
openGLContext.extensions.glGenBuffers (1, &indexBuffer);
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
openGLContext.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof (juce::uint32),
shape.mesh.indices.getRawDataPointer(), GL_STATIC_DRAW);
}
~VertexBuffer()
{
openGLContext.extensions.glDeleteBuffers (1, &vertexBuffer);
openGLContext.extensions.glDeleteBuffers (1, &indexBuffer);
}
void bind()
{
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
}
GLuint vertexBuffer, indexBuffer;
int numIndices;
OpenGLContext& openGLContext;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VertexBuffer)
};
WavefrontObjFile shapeFile;
OwnedArray<VertexBuffer> vertexBuffers;
static void createVertexListFromMesh (const WavefrontObjFile::Mesh& mesh, Array<Vertex>& list, Colour colour)
{
const float scale = 0.2f;
WavefrontObjFile::TextureCoord defaultTexCoord = { 0.5f, 0.5f };
WavefrontObjFile::Vertex defaultNormal = { 0.5f, 0.5f, 0.5f };
for (int i = 0; i < mesh.vertices.size(); ++i)
{
const WavefrontObjFile::Vertex& v = mesh.vertices.getReference (i);
const WavefrontObjFile::Vertex& n
= i < mesh.normals.size() ? mesh.normals.getReference (i) : defaultNormal;
const WavefrontObjFile::TextureCoord& tc
= i < mesh.textureCoords.size() ? mesh.textureCoords.getReference (i) : defaultTexCoord;
Vertex vert =
{
{ scale * v.x, scale * v.y, scale * v.z, },
{ scale * n.x, scale * n.y, scale * n.z, },
{ colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha() },
{ tc.x, tc.y }
};
list.add (vert);
}
}
};
const char* vertexShader;
const char* fragmentShader;
ScopedPointer<OpenGLShaderProgram> shader;
ScopedPointer<Shape> shape;
ScopedPointer<Attributes> attributes;
ScopedPointer<Uniforms> uniforms;
String newVertexShader, newFragmentShader;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};
// (This function is called by the app startup code to create our main component)
Component* createMainContentComponent() { return new MainContentComponent(); }
#endif // MAINCOMPONENT_H_INCLUDED
@@ -0,0 +1,359 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-12 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include <map>
//==============================================================================
/**
This is a quick-and-dirty parser for the 3D OBJ file format.
Just call load() and if there aren't any errors, the 'shapes' array should
be filled with all the shape objects that were loaded from the file.
*/
class WavefrontObjFile
{
public:
WavefrontObjFile() {}
Result load (const String& objFileContent)
{
shapes.clear();
return parseObjFile (StringArray::fromLines (objFileContent));
}
Result load (const File& file)
{
sourceFile = file;
return load (file.loadFileAsString());
}
//==============================================================================
typedef juce::uint32 Index;
struct Vertex { float x, y, z; };
struct TextureCoord { float x, y; };
struct Mesh
{
Array<Vertex> vertices, normals;
Array<TextureCoord> textureCoords;
Array<Index> indices;
};
struct Material
{
Material() noexcept : shininess (1.0f), refractiveIndex (0.0f)
{
zerostruct (ambient);
zerostruct (diffuse);
zerostruct (specular);
zerostruct (transmittance);
zerostruct (emission);
}
String name;
Vertex ambient, diffuse, specular, transmittance, emission;
float shininess, refractiveIndex;
String ambientTextureName, diffuseTextureName,
specularTextureName, normalTextureName;
StringPairArray parameters;
};
struct Shape
{
String name;
Mesh mesh;
Material material;
};
OwnedArray<Shape> shapes;
private:
//==============================================================================
File sourceFile;
struct TripleIndex
{
TripleIndex() noexcept : vertexIndex (-1), textureIndex (-1), normalIndex (-1) {}
bool operator< (const TripleIndex& other) const noexcept { return vertexIndex < other.vertexIndex; }
int vertexIndex, textureIndex, normalIndex;
};
struct IndexMap
{
std::map<TripleIndex, Index> map;
Index getIndexFor (TripleIndex i, Mesh& newMesh, const Mesh& srcMesh)
{
const std::map<TripleIndex, Index>::iterator it (map.find (i));
if (it != map.end())
return it->second;
const Index index = (Index) newMesh.vertices.size();
if (isPositiveAndBelow (i.vertexIndex, srcMesh.vertices.size()))
newMesh.vertices.add (srcMesh.vertices.getReference (i.vertexIndex));
if (isPositiveAndBelow (i.normalIndex, srcMesh.normals.size()))
newMesh.normals.add (srcMesh.normals.getReference (i.normalIndex));
if (isPositiveAndBelow (i.textureIndex, srcMesh.textureCoords.size()))
newMesh.textureCoords.add (srcMesh.textureCoords.getReference (i.textureIndex));
map[i] = index;
return index;
}
};
static float parseFloat (String::CharPointerType& t)
{
t = t.findEndOfWhitespace();
return (float) CharacterFunctions::readDoubleValue (t);
}
static Vertex parseVertex (String::CharPointerType t)
{
Vertex v;
v.x = parseFloat (t);
v.y = parseFloat (t);
v.z = parseFloat (t);
return v;
}
static TextureCoord parseTextureCoord (String::CharPointerType t)
{
TextureCoord tc;
tc.x = parseFloat (t);
tc.y = parseFloat (t);
return tc;
}
static bool matchToken (String::CharPointerType& t, const char* token)
{
const int len = (int) strlen (token);
if (CharacterFunctions::compareUpTo (CharPointer_ASCII (token), t, len) == 0)
{
String::CharPointerType end = t + len;
if (end.isEmpty() || end.isWhitespace())
{
t = end.findEndOfWhitespace();
return true;
}
}
return false;
}
struct Face
{
Face (String::CharPointerType t)
{
while (! t.isEmpty())
triples.add (parseTriple (t));
}
Array<TripleIndex> triples;
void addIndices (Mesh& newMesh, const Mesh& srcMesh, IndexMap& indexMap)
{
TripleIndex i0 (triples[0]), i1, i2 (triples[1]);
for (int i = 2; i < triples.size(); ++i)
{
i1 = i2;
i2 = triples.getReference (i);
newMesh.indices.add (indexMap.getIndexFor (i0, newMesh, srcMesh));
newMesh.indices.add (indexMap.getIndexFor (i1, newMesh, srcMesh));
newMesh.indices.add (indexMap.getIndexFor (i2, newMesh, srcMesh));
}
}
static TripleIndex parseTriple (String::CharPointerType& t)
{
TripleIndex i;
t = t.findEndOfWhitespace();
i.vertexIndex = t.getIntValue32() - 1;
t = findEndOfFaceToken (t);
if (t.isEmpty() || t.getAndAdvance() != '/')
return i;
if (*t == '/')
{
++t;
}
else
{
i.textureIndex = t.getIntValue32() - 1;
t = findEndOfFaceToken (t);
if (t.isEmpty() || t.getAndAdvance() != '/')
return i;
}
i.normalIndex = t.getIntValue32() - 1;
t = findEndOfFaceToken (t);
return i;
}
static String::CharPointerType findEndOfFaceToken (String::CharPointerType t) noexcept
{
return CharacterFunctions::findEndOfToken (t, CharPointer_ASCII ("/ \t"), String::empty.getCharPointer());
}
};
static Shape* parseFaceGroup (const Mesh& srcMesh,
const Array<Face>& faceGroup,
const Material& material,
const String& name)
{
if (faceGroup.size() == 0)
return nullptr;
ScopedPointer<Shape> shape (new Shape());
shape->name = name;
shape->material = material;
IndexMap indexMap;
for (int i = 0; i < faceGroup.size(); ++i)
faceGroup.getReference(i).addIndices (shape->mesh, srcMesh, indexMap);
return shape.release();
}
Result parseObjFile (const StringArray& lines)
{
Mesh mesh;
Array<Face> faceGroup;
Array<Material> knownMaterials;
Material lastMaterial;
String lastName;
for (int lineNum = 0; lineNum < lines.size(); ++lineNum)
{
String::CharPointerType l = lines[lineNum].getCharPointer().findEndOfWhitespace();
if (matchToken (l, "v")) { mesh.vertices.add (parseVertex (l)); continue; }
if (matchToken (l, "vn")) { mesh.normals.add (parseVertex (l)); continue; }
if (matchToken (l, "vt")) { mesh.textureCoords.add (parseTextureCoord (l)); continue; }
if (matchToken (l, "f")) { faceGroup.add (Face (l)); continue; }
if (matchToken (l, "usemtl"))
{
const String name (String (l).trim());
for (int i = knownMaterials.size(); --i >= 0;)
{
if (knownMaterials.getReference(i).name == name)
{
lastMaterial = knownMaterials.getReference(i);
break;
}
}
continue;
}
if (matchToken (l, "mtllib"))
{
Result r = parseMaterial (knownMaterials, String (l).trim());
continue;
}
if (matchToken (l, "g") || matchToken (l, "o"))
{
if (Shape* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName))
shapes.add (shape);
faceGroup.clear();
lastName = StringArray::fromTokens (l, " \t", "")[0];
continue;
}
}
if (Shape* shape = parseFaceGroup (mesh, faceGroup, lastMaterial, lastName))
shapes.add (shape);
return Result::ok();
}
Result parseMaterial (Array<Material>& materials, const String& filename)
{
jassert (sourceFile.exists());
File f (sourceFile.getSiblingFile (filename));
if (! f.exists())
return Result::fail ("Cannot open file: " + filename);
StringArray lines;
lines.addLines (f.loadFileAsString());
materials.clear();
Material material;
for (int i = 0; i < lines.size(); ++i)
{
String::CharPointerType l (lines[i].getCharPointer().findEndOfWhitespace());
if (matchToken (l, "newmtl")) { materials.add (material); material.name = String (l).trim(); continue; }
if (matchToken (l, "Ka")) { material.ambient = parseVertex (l); continue; }
if (matchToken (l, "Kd")) { material.diffuse = parseVertex (l); continue; }
if (matchToken (l, "Ks")) { material.specular = parseVertex (l); continue; }
if (matchToken (l, "Kt")) { material.transmittance = parseVertex (l); continue; }
if (matchToken (l, "Ke")) { material.emission = parseVertex (l); continue; }
if (matchToken (l, "Ni")) { material.refractiveIndex = parseFloat (l); continue; }
if (matchToken (l, "Ns")) { material.shininess = parseFloat (l); continue; }
if (matchToken (l, "map_Ka")) { material.ambientTextureName = String (l).trim(); continue; }
if (matchToken (l, "map_Kd")) { material.diffuseTextureName = String (l).trim(); continue; }
if (matchToken (l, "map_Ks")) { material.specularTextureName = String (l).trim(); continue; }
if (matchToken (l, "map_Ns")) { material.normalTextureName = String (l).trim(); continue; }
StringArray tokens;
tokens.addTokens (l, " \t", "");
if (tokens.size() >= 2)
material.parameters.set (tokens[0].trim(), tokens[1].trim());
}
materials.add (material);
return Result::ok();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavefrontObjFile)
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,9 @@
/*
==============================================================================
VertexShader.cpp
Created: 11 Nov 2014 12:17:40pm
Author: Felix Faire
==============================================================================
*/