intravenous

view src/vein.cc @ 3:94d4c60af435

some progress
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Apr 2012 03:35:18 +0300
parents 3ea290d35984
children c6a6a64df6de
line source
1 #include <stdio.h>
2 #ifndef _MSC_VER
3 #include <alloca.h>
4 #else
5 #include <malloc.h>
6 #endif
7 #include "vein.h"
8 #include "geom.h"
9 #include "sdr.h"
11 Vein::Vein()
12 {
13 gen_dist = 16.0;
14 subdiv = 16;
15 ring_subdiv = 16;
16 rad = 1.0;
18 idxbuf = 0;
19 }
21 Vein::~Vein()
22 {
23 delete [] idxbuf;
24 }
26 Vector3 Vein::calc_center(const Vector3 &ppos) const
27 {
28 Vector3 pt{0, 0, ppos.z};
29 pt.x = sin(ppos.z * 0.75);
30 pt.y = cos(ppos.z * 0.2) * 0.6;
31 return pt;
32 }
34 Vector3 Vein::calc_dir(const Vector3 &ppos) const
35 {
36 Vector3 dir = calc_center(ppos + Vector3(0, 0, 0.01)) - calc_center(ppos - Vector3(0, 0, 0.01));
37 return dir.normalized();
38 }
40 void Vein::build_idxbuf()
41 {
42 delete [] idxbuf;
44 int nfaces = subdiv * ring_subdiv;
45 int nidx = nfaces * 4;
46 idxbuf = new unsigned int[nidx];
47 unsigned int *idxptr = idxbuf;
49 for(int i=0; i<subdiv; i++) {
50 for(int j=0; j<ring_subdiv; j++) {
51 idxptr[0] = i * ring_subdiv + j;
52 idxptr[1] = i * ring_subdiv + ((j + 1) % ring_subdiv);
53 idxptr[2] = idxptr[1] + ring_subdiv;
54 idxptr[3] = idxptr[0] + ring_subdiv;
55 idxptr += 4;
56 }
57 }
58 }
60 bool Vein::init()
61 {
62 if(!(sdr = create_program_load("sdr/vein.v.glsl", "sdr/vein.p.glsl"))) {
63 fprintf(stderr, "failed to load vein shaders\n");
64 return false;
65 }
66 if((attr_tang_loc = get_attrib_loc(sdr, "attr_tang")) == -1) {
67 fprintf(stderr, "can't find tangent attribute!\n");
68 }
69 return true;
70 }
72 void Vein::draw(const Vector3 &ppos) const
73 {
74 float start_z = ppos.z - gen_dist / 2.0;
75 float dz = gen_dist / subdiv;
77 int nslices = subdiv + 1;
78 int nverts = nslices * ring_subdiv;
79 int nfaces = subdiv * ring_subdiv;
80 Vertex *vbuf = (Vertex*)alloca(nverts * sizeof *vbuf);
81 Vertex *vptr = vbuf;
83 Vector3 pt = ppos;
84 pt.z = start_z;
86 for(int i=0; i<nslices; i++) {
87 Vector3 cent = calc_center(pt);
88 Vector3 dir = calc_dir(pt);
89 Vector3 up(0, 1, 0);
90 Vector3 right = cross_product(up, dir);
91 up = cross_product(dir, right);
93 Matrix3x3 vrot{right, up, dir};
94 vrot.transpose();
96 float theta = 0.0, dtheta = 2.0 * M_PI / ring_subdiv;
97 for(int j=0; j<ring_subdiv; j++) {
98 Vector3 vec = Vector3{-cos(theta) * rad, sin(theta) * rad, 0.0};
99 vec.transform(vrot);
100 vec += cent;
102 vptr->pos = vec;
103 vptr->norm = cent - vec;
104 vptr->tang = dir;
105 vptr->tc = Vector2(); // TODO
106 vptr++;
108 theta += dtheta;
109 }
111 pt.z += dz;
112 }
114 // also create the index buffer if it's not valid
115 if(!idxbuf) {
116 ((Vein*)this)->build_idxbuf();
117 }
119 // awesome, now draw it
120 bind_program(sdr);
121 draw_mesh(GL_QUADS, nfaces * 4, vbuf, idxbuf, attr_tang_loc);
122 bind_program(0);
123 }