Using D3, I want to create a polar graph like this figure.
Following the volcano example, I can get the contour correctly rendered.
How do I translate the contours onto a circle to create a polar graph?
Update:
The initial data I'm using is a 2d array, where the first dimension (array[n]) represents period and the second dimension (array[n][0]) represents force. See below for a sample of data and the code I'm using to draw the contour graph.
function draw(spectrumData: Swell["spectrum"]): void {
if (!spectrumData) {
console.warn("spectrumData is undefined");
return;
}
const { spectrum, width, height } = transformSpectrum(spectrumData);
const sizeFactor = 13;
const svg = d3
.select("#spectrum-contour")
.attr("width", width * sizeFactor)
.attr("height", height * sizeFactor);
// Ret the contour size
var contour = d3Contour.contours().size([width, height]);
// Returns "rgb(x, y, z)"
const interpolator = (t: number): string => {
const i0 = d3Hsv.interpolateHsvLong(
d3Hsv.hsv(240, 0.77, 0.73),
d3Hsv.hsv(114, 0.77, 0.73)
);
const i1 = d3Hsv.interpolateHsvLong(
d3Hsv.hsv(114, 0.77, 0.73),
d3Hsv.hsv(0, 0.77, 0.73)
);
return t < 0.2 ? i0(t * 2) : i1((t - 0.2) * 2);
};
const colorScale = d3Scale
.scaleSequential(interpolator)
// extent returns [min, max]
.domain(d3.extent(spectrum));
const path: any = d3Geo.geoPath(
d3Geo.geoIdentity().scale((width * sizeFactor) / width)
);
// draw the contours
svg
.selectAll("path")
.data(contour(spectrum))
.enter()
.append("path")
.attr("d", (feature) => path(feature))
.attr("fill", (d) => colorScale(d.value));
}
// Transform the 2D spectrum array to a 1D array
// and replace negative values with zeros.
function transformSpectrum(data: Swell["spectrum"]): TransformedSpectrum {
const array1d = ([] as number[]).concat.apply([], data);
return {
width: data[0].length,
height: data.length,
spectrum: array1d.map((i) => (i >= 0 ? i : 0)),
};
}
"spectrum": [
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ],
[ 0.0002, 0.0003, 0.0003, 0.0003, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0003, 0.0003, 0.0003, 0.0003, 0.0002, 0.0002, 0.0002, 0.0002, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002, 0.0002, 0.0002, 0.0003, 0.0003, 0.0003, 0.0004, 0.0004, 0.0005, 0.0005, 0.0006, 0.0006, 0.0007, 0.0007, 0.0007 ],
[ 0.0001, 0.0001, 0.0002, 0.0002, 0.0003, 0.0003, 0.0004, 0.0004, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0005, 0.0005, 0.0005, 0.0006, 0.0006, 0.0007, 0.0007, 0.0007, 0.0008, 0.0008 ],
[ 0.0003, 0.0003, 0.0002, 0.0002, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0009, 0.001, 0.0011, 0.0013, 0.0014, 0.0015, 0.0016, 0.0017, 0.0018, 0.0018, 0.0018, 0.0019, 0.0018, 0.0018, 0.0018, 0.0017, 0.0016, 0.0015, 0.0014, 0.0013, 0.0011, 0.001, 0.0008, 0.0007 ],
[ 0.0007, 0.0007, 0.0006, 0.0006, 0.0006, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0006, 0.0006, 0.0007, 0.0008, 0.0009, 0.001, 0.0011, 0.0012, 0.0013, 0.0015, 0.0016, 0.0016, 0.0017, 0.0018, 0.0018, 0.0019, 0.0019, 0.0018, 0.0018, 0.0018, 0.0017, 0.0016, 0.0015, 0.0014, 0.0012, 0.0011, 0.001, 0.0008 ],
[ 0.0007, 0.0006, 0.0005, 0.0004, 0.0004, 0.0003, 0.0002, 0.0002, 0.0002, 0.0002, 0.0002, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0008, 0.001, 0.0012, 0.0013, 0.0015, 0.0017, 0.0018, 0.002, 0.0021, 0.0022, 0.0023, 0.0023, 0.0023, 0.0024, 0.0023, 0.0023, 0.0022, 0.0021, 0.002, 0.0019, 0.0017, 0.0016, 0.0014 ],
[ 0.0001, 0.0001, 0.0002, 0.0002, 0.0003, 0.0004, 0.0006, 0.0007, 0.0009, 0.0011, 0.0013, 0.0016, 0.0018, 0.0021, 0.0023, 0.0026, 0.0029, 0.0032, 0.0034, 0.0037, 0.0039, 0.0041, 0.0042, 0.0044, 0.0045, 0.0045, 0.0046, 0.0046, 0.0045, 0.0044, 0.0043, 0.0042, 0.004, 0.0038, 0.0036, 0.0034, 0.0031, 0.0029, 0.0026, 0.0024 ],
[ 0.0014, 0.001, 0.0006, 0.0003, 0.0, -0.0002, -0.0003, -0.0003, -0.0001, 0.0003, 0.0008, 0.0015, 0.0024, 0.0035, 0.0047, 0.0061, 0.0076, 0.0092, 0.0109, 0.0126, 0.0143, 0.016, 0.0175, 0.019, 0.0203, 0.0214, 0.0224, 0.023, 0.0235, 0.0236, 0.0235, 0.0231, 0.0224, 0.0215, 0.0204, 0.019, 0.0175, 0.0158, 0.014, 0.0122 ],
[ 0.0036, 0.0023, 0.0009, -0.0005, -0.0019, -0.0033, -0.0045, -0.0054, -0.006, -0.0062, -0.0061, -0.0054, -0.0043, -0.0027, -0.0005, 0.0021, 0.0052, 0.0086, 0.0124, 0.0165, 0.0207, 0.0251, 0.0294, 0.0336, 0.0376, 0.0413, 0.0447, 0.0475, 0.0498, 0.0516, 0.0526, 0.0531, 0.0528, 0.0519, 0.0503, 0.0481, 0.0453, 0.0421, 0.0385, 0.0345 ],
[ 0.0031, 0.0022, 0.0013, 0.0003, -0.0008, -0.0018, -0.0027, -0.0035, -0.0041, -0.0045, -0.0046, -0.0044, -0.0039, -0.0029, -0.0016, 0.0, 0.002, 0.0043, 0.0069, 0.0098, 0.0128, 0.0159, 0.0191, 0.0222, 0.0253, 0.0282, 0.0309, 0.0333, 0.0353, 0.0369, 0.038, 0.0387, 0.0389, 0.0386, 0.0378, 0.0366, 0.0349, 0.0328, 0.0304, 0.0277 ],
[ 0.001, -0.0001, -0.0012, -0.0022, -0.0032, -0.0039, -0.0045, -0.0047, -0.0047, -0.0044, -0.0038, -0.0027, -0.0014, 0.0003, 0.0022, 0.0044, 0.0069, 0.0095, 0.0122, 0.015, 0.0177, 0.0204, 0.0229, 0.0252, 0.0272, 0.0289, 0.0302, 0.0311, 0.0316, 0.0316, 0.0312, 0.0303, 0.029, 0.0274, 0.0254, 0.0231, 0.0205, 0.0178, 0.015, 0.0121 ],
[ -0.0002, -0.0006, -0.001, -0.0014, -0.0017, -0.0019, -0.002, -0.0019, -0.0018, -0.0015, -0.0011, -0.0005, 0.0001, 0.0009, 0.0019, 0.0029, 0.0039, 0.0051, 0.0062, 0.0073, 0.0085, 0.0095, 0.0105, 0.0114, 0.0121, 0.0127, 0.0131, 0.0134, 0.0135, 0.0134, 0.0131, 0.0126, 0.012, 0.0113, 0.0104, 0.0094, 0.0084, 0.0072, 0.0061, 0.005 ],
[ 0.0003, 0.0, -0.0004, -0.0007, -0.001, -0.0013, -0.0015, -0.0016, -0.0016, -0.0015, -0.0012, -0.0009, -0.0004, 0.0002, 0.0009, 0.0017, 0.0026, 0.0035, 0.0045, 0.0056, 0.0067, 0.0077, 0.0087, 0.0096, 0.0105, 0.0112, 0.0119, 0.0123, 0.0127, 0.0128, 0.0128, 0.0127, 0.0124, 0.0119, 0.0113, 0.0105, 0.0097, 0.0088, 0.0078, 0.0067 ],
[ -0.0003, -0.0004, -0.0005, -0.0005, -0.0005, -0.0005, -0.0004, -0.0003, -0.0002, 0.0, 0.0002, 0.0005, 0.0008, 0.0011, 0.0014, 0.0018, 0.0021, 0.0025, 0.0028, 0.0032, 0.0035, 0.0038, 0.004, 0.0042, 0.0044, 0.0045, 0.0046, 0.0046, 0.0046, 0.0045, 0.0044, 0.0042, 0.004, 0.0037, 0.0035, 0.0032, 0.0028, 0.0025, 0.0022, 0.0019 ],
[ -0.0004, -0.0006, -0.0008, -0.0009, -0.001, -0.0011, -0.0011, -0.001, -0.0009, -0.0007, -0.0004, -0.0001, 0.0003, 0.0008, 0.0013, 0.0019, 0.0024, 0.003, 0.0036, 0.0042, 0.0048, 0.0053, 0.0057, 0.0062, 0.0065, 0.0067, 0.0069, 0.007, 0.007, 0.0069, 0.0067, 0.0064, 0.0061, 0.0057, 0.0052, 0.0047, 0.0041, 0.0036, 0.003, 0.0024 ],
[ -0.0001, -0.0002, -0.0004, -0.0005, -0.0006, -0.0007, -0.0007, -0.0007, -0.0007, -0.0006, -0.0005, -0.0003, -0.0001, 0.0002, 0.0005, 0.0009, 0.0013, 0.0017, 0.0021, 0.0026, 0.003, 0.0034, 0.0038, 0.0042, 0.0045, 0.0048, 0.005, 0.0051, 0.0052, 0.0053, 0.0052, 0.0051, 0.005, 0.0048, 0.0045, 0.0042, 0.0038, 0.0034, 0.003, 0.0026 ],
[ -0.0003, -0.0003, -0.0003, -0.0003, -0.0003, -0.0002, -0.0002, -0.0001, 0.0, 0.0001, 0.0002, 0.0004, 0.0005, 0.0007, 0.0009, 0.0011, 0.0013, 0.0015, 0.0017, 0.0018, 0.002, 0.0021, 0.0023, 0.0024, 0.0025, 0.0025, 0.0025, 0.0026, 0.0025, 0.0025, 0.0024, 0.0023, 0.0022, 0.0021, 0.002, 0.0018, 0.0017, 0.0015, 0.0014, 0.0012 ],
[ -0.0002, -0.0002, -0.0002, -0.0001, -0.0001, -0.0001, 0.0, 0.0, 0.0001, 0.0002, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0008, 0.0008, 0.0009, 0.001, 0.0011, 0.0011, 0.0011, 0.0012, 0.0012, 0.0012, 0.0012, 0.0012, 0.0011, 0.0011, 0.0011, 0.001, 0.001, 0.0009, 0.0008, 0.0008, 0.0007, 0.0006, 0.0006, 0.0005 ],
[ -0.0001, -0.0001, -0.0002, -0.0001, -0.0001, -0.0001, -0.0001, 0.0, 0.0, 0.0001, 0.0002, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0008, 0.0009, 0.001, 0.0011, 0.0011, 0.0012, 0.0012, 0.0013, 0.0013, 0.0013, 0.0013, 0.0012, 0.0012, 0.0012, 0.0011, 0.0011, 0.001, 0.0009, 0.0008, 0.0008, 0.0007, 0.0006, 0.0005 ],
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0001, 0.0001, 0.0002, 0.0002, 0.0003, 0.0003, 0.0004, 0.0005, 0.0006, 0.0006, 0.0007, 0.0008, 0.0009, 0.001, 0.0011, 0.0011, 0.0012, 0.0013, 0.0013, 0.0014, 0.0014, 0.0014, 0.0014, 0.0015, 0.0014, 0.0014, 0.0014, 0.0014, 0.0013, 0.0013, 0.0012, 0.0012, 0.0011, 0.001, 0.0009 ],
[ -0.0002, -0.0002, -0.0002, -0.0002, -0.0002, -0.0001, -0.0001, -0.0001, 0.0, 0.0001, 0.0002, 0.0002, 0.0003, 0.0004, 0.0005, 0.0007, 0.0008, 0.0009, 0.001, 0.0011, 0.0011, 0.0012, 0.0013, 0.0013, 0.0014, 0.0014, 0.0014, 0.0014, 0.0013, 0.0013, 0.0012, 0.0012, 0.0011, 0.001, 0.0009, 0.0008, 0.0007, 0.0006, 0.0005, 0.0005 ],
[ 0.0002, 0.0002, 0.0002, 0.0001, 0.0001, 0.0, 0.0, 0.0, -0.0001, -0.0001, -0.0001, -0.0001, -0.0001, -0.0001, -0.0001, -0.0001, 0.0, 0.0001, 0.0001, 0.0002, 0.0004, 0.0005, 0.0006, 0.0007, 0.0009, 0.001, 0.0011, 0.0012, 0.0013, 0.0014, 0.0015, 0.0015, 0.0016, 0.0016, 0.0016, 0.0016, 0.0015, 0.0015, 0.0014, 0.0013 ],
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002, 0.0002, 0.0002, 0.0002, 0.0003, 0.0003, 0.0004, 0.0004, 0.0005, 0.0005, 0.0005, 0.0006, 0.0006, 0.0007, 0.0007, 0.0007, 0.0008, 0.0008, 0.0008, 0.0008, 0.0008, 0.0008, 0.0008, 0.0008, 0.0007, 0.0007 ],
[ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0001, 0.0001, 0.0001, 0.0001, 0.0002, 0.0002, 0.0002, 0.0003, 0.0003, 0.0003, 0.0003, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0004, 0.0003, 0.0003, 0.0003, 0.0003, 0.0002 ]
],
Update 2
Using the suggestion below I was able to translate the coordinates with the following:
const path: any = d3Geo.geoPath(
d3Geo.geoTransform({
point: function (x, y) {
const [x2, y2] = polarPoint(x, y);
this.stream.point(x2, y2);
},
})
);
Given your polar plot innerRadius, outerRadius, domainRange (range of arguments), and valueRange (range of values), the polar coordinates of each point (arg, value) are calculated the following way:
const polarPoint = (arg, value) => {
const angle = (arg - domainRange.min) /
(domainRange.max - domainRange.min) * Math.PI * 2;
const radius = (value - valueRange.min) /
(valueRange.max - valueRange.min) * (outerRadius - innerRadius) + innerRadius;
const x = radius * Math.sin(angle);
const y = -radius * Math.cos(angle);
return {x, y};
}
See the snippet as illustration:
const domainRange = {min: 0, max: 100}; // Range of arguments
const valueRange = {min: 0, max: 1000}; // Range of values
const plotWidth = 200; // Width of the cartesian plot
const plotHeight = 100; // Height of the cartesian plot
const innerRadius = 20; // Inner radius of the polar plot
const outerRadius = 100; // Outer radius of the polar plot
const values = [[0, 100],[10,400],[20,700],[30,750],[40,900],[50,600],[60,400],[70,350],[80,300],[90,250],[100,100]]; // pairs of arguments/values
const cartesianPoint = (arg, value) => {
const x = (arg - domainRange.min) / (domainRange.max - domainRange.min) * plotWidth;
const y = -(value - valueRange.min) / (valueRange.max - valueRange.min) * plotHeight;
return {x, y};
};
const polarPoint = (arg, value) => {
const angle = (arg - domainRange.min) / (domainRange.max - domainRange.min) * Math.PI * 2;
const radius = (value - valueRange.min) / (valueRange.max - valueRange.min) * (outerRadius - innerRadius) + innerRadius;
const x = radius * Math.sin(angle);
const y = -radius * Math.cos(angle);
return {x, y};
}
const svg = d3.select('svg');
const cartesianPlot = svg.append('g')
.attr('transform', 'translate(20, 150)');
cartesianPlot.append('rect')
.attr('x', 0)
.attr('y', -plotHeight)
.attr('width', plotWidth)
.attr('height', plotHeight)
.style('fill', '#eee');
let prev = null;
values.forEach(v => {
const point = cartesianPoint(v[0], v[1]);
cartesianPlot.append('circle')
.attr('cx', point.x)
.attr('cy', point.y)
.attr('r', 3)
.style('fill', 'red');
if (prev)
cartesianPlot.append('line')
.attr('x1', prev.x)
.attr('y1', prev.y)
.attr('x2', point.x)
.attr('y2', point.y)
.style('stroke', 'blue')
prev = point;
})
const polarPlot = svg.append('g')
.attr('transform', 'translate(350, 120)');
polarPlot.append('circle')
.attr('r', outerRadius)
.style('fill', '#eee')
polarPlot.append('circle')
.attr('r', innerRadius)
.style('fill', '#fff')
prev = null;
values.forEach(v => {
const point = polarPoint(v[0], v[1]);
polarPlot.append('circle')
.attr('cx', point.x)
.attr('cy', point.y)
.attr('r', 3)
.style('fill', 'red');
if (prev)
polarPlot.append('line')
.attr('x1', prev.x)
.attr('y1', prev.y)
.attr('x2', point.x)
.attr('y2', point.y)
.style('stroke', 'blue')
prev = point;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="250" />
I created a simple 3D cube object using blender and used Jeff Lamarche's blender export to store it in a header file and added it into my project. However I am having trouble rendering it.
header file:
//If not using MC3D, change 1 to 0 to add needed types
#if 0
#import "MC3DTypes.h"
#else
struct texCoord
{
GLfloat u;
GLfloat v;
};
typedef struct texCoord texCoord;
typedef texCoord* texCoordPtr;
typedef struct vec2 vec2;
typedef vec2* vec2Ptr;
struct vec3
{
GLfloat x;
GLfloat y;
GLfloat z;
};
typedef struct vec3 vec3;
typedef vec3* vec3Ptr;
struct vec4
{
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
};
typedef struct vec4 vec4;
typedef vec4* vec4Ptr;
#endif
struct vertexData
{
vec3 vertex;
vec3 normal;
};
typedef struct vertexData vertexData;
typedef vertexData* vertexDataPtr;
static const vertexData MeshVertexData[] = {
{/*v:*/{1.000000, -1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, -0.577349} },
{/*v:*/{1.000000, -1.000000, 1.000000}, /*n:*/{0.577349, -0.577349, -0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
{/*v:*/{1.000000, 1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, 0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{0.999999, 1.000000, 1.000001}, /*n:*/{0.577349, -0.577349, 0.577349} },
{/*v:*/{1.000000, -1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, -0.577349} },
{/*v:*/{1.000000, 1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, 0.577349} },
{/*v:*/{1.000000, -1.000000, 1.000000}, /*n:*/{0.577349, -0.577349, -0.577349} },
{/*v:*/{1.000000, -1.000000, 1.000000}, /*n:*/{0.577349, -0.577349, -0.577349} },
{/*v:*/{0.999999, 1.000000, 1.000001}, /*n:*/{0.577349, -0.577349, 0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
{/*v:*/{-1.000000, 1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, 0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{1.000000, 1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, 0.577349} },
{/*v:*/{1.000000, -1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, -0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{-1.000000, -1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, -0.577349} },
{/*v:*/{1.000000, -1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, -0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
{/*v:*/{1.000000, 1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, 0.577349} },
{/*v:*/{0.999999, 1.000000, 1.000001}, /*n:*/{0.577349, -0.577349, 0.577349} },
{/*v:*/{1.000000, -1.000000, 1.000000}, /*n:*/{0.577349, -0.577349, -0.577349} },
{/*v:*/{1.000000, -1.000000, -1.000000}, /*n:*/{0.577349, 0.577349, -0.577349} },
{/*v:*/{-1.000000, -1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, -0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{-1.000000, 1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, 0.577349} },
{/*v:*/{0.999999, 1.000000, 1.000001}, /*n:*/{0.577349, -0.577349, 0.577349} },
{/*v:*/{-1.000000, -1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, -0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
{/*v:*/{-1.000000, 1.000000, -1.000000}, /*n:*/{-0.577349, 0.577349, 0.577349} },
{/*v:*/{0.999999, 1.000000, 1.000001}, /*n:*/{0.577349, -0.577349, 0.577349} },
{/*v:*/{-1.000000, 1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, 0.577349} },
{/*v:*/{-1.000000, -1.000000, 1.000000}, /*n:*/{-0.577349, -0.577349, -0.577349} },
};
// Example OpenGL ES 1.1 Drawing Code:
// glEnableClientState(GL_VERTEX_ARRAY);
// glEnableClientState(GL_NORMAL_ARRAY);
// glVertexPointer(3, GL_FLOAT, sizeof(VertexData3D), &MeshVertexData[0].vertex);
// glNormalPointer(GL_FLOAT, sizeof(VertexData3D), &MeshVertexData[0].normal);
// glDrawArrays(GL_TRIANGLES, 0, kMeshNumberOfVertices);
// glDisableClientState(GL_VERTEX_ARRAY);
// glDisableClientState(GL_NORMAL_ARRAY);
And here is the code I am using:
//
// ES1Renderer.m
// glTestingGround
//
// Created by David Jacobs on 3/8/10.
// Copyright Stanford University 2010. All rights reserved.
//
#import "ES1Renderer.h"
#import "banana.h"
#import "PVRTexture.h"
#import "cubefr.h"
#define BUFFER_OFFSET(x)((char *)NULL+(x))
#implementation ES1Renderer
// Create an ES 1.1 context
- (id) init
{
if (self = [super init])
{
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context])
{
[self release];
return nil;
}
// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
glGenFramebuffersOES(1, &defaultFramebuffer);
glGenRenderbuffersOES(1, &colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
glEnable(GL_CULL_FACE);
glEnable(GL_CCW);
// ###################### Texture Demo #################################
/*NSString * path = [[NSBundle mainBundle] pathForResource: #"banana" ofType:#"pvrtc"];
texture = [[PVRTexture alloc] initWithContentsOfFile:path];
glBindTexture(GL_TEXTURE_2D, texture.name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/
// #####################################################################
}
return self;
}
- (void) render
{
// Replace the implementation of this method to do your own custom drawing
// This application only creates a single context which is already set current at this point.
// This call is redundant, but needed if dealing with multiple contexts.
[EAGLContext setCurrentContext:context];
// This application only creates a single default framebuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple framebuffers.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
//obj2opengl.pl banana.obj
//To include the converted object all you have to do is
// include generated arrays
// ---------------------------------------------------------------
// Determines the Normalized Device Coordinate -> Window Coordinate Transform
// ---------------------------------------------------------------
glViewport(0, 0, backingWidth, backingHeight);
// ---------------------------------------------------------------
// Determines the Eye Coordinate -> Clip Coordinate Transform
// ---------------------------------------------------------------
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustumf(-2, 2, -3, 3, 5, 20);
// ---------------------------------------------------------------
// Determines the Object Coordinate -> Eye Coordinate Transform
// ---------------------------------------------------------------
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -8);
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// ####################### Geometry Demo #########################
/*
#define TETRA_FRONT 0.0, 0.0, 1.0
#define TETRA_RIGHT 0.943, 0.0, -0.333
#define TETRA_TOP -0.471, 0.816, -0.333
#define TETRA_LEFT -0.471, -0.816, -0.333
#define v1 1.000000, -1.000000, -1.000000
#define v2 1.000000, -1.000000, 1.000000
#define v3 -1.000000, -1.000000, 1.000000
#define v4 -1.000000, -1.000000, -1.000000
#define v5 1.000000, 1.000000, -1.000000
#define v6 0.999999, 1.000000, 1.000001
#define v7 -1.000000, 1.000000, 1.000000
#define v8 -1.000000, 1.000000, -1.000000
static const GLfloat tetraVertices[] = {
TETRA_TOP,
TETRA_RIGHT,
TETRA_LEFT,
TETRA_FRONT,
TETRA_TOP,
TETRA_RIGHT,
};
static const GLfloat newVertices[] = {
v1,
v2,
v3,
v4,
v5,
v6,
v7,
v8
};
#define RED 255, 0, 0,255
#define GREEN 0,255, 0,255
#define BLUE 0, 0,255,255
#define YELLOW 255,255, 0,255
static const GLubyte tetraColors[] = {
RED,
GREEN,
BLUE,
YELLOW,
RED,
GREEN,
};
static const GLubyte newColors[] = {
RED,
RED,
RED,
RED,
RED,
RED,
RED,
RED
};
static float t = 0.0;
t += 1/30.f;
//glVertexPointer(3, GL_FLOAT, 0, tetraVertices);
glVertexPointer(3, GL_FLOAT, 0, newVertices);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, newColors);
//glColorPointer(4, GL_UNSIGNED_BYTE,0, tetraColors);
glEnableClientState(GL_COLOR_ARRAY);
glPushMatrix();
glTranslatef(0, 0, -3);
glRotatef(30*t, 0, 1, 0);
glScalef(3, 3, 3);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glPopMatrix();
glPushMatrix();
glTranslatef(2, 2, 0);
glRotatef(-30*t, 1, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glPopMatrix();
glPushMatrix();
glTranslatef(2, -2, 0);
glRotatef(-60*t, 1, 0, 1);
glScalef(2, 2, 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glPopMatrix();
*/
//glDisableClientState(GL_VERTEX_ARRAY);
//glDisableClientState(GL_NORMAL_ARRAY);
// set input data to arrays
//glVertexPointer(3, GL_FLOAT, 0, MeshVertexData);
//glEnableClientState(GL_VERTEX_ARRAY);
//glNormalPointer(GL_FLOAT, 0,indexes);
//glEnableClientState(GL_NORMAL_ARRAY);
//glTexCoordPointer(2, GL_FLOAT, 0, bananaTexCoords);
//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(MeshVertexData), &MeshVertexData[0].vertex);
glNormalPointer(GL_FLOAT, sizeof(MeshVertexData), &MeshVertexData[0].normal);
//glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &VertexData[0].texCoord);
static float t = 0.0;
t += 1/30.f;
glPushMatrix();
glTranslatef(0, 0, 0);
glRotatef(30*t, 0, 1, 0);
glScalef(1, 1, 1);
//glDrawArrays(GL_TRIANGLES, 0, vertex_count);
glDrawArrays(GL_TRIANGLES, 0, sizeof(&MeshVertexData[0].vertex));
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glLoadIdentity();
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisable(GL_TEXTURE_2D);
// ###############################################################
// Enable lighting
// This application only creates a single color renderbuffer which is already bound at this point.
// This call is redundant, but needed if dealing with multiple renderbuffers.
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
// Allocate color buffer backing based on the current layer size
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
{
NSLog(#"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
return YES;
}
- (void) dealloc
{
// Tear down GL
if (defaultFramebuffer)
{
glDeleteFramebuffersOES(1, &defaultFramebuffer);
defaultFramebuffer = 0;
}
if (colorRenderbuffer)
{
glDeleteRenderbuffersOES(1, &colorRenderbuffer);
colorRenderbuffer = 0;
}
// Tear down context
if ([EAGLContext currentContext] == context)
[EAGLContext setCurrentContext:nil];
[context release];
context = nil;
[super dealloc];
}
#end
Any help is greatly appreciated. Also any tutorials on OpenGL ES would be great.
Thanks in advance
It's not enough to have the vertex and normal data from Blender, you need the projection and model-view matrices and camera and light positions too. A better approach is to export to a file format that includes that, such as Collada, or POD (if you want to keep it simple). The PowerVR SDK includes tools to export from Blender and even a basic game engine that will parse POD. You also get texture coordinates and animations this way. Check out my first article here:
http://montgomery1.com/opengl/