Contributor GSoC Late Introduction

Viveret

New Member
Contributor
Hello, my name's Viveret! Finals suffocated me so here I am applying two days before the deadline! I am a well seasoned, medium rare programmer, with a lot of knowledge about OpenGL, Java, C / C++, and software architecture. I really want to implement the particle system mentioned as I've written a few in my lifetime and I recently won 1st place at the XPRT Women's Hack-A-Thon in Seattle, which had a small cash reward of $2,500! (Still can't believe it)

Anyways, regardless if I'm picked, the next time I get a breather to work on some open source code you'll see me around here. Thanks for reading!

-- Viveret :pinkiehappy:
www.github.com/viveret
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Congratulations on the prize! Well done :)

I see a proposal from you on the GSOC site but yeah it shows a bit that you were short on time ;) It'll be very difficult to catch up with students who have had three weeks to do some initial code work and revise a draft proposal over and over. I don't know if you want to sink in the time to overhaul the proposal to follow a nice template of some sort in describing some relevant background, some ideas for implementations, and a timeline for what you'd expect to do (something like a week by week summary or so). Up to you if you'd like to try but we'd love to see code from you either way! We're happy to teach and mentor whether through GSOC or not :)
 

Viveret

New Member
Contributor
I'm a very fast worker so I'm sure I could get a lot finished and ready for starting point GSoC. I can rewrite the proposal tomorrow morning to include
  • Initial code work??? Or some code from previous projects or relevant code
  • My background and relevant skills
  • Implementation ideas
  • Timeline with deadlines or goals
I'm glad I got my foot in the door, I was really hoping to participate! :flutteryay:
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Huzzah! :)

@Florian will probably be your best contact for particle system stuff. Timeline and implementation ideas would be good. Directly applicable experience is good, like knowing about the right libraries/frameworks and how they might be hooked up in our engine. IRC is good for reviewing the proposal when the right people are awake (the Europeans should be getting up around now, while I'm about to go to bed)

Trying to run the game from source and looking for a quick small bug or two on GitHub to fix also helps a lot!
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
Hi @Viveret and welcome :)

For the particle system task it will pay off if you can show off some more in-depth knowledge of particle systems in general. Even if you are not familiar with our code base (yet) having working with PSs in other engines might put you ahead of other students. If you've developed a PS by yourself and the code is available somewhere it would be a good reference ;)
 

Viveret

New Member
Contributor
For the hackathon I used OpenGL VBOs which I would use again the particle system:
Code:
package com.viveret.xprtworkloadw2016;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.util.Log;
import java.io.InputStream;
import java.io.IOException;

import org.smurn.jply.*;
import org.smurn.jply.util.*;

public class Mesh {
    public static final int BYTES_PER_FLOAT = 4;
    public static final int BYTES_PER_INT = 4;
    public static final int BYTES_PER_SHORT = 2;

    private static int gNumMeshes = 0;

    public float positions[];
    public float norms[];
    public float colors[];
    public int indices[];

    private int mySize, myIndexIndex, myColorIndex;
    private final FloatBuffer myPosBuf;
    private final FloatBuffer myColorBuf;
    private final IntBuffer myIndexBuffer;
    private final int myMeshId;
    private boolean myDataHasChanged;

    // 0 = vert, 1 = col, 2 = indx
    private final int bufs[] = new int[3];
    //    private static boolean gHasInitialized = false;

    private long perfStartTime, perfDuration;

    public Mesh(int vertCapacity, int numIndices) {
        mySize = 0;
        myIndexIndex = 0;
        myColorIndex = 0;
        perfStartTime = System.nanoTime();
        perfDuration = 0;
        GLES20.glGenBuffers(bufs.length, bufs, 0);

        positions = new float[vertCapacity * 3];
        norms = new float[vertCapacity * 3];
        colors = new float[vertCapacity * 4];
        indices = new int[numIndices];
        myPosBuf = ByteBuffer.allocateDirect(positions.length *
                                               BYTES_PER_FLOAT)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();
        myColorBuf = ByteBuffer.allocateDirect(colors.length *
                                               BYTES_PER_FLOAT)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer();
        myIndexBuffer = ByteBuffer.allocateDirect(indices.length *
                                               BYTES_PER_INT)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer();

        myMeshId = gNumMeshes++ - 1;

        dataHasChanged();
        // Position
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufs[0]);
        checkGLError("bind 0");
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, myPosBuf.capacity() * BYTES_PER_FLOAT,
                            myPosBuf, GLES20.GL_DYNAMIC_DRAW);
        checkGLError("buffer data array buf");
        // Color
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufs[1]);
        checkGLError("bind 1");
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, myColorBuf
                            .capacity() * BYTES_PER_FLOAT,
                            myColorBuf, GLES20.GL_DYNAMIC_DRAW);
        checkGLError("buffer color data array buf");
        // Indices
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, bufs[2]);
        checkGLError("bind 2");
        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
                            myIndexBuffer.capacity()
                            * BYTES_PER_INT, myIndexBuffer,
                            GLES20.GL_DYNAMIC_DRAW);
        checkGLError("buffer data element array");
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        checkGLError("bind array buf 0");
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
        checkGLError("bind element array buf 0");
        perfDuration += System.nanoTime() - perfStartTime;
        perfStartTime = 0;
    }

    public int addVert(float[] axes) {
        for (int i = 0; i < axes.length; i++) {
            positions[mySize * 3 + i] = axes[i];
        }
        return mySize++ - 1;
    }

    public int addVert(float x, float y, float z) {
        return addVert(new float[]{x, y, z});
    }

    public void addIndex(int i) {
        indices[myIndexIndex] = i;
        myIndexIndex++;
    }

    public void addIndex(int[] ar) {
        for (int i : ar)
            addIndex(i);
    }

    public int addColor(float[] axes) {
        for (int i = 0; i < axes.length; i++) {
            colors[myColorIndex * 4 + i] = axes[i];
        }
        return myColorIndex++ - 1;
    }

    public int addColor(float r, float g, float b, float a) {
        return addColor(new float[]{r, g, b, a});
    }

    public int getSize() {
        return mySize;
    }

    public void dataHasChanged() {
        myPosBuf.put(positions).position(0);
        myIndexBuffer.put(indices).position(0);
        myColorBuf.put(colors).position(0);
        myDataHasChanged = true;
    }

    public void renderSelf(GL10 unused) {
        checkGLError("before");
        // Position
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufs[0]);
        if (myDataHasChanged) {
            GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0,
                                   myPosBuf.capacity()
                                   * BYTES_PER_FLOAT, myPosBuf);
        }
        GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false,
                                     0, 0);
        GLES20.glEnableVertexAttribArray(0);

        // Color
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufs[1]);
        if (myDataHasChanged) {
            GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0,
                                   myColorBuf.capacity()
                                   * BYTES_PER_FLOAT, myColorBuf);
        }
        GLES20.glVertexAttribPointer(1, 4, GLES20.GL_FLOAT, false,
                                     0, 0);
        GLES20.glEnableVertexAttribArray(1);
           
        // Indices
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, bufs[2]);
        if (myDataHasChanged) {
            GLES20.glBufferSubData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0,
                                   myIndexBuffer.capacity()
                                   * BYTES_PER_INT, myIndexBuffer);
        }
       
        // Render
        //GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mySize);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, myIndexBuffer
                              .capacity(), GLES20.GL_UNSIGNED_INT,
                              0);
        GLES20.glDisableVertexAttribArray(0);
        GLES20.glDisableVertexAttribArray(1);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
       
        myDataHasChanged = false;
    }

    public void translate(float x, float y, float z) {
        for (int i = 0; i < mySize; i += 3) {
            positions[i] += x;
            positions[i+1] += y;
            positions[i+2] += z;
        }
        dataHasChanged();
    }

    public static void checkGLError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(MyApplication.LOGTAG, op + ": glError " + error);
        }
    }

    public void freeGL() {
        final IntBuffer ib = ByteBuffer.allocateDirect(bufs.length *
                                               BYTES_PER_INT)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer();
        GLES20.glDeleteBuffers(ib.capacity(), ib);
    }
}
Available at https://github.com/viveret/XPRT_Winter_2016/blob/master/src/main/java/com/viveret/xprtworkloadw2016/Mesh.java

And 2 years ago, while working on a personal project, I wrote a basic particle engine that had basic animations:
Code:
#ifndef PARTICLE_SYSTEM
#define PARTICLE_SYSTEM


#include "Core.h"
#include "myMath.h"

#include <vector>


#define PARTICLE_DRAG 0.1f
#define PARTICLE_BOUNCE 0.5f
#define PARTICLE_SPEED 0.005f


namespace E_Particle_System
{
    struct P_Particle
    {
        P_Particle();
        P_Particle( Vector2 Pos, Vector2 Velo );
        void Update( float dt );

        Vector2 Position;
        Vector2 Velocity;

        float Duration;
    };


    struct P_Particle_System
    {
        P_Particle_System();

        void Update( float dt );
        void Draw();

        bool Running;


        u_int Particles_Per_Sec;
        float Add_Particle;

                                                 
        u_char Start_R, Start_G, Start_B, Start_A;
        u_char End_R, End_G, End_B, End_A;

        float Start_Size, End_Size;

        Vector2 Position, Velocity;
        float Gravity,Particle_Duration, Rand_Noise;

        std::vector< P_Particle > Particles;


        bool Mem_Used, Mem_Locked;// used == update, locked == draw
    };
}
#endif
Code:
#include "Particle_System.h"

#include "myMath.h"

using namespace E_Particle_System;

            
P_Particle::P_Particle()
{
    this->Duration = 0.f;
}

P_Particle::P_Particle( Vector2 Pos, Vector2 Velo )
{
    this->Duration = 0.f;

    this->Position = Pos;
    this->Velocity = Velo;
}

void P_Particle::Update( float dt )
{
    this->Duration += dt;
                                          
    this->Position.x += this->Velocity.x * dt;
    this->Position.y += this->Velocity.y * dt;

    if( this->Position.y < 0 )
    {
        this->Position.y = 0;
        this->Velocity.y = -this->Velocity.y * PARTICLE_BOUNCE;
    }

    this->Velocity.x -= RoundToUnit( this->Velocity.x ) * PARTICLE_DRAG * dt;
}


P_Particle_System::P_Particle_System()
{
    this->Running = false;
    this->Mem_Locked = false;
    this->Mem_Used = false;


    this->Particles_Per_Sec = 10;
    this->Add_Particle = 0.f;

    this->Particle_Duration = 5.f;

    this->Start_R = 255;
    this->Start_G = 255;
    this->Start_B = 255;
    this->Start_A = 255;
   
    this->End_R = 255;
    this->End_G = 255;
    this->End_B = 255;
    this->End_A = 0;

    this->Start_Size = 0.1f;
    this->End_Size = 0.05f;

    this->Gravity = 0.5f;

    this->Rand_Noise = 0.1f;
}

void P_Particle_System::Update( float dt )
{
    this->Mem_Used = true;     
    while( this->Mem_Locked );// wait until not locked

    for( u_int i = 0;i < this->Particles.size(); i++)
    {
        this->Particles[i].Velocity.y -= this->Gravity * dt * PARTICLE_SPEED;

        this->Particles[i].Update( dt * PARTICLE_SPEED );

        if(this->Particles[i].Duration > this->Particle_Duration)
        {
            this->Particles.erase(this->Particles.begin() + i );
            i--;
        }
    }

    if( this->Running )
    {
        this->Add_Particle += dt * PARTICLE_SPEED;

        if( this->Add_Particle > 1.f/this->Particles_Per_Sec )
        {                   
            this->Add_Particle = 0;

            P_Particle nPart( this->Position, this->Velocity );
                 
            nPart.Position.x += ( rand()%200 - 100 )/100.f * this->Rand_Noise * 1.5f;
            nPart.Position.y += ( rand()%200 - 100 )/100.f * this->Rand_Noise * 1.5f;

            nPart.Duration -= ( rand()%200 - 100 )/100.f * this->Rand_Noise * 8;


            this->Particles.push_back( nPart );
        }
    }      

    this->Mem_Used = false;
}

                      
#include "Engine.h"
extern S_Engine Engine;

void P_Particle_System::Draw()
{                   
    sglDisable( GL_TEXTURE_2D );
                            
    this->Mem_Locked = true;
    while( this->Mem_Used );

    for(u_int i = 0;i < this->Particles.size(); i++)
    {
        float Perc = this->Particles[i].Duration / this->Particle_Duration;
        glColor4ub( u_char((this->End_R - this->Start_R) * Perc) + this->Start_R,
                   u_char((this->End_G - this->Start_G) * Perc) + this->Start_G,
                   u_char((this->End_B - this->Start_B) * Perc) + this->Start_B,
                   u_char((this->End_A - this->Start_A) * Perc) + this->Start_A);

        float Size = Perc * (this->End_Size - this->Start_Size) + this->Start_Size;
                       
        glPointSize( Size * 75.f );
                                                                    
        glBegin( GL_POINTS );                                            
            glVertex2f( this->Particles[i].Position.x-Size, this->Particles[i].Position.y-Size );
        glEnd();

        /*glVertex2f( this->Particles[i].Position.x-Size, this->Particles[i].Position.y-Size );
        glVertex2f( this->Particles[i].Position.x-Size, this->Particles[i].Position.y+Size );
        glVertex2f( this->Particles[i].Position.x+Size, this->Particles[i].Position.y+Size );
        glVertex2f( this->Particles[i].Position.x+Size, this->Particles[i].Position.y-Size );*/
    }
               
    this->Mem_Locked = false;

    glColor4f( 1,1,1,1 );
}
Available at https://github.com/viveret/LivingCode/blob/master/Living_Code/source/Particle_System.h and https://github.com/viveret/LivingCode/blob/master/Living_Code/source/Particle_System.cpp, respectively.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
@Viveret looks good (and impressive!) to me from a high level view :) Submit it as a final proposal just in case! You can update it up to the deadline if needed.

@Florian would probably be the main person for a deeper technical review.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
@Cervator is there anything I could do to improve it?
Not that I could tell you, honestly. I'm a backup mentor at best, mostly I do paperwork and keep the server hamsters fed :D

The Europeans should be waking up again soon so hopefully one or two of them can provide more review :)
 

Viveret

New Member
Contributor
Not that I could tell you, honestly. I'm a backup mentor at best, mostly I do paperwork and keep the server hamsters fed :D

The Europeans should be waking up again soon so hopefully one or two of them can provide more review :)
Alrighty, I'm nervous I'm not including enough but I'll wait for the Europeans to wake up and smell the roses :D
 

Viveret

New Member
Contributor
@Cervator is there anything I could do between now and April 22 (when accepted proposals are announced) that might boost my chances of being accept? Perhaps checking out the repo an issue list to demonstrate relevant skills? :ajsmug:
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
Sure, commiting some Bugfixes vor feature implementations will give us an even better feeling of your skills. Furthermore, we have a little easter hackathon going on over the "weekend" you might want to join. Monday is a public holiday over here, so I'll definitely count that to the weekend :D

Otherwise, stay active and.communicate with us ;) share what you're working on, ask questions when you're stuck somewhere, follow the discussions here in the forums and on github and try to participate ;)
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Yep what @Skaldarnar said :) Since you got here late you missed out on 2-3 weeks of community bonding / small bug fixes and development talk that a few other students managed.

Usually we encourage review of the contributor friendly issues list to see if you can spot something easy to get started with and PR back for review and merging, but really about any issue you can fix is good. Socialize here and on IRC, help review PRs and issues, test things, participate in the weekends particularly, and so on :)
 

Viveret

New Member
Contributor
Well... looks like I didn't make it. :(
Is there anything I could of done to have a better proposal or be a better candidate next time?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Well... looks like I didn't make it. :(
Is there anything I could of done to have a better proposal or be a better candidate next time?
Heya - very sorry to more or less repeat what GSOC told us for the first three years we applied: the numbers just weren't there :(

You made an amazing last-minute effort and have a perfectly suitable proposal + good community intro and contributions. Only thing I can really think of is getting an earlier start.

With 3 slots this year assuming we make it next year we will no longer have the newbie org tag on us, so we'll likely have more slots then. Might be more limited by mentors at that point (since this year we only got 3 primary mentors)

I know it is a poor consolation prize but we still would love to have you around and working on particles or anything of your desire. We mentioned the more regular mentoring program as well as being able to throw more code bounties at things. If you're up for that just let us know :)
 

Viveret

New Member
Contributor
I'd be up for code bounties, I think that the animation system thing directly made other bountied issues easier or essentially done but needs to be used for that situation. Also bounties let me pay for food and essentials cause university is so damn expensive. Sometimes I also like taking breaks off other projects and solving issues here would be great for that.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Awesome :) And agreed on "dependencies" helping like that. We had a few VR-related proposals that we realized were sort of stuck without some more fundamental work on rendering first.

Let me do some organizing over the weekend and talking to our mentors, maybe finding another one or two for "unofficial" projects we can still support some
 
Top